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 bind a delegate item property to top-level property
Forum Updated to NodeBB v4.3 + New Features

How to bind a delegate item property to top-level property

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
13 Posts 5 Posters 1.8k 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.
  • J Offline
    J Offline
    jbrend
    wrote on last edited by
    #3

    The issues qmllint has caught are very valid and result from referencing an outer-level variable that could be (though not in this case) defined in another file. As I understand it, Qt recommends against this given the potential for runtime type mismatches that may be external in nature. This would also prevent the QML compiler from compiling such code.

    In many cases, this problem can be alleviated using a chain of required properties. However, I can find no way of "tunnelling" a property binding through a delegate using that approach.

    1 Reply Last reply
    0
    • B Offline
      B Offline
      Bob64
      wrote on last edited by
      #4

      OK, sorry, it looks like I did not read your original message carefully enough. Nevertheless, I still don 't see why this is a problem. root seems pretty unambiguous in the scope hierarchy.

      J.HilkJ 1 Reply Last reply
      0
      • B Bob64

        OK, sorry, it looks like I did not read your original message carefully enough. Nevertheless, I still don 't see why this is a problem. root seems pretty unambiguous in the scope hierarchy.

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

        @Bob64 said in How to bind a delegate item property to top-level property:

        OK, sorry, it looks like I did not read your original message carefully enough. Nevertheless, I still don 't see why this is a problem. root seems pretty unambiguous in the scope hierarchy.

        technically yes, but if the shown file would not have an Element with the id:root, qml actually traverses the the parents/child tree upwards, until your very own main.qml file or until it finds an item with the id:root

        I ran into this, very hard and confusing to debug.


        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.

        B 1 Reply Last reply
        0
        • J.HilkJ J.Hilk

          @Bob64 said in How to bind a delegate item property to top-level property:

          OK, sorry, it looks like I did not read your original message carefully enough. Nevertheless, I still don 't see why this is a problem. root seems pretty unambiguous in the scope hierarchy.

          technically yes, but if the shown file would not have an Element with the id:root, qml actually traverses the the parents/child tree upwards, until your very own main.qml file or until it finds an item with the id:root

          I ran into this, very hard and confusing to debug.

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

          @J-Hilk I feel that I am still missing something.

          "... if the shown file would not have an Element with the id:root ..."

          Yes, I can understand why a warning would be shown in that case, but in this case it does have an element with id root, so why warn about it? Does qmllint not take any account of the context?

          1 Reply Last reply
          0
          • S Offline
            S Offline
            supa5000
            wrote on last edited by supa5000
            #7

            In at least my case i get rid of the warning with kind of nonsense declaration:

                        delegate: Text {
                            id: txt
                            readonly property var root: root
                            text: root.num.toString()
                        }
            
            

            EDIT: BUT BEWARE! As @jbrend wrote later - and i noticed later - this does not work in real application; the qmllint is happy but the real application does not work! Is no solution!

            J 1 Reply Last reply
            0
            • S supa5000

              In at least my case i get rid of the warning with kind of nonsense declaration:

                          delegate: Text {
                              id: txt
                              readonly property var root: root
                              text: root.num.toString()
                          }
              
              

              EDIT: BUT BEWARE! As @jbrend wrote later - and i noticed later - this does not work in real application; the qmllint is happy but the real application does not work! Is no solution!

              J Offline
              J Offline
              jbrend
              wrote on last edited by
              #8

              @supa5000 I tried your solution using Qt 6.3.0 (released), but I get the following qmllint warning:

              $ qmllint --compiler warning main.qml
              
              Warning: main.qml:24:28: Could not compile binding for text: Cannot load property num from QVariant of ??::root with type QVariant.
                              text: root.num.toString()
                                         ^^^
              

              If I just run the file using qml, I get the following output to the console. The app window shows, but the Text items are not visible.

              $ qml main.qml
              file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
              file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
              file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
              file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
              file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
              file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
              file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
              file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
              file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
              file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
              

              If I use the type of the root item (Rectangle instead of var), I get a similar but expanded warning:

              $ qmllint --compiler warning main.qml
              Warning: main.qml:24:28: Property "num" not found on type "QQuickRectangle"
                              text: root.num.toString()
                                         ^^^
              Warning: main.qml:24:28: Could not compile binding for text: Cannot load property num from QQuickRectangle of ??::root with type QQuickRectangle.
                              text: root.num.toString()
                                         ^^^
              

              The warning about QuickRectangle not having a num property makes sense, since my subclassed version derived from it has the property.

              In order to create compilable QML, I think we are supposed to be getting away from relying on the old context-based resolution mechanisms and also away from using var (QVariant) as a type, but I don't know what we are supposed to be doing in such a case from within a delegate.

              Does anyone have any updated information?

              S 1 Reply Last reply
              0
              • J jbrend

                @supa5000 I tried your solution using Qt 6.3.0 (released), but I get the following qmllint warning:

                $ qmllint --compiler warning main.qml
                
                Warning: main.qml:24:28: Could not compile binding for text: Cannot load property num from QVariant of ??::root with type QVariant.
                                text: root.num.toString()
                                           ^^^
                

                If I just run the file using qml, I get the following output to the console. The app window shows, but the Text items are not visible.

                $ qml main.qml
                file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
                file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
                file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
                file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
                file:///srv/tests/qt/TunnelProp/main.qml:21:23: QML QQuickText*: Binding loop detected for property "root"
                file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
                file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
                file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
                file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
                file:///srv/tests/qt/TunnelProp/main.qml:24: TypeError: Cannot read property 'num' of undefined
                

                If I use the type of the root item (Rectangle instead of var), I get a similar but expanded warning:

                $ qmllint --compiler warning main.qml
                Warning: main.qml:24:28: Property "num" not found on type "QQuickRectangle"
                                text: root.num.toString()
                                           ^^^
                Warning: main.qml:24:28: Could not compile binding for text: Cannot load property num from QQuickRectangle of ??::root with type QQuickRectangle.
                                text: root.num.toString()
                                           ^^^
                

                The warning about QuickRectangle not having a num property makes sense, since my subclassed version derived from it has the property.

                In order to create compilable QML, I think we are supposed to be getting away from relying on the old context-based resolution mechanisms and also away from using var (QVariant) as a type, but I don't know what we are supposed to be doing in such a case from within a delegate.

                Does anyone have any updated information?

                S Offline
                S Offline
                supa5000
                wrote on last edited by supa5000
                #9

                @jbrend My bad, you are right. It did pass qmllint and our test-cases - but indeed as you wrote, it does not work.

                i will edit my old answear to include warning that dont do this.

                No doing it like

                                readonly property var rootLoop: root
                                text: rootLoop.num.toString()
                

                makes the main application to work again, but guess what qmllint says: Unqualified access (on the 'root') part ..

                S 1 Reply Last reply
                0
                • S supa5000

                  @jbrend My bad, you are right. It did pass qmllint and our test-cases - but indeed as you wrote, it does not work.

                  i will edit my old answear to include warning that dont do this.

                  No doing it like

                                  readonly property var rootLoop: root
                                  text: rootLoop.num.toString()
                  

                  makes the main application to work again, but guess what qmllint says: Unqualified access (on the 'root') part ..

                  S Offline
                  S Offline
                  supa5000
                  wrote on last edited by
                  #10

                  I am keeping monologue here but another way to fix this is by "injecting" the upper scope variables via modelData;

                      function packItems(namespace, dataArray) {
                          var ret = [];
                          for (var loop = 0; loop < dataArray.length; loop++) {
                              ret.push([namespace, dataArray[loop]]);
                          }
                          return ret;
                      }
                  

                  And then inject:

                     Repeater:
                       model: packItems( {"root":root }, myDataArray ) 
                           delegate: Text {
                                  id: txt
                                  required property var modelData
                                  readonly property rootLoop: modelData[0]["root"]
                  

                  This is fishy at most, but works and passes the qml lint; i kind of feel like ill doing this; in my case i need the upper level component information for:

                  • delegate item calls root.signalEmitFunction -- when certain button of the delegate item is clicked
                  • delegete item width depends on upper level item width
                  • delegate item position depends on upper level item properties (slider tickmark labels position to be precise)
                  • delegate item gives focus to upper level when released (i guess focus-manager or whatever could do this also)
                  J 1 Reply Last reply
                  0
                  • GrecKoG Offline
                    GrecKoG Offline
                    GrecKo
                    Qt Champions 2018
                    wrote on last edited by GrecKo
                    #11

                    Your packItems could be written like that instead: return dataArray.map(data => {data: data, namespace: namespace});

                    and used like so : readonly property QtObject rootLoop: modelData.namespace.root

                    J 1 Reply Last reply
                    0
                    • S supa5000

                      I am keeping monologue here but another way to fix this is by "injecting" the upper scope variables via modelData;

                          function packItems(namespace, dataArray) {
                              var ret = [];
                              for (var loop = 0; loop < dataArray.length; loop++) {
                                  ret.push([namespace, dataArray[loop]]);
                              }
                              return ret;
                          }
                      

                      And then inject:

                         Repeater:
                           model: packItems( {"root":root }, myDataArray ) 
                               delegate: Text {
                                      id: txt
                                      required property var modelData
                                      readonly property rootLoop: modelData[0]["root"]
                      

                      This is fishy at most, but works and passes the qml lint; i kind of feel like ill doing this; in my case i need the upper level component information for:

                      • delegate item calls root.signalEmitFunction -- when certain button of the delegate item is clicked
                      • delegete item width depends on upper level item width
                      • delegate item position depends on upper level item properties (slider tickmark labels position to be precise)
                      • delegate item gives focus to upper level when released (i guess focus-manager or whatever could do this also)
                      J Offline
                      J Offline
                      jbrend
                      wrote on last edited by
                      #12

                      @supa5000 Great idea and thanks for sharing it!

                      I'm going to leave this item open for now in case there might be more ideas on how to solve this problem.

                      1 Reply Last reply
                      0
                      • GrecKoG GrecKo

                        Your packItems could be written like that instead: return dataArray.map(data => {data: data, namespace: namespace});

                        and used like so : readonly property QtObject rootLoop: modelData.namespace.root

                        J Offline
                        J Offline
                        jbrend
                        wrote on last edited by
                        #13

                        @GrecKo Thank you for this syntax suggestion!

                        1 Reply Last reply
                        0

                        • Login

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