Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Add object to QAbstractListmodel-derived model from QML
QtWS25 Last Chance

Add object to QAbstractListmodel-derived model from QML

Scheduled Pinned Locked Moved QML and Qt Quick
16 Posts 3 Posters 4.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Q Offline
    Q Offline
    qragnar
    wrote on last edited by
    #1

    Hi,
    As you can probably tell, I'm quite new to Qt/QML. I'm cutting my teeth on using my own list model with a ListView. The model holds objects of type Game, so I call it GameModel. Now, I'm able to populate the model and see the objects in the ListView. However, I would like to set the name of a new Game from user input (i.e. from QML). But I don't seem able to create a Game and pass it as a parameter to C++.

    I have this in GameModel:
    @ Q_INVOKABLE bool addGame(Game* g);
    Q_INVOKABLE bool addGame();@

    This works fine:
    @ Button {
    text: "New game"
    onClicked: {
    gmodel.addGame( )
    }
    }

        GameModel {
            id:gmodel
        }@
    

    This will only a pass a null pointer to addGame(Game* g):
    @ Button {
    text: "New game"
    onClicked: {
    gmodel.addGame( { name: "My game"} )
    }
    }@

    Now, I haven't even got a clue if this is supposed to work at any rate, but after several days of searching I'm unable to find an example of what I want to do.

    Furthermore, I seem completely unable to access the elements in GameModel from QML, so I'm not even able to call addGame() and set the name after creation.

    Any help would be appreciated.

    1 Reply Last reply
    0
    • D Offline
      D Offline
      Duff
      wrote on last edited by
      #2

      Are these "game" objects defined in QML or C++?

      --Duff

      1 Reply Last reply
      0
      • Q Offline
        Q Offline
        qragnar
        wrote on last edited by
        #3

        In C++.
        I'm happy to show the code, but as there is a substantial amount, I'm not sure which is relevant. Also, the code I have is working, but I'm lacking something which I don't really know.

        I have come so far as to be able to change the name from within the delegate, by defining this:

        @bool GameModel::setData(const QModelIndex & index, const QVariant & value, int role);@

        ...but I have no idea how to reference the elements outside the delegate.

        The Game objects are stored as QList<Game*> in GameModel;

        in main.cpp:
        @
        qmlRegisterTypeMy::Game("mygame", 1,0, "Game");
        qmlRegisterTypeMy::GameModel("mygame", 1,0, "GameModel");
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
        QQmlContext *ctxt = engine.rootContext();
        My::GameModel gm;
        gm.load_games();
        ctxt->setContextProperty("gameModel", &gm);
        engine.load(QUrl("qml/mygame--/main.qml"));@

        1 Reply Last reply
        0
        • p3c0P Offline
          p3c0P Offline
          p3c0
          Moderators
          wrote on last edited by
          #4

          Hi,

          Check if "this":http://qt-project.org/forums/viewthread/45795/#188768 helps you. Check the function void FileModele::addItem(QString filename) in filemodel.cpp. It is Q_INVOKABLE and is called from QML which adds an item to the ListView and also creates an object of type File.
          Is this what you are looking for ?

          157

          1 Reply Last reply
          0
          • Q Offline
            Q Offline
            qragnar
            wrote on last edited by
            #5

            Hi p3c0,

            That thread is interesting and helpful, but it doesn't quite cover my case. In the thread, heikkik is passing a string, whereas I would like to pass an object.

            As I mentioned, I have defined addGame() and addGame(Game*) in my model, both as Q_INVOKABLE. I can oly call addGame() successfully, whereas addGame(Game*) always receives a null pointer.

            The second issue I have is that I have no clue how to modify the contents of GameModel from outside the delegate, or even accessing their properties.

            1 Reply Last reply
            0
            • p3c0P Offline
              p3c0P Offline
              p3c0
              Moderators
              wrote on last edited by
              #6

              But does your QML have access to the Game class ?

              bq. The second issue I have is that I have no clue how to modify the contents of GameModel from outside the delegate, or even accessing their properties.

              AFAIk, you must have added the modle using setContextProperty so that object should be available from all QML files.

              157

              1 Reply Last reply
              0
              • Q Offline
                Q Offline
                qragnar
                wrote on last edited by
                #7

                Yes. Please see my second post in this thread. Both Game and GameModel are registered with qmlRegisterType() and an instance of the model is available through setContextProperty().

                1 Reply Last reply
                0
                • p3c0P Offline
                  p3c0P Offline
                  p3c0
                  Moderators
                  wrote on last edited by
                  #8

                  IMO, then you need the initialise Game too in QML just as you have done for GameModel and then pass it's id to the addGame().

                  157

                  1 Reply Last reply
                  0
                  • Q Offline
                    Q Offline
                    qragnar
                    wrote on last edited by
                    #9

                    Ok, but since I don't know how many times the user is going to click the "New Game" button, I can't initialise it with static code like this:

                    @Game {
                    id: something
                    name: "Of the game"
                    }@

                    So what I need is the QML equivalent of the following C++ code:
                    @Game g("Name of the game");
                    // OR
                    Game* g = new Game("Name of the game");
                    @

                    It's completely unclear to me how I do that. Naturally, I could bite the bullet and accept that I need to create the object in C++ and pass the new name, but it seems a bit restricted.

                    1 Reply Last reply
                    0
                    • p3c0P Offline
                      p3c0P Offline
                      p3c0
                      Moderators
                      wrote on last edited by
                      #10

                      Not sure, but i think one way to create the Game object dynamically would be through "Component":http://qt-project.org/doc/qt-5/qml-qtqml-component.html and using "createObject":http://qt-project.org/doc/qt-5/qml-qtqml-component.html#createObject-method and then may be you could pass that object to addGame().

                      What would be the restrictions you think if you go thru c++ way ?

                      157

                      1 Reply Last reply
                      0
                      • Q Offline
                        Q Offline
                        qragnar
                        wrote on last edited by
                        #11

                        Well, perhaps mainly that the interface to create a new Game is restricted to passing strings to C++.

                        Also, since I haven't found a way of accessing the elements of the model outside the delegate, I'm unable to manipulate them. I have tried defining an at() method, returning a Game pointer, but this seems unusable in QML.

                        1 Reply Last reply
                        0
                        • p3c0P Offline
                          p3c0P Offline
                          p3c0
                          Moderators
                          wrote on last edited by
                          #12

                          But you can do the business logic in c++ and the QML for just the view.

                          157

                          1 Reply Last reply
                          0
                          • Q Offline
                            Q Offline
                            qragnar
                            wrote on last edited by
                            #13

                            Yep, I guess you're right. I'm still absorbing the philosophy of QML. The way ListView works clearly decouples the business logic.

                            Nonetheless, I'm struggling to see how I can achieve some things in the presentation layer without accessing the elements in the list somehow. Any tips on how to achieve an at()-like method?

                            1 Reply Last reply
                            0
                            • p3c0P Offline
                              p3c0P Offline
                              p3c0
                              Moderators
                              wrote on last edited by
                              #14

                              Now going through your original way,

                              1. Registering the Game.
                              2. Embed Game in "Component":http://qt-project.org/doc/qt-5/qml-qtqml-component.html.
                              3. Create the Game object dynamically using "createObject":http://qt-project.org/doc/qt-5/qml-qtqml-component.html#createObject-method
                              4. Then store that object in an array . For eg.
                                @
                                Component {
                                id: component
                                Game {}
                                }

                              property var gameArray: []
                              var obj = component.createObject(myGame)
                              gameArray.push(obj)
                              @

                              1. Then access it,
                                @
                                var obj = gameArray[index]
                                console.log(obj.color)
                                @

                              Edited

                              157

                              1 Reply Last reply
                              0
                              • Q Offline
                                Q Offline
                                qragnar
                                wrote on last edited by
                                #15

                                Thanks, p3c0!

                                I haven't time to try that for a few days, but it seems workable. Mind you, I'm not sure I follow the logic in the accessing code:
                                @var obj = array[gameArray]@

                                Shouldn't that be? ...
                                @var obj = gameArray[some_index]@

                                1 Reply Last reply
                                0
                                • p3c0P Offline
                                  p3c0P Offline
                                  p3c0
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  Oh Sorry for the typo. Thanks for pointing out. I've now edited the original post.

                                  157

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved