Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. passing lists of data to a Component

passing lists of data to a Component

Scheduled Pinned Locked Moved Solved Brainstorm
13 Posts 3 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M mzimmers
    18 Mar 2024, 16:04

    @TomZ thanks for the reply. One of my goals here is to make the EquipmentConfigList.qml file reusable. I'm looking for a way to aggregate the data I need to display (I would expect to do this inside my Flickable or my reference to the EquipmentConfigList) so that I can use a Repeater (or something similar) to display all the information that's passed to EquipmentConfigList.qml. In C++ I'd use an array of structs (probably) but I don't know how to do this in QML. Any thoughts?

    EDIT:

    This is sort of pseudocode outline of what I'd like to do:

    EquipmentA.qml
    EquipmentB.qml
    EquipmentC.qml
    
    // EquipmentConfig.qml
    
    if (category is A) {
        list = makeListForCategoryA // choosing only the properties I want to display for A
        EquipmentConfigList(list)
    } else if (category is B) {
        list = makeListForCategoryB
        EquipmentConfigList(list)
    } // etc.
    

    My EquipmentA/B/C.qml files ideally wouldn't have to be QML, though I'm not sure what I'd replace them with. But the gist is to have a reusable list that I can conditionally populate based on the category of the equipment object.

    Thanks...

    T Offline
    T Offline
    TomZ
    wrote on 18 Mar 2024, 22:26 last edited by
    #4

    @mzimmers I think you are on the right track, but you seem to be stuck on some minor issues.

    First, remember the strong seperation of model/view. In this specific case you can easily have one model that feeds all 3 types of views. You KNOW that a view will only ask for certain properties if the data is a certain type, as such you can optimize your model code to match (add asserts, even).

    So, in short, to feed your 3 types of views you should only have one backing model. It simply has different properties you query for a specific view.

    Second,
    you can use a Loader with a construction like:

    ListView {
       model: someModel
       Loader {
         source: {
           if (model.someProperty)
             return "./Page1.qml";
          if (model.foo)
             return "./Page2.qml";
          return "./Page3.qml";
       }
    }
    

    Then your pages simply need to use the model property to fetch the data they want to use.

    Page1.qml
    
    Label {
       text: model.something
    }
    
    M 1 Reply Last reply 18 Mar 2024, 23:27
    2
    • T TomZ
      18 Mar 2024, 22:26

      @mzimmers I think you are on the right track, but you seem to be stuck on some minor issues.

      First, remember the strong seperation of model/view. In this specific case you can easily have one model that feeds all 3 types of views. You KNOW that a view will only ask for certain properties if the data is a certain type, as such you can optimize your model code to match (add asserts, even).

      So, in short, to feed your 3 types of views you should only have one backing model. It simply has different properties you query for a specific view.

      Second,
      you can use a Loader with a construction like:

      ListView {
         model: someModel
         Loader {
           source: {
             if (model.someProperty)
               return "./Page1.qml";
            if (model.foo)
               return "./Page2.qml";
            return "./Page3.qml";
         }
      }
      

      Then your pages simply need to use the model property to fetch the data they want to use.

      Page1.qml
      
      Label {
         text: model.something
      }
      
      M Offline
      M Offline
      mzimmers
      wrote on 18 Mar 2024, 23:27 last edited by mzimmers
      #5

      @TomZ I think this is moving in the right direction. A couple points:

      I am indeed maintaining a single model. It contains a list of all the equipment items in the system.

      There will be multiple equipment items of the same category in a system. For this reason, I need to somehow inform my Page1/2/3.qml files of the equipment object I'm using. By the time I'm in this QML area, I've already accessed the model and have a single instance of Equipment in my QML.

      Also (minor) when I changed my Flickable to a ListView, it no longer flicks. Here's the complete code for the section:

      // Flickable {
      ListView {
          boundsBehavior: Flickable.StopAtBounds
          clip: true
          contentHeight: contentItem.childrenRect.height
          implicitWidth: parent.width
          implicitHeight: innerPane.availableHeight
          EquipmentConfigList { // this would become Page1/2/3.qml
              id: equipmentConfigList
              Layout.fillHeight: true
              Layout.preferredWidth: rightColumn.availableWidth
              equipment: equipmentCopy
          }
      }
      

      Any idea why it doesn't flick for me anymore?

      Thanks for the help...

      G 1 Reply Last reply 19 Mar 2024, 00:46
      0
      • M mzimmers
        18 Mar 2024, 23:27

        @TomZ I think this is moving in the right direction. A couple points:

        I am indeed maintaining a single model. It contains a list of all the equipment items in the system.

        There will be multiple equipment items of the same category in a system. For this reason, I need to somehow inform my Page1/2/3.qml files of the equipment object I'm using. By the time I'm in this QML area, I've already accessed the model and have a single instance of Equipment in my QML.

        Also (minor) when I changed my Flickable to a ListView, it no longer flicks. Here's the complete code for the section:

        // Flickable {
        ListView {
            boundsBehavior: Flickable.StopAtBounds
            clip: true
            contentHeight: contentItem.childrenRect.height
            implicitWidth: parent.width
            implicitHeight: innerPane.availableHeight
            EquipmentConfigList { // this would become Page1/2/3.qml
                id: equipmentConfigList
                Layout.fillHeight: true
                Layout.preferredWidth: rightColumn.availableWidth
                equipment: equipmentCopy
            }
        }
        

        Any idea why it doesn't flick for me anymore?

        Thanks for the help...

        G Offline
        G Offline
        GrecKo
        Qt Champions 2018
        wrote on 19 Mar 2024, 00:46 last edited by
        #6

        If you want to have different delegate components based on a type role, use DelegateChooser instead of Loader for delegates.

        If you want to have a single generic delegate, you could define all the possible fields and conditionally show them if there is a corresponding property. Or fetch the properties from the meta-object. Do you want to do that though? What if you want to display a gauge/slider? How would you define the min/max value?

        M 1 Reply Last reply 19 Mar 2024, 01:45
        2
        • G GrecKo
          19 Mar 2024, 00:46

          If you want to have different delegate components based on a type role, use DelegateChooser instead of Loader for delegates.

          If you want to have a single generic delegate, you could define all the possible fields and conditionally show them if there is a corresponding property. Or fetch the properties from the meta-object. Do you want to do that though? What if you want to display a gauge/slider? How would you define the min/max value?

          M Offline
          M Offline
          mzimmers
          wrote on 19 Mar 2024, 01:45 last edited by
          #7

          @GrecKo said in passing lists of data to a Component:

          What if you want to display a gauge/slider? How would you define the min/max value?

          You're a mind reader - I will indeed need to do that elsewhere (the customer wants separate pages for viewing and editing the Equipment fields). I was starting with the easy (readonly) stuff.

          I'm still having trouble putting this all together, though. I need a Flickable (or ListView) that will conditionally display properties of the Equipment object based on the category of the equipment.

          Here's the basis of the Equipment class:

          enum EquipmentCategory {
              CATEGORY_UNKNOWN,
              CATEGORY_VSP,
              CATEGORY_HEATER,
              CATEGORY_HEATPUMP,
              // ...
          }
          class Equipment : public QObject
          {
              Q_OBJECT
              QML_ELEMENT
          
              EquipmentCategory m_category = CATEGORY_UNKNOWN; // exposed to QML
              // ...
          }
          

          So, how do I use a DelegateChooser here:

          Flickable {
              // what is my model?
              DelagateChooser {
                  role: category
                  DelegateChoice {
                      role: CATEGORY_VSP // this doesn't seem right
                      VspDelegate {} // contained an another file
                  }
                  DelegateChoice {
                      role: CATEGORY_HEATER
                      HeaterDelegate {} // contained an another file
                  }
              }
          }
          

          Is this on the right track?

          Thanks...

          G 1 Reply Last reply 19 Mar 2024, 15:14
          0
          • M mzimmers
            19 Mar 2024, 01:45

            @GrecKo said in passing lists of data to a Component:

            What if you want to display a gauge/slider? How would you define the min/max value?

            You're a mind reader - I will indeed need to do that elsewhere (the customer wants separate pages for viewing and editing the Equipment fields). I was starting with the easy (readonly) stuff.

            I'm still having trouble putting this all together, though. I need a Flickable (or ListView) that will conditionally display properties of the Equipment object based on the category of the equipment.

            Here's the basis of the Equipment class:

            enum EquipmentCategory {
                CATEGORY_UNKNOWN,
                CATEGORY_VSP,
                CATEGORY_HEATER,
                CATEGORY_HEATPUMP,
                // ...
            }
            class Equipment : public QObject
            {
                Q_OBJECT
                QML_ELEMENT
            
                EquipmentCategory m_category = CATEGORY_UNKNOWN; // exposed to QML
                // ...
            }
            

            So, how do I use a DelegateChooser here:

            Flickable {
                // what is my model?
                DelagateChooser {
                    role: category
                    DelegateChoice {
                        role: CATEGORY_VSP // this doesn't seem right
                        VspDelegate {} // contained an another file
                    }
                    DelegateChoice {
                        role: CATEGORY_HEATER
                        HeaterDelegate {} // contained an another file
                    }
                }
            }
            

            Is this on the right track?

            Thanks...

            G Offline
            G Offline
            GrecKo
            Qt Champions 2018
            wrote on 19 Mar 2024, 15:14 last edited by
            #8

            @mzimmers said in passing lists of data to a Component:

            role: CATEGORY_VSP // this doesn't seem right

            use roleValue here. And properly expose your enum type to QML.

            The role property of DelegateChooser is a string, so specify the role name as a string here.

            M 2 Replies Last reply 19 Mar 2024, 23:02
            1
            • G GrecKo
              19 Mar 2024, 15:14

              @mzimmers said in passing lists of data to a Component:

              role: CATEGORY_VSP // this doesn't seem right

              use roleValue here. And properly expose your enum type to QML.

              The role property of DelegateChooser is a string, so specify the role name as a string here.

              M Offline
              M Offline
              mzimmers
              wrote on 19 Mar 2024, 23:02 last edited by
              #9
              This post is deleted!
              1 Reply Last reply
              0
              • G GrecKo
                19 Mar 2024, 15:14

                @mzimmers said in passing lists of data to a Component:

                role: CATEGORY_VSP // this doesn't seem right

                use roleValue here. And properly expose your enum type to QML.

                The role property of DelegateChooser is a string, so specify the role name as a string here.

                M Offline
                M Offline
                mzimmers
                wrote on 19 Mar 2024, 23:28 last edited by
                #10

                @GrecKo so, this is what I have now (and it seems to work):

                ListView {
                    anchors.fill: parent
                    model: equipmentCopy
                    clip: true
                    boundsBehavior: Flickable.StopAtBounds
                    delegate: DelegateChooser {
                        role: "category"
                        DelegateChoice {
                            roleValue: NgaUI.CATEGORY_VSP
                            delegate: EquipmentConfigList {
                                equipment: equipmentCopy
                            }
                        }
                    }
                }
                

                It's a little foreign to me, as I've never used an object as a model, but everything seems to work. Thanks for all the help on this.

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  mzimmers
                  wrote on 20 Mar 2024, 13:28 last edited by
                  #11

                  @GrecKo Before I close this topic, I do have a couple of follow-up questions:

                  1. I don't seem to be using a list in the "classical" sense, in that I'm only displaying one item. I realize that a delegate (and therefore, a DelegateChooser) needs a list, but...is there a preferred way to implement what I'm doing? Without a list?

                  2. (sort of related) is it OK to use an object as the model for a ListView? It seems to work OK, but there's nothing in the docs that explicitly says I can do this, so I want to make sure this is licit.

                  Thanks...

                  G 1 Reply Last reply 22 Mar 2024, 14:06
                  0
                  • M mzimmers
                    20 Mar 2024, 13:28

                    @GrecKo Before I close this topic, I do have a couple of follow-up questions:

                    1. I don't seem to be using a list in the "classical" sense, in that I'm only displaying one item. I realize that a delegate (and therefore, a DelegateChooser) needs a list, but...is there a preferred way to implement what I'm doing? Without a list?

                    2. (sort of related) is it OK to use an object as the model for a ListView? It seems to work OK, but there's nothing in the docs that explicitly says I can do this, so I want to make sure this is licit.

                    Thanks...

                    G Offline
                    G Offline
                    GrecKo
                    Qt Champions 2018
                    wrote on 22 Mar 2024, 14:06 last edited by
                    #12

                    @mzimmers I didn't realize you didn't want to use this is a model/view but yes it is indeed supported to have a single object as a model. You were 1 link away ;) https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#object-instances-as-models

                    using Loader like mentioned by TomZ is an alternative.

                    M 1 Reply Last reply 22 Mar 2024, 14:42
                    3
                    • G GrecKo
                      22 Mar 2024, 14:06

                      @mzimmers I didn't realize you didn't want to use this is a model/view but yes it is indeed supported to have a single object as a model. You were 1 link away ;) https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#object-instances-as-models

                      using Loader like mentioned by TomZ is an alternative.

                      M Offline
                      M Offline
                      mzimmers
                      wrote on 22 Mar 2024, 14:42 last edited by
                      #13

                      @GrecKo yeah, this is a weird use case. I actually do want a list, just not a list in the Qt model/view/delegate sense. Ideally, I'd like to create a list (array/vector/whatever) of the properties I want to display, and pass it into a universal component for display, but creating and using that structure seems to be a bit out of reach for JS/QML/me. It's OK; this approach is working, if a bit inelegant.

                      1 Reply Last reply
                      0
                      • M mzimmers has marked this topic as solved on 3 Apr 2024, 17:03

                      13/13

                      22 Mar 2024, 14:42

                      • Login

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