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

Deferred properties are not always executed

    XMLWordPrintable

    Details

    • Commits:
      3b6eeee177b64eebe240d51be0c7bb5f031471d8

      Description

      Deferred properties are executed only in the "outermost" context. If a QML type has multiple deferred properties assigned on different levels / in different context, only the last context with deferred properties is executed, and the others are ignored.

      Consider a QML type with multiple deferred properties:

      #include <QtQml>
      
      class DeferredType : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QObject *object MEMBER m_obj)
          Q_PROPERTY(QQmlListProperty<QObject> list READ list)
          Q_CLASSINFO("DeferredPropertyNames", "list,object")
          Q_CLASSINFO("DefaultProperty", "list")
      
      public:
          DeferredType(QObject *parent = nullptr) : QObject(parent) { }
      
          QQmlListProperty<QObject> list()
          {
              return QQmlListProperty<QObject>(this, m_list);
          }
      
          void print(const QString &type, const QString &props)
          {
              qDebug().noquote() << type << props;
              qDebug() << "\tlist:" << m_list << "\n\tobj:" << m_obj;
          }
      
      private:
          QObjectList m_list;
          QObject *m_obj = nullptr;
      };
      
      static DeferredType* executeDeferred(const QString &qml)
      {
          QQmlEngine engine;
          QQmlComponent component(&engine);
          component.setData(qml.toUtf8(), QUrl());
          DeferredType *object = static_cast<DeferredType *>(component.create());
          qmlExecuteDeferred(object);
          return object;
      }
      
      static void testDeferredType(const QString &type)
      {
          executeDeferred(QString("import QtQml 2.0; import DeferredType 1.0; %1 { }").arg(type))->print(type, "");
          executeDeferred(QString("import QtQml 2.0; import DeferredType 1.0; %1 { QtObject { objectName: 'mylist' } }").arg(type))->print(type, "+ mylist");
          executeDeferred(QString("import QtQml 2.0; import DeferredType 1.0; %1 { object: QtObject { objectName: 'myobject' } }").arg(type))->print(type, "+ myobject");
          executeDeferred(QString("import QtQml 2.0; import DeferredType 1.0; %1 { QtObject { objectName: 'mylist' } object: QtObject { objectName: 'myobject' } }").arg(type))->print(type, "+ mylist + myobject");
      }
      
      int main(int argc, char *argv[])
      {
          QCoreApplication app(argc, argv);
      
          qmlRegisterType<DeferredType>("DeferredType", 1, 0, "EmptyDeferredType");
          qmlRegisterType(QUrl("qrc:/DeferredTypeWithList.qml"), "DeferredType", 1, 0, "DeferredTypeWithList");
          qmlRegisterType(QUrl("qrc:/DeferredTypeWithObject.qml"), "DeferredType", 1, 0, "DeferredTypeWithObject");
          qmlRegisterType(QUrl("qrc:/DeferredTypeWithListAndObject.qml"), "DeferredType", 1, 0, "DeferredTypeWithListAndObject");
      
          testDeferredType("EmptyDeferredType");
          testDeferredType("DeferredTypeWithList");
          testDeferredType("DeferredTypeWithObject");
          testDeferredType("DeferredTypeWithListAndObject");
      }
      
      #include "main.moc"
      

      DeferredTypeWithList.qml:

      import QtQml 2.0
      import DeferredType 1.0
      
      EmptyDeferredType {
          QtObject {
              objectName: "list"
          }
      }
      

      DeferredTypeWithObject.qml:

      import QtQml 2.0
      import DeferredType 1.0
      
      EmptyDeferredType {
          object: QtObject {
              objectName: "object"
          }
      }
      

      DeferredTypeWithListAndObject.qml:

      import QtQml 2.0
      import DeferredType 1.0
      
      EmptyDeferredType {
          QtObject {
              objectName: "list"
          }
          object: QtObject {
              objectName: "object"
          }
      }
      

      In the debug output one can see that a type that has a default object or default list property content defined in .qml, gets ignored when either of the deferred properties is overridden in QML.

      EmptyDeferredType 
      	list: () 
      	obj: QObject(0x0)
      EmptyDeferredType + mylist
      	list: (QObject(0x949090, name = "mylist")) 
      	obj: QObject(0x0)
      EmptyDeferredType + myobject
      	list: () 
      	obj: QObject(0x949680, name = "myobject")
      EmptyDeferredType + mylist + myobject
      	list: (QObject(0x949f00, name = "mylist")) 
      	obj: QObject(0x949d10, name = "myobject")
      DeferredTypeWithList 
      	list: (QObject(0x94a550, name = "list")) 
      	obj: QObject(0x0)
      DeferredTypeWithList + mylist
      	list: (QObject(0x94ad50, name = "mylist")) 
      	obj: QObject(0x0)
      DeferredTypeWithList + myobject
      	list: () 					<=== !!!
      	obj: QObject(0x94b3f0, name = "myobject")
      DeferredTypeWithList + mylist + myobject
      	list: (QObject(0x94bd40, name = "mylist")) 
      	obj: QObject(0x94bb80, name = "myobject")
      DeferredTypeWithObject 
      	list: () 
      	obj: QObject(0x94c0e0, name = "object")
      DeferredTypeWithObject + mylist
      	list: (QObject(0x94c8d0, name = "mylist")) 
      	obj: QObject(0x0)				<=== !!!
      DeferredTypeWithObject + myobject
      	list: () 
      	obj: QObject(0x94d080, name = "myobject")
      DeferredTypeWithObject + mylist + myobject
      	list: (QObject(0x94d880, name = "mylist")) 
      	obj: QObject(0x94d6c0, name = "myobject")
      DeferredTypeWithListAndObject 
      	list: (QObject(0x94df30, name = "list")) 
      	obj: QObject(0x94dd50, name = "object")
      DeferredTypeWithListAndObject + mylist
      	list: (QObject(0x94e6c0, name = "mylist")) 
      	obj: QObject(0x0)				<=== !!!
      DeferredTypeWithListAndObject + myobject
      	list: () 					<=== !!!
      	obj: QObject(0x94ee10, name = "myobject")
      DeferredTypeWithListAndObject + mylist + myobject
      	list: (QObject(0x94f730, name = "mylist")) 
      	obj: QObject(0x94f5b0, name = "myobject")
      

        Attachments

          Issue Links

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

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              jpnurmi J-P Nurmi
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Gerrit Reviews

                  There are no open Gerrit changes