diff options
-rw-r--r-- | src/qml/types/qqmlinstantiator.cpp | 38 | ||||
-rw-r--r-- | src/qml/types/qqmlinstantiator_p_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlinstantiator/data/createMultipleAsync.qml | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp | 43 |
4 files changed, 86 insertions, 7 deletions
diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp index 8b59b0633d..0137a2796d 100644 --- a/src/qml/types/qqmlinstantiator.cpp +++ b/src/qml/types/qqmlinstantiator.cpp @@ -48,6 +48,7 @@ QQmlInstantiatorPrivate::QQmlInstantiatorPrivate() , active(true) , async(false) , ownModel(false) + , requestedIndex(-1) , model(QVariant(1)) , instanceModel(0) , delegate(0) @@ -75,6 +76,15 @@ void QQmlInstantiatorPrivate::clear() q->objectChanged(); } +QObject *QQmlInstantiatorPrivate::modelObject(int index, bool async) +{ + requestedIndex = index; + QObject *o = instanceModel->object(index, async); + requestedIndex = -1; + return o; +} + + void QQmlInstantiatorPrivate::regenerate() { Q_Q(QQmlInstantiator); @@ -92,7 +102,7 @@ void QQmlInstantiatorPrivate::regenerate() } for (int i = 0; i < instanceModel->count(); i++) { - QObject *object = instanceModel->object(i, async); + QObject *object = modelObject(i, async); // If the item was already created we won't get a createdItem if (object) _q_createdItem(i, object); @@ -106,8 +116,18 @@ void QQmlInstantiatorPrivate::_q_createdItem(int idx, QObject* item) Q_Q(QQmlInstantiator); if (objects.contains(item)) //Case when it was created synchronously in regenerate return; + if (requestedIndex != idx) // Asynchronous creation, reference the object + (void)instanceModel->object(idx, false); item->setParent(q); - objects.insert(idx, item); + if (objects.size() < idx + 1) { + int modelCount = instanceModel->count(); + if (objects.capacity() < modelCount) + objects.reserve(modelCount); + objects.resize(idx + 1); + } + if (QObject *o = objects.at(idx)) + instanceModel->release(o); + objects.replace(idx, item); if (objects.count() == 1) q->objectChanged(); q->objectAdded(idx, item); @@ -153,11 +173,15 @@ void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bo if (insert.isMove()) { QVector<QPointer<QObject> > movedObjects = moved.value(insert.moveId); objects = objects.mid(0, index) + movedObjects + objects.mid(index); - } else for (int i = 0; i < insert.count; ++i) { - int modelIndex = index + i; - QObject* obj = instanceModel->object(modelIndex, async); - if (obj) - _q_createdItem(modelIndex, obj); + } else { + if (insert.index <= objects.size()) + objects.insert(insert.index, insert.count, 0); + for (int i = 0; i < insert.count; ++i) { + int modelIndex = index + i; + QObject* obj = modelObject(modelIndex, async); + if (obj) + _q_createdItem(modelIndex, obj); + } } difference += insert.count; } diff --git a/src/qml/types/qqmlinstantiator_p_p.h b/src/qml/types/qqmlinstantiator_p_p.h index 6e936d8580..db8c469039 100644 --- a/src/qml/types/qqmlinstantiator_p_p.h +++ b/src/qml/types/qqmlinstantiator_p_p.h @@ -66,12 +66,14 @@ public: void makeModel(); void _q_createdItem(int, QObject *); void _q_modelUpdated(const QQmlChangeSet &, bool); + QObject *modelObject(int index, bool async); bool componentComplete:1; bool effectiveReset:1; bool active:1; bool async:1; bool ownModel:1; + int requestedIndex; QVariant model; QQmlInstanceModel *instanceModel; QQmlComponent *delegate; diff --git a/tests/auto/qml/qqmlinstantiator/data/createMultipleAsync.qml b/tests/auto/qml/qqmlinstantiator/data/createMultipleAsync.qml new file mode 100644 index 0000000000..8d1ab0ed6a --- /dev/null +++ b/tests/auto/qml/qqmlinstantiator/data/createMultipleAsync.qml @@ -0,0 +1,10 @@ +import QtQml 2.1 + +Instantiator { + model: 10 + asynchronous: true + delegate: QtObject { + property bool success: true + property int idx: index + } +} diff --git a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp index b6ca50cc78..7ee33b1e58 100644 --- a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp +++ b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp @@ -38,6 +38,7 @@ #include <QtQml/qqmlcomponent.h> #include <QtQml/private/qqmlinstantiator_p.h> #include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlincubator.h> #include "../../shared/util.h" #include "stringmodel.h" @@ -53,6 +54,9 @@ private slots: void activeProperty(); void intModelChange(); void createAndRemove(); + + void asynchronous_data(); + void asynchronous(); }; void tst_qqmlinstantiator::createNone() @@ -209,6 +213,45 @@ void tst_qqmlinstantiator::createAndRemove() QCOMPARE(object->property("datum").toString(), names[i]); } } + +void tst_qqmlinstantiator::asynchronous_data() +{ + QTest::addColumn<bool>("asyncIncubator"); + QTest::addColumn<QString>("fileName"); + + QTest::newRow("Asynchronous Instantiator") << false << "createMultipleAsync.qml"; + QTest::newRow("Nested-asynchronous Instantiator") << true << "createMultiple.qml"; +} + +void tst_qqmlinstantiator::asynchronous() +{ + QFETCH(bool, asyncIncubator); + QFETCH(QString, fileName); + + QQmlEngine engine; + QQmlIncubationController incubationController; + engine.setIncubationController(&incubationController); + QQmlComponent component(&engine, testFileUrl(fileName)); + QQmlIncubator incubator(asyncIncubator ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous); + component.create(incubator); + while (!incubator.isReady()) + incubationController.incubateFor(10); + QQmlInstantiator *instantiator = qobject_cast<QQmlInstantiator *>(incubator.object()); + while (incubationController.incubatingObjectCount() > 0) + incubationController.incubateFor(10); + QVERIFY(instantiator != 0); + QCOMPARE(instantiator->isActive(), true); + QCOMPARE(instantiator->count(), 10); + + for (int i=0; i<10; i++) { + QObject *object = instantiator->objectAt(i); + QVERIFY(object); + QCOMPARE(object->parent(), instantiator); + QCOMPARE(object->property("success").toBool(), true); + QCOMPARE(object->property("idx").toInt(), i); + } +} + QTEST_MAIN(tst_qqmlinstantiator) #include "tst_qqmlinstantiator.moc" |