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. Signaling to users of component that binding a property is not safe
QtWS25 Last Chance

Signaling to users of component that binding a property is not safe

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
10 Posts 4 Posters 2.8k Views
  • 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.
  • U Offline
    U Offline
    Uldall
    wrote on last edited by
    #1

    I found the following QML component here:

    import QtQuick 2.0
    
    Rectangle {
        id: myRect
        width: 100; height: 100
        color: "black"
    
        MouseArea {
            id: mouseArea
            anchors.fill: parent
            onClicked: myRect.state == 'clicked' ? myRect.state = "" : myRect.state = 'clicked';
        }
    
        states: [
            State {
                name: "clicked"
                PropertyChanges { target: myRect; color: "red" }
            }
        ]
    }
    

    Let's call it "MyRect.qml". Since MyRect overrides the state property, binding it to a property won't work:

    Item {
        id: root
    
        MyRect {
            id: inner
    
            state: root.state // not safe
        }
    }
    

    Assigning it will however work:

    Item {
        id: root
    
        onStateChanged: inner.state = root.state // safe
    
        MyRect {
            id: inner
        }
    }
    

    On the other hand both binding and assigning would be safe for the property width of MyRect.qml.

    How can a user of MyRect.qml know which properties are safe to bind and which are not without having to examine the source code?

    1 Reply Last reply
    0
    • ODБOïO Offline
      ODБOïO Offline
      ODБOï
      wrote on last edited by
      #2

      How can u say that this is 'safe ' ?? why ?

      Item {
      id: root

      onStateChanged: inner.state = root.state // safe
      
      MyRect {
          id: inner
      }
      

      }

      if MyRect.qml dont has same state names that 'root' how it can work ?

      U 1 Reply Last reply
      0
      • ODБOïO ODБOï

        How can u say that this is 'safe ' ?? why ?

        Item {
        id: root

        onStateChanged: inner.state = root.state // safe
        
        MyRect {
            id: inner
        }
        

        }

        if MyRect.qml dont has same state names that 'root' how it can work ?

        U Offline
        U Offline
        Uldall
        wrote on last edited by
        #3

        @LeLev For the purpose of the example, it is the case that, they are the same. This issue is not what the question is about.

        ODБOïO E 2 Replies Last reply
        0
        • U Uldall

          @LeLev For the purpose of the example, it is the case that, they are the same. This issue is not what the question is about.

          ODБOïO Offline
          ODБOïO Offline
          ODБOï
          wrote on last edited by
          #4
          This post is deleted!
          1 Reply Last reply
          0
          • U Uldall

            @LeLev For the purpose of the example, it is the case that, they are the same. This issue is not what the question is about.

            E Offline
            E Offline
            Eeli K
            wrote on last edited by
            #5

            @Uldall I can't find a way to do that except documentation. QML isn't good for "safe" programming, whatever that means. Even javascript itself isn't type safe or doesn't have "private" things (contra C++), and QML is built on top of it. It might, just might, be possible to do something inside C++ implementation of QML - in Component.onCompleted you could call a custom C++ function which checks as much as can be checked with the public part of the engine, but I don't know if it's possible to find bindings with it.

            U 1 Reply Last reply
            1
            • E Eeli K

              @Uldall I can't find a way to do that except documentation. QML isn't good for "safe" programming, whatever that means. Even javascript itself isn't type safe or doesn't have "private" things (contra C++), and QML is built on top of it. It might, just might, be possible to do something inside C++ implementation of QML - in Component.onCompleted you could call a custom C++ function which checks as much as can be checked with the public part of the engine, but I don't know if it's possible to find bindings with it.

              U Offline
              U Offline
              Uldall
              wrote on last edited by
              #6

              @Eeli-K That is the same conclusion that I have come to, i.e. that documentation is the only way of solving this. I hope that The Qt Company will look into fixing this issue at some point.

              E 2 Replies Last reply
              0
              • U Uldall

                @Eeli-K That is the same conclusion that I have come to, i.e. that documentation is the only way of solving this. I hope that The Qt Company will look into fixing this issue at some point.

                E Offline
                E Offline
                Eeli K
                wrote on last edited by
                #7

                @Uldall Other developers or the company may have different opinions on this; mine is that it's not an issue to be fixed. If you write all of the code you should know what you're doing, and if there's a reusable component made by one party and used by another it should be documented and/or the code should be available to read. Think about javascript (on which QML is based): there's no privacy nor type safety, you can do basically anything with any object if you want to, safety is about coding practices, documentation etc. Still there exist even large reusable libraries which work (relatively) as well as C++ libraries. Same thing with python.

                1 Reply Last reply
                3
                • U Uldall

                  @Eeli-K That is the same conclusion that I have come to, i.e. that documentation is the only way of solving this. I hope that The Qt Company will look into fixing this issue at some point.

                  E Offline
                  E Offline
                  Eeli K
                  wrote on last edited by
                  #8

                  @Uldall Just when I said what I said, KDAB published a blog post: https://www.kdab.com/new-qt-5-10-diagnostics-breaking-qml-bindings/

                  1 Reply Last reply
                  2
                  • johngodJ Offline
                    johngodJ Offline
                    johngod
                    wrote on last edited by johngod
                    #9

                    The first example from @Uldall does work for me, it seems pretty safe, the following snippet shows that changing the state from root affects inner. Please mark this tread has solved if your doubts have been cleared.

                    Item {
                            id: root
                    
                            MyRect {
                                id: inner
                                state: root.state // yes it's safe, but this binding will be broke from inner state assignement
                            }
                    
                            MouseArea {
                                anchors.top: inner.bottom
                                anchors.bottom: parent.bottom
                                anchors.left: parent.left
                                anchors.right: parent.right
                                onClicked: root.state == 'clicked' ? root.state = "" : root.state = 'clicked';
                            }
                        }
                    

                    @Eeli-K nice reading from Kdab. For the sake of completeness it should be noted that if someone on purpose breaks the bindings, it can be defined again from a javascript block http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html#creating-property-bindings-from-javascript

                    1 Reply Last reply
                    0
                    • johngodJ Offline
                      johngodJ Offline
                      johngod
                      wrote on last edited by
                      #10

                      Also please note that while it is not possible directly to change the state from both root and inner without breaking the bindind, in this particular case you can get away with a hack using a intermediate property isClicked:

                      Rectangle {
                      id: myRect
                      width: 100; height: 100
                      color: "black"
                      
                      property bool isClicked: true
                      state: isClicked ? "clicked" : ""
                      
                      MouseArea {
                          id: mouseArea
                          anchors.fill: parent
                          onClicked: {
                              console.log("click from inner")
                              isClicked = !isClicked
                          }
                      }
                      
                      states: [
                          State {
                              name: "clicked"
                              PropertyChanges { target: myRect; color: "red" }
                          }
                        ]
                      }
                      

                      ´

                      Item {
                          id: root
                          anchors.fill: parent
                      
                          MyRect {
                              id: inner
                              
                          }
                      
                          MouseArea {
                              anchors.top: inner.bottom
                              anchors.bottom: parent.bottom
                              anchors.left: parent.left
                              anchors.right: parent.right
                      
                              onClicked: {
                                  console.log("click from root")
                                  inner.isClicked = !inner.isClicked
                              }
                          }
                      }
                      
                      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