Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Populate C++ model from external source in Qt

Populate C++ model from external source in Qt

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 3 Posters 4.4k 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.
  • M Offline
    M Offline
    milan
    wrote on last edited by
    #1

    I need to populate c++ model from a external source (for example USB). I have registered the model in main.cpp like this,

    qmlRegisterType<HardwareDataModel>("org.example", 1, 0, "HardwareDataModel");
    

    I need to change the private member of this HardwareDataModel class from the external source. Because I would like to change the the private data member of this model and fire signal to qml to change the UI. I got stuck how to proceed as I do not know how to populate those private data members. Do I need to instatiate HardwareDataModel in main.cpp? If yes, how to connect the instatiated HardwareDataModel object and one that is qmlRegisteredType (one shown above).

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel-subclass

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      3
      • M Offline
        M Offline
        milan
        wrote on last edited by
        #3

        I am asking how to update the data members of model class without instatiating.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi and welcome to devnet,

          Do you mean you want to modify your model without any object to work on ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          M 2 Replies Last reply
          0
          • SGaistS SGaist

            Hi and welcome to devnet,

            Do you mean you want to modify your model without any object to work on ?

            M Offline
            M Offline
            milan
            wrote on last edited by
            #5

            @SGaist . Sorry I am new to Qt. Yes if possible. But my concern is, QML should not request data i.e QML will not fire signal to C++. Instead, C++ model when it is updated, and the function inside C++ should inform QML to update UI i.e C++ will fire signal to QML. Now, i have only registered the model in main.cpp as using qmlRegisterType only. Also I cannot update the model, unless I fire signal to C++ from QML(which I do not want, I want model to update itself).

            1 Reply Last reply
            0
            • SGaistS SGaist

              Hi and welcome to devnet,

              Do you mean you want to modify your model without any object to work on ?

              M Offline
              M Offline
              milan
              wrote on last edited by
              #6

              @SGaist . Also the C++ model updates itself in every few seconds.

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #7

                Please read the linked part above. It's exactly what you need. The dataChanged signal from the C++ model is what will update the QML view

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                M 1 Reply Last reply
                1
                • VRoninV VRonin

                  Please read the linked part above. It's exactly what you need. The dataChanged signal from the C++ model is what will update the QML view

                  M Offline
                  M Offline
                  milan
                  wrote on last edited by
                  #8

                  @VRonin . Thank you for your reply, but how to update the C++ model itself. Could you help.

                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #9

                    Take this example and add as the last line in People's constructor

                    QTimer::singleShot(2000,m_model,[this](){
                    m_model->setData(
                        m_model->index(0,0),
                        QVariant::fromValue(Person("Marie", "Curie", Date(1867,11,7))),
                        Qt::EditRole);
                    });
                    

                    Hope this helps

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    M 1 Reply Last reply
                    1
                    • VRoninV VRonin

                      Take this example and add as the last line in People's constructor

                      QTimer::singleShot(2000,m_model,[this](){
                      m_model->setData(
                          m_model->index(0,0),
                          QVariant::fromValue(Person("Marie", "Curie", Date(1867,11,7))),
                          Qt::EditRole);
                      });
                      

                      Hope this helps

                      M Offline
                      M Offline
                      milan
                      wrote on last edited by
                      #10

                      @VRonin . Thanks for your reply. But it does not help. This example uses setData to update the model class. The values for setData function in the example comes from QML or hardcoded C++ itself. This is not what I am looking for.

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        How are you using your model currently ?

                        Because from your description, it seems that you only register it. You don't create any instance of it, be it from QML or C++.

                        The documentation @VRonin linked to shows both technique.

                        If that still doesn't help you get further then show us the code you are using.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        M 1 Reply Last reply
                        2
                        • SGaistS SGaist

                          How are you using your model currently ?

                          Because from your description, it seems that you only register it. You don't create any instance of it, be it from QML or C++.

                          The documentation @VRonin linked to shows both technique.

                          If that still doesn't help you get further then show us the code you are using.

                          M Offline
                          M Offline
                          milan
                          wrote on last edited by
                          #12

                          @SGaist

                          // Main QML file
                          import QtQuick 2.5
                          import QtQuick.Window 2.2
                          import QtQuick.Controls 1.5
                          import QtQuick.Layouts 1.2
                          import QtQuick.Controls.Styles 1.4
                          import QtQuick.Extras 1.4
                          
                          // imported module
                          import org.example 1.0
                          
                          Window {
                              visible: true
                              width: 480
                              height: 480
                              
                              // our Generator model
                              HardwareDataModel{
                                  id: hwDataModel
                              }
                              Label {
                                  id: myLabel
                                  text: hwDataModel.varVal
                                  visible: true
                              }
                          }
                          
                          #include <QtGui>
                          #include <QtQml>
                          #include "hardwaredatamodel.h"
                          
                          int main(int argc, char *argv[])
                          {
                              QGuiApplication app(argc, argv);
                              qmlRegisterType<HardwareDataModel>("org.example", 1, 0, "HardwareDataModel");
                              QQmlApplicationEngine engine;
                              engine.load(QUrl(QStringLiteral("qrc:/ui/main.qml")));
                          
                          #ifndef HARDWAREDATAMODEL_H
                          #define HARDWAREDATAMODEL_H
                          
                          #include <QtCore>
                          #include <QtGui>
                          #include <QAbstractItemModel>
                          
                          class HardwareDataModel: public QAbstractItemModel
                          {
                              Q_OBJECT
                              Q_PROPERTY(int hwValue READ hwValue WRITE setHwValue NOTIFY hwValueChanged)
                          
                          public:
                              explicit HardwareDataModel(QObject *parent = nullptr);
                          
                              // Header:
                              QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
                          
                              // Basic functionality:
                              QModelIndex index(int row, int column,
                                                const QModelIndex &parent = QModelIndex()) const override;
                              QModelIndex parent(const QModelIndex &index) const override;
                          
                              int rowCount(const QModelIndex &parent = QModelIndex()) const override;
                              int columnCount(const QModelIndex &parent = QModelIndex()) const override;
                          
                              QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
                              int hwValue() const;
                          
                          public slots:
                              void setHwValue(int hwValue); // this is autogenerated from Q_PROPERTY,  not using it
                          
                          signals:
                              void hwValueChanged();
                          
                          private:
                              int m_hwValue; // this value will be updated in every few secs, from hw source. but I have no idea how to achieve this
                          };
                          
                          #endif // HARDWAREDATAMODEL_H
                          
                          
                          #include "hardwaredatamodel.h"
                          #include "main.h"
                          #include <chrono>
                          #include <thread>
                          
                          HardwareDataModel::HardwareDataModel(QObject *parent) : QAbstractItemModel(parent)
                          {
                          }
                          
                          QVariant HardwareDataModel::headerData(int section, Qt::Orientation orientation, int role) const
                          {
                              // FIXME: Implement me!
                          }
                          
                          QModelIndex HardwareDataModel::index(int row, int column, const QModelIndex &parent) const
                          {
                              // FIXME: Implement me!
                          }
                          
                          QModelIndex HardwareDataModel::parent(const QModelIndex &index) const
                          {
                              // FIXME: Implement me!
                          }
                          
                          int HardwareDataModel::rowCount(const QModelIndex &parent) const
                          {
                              if (!parent.isValid())
                                  return 0;
                          
                              // FIXME: Implement me!
                          }
                          
                          int HardwareDataModel::columnCount(const QModelIndex &parent) const
                          {
                              if (!parent.isValid())
                                  return 0;
                          
                              // FIXME: Implement me!
                          }
                          
                          QVariant HardwareDataModel::data(const QModelIndex &index, int role) const
                          {
                              if (!index.isValid())
                                  return QVariant();
                          
                              // FIXME: Implement me!
                              return QVariant();
                          }
                          
                          int HardwareDataModel::varVal() const
                          {
                              return m_varVal;
                          }
                          
                          void HardwareDataModel::setVarVal(int varVal)
                          {
                               emit hwValueChanged();
                          }
                          
                          
                          1 Reply Last reply
                          0
                          • VRoninV Offline
                            VRoninV Offline
                            VRonin
                            wrote on last edited by
                            #13
                            • You don't need to start from scratch with a QAbstractItemModel subclass. It's usually easier to just use QStandardItemModel and switch to the custom model only if you feel a need for performance reasons.
                            • To update the model whenever you want and with whatever data you want from the C++ side you just call QAbstractItemModel::setData
                            • As posted twice above, to control your model from the C++ side you need to instantiate the model in the c++ side (or have a factory on the C++ side). See the below from http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel-subclass
                             AnimalModel model;
                                model.addAnimal(Animal("Wolf", "Medium"));
                                model.addAnimal(Animal("Polar bear", "Large"));
                                model.addAnimal(Animal("Quoll", "Small"));
                            
                                QQuickView view;
                                view.setResizeMode(QQuickView::SizeRootObjectToView);
                                QQmlContext *ctxt = view.rootContext();
                                ctxt->setContextProperty("myModel", &model);
                            

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            M 1 Reply Last reply
                            2
                            • VRoninV VRonin
                              • You don't need to start from scratch with a QAbstractItemModel subclass. It's usually easier to just use QStandardItemModel and switch to the custom model only if you feel a need for performance reasons.
                              • To update the model whenever you want and with whatever data you want from the C++ side you just call QAbstractItemModel::setData
                              • As posted twice above, to control your model from the C++ side you need to instantiate the model in the c++ side (or have a factory on the C++ side). See the below from http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel-subclass
                               AnimalModel model;
                                  model.addAnimal(Animal("Wolf", "Medium"));
                                  model.addAnimal(Animal("Polar bear", "Large"));
                                  model.addAnimal(Animal("Quoll", "Small"));
                              
                                  QQuickView view;
                                  view.setResizeMode(QQuickView::SizeRootObjectToView);
                                  QQmlContext *ctxt = view.rootContext();
                                  ctxt->setContextProperty("myModel", &model);
                              
                              M Offline
                              M Offline
                              milan
                              wrote on last edited by
                              #14

                              @VRonin . Like I have said before, calling setData function will only set the model data once or as long as it is called. I want to populate it automatically using some thread or some different method.

                              VRoninV 1 Reply Last reply
                              0
                              • M milan

                                @VRonin . Like I have said before, calling setData function will only set the model data once or as long as it is called. I want to populate it automatically using some thread or some different method.

                                VRoninV Offline
                                VRoninV Offline
                                VRonin
                                wrote on last edited by
                                #15

                                I want to populate it automatically using some thread or some different method.

                                I get the feeling that I didn't really understand your needs. To me this is trivial: emit a signal from the different thread/method and connect it to a slot that calls QAbstractItemModel::setData.

                                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                ~Napoleon Bonaparte

                                On a crusade to banish setIndexWidget() from the holy land of Qt

                                M 1 Reply Last reply
                                0
                                • VRoninV VRonin

                                  I want to populate it automatically using some thread or some different method.

                                  I get the feeling that I didn't really understand your needs. To me this is trivial: emit a signal from the different thread/method and connect it to a slot that calls QAbstractItemModel::setData.

                                  M Offline
                                  M Offline
                                  milan
                                  wrote on last edited by milan
                                  #16

                                  @VRonin. Sorry if I could not elaborate my problem enough. I am designing UI for which the backend data comes from the hardware connected to USB port. Now, I have console application that is continously requesting and sending data to/from the USB port (10 data per second). The console prints the data without problem. Next, I need to visualize those data using some GUI. I chose QT as backend data request is in C++. Looking at QT, I saw Model-view pattern is recommended for larger application. So, I tried smaller application with model, whose data-member will be updated from the data received from the USB port. I am thinking of some thread, but it is also not working. The received data has to be represented in the UI updating almost real-time if possible. I chose to update label just for testing, but it would be some different GUI in future. Please let me know my description is still not clear enough.

                                  1 Reply Last reply
                                  0
                                  • VRoninV Offline
                                    VRoninV Offline
                                    VRonin
                                    wrote on last edited by
                                    #17

                                    The description perfectly fits the above model of data update.

                                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                    ~Napoleon Bonaparte

                                    On a crusade to banish setIndexWidget() from the holy land of Qt

                                    M 1 Reply Last reply
                                    3
                                    • VRoninV VRonin

                                      The description perfectly fits the above model of data update.

                                      M Offline
                                      M Offline
                                      milan
                                      wrote on last edited by
                                      #18

                                      @VRonin. Thanks for your reply. I am using QQmlApplicationEngine instead of QQuickView. Can I use qmlRegisterType instead of setContextProperty from QQuickView. Still, I do not understand how can calling setData will solve this problem. It has to be called again and again.

                                      VRoninV 1 Reply Last reply
                                      0
                                      • M milan

                                        @VRonin. Thanks for your reply. I am using QQmlApplicationEngine instead of QQuickView. Can I use qmlRegisterType instead of setContextProperty from QQuickView. Still, I do not understand how can calling setData will solve this problem. It has to be called again and again.

                                        VRoninV Offline
                                        VRoninV Offline
                                        VRonin
                                        wrote on last edited by
                                        #19

                                        @milan said in Populate C++ model from external source in Qt:

                                        Can I use qmlRegisterType instead of setContextProperty from QQuickView

                                        No, you need the model instance to be accessible to the C++ side.

                                        I am using QQmlApplicationEngine instead of QQuickView.

                                        QQmlApplicationEngine inherits QQmlEngine so you can use applicationEngine->rootContext()->setContextProperty("myModel", &model);

                                        I do not understand how can calling setData will solve this problem. It has to be called again and again.

                                        Yes it has, something has to be called again and again to update it though, doesn't it?

                                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                        ~Napoleon Bonaparte

                                        On a crusade to banish setIndexWidget() from the holy land of Qt

                                        M 1 Reply Last reply
                                        0
                                        • VRoninV VRonin

                                          @milan said in Populate C++ model from external source in Qt:

                                          Can I use qmlRegisterType instead of setContextProperty from QQuickView

                                          No, you need the model instance to be accessible to the C++ side.

                                          I am using QQmlApplicationEngine instead of QQuickView.

                                          QQmlApplicationEngine inherits QQmlEngine so you can use applicationEngine->rootContext()->setContextProperty("myModel", &model);

                                          I do not understand how can calling setData will solve this problem. It has to be called again and again.

                                          Yes it has, something has to be called again and again to update it though, doesn't it?

                                          M Offline
                                          M Offline
                                          milan
                                          wrote on last edited by
                                          #20

                                          @VRonin. Thank you very much for your reply. I get error when I try to add this code

                                              QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                                              QGuiApplication app(argc, argv);
                                              HardwareDataModel hardwareDataModel;
                                          
                                              QQmlApplicationEngine* engine;
                                              engine->rootContext()->setContextProperty("HardwareDataModel", &hardwareDataModel);
                                              engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
                                          
                                              if (engine->rootObjects().isEmpty())
                                                  return -1;
                                          
                                              return app.exec();
                                          

                                          When I build this, I get linker error LNK2019.

                                          main.obj:-1: error: LNK2019: unresolved external symbol "public: __cdecl HardwareDataModel::HardwareDataModel(class QObject *)" (??HardwareDataModel@@QEAA@PEAVQObject@@@Z) referenced in function main
                                          

                                          Please help.

                                          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