kde-frameworks/kirigami: Fix systemsettings crash
authorAndreas Sturmlechner <asturm@gentoo.org>
Wed, 20 Nov 2019 11:08:04 +0000 (12:08 +0100)
committerAndreas Sturmlechner <asturm@gentoo.org>
Wed, 20 Nov 2019 12:21:00 +0000 (13:21 +0100)
See also: https://mail.kde.org/pipermail/release-team/2019-November/011662.html
KDE-Bug: https://bugs.kde.org/show_bug.cgi?id=414003
Package-Manager: Portage-2.3.79, Repoman-2.3.18
Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
kde-frameworks/kirigami/files/kirigami-5.64.0-one-qmlcomponentspool-instance-per-engine.patch [new file with mode: 0644]
kde-frameworks/kirigami/kirigami-5.64.0-r1.ebuild [new file with mode: 0644]

diff --git a/kde-frameworks/kirigami/files/kirigami-5.64.0-one-qmlcomponentspool-instance-per-engine.patch b/kde-frameworks/kirigami/files/kirigami-5.64.0-one-qmlcomponentspool-instance-per-engine.patch
new file mode 100644 (file)
index 0000000..3613a8b
--- /dev/null
@@ -0,0 +1,178 @@
+From 4a9820a6df15a55a7d36d343ce70a25ba7d56b79 Mon Sep 17 00:00:00 2001
+From: David Edmundson <kde@davidedmundson.co.uk>
+Date: Wed, 13 Nov 2019 14:23:19 +0000
+Subject: Make QmlComponentsPool one instance per engine
+
+Summary:
+If we create 2 engines in an application the singleton is initialised to
+the first engine. If that first engine disappears the internal m_unit is
+dangling.
+
+A good example of this is systemsettings in the icon view if we enter
+two modules one after another. It's currently only kept alive because
+the sidebar created the first reference.
+
+BUG: 414003
+
+Test Plan:
+System settings in icon view
+opened global theme
+went back
+open fonts theme
+didn't crash
+
+Subscribers: plasma-devel
+
+Tags: #kirigami
+
+Differential Revision: https://phabricator.kde.org/D25284
+---
+ src/columnview.cpp | 54 +++++++++++++++++++++++++++++++++---------------------
+ src/columnview_p.h |  4 +---
+ 2 files changed, 34 insertions(+), 24 deletions(-)
+
+diff --git a/src/columnview.cpp b/src/columnview.cpp
+index cab89f8..35d591e 100644
+--- a/src/columnview.cpp
++++ b/src/columnview.cpp
+@@ -37,23 +37,37 @@ class QmlComponentsPoolSingleton
+ public:
+     QmlComponentsPoolSingleton()
+     {}
+-
+-    QmlComponentsPool self;
++    static QmlComponentsPool *instance(QQmlEngine *engine);
++private:
++    QHash<QQmlEngine*, QmlComponentsPool*> m_instances;
+ };
+ Q_GLOBAL_STATIC(QmlComponentsPoolSingleton, privateQmlComponentsPoolSelf)
+-QmlComponentsPool::QmlComponentsPool(QObject *parent)
+-    : QObject(parent)
+-{}
+-
+-void QmlComponentsPool::initialize(QQmlEngine *engine)
++QmlComponentsPool *QmlComponentsPoolSingleton::instance(QQmlEngine *engine)
+ {
+-    if (!engine || m_instance) {
+-        return;
++    Q_ASSERT(engine);
++    auto componentPool = privateQmlComponentsPoolSelf->m_instances.value(engine);
++
++    if (componentPool) {
++        return componentPool;
+     }
++    componentPool = new QmlComponentsPool(engine);
++
++    QObject::connect(componentPool, &QObject::destroyed, [engine]() {
++        if (privateQmlComponentsPoolSelf) {
++            privateQmlComponentsPoolSelf->m_instances.remove(engine);
++        }
++    });
++    privateQmlComponentsPoolSelf->m_instances[engine] = componentPool;
++    return componentPool;
++}
++
++QmlComponentsPool::QmlComponentsPool(QQmlEngine *engine)
++    : QObject(engine)
++{
+     QQmlComponent *component = new QQmlComponent(engine, this);
+     component->setData(QByteArrayLiteral("import QtQuick 2.7\n"
+@@ -572,12 +586,12 @@ QQuickItem *ContentItem::ensureSeparator(QQuickItem *item)
+     QQuickItem *separatorItem = m_separators.value(item);
+     
+     if (!separatorItem) {
+-        separatorItem = qobject_cast<QQuickItem *>(privateQmlComponentsPoolSelf->self.m_separatorComponent->beginCreate(QQmlEngine::contextForObject(item)));
++        separatorItem = qobject_cast<QQuickItem *>(privateQmlComponentsPoolSelf->instance(qmlEngine(item))->m_separatorComponent->beginCreate(QQmlEngine::contextForObject(item)));
+         if (separatorItem) {
+             separatorItem->setParentItem(item);
+             separatorItem->setZ(9999);
+             separatorItem->setProperty("column", QVariant::fromValue(item));
+-            privateQmlComponentsPoolSelf->self.m_separatorComponent->completeCreate();
++            QmlComponentsPoolSingleton::instance(qmlEngine(item))->m_separatorComponent->completeCreate();
+             m_separators[item] = separatorItem;
+         }
+     }
+@@ -590,12 +604,12 @@ QQuickItem *ContentItem::ensureRightSeparator(QQuickItem *item)
+     QQuickItem *separatorItem = m_rightSeparators.value(item);
+     
+     if (!separatorItem) {
+-        separatorItem = qobject_cast<QQuickItem *>(privateQmlComponentsPoolSelf->self.m_rightSeparatorComponent->beginCreate(QQmlEngine::contextForObject(item)));
++        separatorItem = qobject_cast<QQuickItem *>(QmlComponentsPoolSingleton::instance(qmlEngine(item))->m_rightSeparatorComponent->beginCreate(QQmlEngine::contextForObject(item)));
+         if (separatorItem) {
+             separatorItem->setParentItem(item);
+             separatorItem->setZ(9999);
+             separatorItem->setProperty("column", QVariant::fromValue(item));
+-            privateQmlComponentsPoolSelf->self.m_rightSeparatorComponent->completeCreate();
++            QmlComponentsPoolSingleton::instance(qmlEngine(item))->m_rightSeparatorComponent->completeCreate();
+             m_rightSeparators[item] = separatorItem;
+         }
+     }
+@@ -759,7 +773,7 @@ qreal ColumnView::columnWidth() const
+ void ColumnView::setColumnWidth(qreal width)
+ {
+     // Always forget the internal binding when the user sets anything, even the same value
+-    disconnect(&privateQmlComponentsPoolSelf->self, &QmlComponentsPool::gridUnitChanged, this, nullptr);
++    disconnect(QmlComponentsPoolSingleton::instance(qmlEngine(this)), &QmlComponentsPool::gridUnitChanged, this, nullptr);
+     if (m_contentItem->m_columnWidth == width) {
+         return;
+@@ -902,7 +916,7 @@ int ColumnView::scrollDuration() const
+ void ColumnView::setScrollDuration(int duration)
+ {
+-    disconnect(&privateQmlComponentsPoolSelf->self, &QmlComponentsPool::longDurationChanged, this, nullptr);
++    disconnect(QmlComponentsPoolSingleton::instance(qmlEngine(this)), &QmlComponentsPool::longDurationChanged, this, nullptr);
+     if (m_contentItem->m_slideAnim->duration() == duration) {
+         return;
+@@ -1392,22 +1406,20 @@ void ColumnView::mouseUngrabEvent()
+ void ColumnView::classBegin()
+ {
+-    privateQmlComponentsPoolSelf->self.initialize(qmlEngine(this));
+-
+     auto syncColumnWidth = [this]() {
+-        m_contentItem->m_columnWidth = privateQmlComponentsPoolSelf->self.m_units->property("gridUnit").toInt() * 20;
++        m_contentItem->m_columnWidth = privateQmlComponentsPoolSelf->instance(qmlEngine(this))->m_units->property("gridUnit").toInt() * 20;
+         emit columnWidthChanged();
+     };
+-    connect(&privateQmlComponentsPoolSelf->self, &QmlComponentsPool::gridUnitChanged, this, syncColumnWidth);
++    connect(QmlComponentsPoolSingleton::instance(qmlEngine(this)), &QmlComponentsPool::gridUnitChanged, this, syncColumnWidth);
+     syncColumnWidth();
+     auto syncDuration = [this]() {
+-        m_contentItem->m_slideAnim->setDuration(privateQmlComponentsPoolSelf->self.m_units->property("longDuration").toInt());
++        m_contentItem->m_slideAnim->setDuration(QmlComponentsPoolSingleton::instance(qmlEngine(this))->m_units->property("longDuration").toInt());
+         emit scrollDurationChanged();
+     };
+-    connect(&privateQmlComponentsPoolSelf->self, &QmlComponentsPool::longDurationChanged, this, syncDuration);
++    connect(QmlComponentsPoolSingleton::instance(qmlEngine(this)), &QmlComponentsPool::longDurationChanged, this, syncDuration);
+     syncDuration();
+     QQuickItem::classBegin();
+diff --git a/src/columnview_p.h b/src/columnview_p.h
+index ebf5543..886b96b 100644
+--- a/src/columnview_p.h
++++ b/src/columnview_p.h
+@@ -32,11 +32,9 @@ class QmlComponentsPool: public QObject
+     Q_OBJECT
+ public:
+-    QmlComponentsPool(QObject *parent = nullptr);
++    QmlComponentsPool(QQmlEngine *engine);
+     ~QmlComponentsPool();
+-    void initialize(QQmlEngine *engine);
+-
+     QQmlComponent *m_separatorComponent = nullptr;
+     QQmlComponent *m_rightSeparatorComponent = nullptr;
+     QObject *m_units = nullptr;
+-- 
+cgit v1.1
diff --git a/kde-frameworks/kirigami/kirigami-5.64.0-r1.ebuild b/kde-frameworks/kirigami/kirigami-5.64.0-r1.ebuild
new file mode 100644 (file)
index 0000000..358a9fd
--- /dev/null
@@ -0,0 +1,48 @@
+# Copyright 1999-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+ECM_EXAMPLES="true"
+ECM_QTHELP="false"
+ECM_TEST="true"
+KDE_ORG_NAME="${PN}2"
+QTMIN=5.12.3
+inherit ecm kde.org
+
+DESCRIPTION="Lightweight user interface framework for mobile and convergent applications"
+HOMEPAGE="https://techbase.kde.org/Kirigami"
+EGIT_REPO_URI="${EGIT_REPO_URI/${PN}2/${PN}}"
+
+LICENSE="LGPL-2+"
+KEYWORDS="~amd64 ~arm ~arm64 ~x86"
+IUSE=""
+
+# drop qtgui subslot operator when QT_MINIMAL >= 5.14.0
+BDEPEND="
+       >=dev-qt/linguist-tools-${QTMIN}:5
+"
+DEPEND="
+       >=dev-qt/qtdbus-${QTMIN}:5
+       >=dev-qt/qtdeclarative-${QTMIN}:5
+       >=dev-qt/qtgui-${QTMIN}:5=
+       >=dev-qt/qtnetwork-${QTMIN}:5
+       >=dev-qt/qtquickcontrols2-${QTMIN}:5
+       >=dev-qt/qtsvg-${QTMIN}:5
+"
+RDEPEND="${DEPEND}
+       >=dev-qt/qtgraphicaleffects-${QTMIN}:5
+"
+
+# requires package to already be installed
+RESTRICT+=" test"
+
+PATCHES=( "${FILESDIR}/${P}-one-qmlcomponentspool-instance-per-engine.patch" )
+
+src_configure() {
+       local mycmakeargs=(
+               -DBUILD_EXAMPLES=$(usex examples)
+       )
+
+       ecm_src_configure
+}