diff options
| -rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 4 | ||||
| -rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 2 | ||||
| -rw-r--r-- | src/qml/qml/qqmlincubator.cpp | 4 | ||||
| -rw-r--r-- | src/qml/qml/qqmlincubator_p.h | 2 | ||||
| -rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 24 | ||||
| -rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 8 | ||||
| -rw-r--r-- | src/qmlmodels/qqmldelegatemodel.cpp | 2 | ||||
| -rw-r--r-- | src/quick/items/qquicklistview.cpp | 2 | ||||
| -rw-r--r-- | tests/auto/quick/qquicklistview2/data/innerRequired.qml | 33 | ||||
| -rw-r--r-- | tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp | 22 | ||||
| -rw-r--r-- | tests/auto/quick/qquickrepeater/data/innerRequired.qml | 33 | ||||
| -rw-r--r-- | tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp | 22 |
12 files changed, 138 insertions, 20 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 41af4ed67b..26a7b9afbf 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -349,9 +349,9 @@ RequiredProperties &QQmlComponentPrivate::requiredProperties() return state.creator->requiredProperties(); } -bool QQmlComponentPrivate::hadRequiredProperties() const +bool QQmlComponentPrivate::hadTopLevelRequiredProperties() const { - return state.creator->componentHadRequiredProperties(); + return state.creator->componentHadTopLevelRequiredProperties(); } void QQmlComponentPrivate::clear() diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 26f275f861..55330c6837 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -108,7 +108,7 @@ public: int start; RequiredProperties& requiredProperties(); - bool hadRequiredProperties() const; + bool hadTopLevelRequiredProperties() const; QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; struct ConstructionState { diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 5a3fd2a1f4..52d9fe07ed 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -696,9 +696,9 @@ RequiredProperties &QQmlIncubatorPrivate::requiredProperties() return creator->requiredProperties(); } -bool QQmlIncubatorPrivate::hadRequiredProperties() const +bool QQmlIncubatorPrivate::hadTopLevelRequiredProperties() const { - return creator->componentHadRequiredProperties(); + return creator->componentHadTopLevelRequiredProperties(); } /*! diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h index b178c6aa29..0d91e63f17 100644 --- a/src/qml/qml/qqmlincubator_p.h +++ b/src/qml/qml/qqmlincubator_p.h @@ -106,7 +106,7 @@ public: void forceCompletion(QQmlInstantiationInterrupt &i); void incubate(QQmlInstantiationInterrupt &i); RequiredProperties &requiredProperties(); - bool hadRequiredProperties() const; + bool hadTopLevelRequiredProperties() const; }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index b1bedc7c37..f3af43577d 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -82,6 +82,7 @@ QQmlObjectCreator::QQmlObjectCreator( , propertyCaches(&compilationUnit->propertyCaches) , sharedState(new QQmlObjectCreatorSharedState, QQmlRefPointer<QQmlObjectCreatorSharedState>::Adopt) , topLevelCreator(true) + , isContextObject(true) , incubator(incubator) { init(std::move(parentContext)); @@ -93,7 +94,7 @@ QQmlObjectCreator::QQmlObjectCreator( sharedState->allJavaScriptObjects = nullptr; sharedState->creationContext = creationContext; sharedState->rootContext.reset(); - sharedState->hadRequiredProperties = false; + sharedState->hadTopLevelRequiredProperties = false; if (auto profiler = QQmlEnginePrivate::get(engine)->profiler) { Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, @@ -103,15 +104,15 @@ QQmlObjectCreator::QQmlObjectCreator( } } -QQmlObjectCreator::QQmlObjectCreator( - QQmlRefPointer<QQmlContextData> parentContext, +QQmlObjectCreator::QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, - QQmlObjectCreatorSharedState *inheritedSharedState) + QQmlObjectCreatorSharedState *inheritedSharedState, bool isContextObject) : phase(Startup) , compilationUnit(compilationUnit) , propertyCaches(&compilationUnit->propertyCaches) , sharedState(inheritedSharedState) , topLevelCreator(false) + , isContextObject(isContextObject) , incubator(nullptr) { init(std::move(parentContext)); @@ -1249,7 +1250,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } if (!type.isInlineComponentType()) { - QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data()); + QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data(), + isContextObject); instance = subCreator.create(); if (!instance) { errors += subCreator.errors; @@ -1258,7 +1260,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } else { int subObjectId = type.inlineComponentId(); QScopedValueRollback<int> rollback {compilationUnit->icRoot, subObjectId}; - QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data()); + QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data(), + isContextObject); instance = subCreator.create(subObjectId, nullptr, nullptr, CreationFlags::InlineComponent); if (!instance) { errors += subCreator.errors; @@ -1559,7 +1562,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * continue; if (postHocIt != postHocRequired.end()) postHocRequired.erase(postHocIt); - sharedState->hadRequiredProperties = true; + if (isContextObject) + sharedState->hadTopLevelRequiredProperties = true; sharedState->requiredProperties.insert(propertyData, RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}}); @@ -1617,7 +1621,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * if (postHocIt != postHocRequired.end()) postHocRequired.erase(postHocIt); - sharedState->hadRequiredProperties = true; + if (isContextObject) + sharedState->hadTopLevelRequiredProperties = true; sharedState->requiredProperties.insert( propertyData, RequiredPropertyInfo { @@ -1647,7 +1652,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * continue; postHocRequired.erase(postHocIt); - sharedState->hadRequiredProperties = true; + if (isContextObject) + sharedState->hadTopLevelRequiredProperties = true; sharedState->requiredProperties.insert( propertyData, RequiredPropertyInfo { diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 194a071d95..3e036c0970 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -111,7 +111,7 @@ struct QQmlObjectCreatorSharedState : QQmlRefCount QRecursionNode recursionNode; RequiredProperties requiredProperties; QList<DeferredQPropertyBinding> allQPropertyBindings; - bool hadRequiredProperties; + bool hadTopLevelRequiredProperties; }; class Q_QML_PRIVATE_EXPORT QQmlObjectCreator @@ -150,7 +150,7 @@ public: QFiniteStack<QQmlGuard<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; } RequiredProperties &requiredProperties() {return sharedState->requiredProperties;} - bool componentHadRequiredProperties() const {return sharedState->hadRequiredProperties;} + bool componentHadTopLevelRequiredProperties() const {return sharedState->hadTopLevelRequiredProperties;} static QQmlComponent *createComponent(QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit, @@ -160,7 +160,8 @@ public: private: QQmlObjectCreator(QQmlRefPointer<QQmlContextData> contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, - QQmlObjectCreatorSharedState *inheritedSharedState); + QQmlObjectCreatorSharedState *inheritedSharedState, + bool isContextObject); void init(QQmlRefPointer<QQmlContextData> parentContext); @@ -218,6 +219,7 @@ private: const QQmlPropertyCacheVector *propertyCaches; QQmlRefPointer<QQmlObjectCreatorSharedState> sharedState; bool topLevelCreator; + bool isContextObject; QQmlIncubatorPrivate *incubator; QObject *_qobject; diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 0c763a71be..8ecbadc262 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -961,7 +961,7 @@ static void bindingFunction( void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *modelItemToIncubate, QObject *object) { auto incubatorPriv = QQmlIncubatorPrivate::get(this); - if (incubatorPriv->hadRequiredProperties()) { + if (incubatorPriv->hadTopLevelRequiredProperties()) { QQmlData *d = QQmlData::get(object); auto contextData = d ? d->context : nullptr; if (contextData) { diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 7ddda6196f..cf5d6e02ae 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -1102,7 +1102,7 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString §ion) QQmlComponentPrivate* delegatePriv = QQmlComponentPrivate::get(delegate); QObject *nobj = delegate->beginCreate(context); if (nobj) { - if (delegatePriv->hadRequiredProperties()) { + if (delegatePriv->hadTopLevelRequiredProperties()) { delegate->setInitialProperties(nobj, {{QLatin1String("section"), section}}); } else { context->setContextProperty(QLatin1String("section"), section); diff --git a/tests/auto/quick/qquicklistview2/data/innerRequired.qml b/tests/auto/quick/qquicklistview2/data/innerRequired.qml new file mode 100644 index 0000000000..b45181c0d2 --- /dev/null +++ b/tests/auto/quick/qquicklistview2/data/innerRequired.qml @@ -0,0 +1,33 @@ +import QtQuick + +Item { + ListModel { + id: myModel + ListElement { type: "Dog"; age: 8; noise: "meow" } + ListElement { type: "Cat"; age: 5; noise: "woof" } + } + + component SomeDelegate: Item { + required property int age + property string text + } + + component AnotherDelegate: Item { + property int age + property string text + + SomeDelegate { + age: 0 + text: "" + } + } + + ListView { + id: listView + model: myModel + delegate: AnotherDelegate { + age: model.age + text: model.noise + } + } +} diff --git a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp index 27bf389891..bdc99d2301 100644 --- a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp +++ b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp @@ -60,6 +60,7 @@ private slots: void sectionsNoOverlap(); void metaSequenceAsModel(); void noCrashOnIndexChange(); + void innerRequired(); }; tst_QQuickListView2::tst_QQuickListView2() @@ -307,6 +308,27 @@ void tst_QQuickListView2::noCrashOnIndexChange() QCOMPARE(items->property("count").toInt(), 4); } +void tst_QQuickListView2::innerRequired() +{ + QQmlEngine engine; + const QUrl url(testFileUrl("innerRequired.qml")); + QQmlComponent component(&engine, url); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> o(component.create()); + QVERIFY2(!o.isNull(), qPrintable(component.errorString())); + + QQuickListView *a = qobject_cast<QQuickListView *>( + qmlContext(o.data())->objectForName(QStringLiteral("listView"))); + QVERIFY(a); + + QCOMPARE(a->count(), 2); + QCOMPARE(a->itemAtIndex(0)->property("age").toInt(), 8); + QCOMPARE(a->itemAtIndex(0)->property("text").toString(), u"meow"); + QCOMPARE(a->itemAtIndex(1)->property("age").toInt(), 5); + QCOMPARE(a->itemAtIndex(1)->property("text").toString(), u"woof"); +} + class SingletonModel : public QStringListModel { Q_OBJECT diff --git a/tests/auto/quick/qquickrepeater/data/innerRequired.qml b/tests/auto/quick/qquickrepeater/data/innerRequired.qml new file mode 100644 index 0000000000..5498232fc1 --- /dev/null +++ b/tests/auto/quick/qquickrepeater/data/innerRequired.qml @@ -0,0 +1,33 @@ +import QtQuick + +Item { + ListModel { + id: myModel + ListElement { type: "Dog"; age: 8; noise: "meow" } + ListElement { type: "Cat"; age: 5; noise: "woof" } + } + + component SomeDelegate: Item { + required property int age + property string text + } + + component AnotherDelegate: Item { + property int age + property string text + + SomeDelegate { + age: 0 + text: "" + } + } + + Repeater { + id: repeater + model: myModel + delegate: AnotherDelegate { + age: model.age + text: model.noise + } + } +} diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp index e8b53d046f..9cc2ef4de7 100644 --- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp +++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp @@ -84,6 +84,7 @@ private slots: void ownership(); void requiredProperties(); void contextProperties(); + void innerRequired(); }; class TestObject : public QObject @@ -1174,6 +1175,27 @@ void tst_QQuickRepeater::contextProperties() } } +void tst_QQuickRepeater::innerRequired() +{ + QQmlEngine engine; + const QUrl url(testFileUrl("innerRequired.qml")); + QQmlComponent component(&engine, url); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> o(component.create()); + QVERIFY2(!o.isNull(), qPrintable(component.errorString())); + + QQuickRepeater *a = qobject_cast<QQuickRepeater *>( + qmlContext(o.data())->objectForName(QStringLiteral("repeater"))); + QVERIFY(a); + + QCOMPARE(a->count(), 2); + QCOMPARE(a->itemAt(0)->property("age").toInt(), 8); + QCOMPARE(a->itemAt(0)->property("text").toString(), u"meow"); + QCOMPARE(a->itemAt(1)->property("age").toInt(), 5); + QCOMPARE(a->itemAt(1)->property("text").toString(), u"woof"); +} + QTEST_MAIN(tst_QQuickRepeater) #include "tst_qquickrepeater.moc" |
