From 1817efd1ddaf459e5e2b001c7aa81522e13e7098 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 5 Dec 2011 15:27:00 +1000 Subject: [PATCH] Don't attempt to destroy a null persisted item. Persisted items are still only constructed on demand so we can't assume the object is non null. Change-Id: I1ce9563eb3b9fb1ae611e8afcf9c8c74f0563aec Reviewed-by: Martin Jones --- src/quick/items/qquickvisualdatamodel.cpp | 2 +- .../qtquick2/qquickvisualdatamodel/data/create.qml | 7 ++-- .../tst_qquickvisualdatamodel.cpp | 42 +++++++++++++++------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 649ca6f..4bb061f 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -1398,7 +1398,7 @@ void QQuickVisualDataModelPrivate::itemsRemoved( } else { for (; cacheIndex < remove.cacheIndex + remove.count - removedCache; ++cacheIndex) { QQuickVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex); - if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0) { + if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object) { destroy(cacheItem->object); if (QDeclarativePackage *package = qobject_cast(cacheItem->object)) emitDestroyingPackage(package); diff --git a/tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml index 3475a0d..9f4b754 100644 --- a/tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml +++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml @@ -4,6 +4,8 @@ ListView { width: 200 height: 200 + property var persistentHandle + model: VisualDataModel { id: visualModel @@ -15,11 +17,6 @@ ListView { objectName: "delegate" width: 200 height: 20 - - property bool destroyed: false - - - Component.onDestruction: destroyed = true } } } diff --git a/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp index f0e6228..9e27a20 100644 --- a/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp +++ b/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp @@ -1708,7 +1708,7 @@ void tst_qquickvisualdatamodel::create() QCOMPARE(listview->count(), 20); - QQuickItem *delegate; + QDeclarativeGuard delegate; // persistedItems.includeByDefault is true, so all items belong to persistedItems initially. QVERIFY(delegate = findItem(contentItem, "delegate", 1)); @@ -1725,55 +1725,60 @@ void tst_qquickvisualdatamodel::create() // Request an item instantiated by the view. QVERIFY(delegate = qobject_cast(evaluate(visualModel, "items.create(1)"))); - QCOMPARE(delegate, findItem(contentItem, "delegate", 1)); + QCOMPARE(delegate.data(), findItem(contentItem, "delegate", 1)); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), true); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 1); evaluate(delegate, "VisualDataModel.inPersistedItems = false"); QCOMPARE(listview->count(), 20); - QCOMPARE(evaluate(delegate, "destroyed"), false); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(delegate); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), false); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 0); // Request an item not instantiated by the view. QVERIFY(!findItem(contentItem, "delegate", 15)); QVERIFY(delegate = qobject_cast(evaluate(visualModel, "items.create(15)"))); - QCOMPARE(delegate, findItem(contentItem, "delegate", 15)); + QCOMPARE(delegate.data(), findItem(contentItem, "delegate", 15)); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), true); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 1); evaluate(visualModel, "persistedItems.remove(0)"); - QCOMPARE(evaluate(delegate, "destroyed"), true); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(!delegate); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 0); // Request an item not instantiated by the view, then scroll the view so it will request it. QVERIFY(!findItem(contentItem, "delegate", 16)); QVERIFY(delegate = qobject_cast(evaluate(visualModel, "items.create(16)"))); - QCOMPARE(delegate, findItem(contentItem, "delegate", 16)); + QCOMPARE(delegate.data(), findItem(contentItem, "delegate", 16)); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), true); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 1); evaluate(listview, "positionViewAtIndex(19, ListView.End)"); QCOMPARE(listview->count(), 20); evaluate(delegate, "VisualDataModel.groups = [\"items\"]"); - QCOMPARE(evaluate(delegate, "destroyed"), false); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(delegate); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), false); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 0); // Request and release an item instantiated by the view, then scroll the view so it releases it. QVERIFY(findItem(contentItem, "delegate", 17)); QVERIFY(delegate = qobject_cast(evaluate(visualModel, "items.create(17)"))); - QCOMPARE(delegate, findItem(contentItem, "delegate", 17)); + QCOMPARE(delegate.data(), findItem(contentItem, "delegate", 17)); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), true); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 1); evaluate(visualModel, "items.removeGroups(17, \"persistedItems\")"); - QCOMPARE(evaluate(delegate, "destroyed"), false); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(delegate); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), false); QCOMPARE(evaluate(visualModel, "persistedItems.count"), 0); evaluate(listview, "positionViewAtIndex(1, ListView.Beginning)"); QCOMPARE(listview->count(), 20); - QCOMPARE(evaluate(delegate, "destroyed"), true); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(!delegate); // Adding an item to the persistedItems group won't instantiate it, but if later requested by // the view it will be persisted. @@ -1784,13 +1789,24 @@ void tst_qquickvisualdatamodel::create() QCOMPARE(listview->count(), 20); QVERIFY(delegate = findItem(contentItem, "delegate", 18)); QCOMPARE(evaluate(delegate, "VisualDataModel.inPersistedItems"), true); - QCOMPARE(evaluate(delegate, "destroyed"), false); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(delegate); evaluate(listview, "positionViewAtIndex(1, ListView.Beginning)"); QCOMPARE(listview->count(), 20); - QCOMPARE(evaluate(delegate, "destroyed"), false); + QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete); + QVERIFY(delegate); + + // Remove an uninstantiated but cached item from the persistedItems group. + evaluate(visualModel, "items.addGroups(19, \"persistedItems\")"); + QCOMPARE(evaluate(visualModel, "persistedItems.count"), 2); + QVERIFY(!findItem(contentItem, "delegate", 19)); + // Store a reference to the item so it is retained in the cache. + evaluate(visualModel, "persistentHandle = items.get(19)"); + QCOMPARE(evaluate(visualModel, "persistentHandle.inPersistedItems"), true); + evaluate(visualModel, "items.removeGroups(19, \"persistedItems\")"); + QCOMPARE(evaluate(visualModel, "persistentHandle.inPersistedItems"), false); } - void tst_qquickvisualdatamodel::incompleteModel() { // VisualDataModel is first populated in componentComplete. Verify various functions are -- 2.7.4