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. accessing aggregates (QVector of a struct)
Forum Updated to NodeBB v4.3 + New Features

accessing aggregates (QVector of a struct)

Scheduled Pinned Locked Moved Solved QML and Qt Quick
52 Posts 4 Posters 8.2k Views 4 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #10

    Thanks for the information, guys. I'm making progress, but still can't quite connect all the dots. I've created a BottleList class, with a method:

    QVariantList BottleList::getBottleListQv() {
        QVariantList qvl;
        BottleData bd;
        for (int i = 0; i < NBR_BOTTLES; ++i) {
            bd = getBottleData(i);
            qvl.append(QVariant::fromValue(bd));
        }
        return qvl;
    }
    

    Another class ChangeConsumables creates an instance of BottleList.

    from my QML file:

            function getRackData() {
                var bottleRack = changeConsumablesViewModel.getBottleListQv()
                return bottleRack
            }
            Bottle {
                id: bottle1
                cellText: "W7"
                cellColor: "red"
            }
    

    I have 16 entries similar to bottle1.

    So, what I'm missing is...how to replace the hard-coded "W7" with the name field from the BottleData struct in my BottleList class?

    Thanks.

    kshegunovK 1 Reply Last reply
    0
    • mzimmersM mzimmers

      Thanks for the information, guys. I'm making progress, but still can't quite connect all the dots. I've created a BottleList class, with a method:

      QVariantList BottleList::getBottleListQv() {
          QVariantList qvl;
          BottleData bd;
          for (int i = 0; i < NBR_BOTTLES; ++i) {
              bd = getBottleData(i);
              qvl.append(QVariant::fromValue(bd));
          }
          return qvl;
      }
      

      Another class ChangeConsumables creates an instance of BottleList.

      from my QML file:

              function getRackData() {
                  var bottleRack = changeConsumablesViewModel.getBottleListQv()
                  return bottleRack
              }
              Bottle {
                  id: bottle1
                  cellText: "W7"
                  cellColor: "red"
              }
      

      I have 16 entries similar to bottle1.

      So, what I'm missing is...how to replace the hard-coded "W7" with the name field from the BottleData struct in my BottleList class?

      Thanks.

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #11

      You can refer to the object by id. Like this:

      function loadRackDataFirst() {
          bottle1.cellText = changeConsumablesViewModel.getBottleListQv()[0].name
      }
      

      However you should convert to QString.

      Read and abide by the Qt Code of Conduct

      mzimmersM 1 Reply Last reply
      0
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by fcarney
        #12
        Repeater {
          model: changeConsumablesViewModel.getBottleListQv() // or use property, a property will have a signal to update if the list changes
          Bottle {
            cellText: modelData.name
          }
        }
        

        If you want more interaction then a model might be more appropriate.

        modelData Search for modelData on that page to understand where it comes from.

        C++ is a perfectly valid school of magic.

        mzimmersM 1 Reply Last reply
        0
        • kshegunovK kshegunov

          You can refer to the object by id. Like this:

          function loadRackDataFirst() {
              bottle1.cellText = changeConsumablesViewModel.getBottleListQv()[0].name
          }
          

          However you should convert to QString.

          mzimmersM Offline
          mzimmersM Offline
          mzimmers
          wrote on last edited by
          #13

          @kshegunov the "name" field isn't accessible as I've currently implemented it. I think I may have over-designed this. I've made several changes since my earlier posts, so let me recap my code:

          The struct:

          struct BottleData {
            Q_GADGET
          public:
            uint32_t m_volume;               // amount in bottle (in uL)
            uint32_t m_amountNeeded;         // amount needed for synth (in uL)
            int m_position;                  // still figuring this one out
            std::string m_name;              // name of the reagent
            ReagentBottleType m_bottleType;  // bottle type.
            Q_PROPERTY(uint32_t volume MEMBER m_volume)
            Q_PROPERTY(uint32_t amountNeeded MEMBER m_amountNeeded)
            Q_PROPERTY(int position MEMBER m_position)
            Q_PROPERTY(std::string name MEMBER m_name)
            Q_PROPERTY(ReagentBottleType bottleType MEMBER m_bottleType)
          };
          Q_DECLARE_METATYPE(BottleData)
          

          The class:

          typedef QVector<BottleData> BottleDataList;
          
          class BottleList : public QObject
          {
              Q_OBJECT
          private:
              BottleDataList m_bottleList;
          public:
              explicit BottleList(QObject *parent = nullptr);
              Q_PROPERTY(QVariantList qvl READ getBottleListQv)
              QVariantList getBottleListQv();
              ...
          

          From reading the docs, I was under the impression that I wouldn't need a getter for the fields in the struct, because I used the MEMBER macro. Did I misinterpret this?

          fcarneyF kshegunovK 2 Replies Last reply
          0
          • fcarneyF fcarney
            Repeater {
              model: changeConsumablesViewModel.getBottleListQv() // or use property, a property will have a signal to update if the list changes
              Bottle {
                cellText: modelData.name
              }
            }
            

            If you want more interaction then a model might be more appropriate.

            modelData Search for modelData on that page to understand where it comes from.

            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by mzimmers
            #14

            @fcarney that looks really powerful. The complete definition of each model is like this:

                    Bottle {
                        id: bottle1
                        cellX: 25
                        cellY: 105
                        cellHeight: 75
                        cellWidth: 75
                        bottleScaleFactor: scaleFactor
                        cellText: "W7"
                        cellColor: "red"
                    }
            

            If I use the repeater to load the names, can I alter the individual bottles afterwards?

            Thanks...

            PS: I'm aware that there's a lot of ugly hard-coding in here; I was going to address that after I got the connections working.

            1 Reply Last reply
            0
            • fcarneyF Offline
              fcarneyF Offline
              fcarney
              wrote on last edited by fcarney
              #15

              If I use the repeater to load the names, can I alter the individual bottles afterwards?

              It only alters the copy given to the Repeater. It has no way to get that data back.

              I have not used Q_GADGETs before. What does it print out when you console.log(modelData)? Curious as what QML thinks that objects is.

              C++ is a perfectly valid school of magic.

              mzimmersM 1 Reply Last reply
              0
              • mzimmersM mzimmers

                @kshegunov the "name" field isn't accessible as I've currently implemented it. I think I may have over-designed this. I've made several changes since my earlier posts, so let me recap my code:

                The struct:

                struct BottleData {
                  Q_GADGET
                public:
                  uint32_t m_volume;               // amount in bottle (in uL)
                  uint32_t m_amountNeeded;         // amount needed for synth (in uL)
                  int m_position;                  // still figuring this one out
                  std::string m_name;              // name of the reagent
                  ReagentBottleType m_bottleType;  // bottle type.
                  Q_PROPERTY(uint32_t volume MEMBER m_volume)
                  Q_PROPERTY(uint32_t amountNeeded MEMBER m_amountNeeded)
                  Q_PROPERTY(int position MEMBER m_position)
                  Q_PROPERTY(std::string name MEMBER m_name)
                  Q_PROPERTY(ReagentBottleType bottleType MEMBER m_bottleType)
                };
                Q_DECLARE_METATYPE(BottleData)
                

                The class:

                typedef QVector<BottleData> BottleDataList;
                
                class BottleList : public QObject
                {
                    Q_OBJECT
                private:
                    BottleDataList m_bottleList;
                public:
                    explicit BottleList(QObject *parent = nullptr);
                    Q_PROPERTY(QVariantList qvl READ getBottleListQv)
                    QVariantList getBottleListQv();
                    ...
                

                From reading the docs, I was under the impression that I wouldn't need a getter for the fields in the struct, because I used the MEMBER macro. Did I misinterpret this?

                fcarneyF Offline
                fcarneyF Offline
                fcarney
                wrote on last edited by fcarney
                #16

                @mzimmers said in accessing aggregates (QVector of a struct):

                From reading the docs, I was under the impression that I wouldn't need a getter for the fields in the struct, because I used the MEMBER macro. Did I misinterpret this?

                I "think" so. DOH! I meant to agree to the MEMBER macro doing that, not you misinterpreting this.

                C++ is a perfectly valid school of magic.

                1 Reply Last reply
                0
                • fcarneyF fcarney

                  If I use the repeater to load the names, can I alter the individual bottles afterwards?

                  It only alters the copy given to the Repeater. It has no way to get that data back.

                  I have not used Q_GADGETs before. What does it print out when you console.log(modelData)? Curious as what QML thinks that objects is.

                  mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #17

                  @fcarney my console.log isn't working for this app, so I can't tell you. I discovered Q_GADGET from some online searching; in simplest terms, it's a lightweight version of Q_OBJECT (no signals/slots).

                  I'm not at all concerned with updating anything other than my display. But now you have me wondering where I should really define all those values. (I would rather not use JSON, but that's probably the right way to do this.)

                  fcarneyF 1 Reply Last reply
                  0
                  • mzimmersM mzimmers

                    @fcarney my console.log isn't working for this app, so I can't tell you. I discovered Q_GADGET from some online searching; in simplest terms, it's a lightweight version of Q_OBJECT (no signals/slots).

                    I'm not at all concerned with updating anything other than my display. But now you have me wondering where I should really define all those values. (I would rather not use JSON, but that's probably the right way to do this.)

                    fcarneyF Offline
                    fcarneyF Offline
                    fcarney
                    wrote on last edited by fcarney
                    #18

                    @mzimmers If you want your display to interact with the data then a full blown QAbstractListModel would be a better fit. Then each piece of the BottleData object could be its own role. With a setData routine you can edit that model.

                    C++ is a perfectly valid school of magic.

                    1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @kshegunov the "name" field isn't accessible as I've currently implemented it. I think I may have over-designed this. I've made several changes since my earlier posts, so let me recap my code:

                      The struct:

                      struct BottleData {
                        Q_GADGET
                      public:
                        uint32_t m_volume;               // amount in bottle (in uL)
                        uint32_t m_amountNeeded;         // amount needed for synth (in uL)
                        int m_position;                  // still figuring this one out
                        std::string m_name;              // name of the reagent
                        ReagentBottleType m_bottleType;  // bottle type.
                        Q_PROPERTY(uint32_t volume MEMBER m_volume)
                        Q_PROPERTY(uint32_t amountNeeded MEMBER m_amountNeeded)
                        Q_PROPERTY(int position MEMBER m_position)
                        Q_PROPERTY(std::string name MEMBER m_name)
                        Q_PROPERTY(ReagentBottleType bottleType MEMBER m_bottleType)
                      };
                      Q_DECLARE_METATYPE(BottleData)
                      

                      The class:

                      typedef QVector<BottleData> BottleDataList;
                      
                      class BottleList : public QObject
                      {
                          Q_OBJECT
                      private:
                          BottleDataList m_bottleList;
                      public:
                          explicit BottleList(QObject *parent = nullptr);
                          Q_PROPERTY(QVariantList qvl READ getBottleListQv)
                          QVariantList getBottleListQv();
                          ...
                      

                      From reading the docs, I was under the impression that I wouldn't need a getter for the fields in the struct, because I used the MEMBER macro. Did I misinterpret this?

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by kshegunov
                      #19

                      @mzimmers said in accessing aggregates (QVector of a struct):

                      Q_DECLARE_METATYPE(BottleData)
                      

                      is already done by the Q_GADGET so it's superfluous.

                      Switch

                      std::string m_name;
                      

                      to QString.

                      Register the type with QML (qmlRegisterType) if you intend to create instances of it from there.

                      From reading the docs, I was under the impression that I wouldn't need a getter for the fields in the struct, because I used the MEMBER macro. Did I misinterpret this?

                      Nope, this is correct as far as I recall.

                      If I use the repeater to load the names, can I alter the individual bottles afterwards?

                      I don't think so, but I'm a noobster with QML. I believe you can imperatively create the items like this (untested):

                      Component {
                              id: component
                              Bottle { cellText: "default text" }
                              onCompleted: changeConsumablesViewModel.getBottleListQv().forEach(element => function(element)  {
                                 createObject(parentItemId, { cellText: element.name });
                              }, this);
                      }
                      

                      or something akin.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #20

                        OK, so why doesn't this work?

                            Rectangle {
                                id: rack
                                function getBottleName(i) {
                                    return changeConsumablesViewModel.getBottleListQv()[i].m_name
                                }
                                Bottle {
                                    cellText: rack.getBottleName(0)// "W7"
                                }
                        

                        I get this error on the line with the "return" statement:

                        TypeError: Cannot read property 'm_name' of undefined

                        kshegunovK 1 Reply Last reply
                        0
                        • mzimmersM mzimmers

                          OK, so why doesn't this work?

                              Rectangle {
                                  id: rack
                                  function getBottleName(i) {
                                      return changeConsumablesViewModel.getBottleListQv()[i].m_name
                                  }
                                  Bottle {
                                      cellText: rack.getBottleName(0)// "W7"
                                  }
                          

                          I get this error on the line with the "return" statement:

                          TypeError: Cannot read property 'm_name' of undefined

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #21

                          @mzimmers said in accessing aggregates (QVector of a struct):

                          TypeError: Cannot read property 'm_name' of undefined

                          Your property is called name, also check the elements you get in that array. Side note: you may need to wait for the component to be fully loaded before doing that (but take with a grain of salt).

                          Read and abide by the Qt Code of Conduct

                          mzimmersM 1 Reply Last reply
                          1
                          • kshegunovK kshegunov

                            @mzimmers said in accessing aggregates (QVector of a struct):

                            TypeError: Cannot read property 'm_name' of undefined

                            Your property is called name, also check the elements you get in that array. Side note: you may need to wait for the component to be fully loaded before doing that (but take with a grain of salt).

                            mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by
                            #22

                            @kshegunov said in accessing aggregates (QVector of a struct):

                            @mzimmers said in accessing aggregates (QVector of a struct):

                            TypeError: Cannot read property 'm_name' of undefined

                            Your property is called name, also check the elements you get in that array.

                            Tried with "name" -- same error.

                            Side note: you may need to wait for the component to be fully loaded before doing that (but take with a grain of salt).

                            Actually, I think you're on to it here. For some reason, the people who wrote this app (I'm just maintaining it) load all the QML files up-front, rather than as-needed. I think the problem is that this is an empty vector when this function is first called...I need to think of how best to handle that.

                            kshegunovK 1 Reply Last reply
                            0
                            • mzimmersM mzimmers

                              @kshegunov said in accessing aggregates (QVector of a struct):

                              @mzimmers said in accessing aggregates (QVector of a struct):

                              TypeError: Cannot read property 'm_name' of undefined

                              Your property is called name, also check the elements you get in that array.

                              Tried with "name" -- same error.

                              Side note: you may need to wait for the component to be fully loaded before doing that (but take with a grain of salt).

                              Actually, I think you're on to it here. For some reason, the people who wrote this app (I'm just maintaining it) load all the QML files up-front, rather than as-needed. I think the problem is that this is an empty vector when this function is first called...I need to think of how best to handle that.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by kshegunov
                              #23

                              @mzimmers said in accessing aggregates (QVector of a struct):

                              Actually, I think you're on to it here. For some reason, the people who wrote this app (I'm just maintaining it) load all the QML files up-front, rather than as-needed. I think the problem is that this is an empty vector when this function is first called...I need to think of how best to handle that.

                              Check that through the console. If you want, you can try to wait for the component by adding[1]:

                              Component.onCompleted: <js code to do w/e>
                              

                              [1]: https://doc.qt.io/qt-5/qml-qtqml-component.html#completed-signal

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0
                              • fcarneyF Offline
                                fcarneyF Offline
                                fcarney
                                wrote on last edited by fcarney
                                #24

                                Okay, I tested it. I cannot get Q_GADGET to work so I used Q_OBJECT:
                                class in main.cpp:

                                using ReagentBottleType = int;
                                class BottleData : public QObject
                                {
                                    Q_OBJECT
                                
                                    Q_PROPERTY(int volume MEMBER m_volume NOTIFY somethingChanged)
                                    Q_PROPERTY(int amountNeeded MEMBER m_amountNeeded NOTIFY somethingChanged)
                                    Q_PROPERTY(int position MEMBER m_position NOTIFY somethingChanged)
                                    Q_PROPERTY(std::string name MEMBER m_name NOTIFY somethingChanged)
                                    Q_PROPERTY(ReagentBottleType bottleType MEMBER m_bottleType NOTIFY somethingChanged)
                                public:
                                    BottleData(QObject* parent=nullptr)
                                        : QObject(parent)
                                    {
                                        connect(this, &BottleData::somethingChanged, [this](){
                                            qDebug() << "somethingChanged" << m_position << QString::fromStdString(m_name) << m_volume;
                                        });
                                    }
                                
                                    int m_volume=0;               // amount in bottle (in uL)
                                    int m_amountNeeded=0;         // amount needed for synth (in uL)
                                    int m_position=0;                  // still figuring this one out
                                    std::string m_name="";              // name of the reagent
                                    int m_bottleType=0;  // bottle type.
                                
                                signals:
                                    void somethingChanged();
                                };
                                

                                setting contextProperty in main.cpp for testing:

                                TestObj testobj;
                                auto context = engine.rootContext();
                                context->setContextProperty("varlisttestobj", &testobj);
                                

                                QML to exercise the object in C++:

                                Column {
                                        anchors.top: listview1.bottom
                                        Repeater {
                                            model: varlisttestobj.varList
                                
                                            Row {
                                                id: bottledelegate
                                
                                                width: 50
                                                spacing: 20
                                
                                                Component.onCompleted: console.log(modelData, modelData.position, modelData.volume)
                                
                                                Timer {
                                                    interval: 1000
                                                    repeat: true
                                                    running: true
                                                    onTriggered: {
                                                        modelData.volume += 1
                                                    }
                                                }
                                
                                                Text {
                                                    text: modelData.position
                                                    height: 20
                                                }
                                                Text {
                                                    text: modelData.volume
                                                    height: 20
                                                }
                                            }
                                        }
                                    }
                                

                                QML did not like uint32_t at all. So you will have to find another type that it likes on that page with compatible QML types I linked earlier.

                                C++ is a perfectly valid school of magic.

                                1 Reply Last reply
                                1
                                • fcarneyF Offline
                                  fcarneyF Offline
                                  fcarney
                                  wrote on last edited by
                                  #25

                                  Oops, I forgot test object in main.cpp:

                                  class TestObj : public QObject
                                  {
                                      Q_OBJECT
                                      Q_PROPERTY(QVariantList varList READ varList NOTIFY varListChanged)
                                      //Q_PROPERTY(QObjectList objList READ objList NOTIFY objListChanged)
                                  
                                  public:
                                      TestObj(QObject* parent=nullptr)
                                          : QObject(parent)
                                      {
                                          for(int count=0; count<10; ++count){
                                              auto bottle = new BottleData();
                                              bottle->m_volume = count*10;
                                              bottle->m_position = count;
                                              m_bottleData.append(bottle);
                                          }
                                  
                                          emit varListChanged();
                                      }
                                  
                                      QVariantList varList(){
                                          QVariantList list;
                                          for(auto bottleData: qAsConst(m_bottleData)){
                                              list.append(QVariant::fromValue(bottleData));
                                          }
                                          return list;
                                      }
                                      /*
                                      QObjectList objList(){
                                          QObjectList list;
                                          for(auto bottleData: qAsConst(m_bottleData)){
                                              list.append(bottleData);
                                          }
                                          return list;
                                      }
                                      */
                                  
                                  
                                  signals:
                                      void varListChanged();
                                  
                                  private:
                                      QVector<BottleData*> m_bottleData;
                                  
                                  };
                                  

                                  C++ is a perfectly valid school of magic.

                                  1 Reply Last reply
                                  0
                                  • fcarneyF Offline
                                    fcarneyF Offline
                                    fcarney
                                    wrote on last edited by
                                    #26

                                    I didn't expect it to trigger the somethingChanged signal in the BottleData object.

                                    C++ is a perfectly valid school of magic.

                                    1 Reply Last reply
                                    0
                                    • fcarneyF Offline
                                      fcarneyF Offline
                                      fcarney
                                      wrote on last edited by
                                      #27

                                      Trying to assign to std::string didnt work either:

                                      modelData.name = "fred"
                                      

                                      error:

                                      Error: Cannot assign QString to an unregistered type
                                      

                                      C++ is a perfectly valid school of magic.

                                      1 Reply Last reply
                                      0
                                      • kshegunovK Offline
                                        kshegunovK Offline
                                        kshegunov
                                        Moderators
                                        wrote on last edited by kshegunov
                                        #28

                                        Okay, so here you go:

                                        types.h

                                        #ifndef TYPES_H
                                        #define TYPES_H
                                        
                                        #include <QObject>
                                        #include <QVector>
                                        #include <QVariant>
                                        #include <QVariantList>
                                        
                                        struct Bottle
                                        {
                                            Q_GADGET
                                        
                                            Q_PROPERTY(QString name MEMBER m_name)
                                            Q_PROPERTY(qreal size MEMBER m_size)
                                        
                                        public:
                                            QString m_name;
                                            qreal m_size;
                                        };
                                        
                                        class DataSource : public QObject
                                        {
                                            Q_OBJECT
                                        
                                        public:
                                            Q_INVOKABLE QVariantList getData();
                                        };
                                        
                                        
                                        #endif // TYPES_H
                                        

                                        main.cpp

                                        #include <QGuiApplication>
                                        #include <QQmlApplicationEngine>
                                        #include <QQmlContext>
                                        
                                        #include "types.h"
                                        
                                        QVariantList DataSource::getData()
                                        {
                                            return {
                                                QVariant::fromValue<Bottle>({ "First bottle", 0.75 }),
                                                QVariant::fromValue<Bottle>({ "Second bottle", 0.70 })
                                            };
                                        }
                                        
                                        int main(int argc, char *argv[])
                                        {
                                            QGuiApplication app(argc, argv);
                                        
                                            QQmlApplicationEngine engine;
                                            engine.addImportPath(QStringLiteral("qrc:/"));
                                            QUrl url(QStringLiteral("qrc:/main.qml"));
                                            QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url] (QObject * obj, const QUrl & objUrl) -> void {
                                                if (!obj && url == objUrl)
                                                    QCoreApplication::exit(-1);
                                            }, Qt::QueuedConnection);
                                        
                                            DataSource source;
                                            engine.rootContext()->setContextProperty(QStringLiteral("DataSource"), &source);
                                        
                                            qmlRegisterUncreatableType<Bottle>("Example", 1, 0, "Bottle", "");
                                        
                                            engine.load(url);
                                        
                                            return app.exec();
                                        }
                                        

                                        main.qml

                                        import QtQuick 2.15
                                        import QtQuick.Window 2.15
                                        import QtQuick.Controls 2.15
                                        
                                        import Example 1.0
                                        
                                        Window {
                                            id: mainWindow
                                            visible: true
                                            width: 300
                                            height: 200
                                            title: qsTr("Some title")
                                        
                                            Component {
                                                id: template
                                                Text {
                                                    text: "defaultText"
                                                }
                                            }
                                        
                                            Column {
                                               Component.onCompleted: DataSource.getData().forEach(function(element) {
                                                   template.createObject(this, { text: element.name });
                                               }, this)
                                            }
                                        }
                                        

                                        PS. QML is damn annoying ...

                                        Read and abide by the Qt Code of Conduct

                                        mzimmersM 1 Reply Last reply
                                        1
                                        • kshegunovK kshegunov

                                          Okay, so here you go:

                                          types.h

                                          #ifndef TYPES_H
                                          #define TYPES_H
                                          
                                          #include <QObject>
                                          #include <QVector>
                                          #include <QVariant>
                                          #include <QVariantList>
                                          
                                          struct Bottle
                                          {
                                              Q_GADGET
                                          
                                              Q_PROPERTY(QString name MEMBER m_name)
                                              Q_PROPERTY(qreal size MEMBER m_size)
                                          
                                          public:
                                              QString m_name;
                                              qreal m_size;
                                          };
                                          
                                          class DataSource : public QObject
                                          {
                                              Q_OBJECT
                                          
                                          public:
                                              Q_INVOKABLE QVariantList getData();
                                          };
                                          
                                          
                                          #endif // TYPES_H
                                          

                                          main.cpp

                                          #include <QGuiApplication>
                                          #include <QQmlApplicationEngine>
                                          #include <QQmlContext>
                                          
                                          #include "types.h"
                                          
                                          QVariantList DataSource::getData()
                                          {
                                              return {
                                                  QVariant::fromValue<Bottle>({ "First bottle", 0.75 }),
                                                  QVariant::fromValue<Bottle>({ "Second bottle", 0.70 })
                                              };
                                          }
                                          
                                          int main(int argc, char *argv[])
                                          {
                                              QGuiApplication app(argc, argv);
                                          
                                              QQmlApplicationEngine engine;
                                              engine.addImportPath(QStringLiteral("qrc:/"));
                                              QUrl url(QStringLiteral("qrc:/main.qml"));
                                              QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url] (QObject * obj, const QUrl & objUrl) -> void {
                                                  if (!obj && url == objUrl)
                                                      QCoreApplication::exit(-1);
                                              }, Qt::QueuedConnection);
                                          
                                              DataSource source;
                                              engine.rootContext()->setContextProperty(QStringLiteral("DataSource"), &source);
                                          
                                              qmlRegisterUncreatableType<Bottle>("Example", 1, 0, "Bottle", "");
                                          
                                              engine.load(url);
                                          
                                              return app.exec();
                                          }
                                          

                                          main.qml

                                          import QtQuick 2.15
                                          import QtQuick.Window 2.15
                                          import QtQuick.Controls 2.15
                                          
                                          import Example 1.0
                                          
                                          Window {
                                              id: mainWindow
                                              visible: true
                                              width: 300
                                              height: 200
                                              title: qsTr("Some title")
                                          
                                              Component {
                                                  id: template
                                                  Text {
                                                      text: "defaultText"
                                                  }
                                              }
                                          
                                              Column {
                                                 Component.onCompleted: DataSource.getData().forEach(function(element) {
                                                     template.createObject(this, { text: element.name });
                                                 }, this)
                                              }
                                          }
                                          

                                          PS. QML is damn annoying ...

                                          mzimmersM Offline
                                          mzimmersM Offline
                                          mzimmers
                                          wrote on last edited by
                                          #29

                                          @kshegunov said in accessing aggregates (QVector of a struct):

                                          PS. QML is damn annoying ...

                                          Heh...no argument there, but if I'm reading the tea leaves correctly, it's here to stay.

                                          I understand your C++ code, but I'm still trying to figure out what your QML results in. What exactly is this doing?

                                          Component {
                                                  id: template
                                                  Text {
                                                      text: "defaultText"
                                                  }
                                              }
                                          
                                              Column {
                                                 Component.onCompleted: DataSource.getData().forEach(function(element) {
                                                     template.createObject(this, { text: element.name });
                                                 }, this)
                                              }
                                          
                                          kshegunovK 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