From cea2e8e110e90cc98d561609333fddbc7652ccba Mon Sep 17 00:00:00 2001 From: Alexandr Rekunkov Date: Mon, 30 Mar 2015 13:29:52 +0300 Subject: fix model leak in QQmlInstantiator Change-Id: Ieb6ef229bc999f1a35adc2a157bd42a38908f7d7 Task-number: QTBUG-45271 Reviewed-by: Shawn Rutledge Reviewed-by: Simon Hausmann --- src/qml/types/qqmlinstantiator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/types') diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp index 891011081d..1ee6532822 100644 --- a/src/qml/types/qqmlinstantiator.cpp +++ b/src/qml/types/qqmlinstantiator.cpp @@ -169,7 +169,7 @@ void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bo void QQmlInstantiatorPrivate::makeModel() { Q_Q(QQmlInstantiator); - QQmlDelegateModel* delegateModel = new QQmlDelegateModel(qmlContext(q)); + QQmlDelegateModel* delegateModel = new QQmlDelegateModel(qmlContext(q), q); instanceModel = delegateModel; ownModel = true; delegateModel->setDelegate(delegate); -- cgit v1.2.3 From 8018c4b6e7743c576a3548f6e73e588f19f632a9 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 23 Apr 2015 11:12:08 +0200 Subject: Instantiator: Make asynchronous mode work This patch proceeds in two steps. First, and the most trivial, we make sure not to offend the Instantiator's objects container since asynchronous creation also means the objects can be created in any order. We do so by ensuring the objects container has always the necessary size. The second step is to make sure the objects don't get destroyed by the delegate model when their incubation tasks are asynchronous. We force to keep an extra reference calling the object() function on the instance model, but only if the creation was asynchronous. However, it's not enough to check for the Instantiatior async value since the incubation tasks in QQmlDelegateModel are async-if-nested. Therefore, we need to keep track of the object index requested to the model and see if it matches when the createdItem() signal gets emitted. Task-number: QTBUG-36410 Change-Id: I180b03b6a7468d6521827a9631755577e9e6d357 Reviewed-by: Andrew den Exter --- src/qml/types/qqmlinstantiator.cpp | 38 +++++++++++++++++++++++++++++------- src/qml/types/qqmlinstantiator_p_p.h | 2 ++ 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src/qml/types') 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 > 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; -- cgit v1.2.3