Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-102779

Allow detaching of value types when writing to a QML-defined property

    XMLWordPrintable

Details

    Description

      When using a DragHandler I wrote something like this :

      Item {
          id: root
      
          property bool allowRotations: true;
      
          signal translate(vector2d screenSpaceDelta);
      
          // Translation handler
          DragHandler{
              target: null
              acceptedButtons: allowRotations ? Qt.MiddleButton: Qt.LeftButton
      
              property var lastTranslation: null
      
              onActiveChanged: {
                  console.log(`onActiveChanged(${active})`)
                  if(active) {
                      console.log("Reset lastTranslation")
                      lastTranslation = null
                  }
              }
      
              onActiveTranslationChanged: {
                  console.log(`Before: activeTranslation = ${activeTranslation}, lastTranslation = ${lastTranslation}`)
                  if (lastTranslation !== null) {
                      let delta = activeTranslation.minus(lastTranslation)
                      root.translate(delta)
                  }
                  lastTranslation = activeTranslation
                  console.log(`After: activeTranslation = ${activeTranslation}, lastTranslation = ${lastTranslation}`)
              }
          }
      }
      

      This code would produce logs such as this one:

      qml: onActiveChanged(true)
      qml: Reset lastTranslation
      qml: Before: activeTranslation = QVector2D(10, -2), lastTranslation = null
      qml: After: activeTranslation = QVector2D(10, -2), lastTranslation = null
      qml: Before: activeTranslation = QVector2D(11, -2), lastTranslation = QVector2D(11, -2)
      qml:   => Listener got translate delta: QVector2D(0, 0)
      qml: After: activeTranslation = QVector2D(11, -2), lastTranslation = QVector2D(11, -2)
      qml: Before: activeTranslation = QVector2D(11, -3), lastTranslation = QVector2D(11, -3)
      qml:   => Listener got translate delta: QVector2D(0, 0)
      qml: After: activeTranslation = QVector2D(11, -3), lastTranslation = QVector2D(11, -3)
      qml: onActiveChanged(false)
      

      As you can see, there is something really strange going on: lastTranslation seems to be assigned... before it is assigned!

      I finally came up with a possible explanation to this; does the lastTranslation property returns a pointer internally, to a single QVector3 that would be reused over time? If there exists actually only one value of QVector2D aliased by both variables this would explain the observed behaviour.

      The documentation kind of hints that it might be the case, but not clearly:

      The translation while the drag gesture is being performed. It is 0, 0 when the gesture begins, and increases as the event point(s) are dragged downward and to the right. After the gesture ends, it stays the same; and when the next drag gesture begins, it is reset to 0, 0 again.

      It seems a reasonable assumption to me that vectors should be values, not references. Having DragHandler modify the values that it returned previously in an uncontrolled fashion when user code may have stored that value without suspecting is a very unexpected behaviour to me. Is this common practice in the Qt APIs?

      If this behaviour is an exception, I suggest that is is changed in such a way that DragHandler instantiates new vectors every time, or to document this aliasing and reuse of QVector2D in the type documentation. If this is common practice, please let me know how I can learn more about the places where aliasing occurs in the API?

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qtqmlteam Qt Qml Team User
            graslany Yves Grasland
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes