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 elements of structs in a list
Forum Updated to NodeBB v4.3 + New Features

accessing elements of structs in a list

Scheduled Pinned Locked Moved Solved QML and Qt Quick
17 Posts 5 Posters 1.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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by mzimmers
    #1

    Hi all -

    I've defined a struct:

    struct SceneFeature : public QObject {
        Q_OBJECT
        QML_ELEMENT
    public:
        QUuid m_featureId = QUuid();
        Q_PROPERTY(QUuid uuid READ uuid WRITE setUuid NOTIFY uuidChanged FINAL)
        QUuid uuid() { return m_featureId; }
        ...
    };
    Q_DECLARE_METATYPE(SceneFeature)
    

    and I use it in this class:

    typedef std::shared_ptr<SceneFeature> SceneFeaturePtr;
    Q_DECLARE_METATYPE(SceneFeaturePtr)
    
    typedef QList<SceneFeaturePtr> SceneFeatureList;
    Q_DECLARE_METATYPE(SceneFeatureList)
    
    class Scene : public QObject
    {
        Q_OBJECT
        QML_ELEMENT
    
        QUuid m_uuid { QUuid() };
    public:
        Q_PROPERTY(QList<SceneFeaturePtr> featureList READ featureList WRITE setFeatureList NOTIFY featureListChanged FINAL)
        SceneFeatureList featureList() { return m_featureList; }
        ...
    }
    

    and I try to access it from QML:

    property Scene sceneCopy
    ListView {
        id: listView
        model: sceneCopy.featureList
        delegate: Text { text: model.uuid } // I realize this is wrong.
        ...
    

    but model.uuid is undefined at run time. Can someone tell me what I'm doing wrong here?

    EDIT: I should have pointed out that the model in my ListView appears to be good, judging from printouts. So, the problem appears to be in how I access it.

    Thanks...

    1 Reply Last reply
    0
    • mzimmersM mzimmers

      @J-Hilk said in accessing elements of structs in a list:

      I',m not sure what featureList actually is. I have a feeling it's not a class derived from QAbstractListModel but rather a simple QList<QObjectDerivedClassInstances> ?

          typedef QList<SceneFeaturePtr> SceneFeatureList;
          SceneFeatureList m_featureList;
      
          Q_PROPERTY(QList<SceneFeaturePtr> featureList READ featureList WRITE setFeatureList NOTIFY featureListChanged FINAL)
          QList<SceneFeaturePtr> featureList() { return m_featureList; }
      

      So no, it's not derived from a Model class.

      Your suggestion, along with my adding this code to my struct:

          Q_PROPERTY(QUuid featureId READ featureId WRITE setFeatureId NOTIFY featureIdChanged FINAL)
          QUuid featureId() { return m_featureId; }
      

      allows the QML to access the struct list. So, I think the answer is is that I don't necessarily need a proper model for access to the struct, as long as I've created Q_PROPERTY to its elements?

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #17

      @mzimmers correct,

      you can give your QML ListView literally anything as a model :D if it is an actuall Qt based ItemModel of some kind, you can access data via the roles of the model:

      ListView {
          model: myModel
          delegate: Item {
              Text {
                  text: model.someCustomRole // Access data via custom role
              }
          }
      }
      

      for all other cases it is via modelData

      ListView {
          model: ["a", "b", "c"]
          delegate: Item {
              Text {
                  text: modelData // Access data for this specific index
              }
          }
      }
      

      or manual index lookup

      property var myModel: ["a", "b", "c"]
      ListView {
          model: myModel
          delegate: Item {
              Text {
                  text: myModel[index]
              }
          }
      }
      

      So, I think the answer is is that I don't necessarily need a proper model for access to the struct, as long as I've created Q_PROPERTY to its elements?

      yes, it doesn't have to be a full blown QObject base class either, Q_GADET is enough, prevents you from using signals though.


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      1 Reply Last reply
      1
      • A Offline
        A Offline
        ankou29666
        wrote on last edited by ankou29666
        #2

        yeah I'm looking again at the doc and and it confirms my thought : I don't remember ever seeing any delegate's component making a binding to the model itself. But directly to the model's properties. Look at ListView's (and other similar components) documentation : you never see the delegate refer to model.property, but directly to property instead.

        my guess would be delegate: Text { text: uuid }

        and anyways, your list has no uuid property, only the elements of the list have one. It's a bit like making list.elementProperty instead of list[index].property.

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

          Isn’t this the exact same as the “ QObjectList-based Model” example in the docs?

          "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

          mzimmersM A 2 Replies Last reply
          0
          • VRoninV VRonin

            Isn’t this the exact same as the “ QObjectList-based Model” example in the docs?

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

            @VRonin said in accessing elements of structs in a list:

            Isn’t this the exact same as the “ QObjectList-based Model” example in the docs?

            From the C++ side, it is, and I think I've done what I need to there. I suspect I'm messing things up on the QML side.

            Unless...I actually need a model for my struct. I'm really hoping that's not the case here.

            1 Reply Last reply
            0
            • VRoninV VRonin

              Isn’t this the exact same as the “ QObjectList-based Model” example in the docs?

              A Offline
              A Offline
              ankou29666
              wrote on last edited by
              #5

              @VRonin said in accessing elements of structs in a list:

              Isn’t this the exact same as the “ QObjectList-based Model” example in the docs?

              This example looks irrelevant to me. If the property belongs to an item in the list, it's a non-sense accessing that property as if it was belonging to the list itself.

              @mzimmers said in accessing elements of structs in a list:

              Unless...I actually need a model for my struct. I'm really hoping that's not the case here.

              A view without a suitable model doesn't make any more sense in my opinion.

              mzimmersM 1 Reply Last reply
              0
              • A ankou29666

                @VRonin said in accessing elements of structs in a list:

                Isn’t this the exact same as the “ QObjectList-based Model” example in the docs?

                This example looks irrelevant to me. If the property belongs to an item in the list, it's a non-sense accessing that property as if it was belonging to the list itself.

                @mzimmers said in accessing elements of structs in a list:

                Unless...I actually need a model for my struct. I'm really hoping that's not the case here.

                A view without a suitable model doesn't make any more sense in my opinion.

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

                @ankou29666 said in accessing elements of structs in a list:

                This example looks irrelevant to me. If the property belongs to an item in the list, it's a non-sense accessing that property as if it was belonging to the list itself.

                So, what would you recommend in this instance?

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  ankou29666
                  wrote on last edited by ankou29666
                  #7

                  as I said earlier : delegate: Text { text: uuid } seems to me the right way.
                  Since the delegate displays property for the current item, it's a non-sense to access that property as if it was a property of the list. As I understand by reading ListView / TableView / Repeater doc, the current item is implicit.

                  But as your data is a simple list and not ListModel, I'm not certain that the previous correction will be sufficient.

                  GrecKoG 1 Reply Last reply
                  0
                  • J.HilkJ Offline
                    J.HilkJ Offline
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #8

                    QUuid is not a trivial type and therefore needs to be known to the QMetaObject system, apparently it is not registered by default.

                    do that via Q_DECLARE_METATYPE and qRegisterMetaType

                    Alternatively, as you can't do much with QUuid in QML itself, change the property to a QString and call toString() on your Quuid in the return/getter function


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    mzimmersM 1 Reply Last reply
                    2
                    • A ankou29666

                      as I said earlier : delegate: Text { text: uuid } seems to me the right way.
                      Since the delegate displays property for the current item, it's a non-sense to access that property as if it was a property of the list. As I understand by reading ListView / TableView / Repeater doc, the current item is implicit.

                      But as your data is a simple list and not ListModel, I'm not certain that the previous correction will be sufficient.

                      GrecKoG Offline
                      GrecKoG Offline
                      GrecKo
                      Qt Champions 2018
                      wrote on last edited by
                      #9

                      @ankou29666 said in accessing elements of structs in a list:

                      Since the delegate displays property for the current item, it's a non-sense to access that property as if it was a property of the list.

                      Are you talking about text: model.uuid? That's not accessing the property as it was a property of the list. model in the delegate is different than model in the ListView. It's a context property fed by the view to the delegate, containing properties for each role of the delegate's row.

                      Note that required properties are now preferred over context properties.

                      @mzimmers QML doesn't know how to access std::shared_ptr. Are you sure you want to share the ownership of your objects with QML?

                      A mzimmersM 2 Replies Last reply
                      3
                      • GrecKoG GrecKo

                        @ankou29666 said in accessing elements of structs in a list:

                        Since the delegate displays property for the current item, it's a non-sense to access that property as if it was a property of the list.

                        Are you talking about text: model.uuid? That's not accessing the property as it was a property of the list. model in the delegate is different than model in the ListView. It's a context property fed by the view to the delegate, containing properties for each role of the delegate's row.

                        Note that required properties are now preferred over context properties.

                        @mzimmers QML doesn't know how to access std::shared_ptr. Are you sure you want to share the ownership of your objects with QML?

                        A Offline
                        A Offline
                        ankou29666
                        wrote on last edited by
                        #10

                        @GrecKo said in accessing elements of structs in a list:

                        @ankou29666 said in accessing elements of structs in a list:

                        Since the delegate displays property for the current item, it's a non-sense to access that property as if it was a property of the list.

                        Are you talking about text: model.uuid? That's not accessing the property as it was a property of the list. model in the delegate is different than model in the ListView. It's a context property fed by the view to the delegate, containing properties for each role of the delegate's row.

                        yep this is exactly what I was talking about. And reading once again documentation for Repeater, TableView, ListView, beyond the link posted by VRonin, I find no code, where the delegate explicitly calls model.property, it's always directly the property.

                        But thanks for the clue, I'll try that and check by myself as soon as I move a little further in my own project.

                        1 Reply Last reply
                        0
                        • GrecKoG Offline
                          GrecKoG Offline
                          GrecKo
                          Qt Champions 2018
                          wrote on last edited by
                          #11

                          https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#models

                          If there is a naming clash between the model's properties and the delegate's properties, the roles can be accessed with the qualified model name instead. For example, if a Text type had (non-required) type or age properties, the text in the above example would display those property values instead of the type and age values from the model item. In this case, the properties could have been referenced as model.type and model.age instead to ensure the delegate displays the property values from the model item. For this to work, you need to require a model property in your delegate (unless you are using context properties).

                          1 Reply Last reply
                          1
                          • A Offline
                            A Offline
                            ankou29666
                            wrote on last edited by
                            #12

                            Thanks, very interesting.

                            1 Reply Last reply
                            0
                            • J.HilkJ J.Hilk

                              QUuid is not a trivial type and therefore needs to be known to the QMetaObject system, apparently it is not registered by default.

                              do that via Q_DECLARE_METATYPE and qRegisterMetaType

                              Alternatively, as you can't do much with QUuid in QML itself, change the property to a QString and call toString() on your Quuid in the return/getter function

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

                              @J-Hilk said in accessing elements of structs in a list:

                              QUuid is not a trivial type and therefore needs to be known to the QMetaObject system, apparently it is not registered by default.

                              Yeah, I didn't choose a good example for my post. I'm getting the same results with a QString. It's somthing that I'm doing wrong.

                              J.HilkJ 1 Reply Last reply
                              0
                              • GrecKoG GrecKo

                                @ankou29666 said in accessing elements of structs in a list:

                                Since the delegate displays property for the current item, it's a non-sense to access that property as if it was a property of the list.

                                Are you talking about text: model.uuid? That's not accessing the property as it was a property of the list. model in the delegate is different than model in the ListView. It's a context property fed by the view to the delegate, containing properties for each role of the delegate's row.

                                Note that required properties are now preferred over context properties.

                                @mzimmers QML doesn't know how to access std::shared_ptr. Are you sure you want to share the ownership of your objects with QML?

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

                                @GrecKo said in accessing elements of structs in a list:

                                Note that required properties are now preferred over context properties.

                                I assume you're referring to my code for sceneCopy - what would be the benefit of making that required?

                                @mzimmers QML doesn't know how to access std::shared_ptr. Are you sure you want to share the ownership of your objects with QML?

                                No, I'm not sure. I just like to use smart pointers wherever possible to reduce memory leaks. I can easily change this to see if it helps, but I still believe my problem lies elsewhere. This is kind of new to me - I've never done a "model within a model" before.

                                1 Reply Last reply
                                0
                                • mzimmersM mzimmers

                                  @J-Hilk said in accessing elements of structs in a list:

                                  QUuid is not a trivial type and therefore needs to be known to the QMetaObject system, apparently it is not registered by default.

                                  Yeah, I didn't choose a good example for my post. I'm getting the same results with a QString. It's somthing that I'm doing wrong.

                                  J.HilkJ Offline
                                  J.HilkJ Offline
                                  J.Hilk
                                  Moderators
                                  wrote on last edited by
                                  #15

                                  @mzimmers I',m not sure what featureList actually is. I have a feeling it's not a class derived from QAbstractListModel but rather a simple QList<QObjectDerivedClassInstances> ?

                                  than this:

                                  ListView {
                                      id: listView
                                      model: sceneCopy.featureList
                                      delegate: Text { text: model.uuid } // I realize this is wrong.
                                  

                                  should be

                                  ListView {
                                      id: listView
                                      model: sceneCopy.featureList
                                      delegate: Text { text: modelData.uuid }
                                  
                                  

                                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                  Q: What's that?
                                  A: It's blue light.
                                  Q: What does it do?
                                  A: It turns blue.

                                  mzimmersM 1 Reply Last reply
                                  1
                                  • J.HilkJ J.Hilk

                                    @mzimmers I',m not sure what featureList actually is. I have a feeling it's not a class derived from QAbstractListModel but rather a simple QList<QObjectDerivedClassInstances> ?

                                    than this:

                                    ListView {
                                        id: listView
                                        model: sceneCopy.featureList
                                        delegate: Text { text: model.uuid } // I realize this is wrong.
                                    

                                    should be

                                    ListView {
                                        id: listView
                                        model: sceneCopy.featureList
                                        delegate: Text { text: modelData.uuid }
                                    
                                    
                                    mzimmersM Offline
                                    mzimmersM Offline
                                    mzimmers
                                    wrote on last edited by
                                    #16

                                    @J-Hilk said in accessing elements of structs in a list:

                                    I',m not sure what featureList actually is. I have a feeling it's not a class derived from QAbstractListModel but rather a simple QList<QObjectDerivedClassInstances> ?

                                        typedef QList<SceneFeaturePtr> SceneFeatureList;
                                        SceneFeatureList m_featureList;
                                    
                                        Q_PROPERTY(QList<SceneFeaturePtr> featureList READ featureList WRITE setFeatureList NOTIFY featureListChanged FINAL)
                                        QList<SceneFeaturePtr> featureList() { return m_featureList; }
                                    

                                    So no, it's not derived from a Model class.

                                    Your suggestion, along with my adding this code to my struct:

                                        Q_PROPERTY(QUuid featureId READ featureId WRITE setFeatureId NOTIFY featureIdChanged FINAL)
                                        QUuid featureId() { return m_featureId; }
                                    

                                    allows the QML to access the struct list. So, I think the answer is is that I don't necessarily need a proper model for access to the struct, as long as I've created Q_PROPERTY to its elements?

                                    J.HilkJ 1 Reply Last reply
                                    0
                                    • mzimmersM mzimmers

                                      @J-Hilk said in accessing elements of structs in a list:

                                      I',m not sure what featureList actually is. I have a feeling it's not a class derived from QAbstractListModel but rather a simple QList<QObjectDerivedClassInstances> ?

                                          typedef QList<SceneFeaturePtr> SceneFeatureList;
                                          SceneFeatureList m_featureList;
                                      
                                          Q_PROPERTY(QList<SceneFeaturePtr> featureList READ featureList WRITE setFeatureList NOTIFY featureListChanged FINAL)
                                          QList<SceneFeaturePtr> featureList() { return m_featureList; }
                                      

                                      So no, it's not derived from a Model class.

                                      Your suggestion, along with my adding this code to my struct:

                                          Q_PROPERTY(QUuid featureId READ featureId WRITE setFeatureId NOTIFY featureIdChanged FINAL)
                                          QUuid featureId() { return m_featureId; }
                                      

                                      allows the QML to access the struct list. So, I think the answer is is that I don't necessarily need a proper model for access to the struct, as long as I've created Q_PROPERTY to its elements?

                                      J.HilkJ Offline
                                      J.HilkJ Offline
                                      J.Hilk
                                      Moderators
                                      wrote on last edited by
                                      #17

                                      @mzimmers correct,

                                      you can give your QML ListView literally anything as a model :D if it is an actuall Qt based ItemModel of some kind, you can access data via the roles of the model:

                                      ListView {
                                          model: myModel
                                          delegate: Item {
                                              Text {
                                                  text: model.someCustomRole // Access data via custom role
                                              }
                                          }
                                      }
                                      

                                      for all other cases it is via modelData

                                      ListView {
                                          model: ["a", "b", "c"]
                                          delegate: Item {
                                              Text {
                                                  text: modelData // Access data for this specific index
                                              }
                                          }
                                      }
                                      

                                      or manual index lookup

                                      property var myModel: ["a", "b", "c"]
                                      ListView {
                                          model: myModel
                                          delegate: Item {
                                              Text {
                                                  text: myModel[index]
                                              }
                                          }
                                      }
                                      

                                      So, I think the answer is is that I don't necessarily need a proper model for access to the struct, as long as I've created Q_PROPERTY to its elements?

                                      yes, it doesn't have to be a full blown QObject base class either, Q_GADET is enough, prevents you from using signals though.


                                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                      Q: What's that?
                                      A: It's blue light.
                                      Q: What does it do?
                                      A: It turns blue.

                                      1 Reply Last reply
                                      1
                                      • mzimmersM mzimmers has marked this topic as solved on

                                      • Login

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