Don't leak objects when a VisualDataModel is destroyed before a view.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Wed, 16 Nov 2011 03:08:16 +0000 (13:08 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 21 Nov 2011 05:16:30 +0000 (06:16 +0100)
If an item is still referenced by a view when the VisualDataModel is
destroyed delete it, otherwise it will leak as the view have no
interface to release it and deleting the item won't delete the package.

Task-number: QTBUG-22672
Change-Id: I7b89962d724d7a391c97722638e03b7a186b8a8f
Reviewed-by: Chris Adams <christopher.adams@nokia.com>

src/declarative/items/qquickvisualdatamodel.cpp
tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_listView.qml [new file with mode: 0644]
tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_package.qml [new file with mode: 0644]
tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml [new file with mode: 0644]
tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml [new file with mode: 0644]
tests/auto/declarative/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp

index 5cf2d6c..7d0abfc 100644 (file)
@@ -457,7 +457,9 @@ QQuickVisualDataModel::QQuickVisualDataModel(QDeclarativeContext *ctxt, QObject
 QQuickVisualDataModel::~QQuickVisualDataModel()
 {
     Q_D(QQuickVisualDataModel);
+
     foreach (QQuickVisualDataModelCacheItem *cacheItem, d->m_cache) {
+        delete cacheItem->object;
         cacheItem->object = 0;
         cacheItem->objectRef = 0;
         if (!cacheItem->isReferenced())
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_listView.qml b/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_listView.qml
new file mode 100644 (file)
index 0000000..103c4d2
--- /dev/null
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+ListView {
+    width: 100
+    height: 100
+
+    model: myModel
+    delegate: Item {
+        objectName: "delegate"
+        width: 100
+        height: 20
+    }
+}
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_package.qml b/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_package.qml
new file mode 100644 (file)
index 0000000..b47f22d
--- /dev/null
@@ -0,0 +1,42 @@
+import QtQuick 2.0
+
+Item {
+    width: 100
+    height: 100
+
+    ListView {
+        anchors.fill: parent
+
+        model: visualModel.parts.list
+    }
+    VisualDataModel {
+        id: visualModel
+
+        model: myModel
+        delegate: Package {
+            Item {
+                Package.name: "list"
+                width: 100
+                height: 20
+            }
+
+            Item {
+                id: gridItem
+                Package.name: "grid"
+                width: 50
+                height: 50
+            }
+            Rectangle {
+                objectName: "delegate"
+                parent: gridItem
+                width: 20
+                height: 20
+            }
+        }
+    }
+    GridView {
+        anchors.fill: parent
+
+        model: visualModel.parts.grid
+    }
+}
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml b/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml
new file mode 100644 (file)
index 0000000..bc61912
--- /dev/null
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+PathView {
+    width: 100
+    height: 100
+
+    model: myModel
+    delegate: Item {
+        objectName: "delegate"
+        width: 100
+        height: 20
+    }
+
+    path: Path {
+        startX: 50; startY: 0
+        PathLine { x: 50; y: 100 }
+    }
+}
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml b/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml
new file mode 100644 (file)
index 0000000..e97e0da
--- /dev/null
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+Grid {
+    Repeater {
+        width: 100
+        height: 100
+
+        model: myModel
+        delegate: Item {
+            objectName: "delegate"
+            width: 50
+            height: 50
+        }
+    }
+}
index 706c20f..44759d4 100644 (file)
@@ -131,6 +131,8 @@ private slots:
     void modelProperties();
     void noDelegate_data();
     void noDelegate();
+    void itemsDestroyed_data();
+    void itemsDestroyed();
     void qaimRowsMoved();
     void qaimRowsMoved_data();
     void remove_data();
@@ -628,6 +630,37 @@ void tst_qquickvisualdatamodel::noDelegate()
     QCOMPARE(vdm->count(), 0);
 }
 
+void tst_qquickvisualdatamodel::itemsDestroyed_data()
+{
+    QTest::addColumn<QUrl>("source");
+
+    QTest::newRow("listView") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_listView.qml"));
+    QTest::newRow("package") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_package.qml"));
+    QTest::newRow("pathView") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_pathView.qml"));
+    QTest::newRow("repeater") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_repeater.qml"));
+}
+
+void tst_qquickvisualdatamodel::itemsDestroyed()
+{
+    QFETCH(QUrl, source);
+
+    QDeclarativeGuard<QQuickItem> delegate;
+
+    {
+        QQuickView view;
+        QStandardItemModel model;
+        initStandardTreeModel(&model);
+        view.rootContext()->setContextProperty("myModel", &model);
+        view.setSource(source);
+
+        view.show();
+        QTest::qWaitForWindowShown(&view);
+
+        QVERIFY(delegate = findItem<QQuickItem>(view.rootItem(), "delegate", 1));
+    }
+    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+    QVERIFY(!delegate);
+}
 
 void tst_qquickvisualdatamodel::qaimRowsMoved()
 {