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

No way to set initial properties in QtQuick

    XMLWordPrintable

Details

    • All

    Description

      This bug/suggestion could also have been described as "QQmlComponent::setInitialProperties doesn't work" or "QQmlIncubator::setInitialProperties doesn't work". But the fundamental issue is that there's no way to set initial properties of items from C++ using QtQuick - it would be great if this turned out to be a wrong claim .

      TL;DR: The final section describes the workaround

      As far as I can tell, "initial properties" isn't defined in the documentation (e.g., QQmlIncubator says: "Called after the object is first created, but before property bindings are evaluated and, if applicable, QQmlParserStatus::componentComplete() is called. This is equivalent to the point between QQmlComponent::beginCreate() and QQmlComponent::completeCreate(), and can be used to assign initial values to the object's properties.")

      The words "evaluated" and "initial" aren't described, but I think a reasonable definition is one where a QML snippet defines properties that have values for which no notify signals are sent, e.g., in the following example, nobody would expect the "onValueChanged" function to be called:

      Item {
          property int value: 41
          onValueChanged: console.info("value was changed to " + value);
      }
      

      If the notify signal handler is called, there's really no difference between declaring the value and later assigning to it, vs providing an initial value. The former is unwanted, however, as it implies that initial values for properties cannot be relied on, but must be checked.

      Having property change handles invoked for properties that haven't changed, i.e., still have their initial value, has caused many problems, bugs, in our code, typically leading to complex crashes in V4 land, as side effects triggered by such state changes quickly end up in undefined territory. It's important for the integrity of QML that change notifications are not triggered during construction of items. If the value truly is its initial, first observable value, the change notification is, after all, useless.

      Attached are some examples, attempts, illustrating our problem .

      1. QML only. No valueChanged called. Good!
      2. QML only, using Loader's itemChanged. ValueChange called after completion. Good!
      3. C++ (qmake), using QQmlComponent::setInitialProperties. valueChanged called during creation. Bad!
      4. C++ (qmake), using QQmlComponent::begin/completeCreate APIs. valueChanged called during creation. Bad!
      5. C++ (qmake), using QQmlIncubator::setInitialProperties. valueChanged called during creation. Bad!
      6. C++ (qmake), using custom QQmlIncubator reimplementing setInitialState(). valueChanged called during creation. Bad!

      We have also seen this bug in ListView, where onFooChanged() is called due to role changes in delegates before the delegate has been completed.

      The workaround is always a variation around this:

      Item {
          property int value: 41
          property bool completed: false
          onValueChanged: {
              if (completed)
                  handleValueChange();
          }
          Component.onCompleted: {
              completed = true;
          }
      
          function handleValueChange() {
          }
      }
      

      Attachments

        Issue Links

          For Gerrit Dashboard: QTBUG-114403
          # Subject Branch Project Status CR V

          Activity

            People

              qtqmlteam Qt Qml Team User
              andrhans Andreas Aardal Hanssen
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There is 1 open Gerrit change