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

how to distinguish between multiple C++ models?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
13 Posts 4 Posters 1.0k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    I'm trying to code a list within a list, that draws upon two models (both defined in C++). I'm having trouble figuring out how to distinguish between the models in my inner list. How can I identify which model I want to use here?

    This is a simplified example; my real code is a bit more elaborate. Thanks...

    // C++
    typedef QList<QUuid> ZoneEquipmentList;
    class Zone {
        Q_GADGET
        ZoneEquipmentList m_equipmentList;
    public:
        Q_PROPERTY(ZoneEquipmentList equipmentList MEMBER m_equipmentList)
        ZoneEquipmentList equipmentList() const { return m_equipmentList; }
    ...
    }
    // QML
    ListView {
        id: infoScreen
        model: zoneModel // defined by me
        delegate: Rectangle {
            id: infoDelegate
            Column {
                Text {
                    text: "zone ID is " + model.uuid
                }
    
                ListView {
                    model: zoneModel.getZone(model.equipmentList)
                    delegate: Column {
                        Text {
                            text: // how to distinguish between models here?
                        }
                    }
                }
            }
        }
    }
    
    
    
    sierdzioS 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
      • mzimmersM mzimmers

        Hi all -

        I'm trying to code a list within a list, that draws upon two models (both defined in C++). I'm having trouble figuring out how to distinguish between the models in my inner list. How can I identify which model I want to use here?

        This is a simplified example; my real code is a bit more elaborate. Thanks...

        // C++
        typedef QList<QUuid> ZoneEquipmentList;
        class Zone {
            Q_GADGET
            ZoneEquipmentList m_equipmentList;
        public:
            Q_PROPERTY(ZoneEquipmentList equipmentList MEMBER m_equipmentList)
            ZoneEquipmentList equipmentList() const { return m_equipmentList; }
        ...
        }
        // QML
        ListView {
            id: infoScreen
            model: zoneModel // defined by me
            delegate: Rectangle {
                id: infoDelegate
                Column {
                    Text {
                        text: "zone ID is " + model.uuid
                    }
        
                    ListView {
                        model: zoneModel.getZone(model.equipmentList)
                        delegate: Column {
                            Text {
                                text: // how to distinguish between models here?
                            }
                        }
                    }
                }
            }
        }
        
        
        
        sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #2

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

        (Z(:^

        mzimmersM 1 Reply Last reply
        1
        • 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