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
Forum Updated to NodeBB v4.3 + New Features

passing lists of data to a Component

Scheduled Pinned Locked Moved Solved Brainstorm
13 Posts 3 Posters 1.9k Views 1 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.
  • TomZT TomZ

    Yap, that's a bit messy...

    You obviously know about the Loader.setSource second argument. Which doesn't work for a Component.

    Here is one solution:

    Loader {
      onLoaded: item.someProperty = someValue
    }
    

    Your component should have that property and your code here can set it to anything.
    Biggest downside is that the property is null for a small while which may cause you to have warnings unless you check for that in usages.

    Now, the main upside here is that you can call into C++ code and pass in a 'parent' object for memory management (QObject constructor arg). If you pass in the 'item' (property of loader) then your created QObject's livespan will be tied to the loaded item.

    I use this method often in things like a delegate. Your delegate is a thin wrapper around a Loader, the loader selects the Compenent on some properties in the 'modelData' and then assigns the modelData to some property of the component on load.

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

    @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...

    TomZT 1 Reply Last reply
    0
    • mzimmersM mzimmers

      @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...

      TomZT Offline
      TomZT Offline
      TomZ
      wrote on 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
      }
      
      mzimmersM 1 Reply Last reply
      2
      • TomZT TomZ

        @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
        }
        
        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on 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...

        GrecKoG 1 Reply Last reply
        0
        • mzimmersM mzimmers

          @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...

          GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on 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?

          mzimmersM 1 Reply Last reply
          2
          • GrecKoG GrecKo

            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?

            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on 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...

            GrecKoG 1 Reply Last reply
            0
            • mzimmersM mzimmers

              @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...

              GrecKoG Offline
              GrecKoG Offline
              GrecKo
              Qt Champions 2018
              wrote on 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.

              mzimmersM 2 Replies Last reply
              1
              • GrecKoG GrecKo

                @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.

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #9
                This post is deleted!
                1 Reply Last reply
                0
                • GrecKoG GrecKo

                  @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.

                  mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on 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
                  • mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on 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...

                    GrecKoG 1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @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...

                      GrecKoG Offline
                      GrecKoG Offline
                      GrecKo
                      Qt Champions 2018
                      wrote on 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.

                      mzimmersM 1 Reply Last reply
                      3
                      • GrecKoG GrecKo

                        @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.

                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on 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
                        • 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