Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.9.1
-
None
-
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
- is required for
-
QTBUG-50992 QQC2: Object destroyed during incubation
- Closed
For Gerrit Dashboard: QTBUG-63200 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
206197,4 | Fix execution of deferred properties | 5.9 | qt/qtdeclarative | Status: MERGED | -2 | 0 |