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?



  • @Obi-Wan in order to use the model properties in delegate, this is the syntax:

    model.<propertyName>



  • @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
    }
    


  • @Obi-Wan i think you don't need to exposed your modelManager, you can omit that line.



  • @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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.