Important: Please read the Qt Code of Conduct -

Problem, How do I return my own QObject derived custom class as "QVariant"?

  • Implementing a derived "QAbstractListModel::data" method.

    Q_DECLARE_METATYPE(myType); doesn't even compile.... returning my custom object results in a compilation error.

    How can this be done?

  • Some code?

  • Ok. hint well taken.

    This is a class I got. Fairly simple. I want to have a QListView that'll connect to a model that owns a list of such instances. The reason is I need to manipulate the drawing (complex w/ added buttons per row) as well as sorting.

    When i implement ::data on my derived QAbstractListModel i am trying to return one of these objects (which i store on a std::vector). I get a compilation error as its wants a QVariant and it's not compatible with my class. I tried adding Q_DECLARE_METATYPE(Contact); after my class declaration but it gives me a compilation error (../source/Contact.h:42: error: expected constructor, destructor, or type conversion before ';' token)

    [i do implement the constructor, copy constructor and assignment operator in the cpp file. no worries]
    #include <QtGlobal>
    #include <QObject>

    typedef enum ContactOnlineStatus_
    OFFLINE = 0,
    ONLINE = 1,
    BUSY = 2
    } ContactOnlineStatus;

    class Contact : public QObject

    explicit Contact(QObject *parent = 0);
    Contact (const Contact & rhs);
    Contact & operator=(const Contact & rhs);

    // setters
    void SetName(QString name) { this->name = name;}
    void SetOnlineStatus(ContactOnlineStatus status) {this->onlineStatus = status;}
    void SetInBuddyList(bool inBuddyList) {this->inBuddyList = inBuddyList;}
    // getters
    QString GetName() {return name;}
    ContactOnlineStatus GetOnlineStatus() {return onlineStatus;}
    bool GetInBuddyList() {return inBuddyList;}

    QString name;
    ContactOnlineStatus onlineStatus;
    bool inBuddyList;


    The model....
    class ContactsModel : public QAbstractListModel
    explicit ContactsModel(QObject *parent = 0);

    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;


    public slots:

    std::vector<Contact> contacts;

    The ::Data implementation...

    @QVariant ContactsModel::data(const QModelIndex &index, int role) const
    if (!index.isValid())
    return QVariant();

    if (index.row() >= this->contacts.size())

    return QVariant();

    if (role == Qt::DisplayRole)

    return qVariantFromValue(this->contacts[index.row()]); <-- this is one of the things I tried. nothing worked.....
    return QVariant();

  • One correction.


    @return qVariantFromValue(this->contacts[index.row()]);@


    @return qVariantFromValue(&this->contacts[index.row()]);@

    as it needs a pointer.. but now I am getting a build error:

    /Library/Frameworks/QtCore.framework/Headers/qmetatype.h:222: error: 'qt_metatype_id' is not a member of 'QMetaTypeId<const Contact*>'

    It's obvious I am missing a declaration to "validate" the class I am using. What it is escapes me.

  • "Q_DECLARE_METATYPE" is simply unknown. do I need to include an *.h file for it? my compiler simply doesn't know about this. This is really weird.

  • You need:

    @#include <QMetaType>@

  • Yep. i got it compiling now. thanks.

  • Good stuff. If you ever need to pass your custom types as arguments in signals across thread boundaries remember that you will also need to call qRegisterMetaType() too.

  • At what point do you call QRegisterMetaType()? application object? after main?

  • It's all in the "docs": You call it before you use it in a signal/slot connection. This is only needed if you need to pass your type as an argument in a queued connection. If all your connections are within the sam thread then you do not need to worry about it.

    If you do need it then just call it once for your type before you use it in a connection.

  • Looks like your std::vector (why not use QVector or QList?) contains actual instances of your Contact class. Because Contact inherits QObject, and QObject is not mend to be copied around, you should store pointers in your vector instead.

  • Agreed. The compiler should complain about a lack of a public QObject copy constructor (assuming that you call the base class copy ctor in your overridden one). Never try to copy QObject's around. What happens to the parent for example ie who owns the new object?

Log in to reply