Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Using C++ model in QML
Forum Updated to NodeBB v4.3 + New Features

Using C++ model in QML

Scheduled Pinned Locked Moved Mobile and Embedded
8 Posts 2 Posters 3.1k Views 2 Watching
  • 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.
  • I Offline
    I Offline
    imyrvold
    wrote on 12 Jul 2015, 05:06 last edited by imyrvold 7 Dec 2015, 06:45
    #1

    I have a ListView in my QML file with a model from C++. The model have a QString, a bool and a QList.

    The model works perfect when I don't use the QList:

        QList<QObject*> dataList;
        DataObject *ob = new DataObject("main", false);
        dataList.append(ob);
        dataList.append(new DataObject("Item 2", false));
        dataList.append(new DataObject("Item 3", true));
        dataList.append(new DataObject("Item 4", true));
    
        QQmlContext *ctxt = engine.rootContext();
        ctxt->setContextProperty("checkModel", QVariant::fromValue(dataList));
    

    But the DataObject class contains a QList that contains a list of DataObject classes. Here is where I have problems, as I can't make my project compile.

    I have tried declaring my instance variable as a list of QVariant pointers:

    private:
        QString m_group;
        bool m_checked;
        QList<QVariant*> m_elements;
    

    But my addElement method will not compile, complaining about:
    no matching member function for call to 'append'

    void DataObject::addElement(DataObject *ob)
    {
        m_elements.append(QVariant::fromValue(ob));
    }
    

    What am I doing wrong here?

    P 1 Reply Last reply 13 Jul 2015, 03:49
    0
    • I imyrvold
      12 Jul 2015, 05:06

      I have a ListView in my QML file with a model from C++. The model have a QString, a bool and a QList.

      The model works perfect when I don't use the QList:

          QList<QObject*> dataList;
          DataObject *ob = new DataObject("main", false);
          dataList.append(ob);
          dataList.append(new DataObject("Item 2", false));
          dataList.append(new DataObject("Item 3", true));
          dataList.append(new DataObject("Item 4", true));
      
          QQmlContext *ctxt = engine.rootContext();
          ctxt->setContextProperty("checkModel", QVariant::fromValue(dataList));
      

      But the DataObject class contains a QList that contains a list of DataObject classes. Here is where I have problems, as I can't make my project compile.

      I have tried declaring my instance variable as a list of QVariant pointers:

      private:
          QString m_group;
          bool m_checked;
          QList<QVariant*> m_elements;
      

      But my addElement method will not compile, complaining about:
      no matching member function for call to 'append'

      void DataObject::addElement(DataObject *ob)
      {
          m_elements.append(QVariant::fromValue(ob));
      }
      

      What am I doing wrong here?

      P Offline
      P Offline
      p3c0
      Moderators
      wrote on 13 Jul 2015, 03:49 last edited by
      #2

      @imyrvold
      So hwo about QList<DataObject*> dataList ? and then the rest as usual i.e appending DataObject directly instead of QVariant

      157

      I 1 Reply Last reply 13 Jul 2015, 07:35
      0
      • P p3c0
        13 Jul 2015, 03:49

        @imyrvold
        So hwo about QList<DataObject*> dataList ? and then the rest as usual i.e appending DataObject directly instead of QVariant

        I Offline
        I Offline
        imyrvold
        wrote on 13 Jul 2015, 07:35 last edited by imyrvold
        #3

        @p3c0
        The first thing I tried, was as you suggested, but this doesn't quite work, because I want dataList to function as a ListView model, like this:

        Item {
            width: 200
            height: childView.contentHeight
            visible: mainRow.expanded
        
            ListView {
                id: childView
                anchors.fill: parent
                model: elements
                delegate: groupsDelegate
                focus: true
            }
        }
        
            DataObject *ob = new DataObject("main", false);
            DataObject *ob1 = new DataObject("hr", true);
            DataObject *ob2 = new DataObject("ht", true);
            ob->addElement(ob1);
            ob->addElement(ob2);
            dataList.append(ob);
            dataList.append(new DataObject("Item 2", false));
            dataList.append(new DataObject("Item 3", true));
            dataList.append(new DataObject("Item 4", true));
        
            QQmlContext *ctxt = engine.rootContext();
            ctxt->setContextProperty("checkModel", QVariant::fromValue(dataList));
        

        My addElement is:

        void DataObject::addElement(DataObject *ob)
        {
            m_elements.append(ob);
        }
        

        I get the two elements in the ListView, but QML doesn't recognize them to be a ListModel, because I get a reference error in the log and they shows up without the group name

        qrc:/TreeView.qml:40: ReferenceError: elements is not defined
        qrc:/TreeView.qml:61: ReferenceError: group is not defined
        qrc:/TreeView.qml:73: ReferenceError: elements is not defined
        qrc:/TreeView.qml:40: ReferenceError: elements is not defined
        qrc:/TreeView.qml:61: ReferenceError: group is not defined
        qrc:/TreeView.qml:73: ReferenceError: elements is not defined
        qml: [object Object]
        qml: [DataObject(0x7faceb2958b0),DataObject(0x7faceb295970)]

        and the two console.log lines shows the difference between the checkModel and the elements list (the last with the list of DataObject's).

        The result is this:
        IncompleteCheckBoxes

        1 Reply Last reply
        0
        • I Offline
          I Offline
          imyrvold
          wrote on 13 Jul 2015, 07:50 last edited by
          #4

          Here is an example of how I want the ListModel to be:

                  ListModel {
                      id:listModel
                      ListElement {
                          group: "main"
                          elements: [
                              ListElement {
                                  group: "hr"
                                  elements: [
                                      ListElement {
                                          group: "mainarmA"
                                          elements: []
                                      },
                                      ListElement {
                                          group: "mainarmC"
                                          elements: []
                                      },
                                      ListElement {
                                          group: "mainarmE"
                                          elements: []
                                      }
                                  ]
                              },
                              ListElement {
                                  group: "ht"
                                  elements: [
                                      ListElement {
                                          group: "mainarmD"
                                          elements: []
                                      }
                                  ]
                              }
                          ]
                      }
                      ListElement {
                          group: "aux"
                          elements: [
                              ListElement {
                                  group: "hr"
                                  elements: [
                                      ListElement {
                                          group: "mainarmB"
                                          elements: []
                                      }
                                  ]
                              }
                          ]
                      }
                  }
          

          Then it should look like this:
          IMG

          P 1 Reply Last reply 13 Jul 2015, 07:59
          0
          • I imyrvold
            13 Jul 2015, 07:50

            Here is an example of how I want the ListModel to be:

                    ListModel {
                        id:listModel
                        ListElement {
                            group: "main"
                            elements: [
                                ListElement {
                                    group: "hr"
                                    elements: [
                                        ListElement {
                                            group: "mainarmA"
                                            elements: []
                                        },
                                        ListElement {
                                            group: "mainarmC"
                                            elements: []
                                        },
                                        ListElement {
                                            group: "mainarmE"
                                            elements: []
                                        }
                                    ]
                                },
                                ListElement {
                                    group: "ht"
                                    elements: [
                                        ListElement {
                                            group: "mainarmD"
                                            elements: []
                                        }
                                    ]
                                }
                            ]
                        }
                        ListElement {
                            group: "aux"
                            elements: [
                                ListElement {
                                    group: "hr"
                                    elements: [
                                        ListElement {
                                            group: "mainarmB"
                                            elements: []
                                        }
                                    ]
                                }
                            ]
                        }
                    }
            

            Then it should look like this:
            IMG

            P Offline
            P Offline
            p3c0
            Moderators
            wrote on 13 Jul 2015, 07:59 last edited by
            #5

            @imyrvold It seems you want to implement TreeView. why don't you use it directly ? Qt 5.5 now has TreeView.

            157

            I 1 Reply Last reply 13 Jul 2015, 12:44
            0
            • P p3c0
              13 Jul 2015, 07:59

              @imyrvold It seems you want to implement TreeView. why don't you use it directly ? Qt 5.5 now has TreeView.

              I Offline
              I Offline
              imyrvold
              wrote on 13 Jul 2015, 12:44 last edited by
              #6

              @p3c0
              I didn't know that. I will investigate it, certainly. Thank you for the tip!

              1 Reply Last reply
              0
              • I Offline
                I Offline
                imyrvold
                wrote on 14 Jul 2015, 04:41 last edited by imyrvold
                #7

                To wrap this up, I have concluded that setting the QQmlContext property doesn't work in my case. I found another way to do it, that works perfectly, with the same DataObject, and that is to use QMetaObject to invokeMethod in my ListModel with the DataObject as parameter, and append the DataObject in the invoked function.
                In the following main.cpp listing which shows this, the commented out lines are the ones that for some reason didn't work:

                #include <QApplication>
                #include <QQmlApplicationEngine>
                #include <QQmlComponent>
                //#include <QQmlContext>
                #include <qqml.h>
                #include <QQuickItem>
                #include <QQuickView>
                #include "dataobject.h"
                
                int main(int argc, char *argv[])
                {
                    QApplication app(argc, argv);
                
                    QQmlApplicationEngine engine;
                
                 //    QList<QObject*> dataList;
                
                    DataObject *ob = new DataObject("main", false);
                    DataObject *ob1 = new DataObject("hr", false);
                    DataObject *ob2 = new DataObject("ht", true);
                    DataObject *ob11 = new DataObject("mainarmA", false);
                    DataObject *ob12 = new DataObject("mainarmC", false);
                    DataObject *ob13 = new DataObject("mainarmE", true);
                    DataObject *ob21 = new DataObject("mainarmD", true);
                    ob1->addElement(ob11);
                    ob1->addElement(ob12);
                    ob1->addElement(ob13);
                    ob2->addElement(ob21);
                    ob->addElement(ob1);
                    ob->addElement(ob2);
                
                    QVariant v;
                    v = QVariant::fromValue(ob);
                
                //    dataList.append(ob);
                
                //    QQmlContext *ctxt = engine.rootContext();
                //    ctxt->setContextProperty("checkModel", QVariant::fromValue(dataList));
                
                    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                
                    QMetaObject::invokeMethod((QObject *)engine.rootObjects().first()->findChild<QObject *>("checklistModel"),  "appendElement", Q_ARG(QVariant, v));
                
                    return app.exec();
                }
                

                and the ListModel with the invoked function:

                        ListModel {
                            id:checklistModel
                            objectName: "checklistModel"
                            function appendElement(ob) {
                                checklistModel.append(ob)
                            }
                        }
                
                P 1 Reply Last reply 15 Jul 2015, 05:21
                0
                • I imyrvold
                  14 Jul 2015, 04:41

                  To wrap this up, I have concluded that setting the QQmlContext property doesn't work in my case. I found another way to do it, that works perfectly, with the same DataObject, and that is to use QMetaObject to invokeMethod in my ListModel with the DataObject as parameter, and append the DataObject in the invoked function.
                  In the following main.cpp listing which shows this, the commented out lines are the ones that for some reason didn't work:

                  #include <QApplication>
                  #include <QQmlApplicationEngine>
                  #include <QQmlComponent>
                  //#include <QQmlContext>
                  #include <qqml.h>
                  #include <QQuickItem>
                  #include <QQuickView>
                  #include "dataobject.h"
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication app(argc, argv);
                  
                      QQmlApplicationEngine engine;
                  
                   //    QList<QObject*> dataList;
                  
                      DataObject *ob = new DataObject("main", false);
                      DataObject *ob1 = new DataObject("hr", false);
                      DataObject *ob2 = new DataObject("ht", true);
                      DataObject *ob11 = new DataObject("mainarmA", false);
                      DataObject *ob12 = new DataObject("mainarmC", false);
                      DataObject *ob13 = new DataObject("mainarmE", true);
                      DataObject *ob21 = new DataObject("mainarmD", true);
                      ob1->addElement(ob11);
                      ob1->addElement(ob12);
                      ob1->addElement(ob13);
                      ob2->addElement(ob21);
                      ob->addElement(ob1);
                      ob->addElement(ob2);
                  
                      QVariant v;
                      v = QVariant::fromValue(ob);
                  
                  //    dataList.append(ob);
                  
                  //    QQmlContext *ctxt = engine.rootContext();
                  //    ctxt->setContextProperty("checkModel", QVariant::fromValue(dataList));
                  
                      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                  
                      QMetaObject::invokeMethod((QObject *)engine.rootObjects().first()->findChild<QObject *>("checklistModel"),  "appendElement", Q_ARG(QVariant, v));
                  
                      return app.exec();
                  }
                  

                  and the ListModel with the invoked function:

                          ListModel {
                              id:checklistModel
                              objectName: "checklistModel"
                              function appendElement(ob) {
                                  checklistModel.append(ob)
                              }
                          }
                  
                  P Offline
                  P Offline
                  p3c0
                  Moderators
                  wrote on 15 Jul 2015, 05:21 last edited by
                  #8

                  @imyrvold Glad that you found the solution :) But to be future ready use TreeView as the view and QAbstractItemModel as the model.

                  157

                  1 Reply Last reply
                  0

                  1/8

                  12 Jul 2015, 05:06

                  • Login

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