Problem, How do I return my own QObject derived custom class as "QVariant"?
-
wrote on 18 Mar 2011, 17:35 last edited by
Some code?
-
wrote on 18 Mar 2011, 19:07 last edited by
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
{
Q_OBJECTpublic:
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;}
private:
QString name;
ContactOnlineStatus onlineStatus;
bool inBuddyList;};@
The model....
@
class ContactsModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit ContactsModel(QObject *parent = 0);virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
signals:
public slots:
private:
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.....
}
else
return QVariant();
}@ -
wrote on 18 Mar 2011, 19:13 last edited by
One correction.
Changed:
@return qVariantFromValue(this->contacts[index.row()]);@
To:
@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.
-
wrote on 18 Mar 2011, 19:20 last edited by
"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.
-
wrote on 18 Mar 2011, 19:52 last edited by
You need:
@#include <QMetaType>@
-
wrote on 18 Mar 2011, 19:54 last edited by
Yep. i got it compiling now. thanks.
-
wrote on 18 Mar 2011, 19:56 last edited by
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.
-
wrote on 18 Mar 2011, 20:05 last edited by
At what point do you call QRegisterMetaType()? application object? after main?
-
wrote on 18 Mar 2011, 22:13 last edited by
It's all in the "docs":http://doc.qt.nokia.com/latest/qmetatype.html#qRegisterMetaType. 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.
-
wrote on 19 Mar 2011, 06:26 last edited by
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.
-
wrote on 19 Mar 2011, 08:49 last edited by
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?
11/12