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. how to distinguish between multiple C++ models?

how to distinguish between multiple C++ models?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
13 Posts 4 Posters 1.1k 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.
  • sierdzioS sierdzio

    @mzimmers said in how to distinguish between multiple C++ models?:

    It's been a while since I've done something like it, but I think the trick was:

    • use model or modelData to access the "current" (inner) model
    • when you need a property from "parent" model, declare it as a property in inner ListView

    So:

    ListView {
      model: zoneModel.getZone(model.equipmentList)
      property string parentProperty: model.someParentProp
      delegate: Column {
        Text {
          text: model.propertyFromInnerModel + parenProperty
        }
      }
    }
    
    mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by mzimmers
    #3

    @sierdzio doesn't seem to be working, at least not how I'm trying. The inner code still seems to be confused about which model to use.

    The taxonomy is: the ZoneModel maintains a list of Zones; and each Zone has a list of Equipment item UUIDs. I'm trying to:

    1. list each zone
    2. for each zone, list its equipment items
    3. for each equipment item, list a few properties

    I've further reduced the example:

    ListView {
        id: infoScreen
        model: zoneModel
        delegate: ListView {
            model: zoneModel.getZone(model.equipmentList) // error on this line
            delegate: Text {
                    text: "equipment name: " + model.name
                }
            }
        }
    }
    

    And I get a runtime error: TypeError: Cannot read property 'equipmentList' of undefined.

    Shouldn't the model be something more like:

    model: zoneModel.getZone(index).equipmentList
    

    I know this isn't right, because 1) it doesn't display anything, and 2) it crashes after a few seconds, but it seems closer to what I'm trying to use as the model.

    fcarneyF 1 Reply Last reply
    0
    • mzimmersM mzimmers

      @sierdzio doesn't seem to be working, at least not how I'm trying. The inner code still seems to be confused about which model to use.

      The taxonomy is: the ZoneModel maintains a list of Zones; and each Zone has a list of Equipment item UUIDs. I'm trying to:

      1. list each zone
      2. for each zone, list its equipment items
      3. for each equipment item, list a few properties

      I've further reduced the example:

      ListView {
          id: infoScreen
          model: zoneModel
          delegate: ListView {
              model: zoneModel.getZone(model.equipmentList) // error on this line
              delegate: Text {
                      text: "equipment name: " + model.name
                  }
              }
          }
      }
      

      And I get a runtime error: TypeError: Cannot read property 'equipmentList' of undefined.

      Shouldn't the model be something more like:

      model: zoneModel.getZone(index).equipmentList
      

      I know this isn't right, because 1) it doesn't display anything, and 2) it crashes after a few seconds, but it seems closer to what I'm trying to use as the model.

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

      @mzimmers You can use attached properties for ListView. To get the model for the ListView for the current delegate then do ListView.view.model. You are also dealing with 3 different models by having a nested listview. The injected model of the first listview, the injected model of the second listview, and the model property of the nested listview. It would be better if the nested listview delegate looked like this:

      delegate: Item {
          // injected model here
      
          ListView {
              // model of this listview is not occluded
          }
      }
      

      C++ is a perfectly valid school of magic.

      mzimmersM 1 Reply Last reply
      1
      • fcarneyF fcarney

        @mzimmers You can use attached properties for ListView. To get the model for the ListView for the current delegate then do ListView.view.model. You are also dealing with 3 different models by having a nested listview. The injected model of the first listview, the injected model of the second listview, and the model property of the nested listview. It would be better if the nested listview delegate looked like this:

        delegate: Item {
            // injected model here
        
            ListView {
                // model of this listview is not occluded
            }
        }
        
        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #5

        @fcarney I actually have a Rectangle as the delegate for my outer list; I just removed it from my posted code.

        What does "injected model" mean exactly?

        Thanks...

        fcarneyF 1 Reply Last reply
        0
        • mzimmersM mzimmers

          @fcarney I actually have a Rectangle as the delegate for my outer list; I just removed it from my posted code.

          What does "injected model" mean exactly?

          Thanks...

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

          @mzimmers said in how to distinguish between multiple C++ models?:

          What does "injected model" mean exactly?

          The delegate gets the keyword "model" injected into its namespace doesn't it? So that the delegate can use the word "model" to refer to the model of the view?

          C++ is a perfectly valid school of magic.

          mzimmersM 1 Reply Last reply
          1
          • fcarneyF fcarney

            @mzimmers said in how to distinguish between multiple C++ models?:

            What does "injected model" mean exactly?

            The delegate gets the keyword "model" injected into its namespace doesn't it? So that the delegate can use the word "model" to refer to the model of the view?

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

            @fcarney OK, I see (just not really familiar with the term "injected" in Qt-land).

            I've made a couple changes:

            ListView {
                id: infoScreen
                model: zoneModel
                delegate: Rectangle {
                    id: zoneDelegate
            
                    Column {
                        Text {
                            text: "zone UUID: " + model.uuid
                        }
            
                        ListView {
                            id: equipmentList
                            model: zoneModel.getZone(1).equipmentList // ?? how to use index in getZone()?
                            delegate: Column {
                                id: equipmentDetails
                                anchors.fill: parent
                                Text {
                                    text: "equipment name: " + equipmentDetails.ListView.view.model
                                }
                            }
                        }
                    }
                }
            }
            

            This gets me the zone UUID in the inner ListView. Running it verifies the data is correct. Now, I need to use this UUID in a call to my equipment model in order to get the equipment details from the equipment list (via the equipment model).

            Maybe I'm trying to do too much in QML, and I should add a routine to my Zone model to retrieve a equipment item (the whole item, not just its UUID)?

            EDIT: OK, I got most of it working; the missing ingredient was modelData:

            ListView {
                id: equipmentList
                model: zoneModel.getZone(1).equipmentList
                delegate: Column {
                    Text {
                        text: "equipment name: " + equipmentModel.getItem(modelData).name()
                    }
                }
            }
            

            Now...how can I replace that "1" with something to represent the current index for that iteration through the model?

            J.HilkJ 1 Reply Last reply
            1
            • mzimmersM mzimmers

              @fcarney OK, I see (just not really familiar with the term "injected" in Qt-land).

              I've made a couple changes:

              ListView {
                  id: infoScreen
                  model: zoneModel
                  delegate: Rectangle {
                      id: zoneDelegate
              
                      Column {
                          Text {
                              text: "zone UUID: " + model.uuid
                          }
              
                          ListView {
                              id: equipmentList
                              model: zoneModel.getZone(1).equipmentList // ?? how to use index in getZone()?
                              delegate: Column {
                                  id: equipmentDetails
                                  anchors.fill: parent
                                  Text {
                                      text: "equipment name: " + equipmentDetails.ListView.view.model
                                  }
                              }
                          }
                      }
                  }
              }
              

              This gets me the zone UUID in the inner ListView. Running it verifies the data is correct. Now, I need to use this UUID in a call to my equipment model in order to get the equipment details from the equipment list (via the equipment model).

              Maybe I'm trying to do too much in QML, and I should add a routine to my Zone model to retrieve a equipment item (the whole item, not just its UUID)?

              EDIT: OK, I got most of it working; the missing ingredient was modelData:

              ListView {
                  id: equipmentList
                  model: zoneModel.getZone(1).equipmentList
                  delegate: Column {
                      Text {
                          text: "equipment name: " + equipmentModel.getItem(modelData).name()
                      }
                  }
              }
              

              Now...how can I replace that "1" with something to represent the current index for that iteration through the model?

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

              @mzimmers said in how to distinguish between multiple C++ models?:

              Now...how can I replace that "1" with something to represent the current index for that iteration through the model?

              via index literary :D !!!!
              The delegate gets a index property "injected" and you can access it. In your case. zoneDelegate should have access to it


              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
              • J.HilkJ J.Hilk

                @mzimmers said in how to distinguish between multiple C++ models?:

                Now...how can I replace that "1" with something to represent the current index for that iteration through the model?

                via index literary :D !!!!
                The delegate gets a index property "injected" and you can access it. In your case. zoneDelegate should have access to it

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

                @J-Hilk I guess I don't understand -- I tried this:

                ListView {
                    model: zoneModel
                    delegate: Rectangle {
                        id: zoneDelegate
                
                        Column {
                            Text {
                                text: "zoneDelegate.index: " + zoneDelegate.index // undefined
                            }
                
                            ListView {
                                model: zoneModel.getZone(zoneDelegate.index).equipmentList
                                delegate: Column {
                                    Text {
                                        text: "equipment uuid: " + equipmentModel.getItem(modelData).uuid()
                                    }
                                }
                            }
                        }
                    }
                }
                

                and zoneDelegate.index comes back as undefined.

                J.HilkJ 1 Reply Last reply
                0
                • mzimmersM mzimmers

                  @J-Hilk I guess I don't understand -- I tried this:

                  ListView {
                      model: zoneModel
                      delegate: Rectangle {
                          id: zoneDelegate
                  
                          Column {
                              Text {
                                  text: "zoneDelegate.index: " + zoneDelegate.index // undefined
                              }
                  
                              ListView {
                                  model: zoneModel.getZone(zoneDelegate.index).equipmentList
                                  delegate: Column {
                                      Text {
                                          text: "equipment uuid: " + equipmentModel.getItem(modelData).uuid()
                                      }
                                  }
                              }
                          }
                      }
                  }
                  

                  and zoneDelegate.index comes back as undefined.

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

                  @mzimmers yeah, thats not a property in the normal sense. You'll have to actually "store" it locally to access it out of the scope:

                  Window {
                      width: 640
                      height: 480
                      visible: true
                      title: qsTr("Hello World")
                  
                      ListView{
                          id:view1
                          anchors.fill: parent
                          model: 10
                          delegate: Item {
                              id:view1Delegate
                              property int indexPropagation: index
                              height: 50
                              width: 640
                              ListView {
                                  id:view2
                                  anchors.fill: parent
                                   model: ["Apples", "Bananas", "Oranges"]
                                   delegate: Label {
                                       height: contentHeight
                                       width: view2.width
                                       text: modelData + " " + view1Delegate.indexPropagation + " " + index
                                   }
                              }
                          }
                      }
                  }
                  

                  24f83b95-72c4-49b2-bb83-98d1b192ac75-image.png


                  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
                  • J.HilkJ J.Hilk

                    @mzimmers yeah, thats not a property in the normal sense. You'll have to actually "store" it locally to access it out of the scope:

                    Window {
                        width: 640
                        height: 480
                        visible: true
                        title: qsTr("Hello World")
                    
                        ListView{
                            id:view1
                            anchors.fill: parent
                            model: 10
                            delegate: Item {
                                id:view1Delegate
                                property int indexPropagation: index
                                height: 50
                                width: 640
                                ListView {
                                    id:view2
                                    anchors.fill: parent
                                     model: ["Apples", "Bananas", "Oranges"]
                                     delegate: Label {
                                         height: contentHeight
                                         width: view2.width
                                         text: modelData + " " + view1Delegate.indexPropagation + " " + index
                                     }
                                }
                            }
                        }
                    }
                    

                    24f83b95-72c4-49b2-bb83-98d1b192ac75-image.png

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

                    @J-Hilk partial success:

                    ListView {
                        model: zoneModel
                        delegate: Rectangle {
                            id: zoneDelegate
                            property int zoneIndex: index
                            Column {
                                Text {
                                    text: "zoneDelegate.index: " + zoneDelegate.zoneIndex // this works
                                }
                    
                                ListView { // something in this causes crash
                                    model: zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                                    delegate: Column {
                                        Text {
                                            text: "equipment uuid: " + equipmentModel.getItem(modelData).uuid()
                                        }
                                    }
                                }
                            }
                        }
                    }
                    

                    With this code, the app hangs for a few seconds then crashes (no reason given in console). I suspect the problem is in my use of that property in my model declaration:

                    model: zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                    
                    
                    J.HilkJ 1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @J-Hilk partial success:

                      ListView {
                          model: zoneModel
                          delegate: Rectangle {
                              id: zoneDelegate
                              property int zoneIndex: index
                              Column {
                                  Text {
                                      text: "zoneDelegate.index: " + zoneDelegate.zoneIndex // this works
                                  }
                      
                                  ListView { // something in this causes crash
                                      model: zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                                      delegate: Column {
                                          Text {
                                              text: "equipment uuid: " + equipmentModel.getItem(modelData).uuid()
                                          }
                                      }
                                  }
                              }
                          }
                      }
                      

                      With this code, the app hangs for a few seconds then crashes (no reason given in console). I suspect the problem is in my use of that property in my model declaration:

                      model: zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                      
                      
                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by J.Hilk
                      #12

                      @mzimmers make your getZone function so that it catches invalid indexes. I had it happen, that the value was negative for some reason. Didn't happen always but caused problems non the less


                      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 make your getZone function so that it catches invalid indexes. I had it happen, that the value was negative for some reason. Didn't happen always but caused problems non the less

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

                        @J-Hilk that’s easily enough done. What’s the cleanest way to make the model null if the index is bad?

                        EDIT:

                        This is kind of a hack, but here's my getZone():

                        Zone ZoneModel::getZone(int index)
                        {
                            Zone z = Zone(); // c'tor creates Zone with all empty elements
                            do {
                                if (index < 0) {
                                    qDebug() << "ZoneModel::getZone(): invalid index" << index << "requested.";
                                    continue;
                                }
                                if (m_list->size() <= index) {
                                    qDebug() << "ZoneModel::getZone(): requested index" << index << "exceeds list size.";
                                    continue;
                                }
                                z = m_list->getItem(index);
                            } while (false);
                            
                            return z;
                        }
                        

                        And my model check:

                        model: zoneModel.getZone(zoneDelegate.zoneIndex).name !== ""
                            ? zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                            : null
                        

                        If there's no better way to do this, I suppose I should add a "valid" flag to my Zone class. Set to false by default upon construction; set to true whenever a Zone is created anywhere but getZone(). Thoughts?

                        Thanks…

                        EDIT 2:

                        I decided I liked this better:

                        model: (zoneModel.listSize() > zoneDelegate.zoneIndex)
                            ? zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                            : null
                        

                        EDIT 3:

                        I like this even better:

                        model: (zoneDelegate.zoneIndex >= 0 && zoneModel.listSize() > zoneDelegate.zoneIndex)
                            ? zoneModel.getZone(zoneDelegate.zoneIndex).equipmentList
                            : null
                        

                        Anyway, enough fun and games. Unless someone sees a problem with this, I'll go ahead and consider it solved. Thanks to everyone who assisted.

                        1 Reply Last reply
                        1
                        • mzimmersM mzimmers has marked this topic as solved on
                        • mzimmersM mzimmers has marked this topic as unsolved on
                        • 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