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. dealing with model polymorphism in QML
Forum Updated to NodeBB v4.3 + New Features

dealing with model polymorphism in QML

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

    Hi all -

    I have a (C++) model that implements a list of objects (actually pointers to objects, but that's probably not important here). The objects are of various subclasses, all inherited from the same parent. Super short example:

    enum Category {
        CATEGORY_UNKNOWN,
        CATEGORY_PUMP,
        CATEGORY_HEATER,
        ...
    }
    struct Equipment {
        QUuid m_uuid = QUuid();
        Category m_category = CATEGORY_UNKNOWN;
        ...
    }
    struct Pump : public Equipment {
        int horsepower;
        ...
    }
    

    And somewhere in the code, instances of Pump have their category changed to CATEGORY_PUMP.

    In QML, I have a GridView that uses the list as its model. My problem is how to implement a delegate that only attempts to do something with "horsepower" when the category is CATEGORY_PUMP?

    Thanks...

    B 1 Reply Last reply
    0
    • mzimmersM mzimmers

      @Bob64 interesting...another part of the QML world I'd never seen.

      It looks like it will work with a GridView instead of a TableView, so that's good news for me. If I want my DelegateChooser to use the category property of my struct, how do I code this?

      Here's a little more of my C++:

      struct Equipment {
          QUuid m_uuid = QUuid();
          Category m_category = CATEGORY_UNKNOWN;  // from an enum
          Q_PROPERTY (Category category MEMBER m_category)
      ...
      }
      struct Pump : public Equipment {
          int horsepower;
          ...
      }
      

      There's also a model that maintains a list of these.

      Here's the QML I tried, just a test:

      GridView {
          model: equipmentProxyModel
          DelegateChooser {
              role: "category"
              DelegateChoice { roleValue: 1; ItemDelegate { Rectangle { height: 20; width: 20; color: 'blue' }}}
          }
      ...
      

      It doesn't display the rectangle. It looks like I'm somehow missing a link between the "category" property in my struct, and the role that the DelegateChoice expects. Can you tell me what might be missing?

      Thanks...

      B Offline
      B Offline
      Bob64
      wrote on last edited by
      #4

      @mzimmers I am sorry - I have only used this feature once myself so I don't have a huge amount of experience of it. In my case, the role was assigned to a role name that I expose from my model. The documentation implies that alternatively one may specify the name of a property of the model. As I understand it, that is what you are doing, but I haven't tried that approach.

      1 Reply Last reply
      0
      • mzimmersM mzimmers

        Hi all -

        I have a (C++) model that implements a list of objects (actually pointers to objects, but that's probably not important here). The objects are of various subclasses, all inherited from the same parent. Super short example:

        enum Category {
            CATEGORY_UNKNOWN,
            CATEGORY_PUMP,
            CATEGORY_HEATER,
            ...
        }
        struct Equipment {
            QUuid m_uuid = QUuid();
            Category m_category = CATEGORY_UNKNOWN;
            ...
        }
        struct Pump : public Equipment {
            int horsepower;
            ...
        }
        

        And somewhere in the code, instances of Pump have their category changed to CATEGORY_PUMP.

        In QML, I have a GridView that uses the list as its model. My problem is how to implement a delegate that only attempts to do something with "horsepower" when the category is CATEGORY_PUMP?

        Thanks...

        B Offline
        B Offline
        Bob64
        wrote on last edited by
        #2

        @mzimmers it sounds like you might want to use a different delegate depending on the category of the current model item. I wonder if DelegateChooser would help you here.

        mzimmersM 1 Reply Last reply
        1
        • B Bob64

          @mzimmers it sounds like you might want to use a different delegate depending on the category of the current model item. I wonder if DelegateChooser would help you here.

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

          @Bob64 interesting...another part of the QML world I'd never seen.

          It looks like it will work with a GridView instead of a TableView, so that's good news for me. If I want my DelegateChooser to use the category property of my struct, how do I code this?

          Here's a little more of my C++:

          struct Equipment {
              QUuid m_uuid = QUuid();
              Category m_category = CATEGORY_UNKNOWN;  // from an enum
              Q_PROPERTY (Category category MEMBER m_category)
          ...
          }
          struct Pump : public Equipment {
              int horsepower;
              ...
          }
          

          There's also a model that maintains a list of these.

          Here's the QML I tried, just a test:

          GridView {
              model: equipmentProxyModel
              DelegateChooser {
                  role: "category"
                  DelegateChoice { roleValue: 1; ItemDelegate { Rectangle { height: 20; width: 20; color: 'blue' }}}
              }
          ...
          

          It doesn't display the rectangle. It looks like I'm somehow missing a link between the "category" property in my struct, and the role that the DelegateChoice expects. Can you tell me what might be missing?

          Thanks...

          B GrecKoG 2 Replies Last reply
          0
          • mzimmersM mzimmers

            @Bob64 interesting...another part of the QML world I'd never seen.

            It looks like it will work with a GridView instead of a TableView, so that's good news for me. If I want my DelegateChooser to use the category property of my struct, how do I code this?

            Here's a little more of my C++:

            struct Equipment {
                QUuid m_uuid = QUuid();
                Category m_category = CATEGORY_UNKNOWN;  // from an enum
                Q_PROPERTY (Category category MEMBER m_category)
            ...
            }
            struct Pump : public Equipment {
                int horsepower;
                ...
            }
            

            There's also a model that maintains a list of these.

            Here's the QML I tried, just a test:

            GridView {
                model: equipmentProxyModel
                DelegateChooser {
                    role: "category"
                    DelegateChoice { roleValue: 1; ItemDelegate { Rectangle { height: 20; width: 20; color: 'blue' }}}
                }
            ...
            

            It doesn't display the rectangle. It looks like I'm somehow missing a link between the "category" property in my struct, and the role that the DelegateChoice expects. Can you tell me what might be missing?

            Thanks...

            B Offline
            B Offline
            Bob64
            wrote on last edited by
            #4

            @mzimmers I am sorry - I have only used this feature once myself so I don't have a huge amount of experience of it. In my case, the role was assigned to a role name that I expose from my model. The documentation implies that alternatively one may specify the name of a property of the model. As I understand it, that is what you are doing, but I haven't tried that approach.

            1 Reply Last reply
            0
            • mzimmersM mzimmers

              @Bob64 interesting...another part of the QML world I'd never seen.

              It looks like it will work with a GridView instead of a TableView, so that's good news for me. If I want my DelegateChooser to use the category property of my struct, how do I code this?

              Here's a little more of my C++:

              struct Equipment {
                  QUuid m_uuid = QUuid();
                  Category m_category = CATEGORY_UNKNOWN;  // from an enum
                  Q_PROPERTY (Category category MEMBER m_category)
              ...
              }
              struct Pump : public Equipment {
                  int horsepower;
                  ...
              }
              

              There's also a model that maintains a list of these.

              Here's the QML I tried, just a test:

              GridView {
                  model: equipmentProxyModel
                  DelegateChooser {
                      role: "category"
                      DelegateChoice { roleValue: 1; ItemDelegate { Rectangle { height: 20; width: 20; color: 'blue' }}}
                  }
              ...
              

              It doesn't display the rectangle. It looks like I'm somehow missing a link between the "category" property in my struct, and the role that the DelegateChoice expects. Can you tell me what might be missing?

              Thanks...

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

              @mzimmers Why do you have a zero sized ItemDelegate wrapping your Rectangle?

              mzimmersM 2 Replies Last reply
              1
              • GrecKoG GrecKo

                @mzimmers Why do you have a zero sized ItemDelegate wrapping your Rectangle?

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by mzimmers
                #6
                This post is deleted!
                1 Reply Last reply
                0
                • mzimmersM mzimmers has marked this topic as solved on
                • GrecKoG GrecKo

                  @mzimmers Why do you have a zero sized ItemDelegate wrapping your Rectangle?

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

                  @GrecKo OK, I fixed that, and now it's working, but only for members of the base class:

                  GridView {
                      model: equipmentProxyModel
                      delegate: chooser
                      DelegateChooser {
                          id: chooser
                          role: "category"
                          DelegateChoice {
                              roleValue: EquipmentNS.CATEGORY_UNKNOWN;
                              ItemDelegate {
                                  height: 20
                                  width: 20
                                  Label { text: uuid }
                              }
                          }
                          DelegateChoice {
                              roleValue: EquipmentNS.CATEGORY_VSP;
                              ItemDelegate {
                                  height: 20
                                  width: 20
                                  Label { text: horsepower } // unrecognized.
                              }
                          }
                  

                  I understand why it's failing (the parent class doesn't have that member), but I'm not sure what to do about it. Is there a way to fix this in the QML, or do I need to refine my data()/setdata() functions in my model?

                  GrecKoG 1 Reply Last reply
                  0
                  • mzimmersM mzimmers

                    @GrecKo OK, I fixed that, and now it's working, but only for members of the base class:

                    GridView {
                        model: equipmentProxyModel
                        delegate: chooser
                        DelegateChooser {
                            id: chooser
                            role: "category"
                            DelegateChoice {
                                roleValue: EquipmentNS.CATEGORY_UNKNOWN;
                                ItemDelegate {
                                    height: 20
                                    width: 20
                                    Label { text: uuid }
                                }
                            }
                            DelegateChoice {
                                roleValue: EquipmentNS.CATEGORY_VSP;
                                ItemDelegate {
                                    height: 20
                                    width: 20
                                    Label { text: horsepower } // unrecognized.
                                }
                            }
                    

                    I understand why it's failing (the parent class doesn't have that member), but I'm not sure what to do about it. Is there a way to fix this in the QML, or do I need to refine my data()/setdata() functions in my model?

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

                    @mzimmers This doesn't have to do with classes. You are trying to access the roles of your model. Does your model has a "horsepower" role?

                    I guess what you want to do is provide an object role just returning a pointer. And then accessing properties of that object in the delegate.
                    Let's call it "equipment", you could then access the horsepower in the delegate with text: equipment.horsepower.

                    mzimmersM 1 Reply Last reply
                    1
                    • GrecKoG GrecKo

                      @mzimmers This doesn't have to do with classes. You are trying to access the roles of your model. Does your model has a "horsepower" role?

                      I guess what you want to do is provide an object role just returning a pointer. And then accessing properties of that object in the delegate.
                      Let's call it "equipment", you could then access the horsepower in the delegate with text: equipment.horsepower.

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

                      @GrecKo thanks for the suggestion. I already have a "completeObject" role which returns the entire object.

                      I realize this isn't a QML question, but in your opinion, is it better to keep all the roles and role processing in the model code, or should I build this into the subclasses? I was thinking of the latter, just to prevent the model code from becoming huge if nothing else, but I'm running into design problems with that approach. What do experienced model builders do in this situation?

                      Thanks...

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