Access model owned by class in QML
-
Hi!
I've seen several topics on similar problems, but I still haven't been able to solve it, so I'm making a new thread.
I have a class, ModelManager, that owns an instance of MyListModel, inheriting from QAbstractListModel. The ModelManager is the .cpp backend that is exposed to QML through a call to setContextProperty in main.cpp.
I would like to access myListModel in QML and use it as a model for a Repeater.
My idea was to have the ModelManager own an instance of myListModel and have a Q_INVOKABLE getter in ModelManager.
In ModelManager I have:
class ModelManager : QObject { Q_OBJECT public: ModelManager(QObject* parent = 0); Q_INVOKABLE MyListModel* myListModel() {return &myListModel_;} private: MyListModel myListModel_; }
And in the Repeater I want to write:
Repeater { model: manager.myListModel() ... }
I can't get it working however. I've read several posts about out it here on the forum. Some mention qmlRegisterType, which I've tried calling in my main.cpp with no luck.
qmlRegisterType<MyListModel>("ListModel",1,0, "listModel");
and then importing it with:
import ListModel 1.0
But no matter what I try, I always get the error:
Unkown return type: MyListModel*
I've also tried returing QObject* in myListModel(). This runs, but I get a very nasty error and crash, I'm assuming when the Repeater actually tries to access the model.
Any ideas about what I'm getting wrong?
-
@Obi-Wan you don't need to have a Q_INVOKABLE getter to expose your MyListModel into QML components instead use QQmlContext class, try it this way:
//main.cpp QQmlContext *context = new QQmlContext(engine.rootContext()); context->setContextProperty("myListModel", &myListModel); //qml file Repeater { model: myListModel ... }
-
@literA2 Thanks!
This seems to work, as in the text turns blue if I write myListModel in QML, but I'm having a hard time confirming if it does!
myListModel currently is a list of doubles, I tought I could should these in a QML window by writing:
ListView { id: testView width: 200 height: 200 x: 50 y: 50 model: myListModel delegate: Text { text: display // As this is the default role }
Shouldn't this work?
-
@literA2 Thanks again, that does indeed work!
I'm not sure what I'm doing wrong, but I often have trouble figuring out these smaller details. I keep looking in the documentation, but I guess I keep looking in the wrong place.
In any case, my complete solution to the original problem is, as per @literA2's suggestion, to use setContextProperty in main.cpp. The model is still owned by the modelManager in my case, but I expose the model to QML in main.cpp by calling a getter.
main.cpp
ModelManager modelManager; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("myListModel", modelManager.myListModel()); ...
myListModel() returns a pointer to the MyListModel of the ModelManager.
In my case, I can test that this works by having a ListView that displays the contents of the model like this. I'm using the default display role currently.
ListView { id: testView width: 200 height: 200 x: 50 y: 50 model: myListModel delegate: Text { text: model.display }
-
@literA2 said in Access model owned by class in QML:
@Obi-Wan i think you don't need to exposed your modelManager, you can omit that line.
You are absolutely right I think, it is only there because I'm using for something else. I'll remove it here for clarity.