Blame SOURCES/0011-Fix-QML-property-cache-leaks-of-delegate-items.patch

383017
From b2862e2bd84d651c1f4fb2ced96ee6f40ea1f3e4 Mon Sep 17 00:00:00 2001
383017
From: Andrei Golubev <andrei.golubev@qt.io>
383017
Date: Fri, 20 Nov 2020 10:44:44 +0100
383017
Subject: [PATCH 11/28] Fix QML property cache leaks of delegate items
383017
383017
The delegate items are destroyed through an event loop by a call to a
383017
deleteLater(). This, however, doesn't work when the application is
383017
in the process of exiting and the event loop is already closed (i.e.
383017
we're in a stack unwinding part that starts after app.exec())
383017
383017
Combat this situation by setting a parent of the to-be-deleted object
383017
to some QObject that will be destroyed e.g. QCoreApplication::instance()
383017
before the program finishes. As QObjects clean their children on
383017
destruction, this will make sure that we cleanup the previously leaking
383017
thing regardless of the event loop
383017
383017
Added a test to check that delegates are destroyed (as a separate binary
383017
due to differences in main() function)
383017
383017
Fixes: QTBUG-87228
383017
Change-Id: I59066603b77497fe4fd8d051798c3e4b47c119f0
383017
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
383017
(cherry picked from commit 3a5617dc45e281552b9c1f7a04f0561b8fa14d94)
383017
---
383017
 src/qmlmodels/qqmldelegatemodel.cpp           | 11 ++-
383017
 .../qquickview_extra/data/qtbug_87228.qml     | 30 ++++++++
383017
 .../qquickview_extra/qquickview_extra.pro     | 12 +++
383017
 .../qquickview_extra/tst_qquickview_extra.cpp | 77 +++++++++++++++++++
383017
 tests/auto/quick/quick.pro                    |  1 +
383017
 5 files changed, 130 insertions(+), 1 deletion(-)
383017
 create mode 100644 tests/auto/quick/qquickview_extra/data/qtbug_87228.qml
383017
 create mode 100644 tests/auto/quick/qquickview_extra/qquickview_extra.pro
383017
 create mode 100644 tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp
383017
383017
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
383017
index 725b9e8bc3..12c3d11937 100644
383017
--- a/src/qmlmodels/qqmldelegatemodel.cpp
383017
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
383017
@@ -1,6 +1,6 @@
383017
 /****************************************************************************
383017
 **
383017
-** Copyright (C) 2016 The Qt Company Ltd.
383017
+** Copyright (C) 2020 The Qt Company Ltd.
383017
 ** Contact: https://www.qt.io/licensing/
383017
 **
383017
 ** This file is part of the QtQml module of the Qt Toolkit.
383017
@@ -2379,6 +2379,15 @@ void QQmlDelegateModelItem::destroyObject()
383017
         data->ownContext = nullptr;
383017
         data->context = nullptr;
383017
     }
383017
+    /* QTBUG-87228: when destroying object at the application exit, the deferred
383017
+     * parent by setting it to QCoreApplication instance if it's nullptr, so
383017
+     * deletion won't work. Not to leak memory, make sure our object has a that
383017
+     * the parent claims the object at the end of the lifetime. When not at the
383017
+     * application exit, normal event loop will handle the deferred deletion
383017
+     * earlier.
383017
+     */
383017
+    if (object->parent() == nullptr)
383017
+        object->setParent(QCoreApplication::instance());
383017
     object->deleteLater();
383017
 
383017
     if (attached) {
383017
diff --git a/tests/auto/quick/qquickview_extra/data/qtbug_87228.qml b/tests/auto/quick/qquickview_extra/data/qtbug_87228.qml
383017
new file mode 100644
383017
index 0000000000..ff10eba23d
383017
--- /dev/null
383017
+++ b/tests/auto/quick/qquickview_extra/data/qtbug_87228.qml
383017
@@ -0,0 +1,30 @@
383017
+import QtQml 2.12
383017
+import QtQml.Models 2.12
383017
+import QtQuick 2.12
383017
+
383017
+Item {
383017
+    height: 480
383017
+    width: 320
383017
+    Rectangle {
383017
+        id: rootRect
383017
+
383017
+        function addItem(desc) {
383017
+            myModel.append({"desc": desc});
383017
+        }
383017
+
383017
+        Rectangle {
383017
+            ListView {
383017
+                objectName: "listView"
383017
+                delegate: Text {
383017
+                    required property string desc
383017
+                    text: desc
383017
+                }
383017
+                model: ListModel { id: myModel }
383017
+            }
383017
+        }
383017
+
383017
+        Component.onCompleted: {
383017
+            addItem("Test creation of a delegate with a property");
383017
+        }
383017
+    }
383017
+}
383017
diff --git a/tests/auto/quick/qquickview_extra/qquickview_extra.pro b/tests/auto/quick/qquickview_extra/qquickview_extra.pro
383017
new file mode 100644
383017
index 0000000000..b40af0ce19
383017
--- /dev/null
383017
+++ b/tests/auto/quick/qquickview_extra/qquickview_extra.pro
383017
@@ -0,0 +1,12 @@
383017
+CONFIG += testcase
383017
+TARGET = tst_qquickview_extra
383017
+macx:CONFIG -= app_bundle
383017
+
383017
+SOURCES += tst_qquickview_extra.cpp
383017
+
383017
+include (../../shared/util.pri)
383017
+include (../shared/util.pri)
383017
+
383017
+TESTDATA = data/*
383017
+
383017
+QT += core-private gui-private qml-private quick-private testlib
383017
diff --git a/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp b/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp
383017
new file mode 100644
383017
index 0000000000..f697a438bd
383017
--- /dev/null
383017
+++ b/tests/auto/quick/qquickview_extra/tst_qquickview_extra.cpp
383017
@@ -0,0 +1,77 @@
383017
+/****************************************************************************
383017
+**
383017
+** Copyright (C) 2020 The Qt Company Ltd.
383017
+** Contact: https://www.qt.io/licensing/
383017
+**
383017
+** This file is part of the test suite of the Qt Toolkit.
383017
+**
383017
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
383017
+** Commercial License Usage
383017
+** Licensees holding valid commercial Qt licenses may use this file in
383017
+** accordance with the commercial license agreement provided with the
383017
+** Software or, alternatively, in accordance with the terms contained in
383017
+** a written agreement between you and The Qt Company. For licensing terms
383017
+** and conditions see https://www.qt.io/terms-conditions. For further
383017
+** information use the contact form at https://www.qt.io/contact-us.
383017
+**
383017
+** GNU General Public License Usage
383017
+** Alternatively, this file may be used under the terms of the GNU
383017
+** General Public License version 3 as published by the Free Software
383017
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
383017
+** included in the packaging of this file. Please review the following
383017
+** information to ensure the GNU General Public License requirements will
383017
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
383017
+**
383017
+** $QT_END_LICENSE$
383017
+**
383017
+****************************************************************************/
383017
+#include <qtest.h>
383017
+#include <QtTest/QSignalSpy>
383017
+#include <QtQuick/qquickview.h>
383017
+#include <QtQuick/qquickitem.h>
383017
+#include <QtQml/qqmlengine.h>
383017
+#include "../../shared/util.h"
383017
+#include <QtCore/QDebug>
383017
+#include <QtCore/QTimer>
383017
+
383017
+// Extra app-less tests
383017
+class tst_QQuickViewExtra : public QQmlDataTest
383017
+{
383017
+    Q_OBJECT
383017
+public:
383017
+    tst_QQuickViewExtra();
383017
+
383017
+private slots:
383017
+    void qtbug_87228();
383017
+};
383017
+
383017
+tst_QQuickViewExtra::tst_QQuickViewExtra() { }
383017
+
383017
+void tst_QQuickViewExtra::qtbug_87228()
383017
+{
383017
+    QScopedPointer<QSignalSpy> deletionSpy;
383017
+    {
383017
+        int argc = 0;
383017
+        QGuiApplication app(argc, nullptr);
383017
+        QQuickView view;
383017
+
383017
+        view.setSource(testFileUrl("qtbug_87228.qml"));
383017
+        view.show();
383017
+        QTimer::singleShot(500, &app, QCoreApplication::quit);
383017
+        app.exec();
383017
+
383017
+        QObject *listView = view.findChild<QObject *>("listView");
383017
+        QVERIFY(listView);
383017
+        QQuickItem *contentItem = listView->property("contentItem").value<QQuickItem *>();
383017
+        QVERIFY(contentItem);
383017
+        auto children = contentItem->childItems();
383017
+        QVERIFY(children.size() > 0);
383017
+        // for the sake of this test, any child would be suitable, so pick first
383017
+        deletionSpy.reset(new QSignalSpy(children[0], SIGNAL(destroyed(QObject *))));
383017
+    }
383017
+    QCOMPARE(deletionSpy->count(), 1);
383017
+}
383017
+
383017
+QTEST_APPLESS_MAIN(tst_QQuickViewExtra)
383017
+
383017
+#include "tst_qquickview_extra.moc"
383017
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
383017
index 541bfdd527..45bcf8a9ce 100644
383017
--- a/tests/auto/quick/quick.pro
383017
+++ b/tests/auto/quick/quick.pro
383017
@@ -85,6 +85,7 @@ QUICKTESTS += \
383017
     qquicktextinput \
383017
     qquickvisualdatamodel \
383017
     qquickview \
383017
+    qquickview_extra \
383017
     qquickcanvasitem \
383017
     qquickdesignersupport \
383017
     qquickscreen \
383017
-- 
383017
2.31.1
383017