I'm exposing a QList<QObject*> property from C++ to QML. There I can
access it, for example, with the following code.
ListView {
anchors.fill: parent
model: myModel.dataObjects //dataObjects is QList<QQobject*>
delegate: Rectangle {
height: 25
width: 100
color: model.modelData.color
Text { text: model.modelData.name}
}
}
Now I've tried to put some dummy data in place to simulate the model if
the QML code is run without C++ backend. So I've created the following.
// dummydata/myModel.qml
import Qt 4.7
Item {
property alias dataObjects: listModel
ListModel {
id: listModel
ListElement {
name: "Dummy Peter"
color: "orange"
}
ListElement {
name: "Dummy Paul"
color: "yellow"
}
}
}
Unfortunately this is not working as expected. It only works if I remove
the "modelData" part from the delegate. E.g. the following works.
ListView {
anchors.fill: parent
model: myModel.dataObjects //dataObjects is QList<QQobject*>
delegate: Rectangle {
height: 25
width: 100
color: model.color // removed modelData
Text { text: model.name} // removed modelData
}
}
How can I create a dummy model that I can use as a drop-in replacement for my QList<QObject*> model?
Thanks!
Conny
_______________________________________________
Qt-qml mailing list
Qt-...@trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-qml
Hi,
There is a discrepancy in how QAbstractItemModel models and QList<QObject*> models expose data (see http://doc.qt.nokia.com/4.7-snapshot/qdeclarativemodels.html#qlist-qobject and http://bugreports.qt.nokia.com/browse/QTBUG-13576 for more). To work around that, you'll need your dummy data to be a list of objects rather than a proper model, to mimic what you are doing in C++. Here's an example of how your could modify your above code to do that:
// MyObject.qml
import Qt 4.7
QtObject {
property string name
property color color
}
// dummydata/myModel.qml
import Qt 4.7
QtObject {
property list<QtObject> dataObjects:[
MyObject {
name: "Dummy Peter"
color: "orange"
},
MyObject {
name: "Dummy Paul"
color: "yellow"
}
]
}
Alternatively, you could use a model rather than a list of objects on the C++ side, and then model.color, model.name, etc should work for both. If you'd like to go this route you might be interested in QObjectListModel (http://qt.gitorious.org/qt-labs/qml-object-model), which is meant to be a more powerful alternative to QList<QObject*> that retains much of the ease of use of working with a simple list.
Regards,
Michael
On Mon, 2010-09-13 at 04:29 +0200, michael...@nokia.com wrote:
> There is a discrepancy in how QAbstractItemModel models and QList<QObject*> models expose data (see http://doc.qt.nokia.com/4.7-snapshot/qdeclarativemodels.html#qlist-qobject and http://bugreports.qt.nokia.com/browse/QTBUG-13576 for more). To work around that, you'll need your dummy data to be a list of objects rather than a proper model, to mimic what you are doing in C++. Here's an example of how your could modify your above code to do that:
thanks for the pointers. I've subscribed to the ticket you mentioned.
> // MyObject.qml
> import Qt 4.7
> QtObject {
> property string name
> property color color
> }
>
> // dummydata/myModel.qml
> import Qt 4.7
> QtObject {
> property list<QtObject> dataObjects:[
> MyObject {
> name: "Dummy Peter"
> color: "orange"
> },
> MyObject {
> name: "Dummy Paul"
> color: "yellow"
> }
> ]
> }
If I do it like above, I get errors in myModelqml.
'name' is not a valid property name
'color' is not a valid property name
I tried it both with QtObject and with Item with the same result. So use
the ListModel and try to change the C++ side.
> Alternatively, you could use a model rather than a list of objects on the C++ side, and then model.color, model.name, etc should work for both. If you'd like to go this route you might be interested in QObjectListModel (http://qt.gitorious.org/qt-labs/qml-object-model), which is meant to be a more powerful alternative to QList<QObject*> that retains much of the ease of use of working with a simple list.
I tried it with QObjectListModel, but I get the following error:
QMetaProperty::read: Unable to handle unregistered datatype
'QObjectListModel' for property 'MyModel::dataObjects'
I also tried changing the return value of the property to
QAbstractItemModel and QObject. But with the same outcome.
I will now try to implement my own QAbstractItemModel like in this
example[1]. However, I would prefer a more generic way. In fact the
QObjectListModel really looks like the right thing. Do you have any idea
what I'm doing wrong?
Thanks!
Conny
[1]
http://gutenberg.troll.no/4.7-snapshot/declarative-modelviews-abstractitemmodel.html
So I did my own model and first I got the exact same problem:
QMetaProperty::read: Unable to handle unregistered datatype
'MyListModel*' for property 'MyApp::myModel'.
The problems seems to be that I'm exposing a 'manager' class, e.g. MyApp
to QML and the data model is a property of this class.
If I expose the model directly everything is working. So, for example,
doing:
MyListModel* mod = new MyListModel();
mod->addObject(MyObject("Name 1", "bla 1"));
mod->addObject(MyObject("Name 2", "bla 2"));
ctxt->setContextProperty("myMod", mod);
I can use 'myMod' as model for ListViews.
However, if I have a class MyApp and MyApp has a property MyApp::myModel
that returns an instance of MyListModel and I expose it like:
ctxt->setContextProperty("myApp", app);
I should be able to use 'myApp.myModel' as model for a ListView.
Unfortunately this is not working. Instead I just get the error
mentioned above.
Do I have to use Q_DECLARE_METATYPE() with MyListModel? I'll give it a,
but I would be very grateful for additional hints.
Thanks!
Conny
After adding Q_DECLARE_METATYPE(MyListModel*); to the bottom of
MyListModel.h and qReisterMetaType<MyListModel*>("MyListModel"); to
main.cpp, the error message is gone.
Unfortunately all roles of my model are now [undefined].
Anything else I can try?
On 13. sep. 2010, at 14.55, ext Cornelius Hald wrote:
> On Mon, 2010-09-13 at 13:38 +0200, Cornelius Hald wrote:
>> Do I have to use Q_DECLARE_METATYPE() with MyListModel? I'll give it a,
>> but I would be very grateful for additional hints.
>
> After adding Q_DECLARE_METATYPE(MyListModel*); to the bottom of
> MyListModel.h and qReisterMetaType<MyListModel*>("MyListModel"); to
> main.cpp, the error message is gone.
> Unfortunately all roles of my model are now [undefined].
>
> Anything else I can try?
You probably need to define your role names;
http://doc.qt.nokia.com/4.7-snapshot/qabstractitemmodel.html#setRoleNames
Cheers,
Henrik
Thanks, but the role names are set. As I said, if I directly expose the model object everthing works fine. The trouble starts if I expose an object that provides the model object as property.
Maybe this is not the recommended approach?
Cheers,
Conny
On 13/09/2010, at 7:24 PM, ext Cornelius Hald wrote:
> Hi Michael,
>
> On Mon, 2010-09-13 at 04:29 +0200, michael...@nokia.com wrote:
>> There is a discrepancy in how QAbstractItemModel models and QList<QObject*> models expose data (see http://doc.qt.nokia.com/4.7-snapshot/qdeclarativemodels.html#qlist-qobject and http://bugreports.qt.nokia.com/browse/QTBUG-13576 for more). To work around that, you'll need your dummy data to be a list of objects rather than a proper model, to mimic what you are doing in C++. Here's an example of how your could modify your above code to do that:
>
> thanks for the pointers. I've subscribed to the ticket you mentioned.
>
>> // MyObject.qml
>> import Qt 4.7
>> QtObject {
>> property string name
>> property color color
>> }
>>
>> // dummydata/myModel.qml
>> import Qt 4.7
>> QtObject {
>> property list<QtObject> dataObjects:[
>> MyObject {
>> name: "Dummy Peter"
>> color: "orange"
>> },
>> MyObject {
>> name: "Dummy Paul"
>> color: "yellow"
>> }
>> ]
>> }
>
> If I do it like above, I get errors in myModelqml.
> 'name' is not a valid property name
> 'color' is not a valid property name
Is the above the exact wording of the error message you are seeing (if so, what release version are you using)? If the objects in the list are QtObjects, I get the message "Cannot assign to non-existent property "name"", but as long as they are of a custom type that we've defined (in this case MyObject), with the corresponding custom properties, it all works as described for me (note that MyObject.qml needs to go in the root directory, rather than the dummydata directory). I'm happy to send you a tar of the files I'm testing with, if this is still something you want to pursue.
> I tried it both with QtObject and with Item with the same result. So use
> the ListModel and try to change the C++ side.
>
>> Alternatively, you could use a model rather than a list of objects on the C++ side, and then model.color, model.name, etc should work for both. If you'd like to go this route you might be interested in QObjectListModel (http://qt.gitorious.org/qt-labs/qml-object-model), which is meant to be a more powerful alternative to QList<QObject*> that retains much of the ease of use of working with a simple list.
>
> I tried it with QObjectListModel, but I get the following error:
> QMetaProperty::read: Unable to handle unregistered datatype
> 'QObjectListModel' for property 'MyModel::dataObjects'
>
> I also tried changing the return value of the property to
> QAbstractItemModel and QObject. But with the same outcome.
>
> I will now try to implement my own QAbstractItemModel like in this
> example[1]. However, I would prefer a more generic way. In fact the
> QObjectListModel really looks like the right thing. Do you have any idea
> what I'm doing wrong?
You'll need to register the QObjectListModel type to use it in a property, using qmlRegisterType<QObjectListModel>();
Regards,
Michael
On Tue, 2010-09-14 at 01:00 +0200, michael...@nokia.com wrote:
> Is the above the exact wording of the error message you are seeing (if so, what release version are you using)? If the objects in the list are QtObjects, I get the message "Cannot assign to non-existent property "name"", but as long as they are of a custom type that we've defined (in this case MyObject), with the corresponding custom properties, it all works as described for me (note that MyObject.qml needs to go in the root directory, rather than the dummydata directory). I'm happy to send you a tar of the files I'm testing with, if this is still something you want to pursue.
The error above is the error I receive from QtCreator. I noticed that I
can still execute the code with qmlviewer. So it looks like a QtCreator
issue. Still, I'm having the problem with the import of MyObject. For
some reason dummydata/myModel.qml can't find MyObject.qml. Not if I put
it into 'dummydata' and not if I put it into the parent folder (which is
not the root folder). I've tried different imports relative to
myModel.qml and relative to the component that uses myModel.qml, but
without success.
Anyways, I will not use the QList<> approach in my application because
of the .modelData issue. Still, if it is no problem for you, please send
me your example. I'm always curious :) Ah and I'm using Qt 4.7-rc1 on
Ubuntu taken from this[1] PPA.
> You'll need to register the QObjectListModel type to use it in a property, using qmlRegisterType<QObjectListModel>();
Thanks! qmlRegisterType() helped with my own model (derived from
QAbstractListModel). With QObjectListModel I'm still having a problem,
because I don't understand how the roles are defined. From looking at
the code and the comments it looks like only one role with the name
"object" is defined. But then, how should I use it in QML?
Until I fully understand QObjectListModel I'll use my own
QAbstractListModels. But I hope I can switch eventually.
Thanks for all the help!
Conny
[1] https://edge.launchpad.net/~kubuntu-ppa/+archive/experimental
I've reported that as
http://bugreports.qt.nokia.com/browse/QTCREATORBUG-2340
Cheers,
Christian
Thank you. I've directly commented there.
Cheers,
Conny
> Thanks! qmlRegisterType() helped with my own model (derived from
> QAbstractListModel). With QObjectListModel I'm still having a problem,
> because I don't understand how the roles are defined. From looking at
> the code and the comments it looks like only one role with the name
> "object" is defined. But then, how should I use it in QML?
Define Q_PROPERTIES and access them on the object.
delegate : Text { text: model.object.someProp; height : 20 }
I wrote something similar before but used the term 'data' instead of
'object', so I used model.data.someProp.
http://steveire.wordpress.com/2010/02/19/qml-with-akonadi-or-how-to-use-
your-existing-model-view-design-with-qml/
All the best,
Steve.
Thanks Steve, but then I'm having the same problem as with
QList<QObject*> models. In both cases they are accessed in a different
way compared with QML ListModels.
Maybe we could write a generic wrapper like, for example, ListModel<T>
that would expose all properties of the containing type T as roles. Not
sure if that is possible, though. It's just a couple of days since I'm
in Qt land :)
Anyways, I'll read your article - I probably can learn something.
Thanks!
Conny
I was wrong -- it was picking the file up for me because the root folder happened to be my working directory. With change http://scm.dev.nokia.troll.no/projects/qt/repos/qt-qml/commits/a2ca8c305e6ebe145b82588d088f5dc16a4db861 MyObject should be picked up if placed within the dummydata folder.
Regards,
Michael
One of the reasons I haven't done this for QObjectListModel is because it is not very pretty/fast with our current model API -- the model would have to monitor all changes to the object's properties, and emit dataChanged appropriately.
With object, the binding below is automatically updated when the object's name property changes (thanks to NOTIFY):
Text { text: model.object.name }
In the binding below, the model needs to know when the name property of the object changes, so it can emit dataChanged, causing the binding to update:
Text { text: model.name }
I think having the single "object" role is probably still the best solution for QObjectListModel, but I agree it is annoying that this doesn't fit in well with doing dummydata.
Regards,
Michael
Thanks for the explanation. It's much clearer now. Just to make sure I
did completely understand the issue: The performance issue is also valid
for custom models based on QAbstractListModel, right? There the
situation is the same that whenever a property of a contained object
changes, the model needs to be informed and the model then informs the
view?
> I think having the single "object" role is probably still the best solution for QObjectListModel, but I agree it is annoying that this doesn't fit in well with doing dummydata.
I see your point, but also I feel that using dummydata is very important
for me. So for now I'll stick to my QAbstractListModels. When the fix,
you posted earlier, is released, it should be possible to construct
dummydata that is compatible with QObjectListModel. I'll then give it
another try.
For now, thanks a lot for all the support. It's really a great list with
very helpful people here :)
Cheers,
Conny
The link is timing out for me, but I suppose you linked to a fix. So
thanks a lot!
Cheers,
Conny
Regards,
Michael
________________________________________
From: ext Cornelius Hald [ha...@icandy.de]
Sent: Wednesday, September 15, 2010 5:26 PM
To: Brasser Michael (Nokia-MS-Qt/Brisbane)
Cc: qt-...@trolltech.com
Subject: Re: [Qt-qml] Dummy model for QList<QObject*> model