diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-03-20 11:11:02 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-05-09 10:45:49 +0000 |
commit | 3b806a18cc665b5ae0e12d45fe170bfc3f00352a (patch) | |
tree | 1403138f7ef2d9cd832e21b9c09dca073b049db1 /tests/auto/quick/qquickrepeater | |
parent | a393929fd149906596bd74480a561b986a87b35d (diff) |
Fix crash when using repeaters with packages
When receiving the modelUpdated signal from the delegate model, the
repeater - unlike other views - queries for the objects right away. That
may result in instant incubation and when using Packages, we will end up
delivering the initItem signal emission for the parts models via
QQmlDelegateModelGroupPrivate::initPackage for _both_ repeaters
immediately. For the first repeater that's expected, but for the second
repeater that means initItem is received before modelUpdated was called.
That is very confusing for the repeater as d->deletables is not set up
yet.
While it's possible to make the repeater more "robust" towards such
behaving models, it seems cleaner to make the model behave well, by
ensuring that we emit initItem after modelUpdated.
Task-number: QTBUG-50349
Change-Id: Id2f3ba135e34d0111c8896bb4ecdfe51c8c649da
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'tests/auto/quick/qquickrepeater')
-rw-r--r-- | tests/auto/quick/qquickrepeater/data/package.qml | 35 | ||||
-rw-r--r-- | tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp | 24 |
2 files changed, 59 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickrepeater/data/package.qml b/tests/auto/quick/qquickrepeater/data/package.qml new file mode 100644 index 0000000000..1f9eb0d970 --- /dev/null +++ b/tests/auto/quick/qquickrepeater/data/package.qml @@ -0,0 +1,35 @@ +import QtQuick 2.0 +import QtQml.Models 2.2 +import QtQuick.Window 2.0 + +Window { + width: 300 + height: 300 + visible: true + DelegateModel { + id: mdl + + model: 1 + delegate: Package { + Item { + id: first + Package.name: "first" + objectName: "firstItem" + } + Item{ + id: second + Package.name: "second" + objectName: "secondItem" + } + } + } + + Repeater { + id: repeater1 + model: mdl.parts.first + } + Repeater { + id: repeater2 + model: mdl.parts.second + } +} diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp index 0499e2f9a6..791c3ae19a 100644 --- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp +++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp @@ -76,6 +76,7 @@ private slots: void stackingOrder(); void objectModel(); void QTBUG54859_asynchronousMove(); + void package(); }; class TestObject : public QObject @@ -1014,6 +1015,29 @@ void tst_QQuickRepeater::QTBUG54859_asynchronousMove() QTRY_COMPARE(item->property("finished"), QVariant(true)); } +void tst_QQuickRepeater::package() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("package.qml")); + + QScopedPointer<QObject>o(component.create()); // don't crash! + QVERIFY(o != nullptr); + + { + QQuickRepeater *repeater1 = qobject_cast<QQuickRepeater*>(qmlContext(o.data())->contextProperty("repeater1").value<QObject*>()); + QVERIFY(repeater1); + QCOMPARE(repeater1->count(), 1); + QCOMPARE(repeater1->itemAt(0)->objectName(), "firstItem"); + } + + { + QQuickRepeater *repeater2 = qobject_cast<QQuickRepeater*>(qmlContext(o.data())->contextProperty("repeater2").value<QObject*>()); + QVERIFY(repeater2); + QCOMPARE(repeater2->count(), 1); + QCOMPARE(repeater2->itemAt(0)->objectName(), "secondItem"); + } +} + QTEST_MAIN(tst_QQuickRepeater) #include "tst_qquickrepeater.moc" |