diff options
author | Robert Griebl <robert.griebl@pelagicore.com> | 2015-10-29 01:12:27 +0100 |
---|---|---|
committer | Robert Griebl <robert.griebl@pelagicore.com> | 2015-11-02 10:14:00 +0000 |
commit | c606a37aa4c8968a92d0fcaf27cedbf311397754 (patch) | |
tree | 467134131b21d85de38c6c0ffa2de593d560a96a | |
parent | 5a4d9e558c02a32114e98dcae2307eef688a7eb4 (diff) | |
download | qtapplicationmanager-c606a37aa4c8968a92d0fcaf27cedbf311397754.tar.gz |
Finally applied Dominik's QML singleton ownership workaround.
QML expects C++ singletons to be owned by the QML engine, but this is not
always desireable. Simon has already acknowledged that we should add an
public API in Qt for that, but in the meantime this is the only way to do it.
Change-Id: I734cd77214c3b91e701dae62bc9712c0b85de718
Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
-rw-r--r-- | src/installer-lib/applicationinstaller.cpp | 5 | ||||
-rw-r--r-- | src/installer-lib/applicationinstaller.h | 2 | ||||
-rw-r--r-- | src/installer-lib/installer-lib.pro | 2 | ||||
-rw-r--r-- | src/manager-lib/applicationmanager.cpp | 9 | ||||
-rw-r--r-- | src/manager-lib/applicationmanager.h | 2 | ||||
-rw-r--r-- | src/manager-lib/manager-lib.pro | 4 | ||||
-rw-r--r-- | src/manager-lib/notificationmanager.cpp | 8 | ||||
-rw-r--r-- | src/manager-lib/notificationmanager.h | 2 | ||||
-rw-r--r-- | src/manager-lib/qml-utilities.cpp | 48 | ||||
-rw-r--r-- | src/manager-lib/qml-utilities.h | 33 | ||||
-rw-r--r-- | src/manager/main.cpp | 5 | ||||
-rw-r--r-- | src/manager/windowmanager.cpp | 8 | ||||
-rw-r--r-- | src/manager/windowmanager.h | 2 |
13 files changed, 120 insertions, 10 deletions
diff --git a/src/installer-lib/applicationinstaller.cpp b/src/installer-lib/applicationinstaller.cpp index 097445f7..8376919f 100644 --- a/src/installer-lib/applicationinstaller.cpp +++ b/src/installer-lib/applicationinstaller.cpp @@ -43,6 +43,7 @@ #include "exception.h" #include "global.h" #include "applicationmanager.h" +#include "qml-utilities.h" #define AM_AUTHENTICATE_DBUS(RETURN_TYPE) \ @@ -218,8 +219,10 @@ ApplicationInstaller *ApplicationInstaller::instance() return s_instance; } -QObject *ApplicationInstaller::instanceForQml(QQmlEngine *, QJSEngine *) +QObject *ApplicationInstaller::instanceForQml(QQmlEngine *qmlEngine, QJSEngine *) { + if (qmlEngine) + retakeSingletonOwnershipFromQmlEngine(qmlEngine, instance()); return instance(); } diff --git a/src/installer-lib/applicationinstaller.h b/src/installer-lib/applicationinstaller.h index 7b94e993..2d6263cd 100644 --- a/src/installer-lib/applicationinstaller.h +++ b/src/installer-lib/applicationinstaller.h @@ -72,7 +72,7 @@ public: const QDir &manifestDir, const QDir &imageMountDir, QString *error); static ApplicationInstaller *instance(); - static QObject *instanceForQml(QQmlEngine *, QJSEngine *); + static QObject *instanceForQml(QQmlEngine *qmlEngine, QJSEngine *); bool developmentMode() const; void setDevelopmentMode(bool b); diff --git a/src/installer-lib/installer-lib.pro b/src/installer-lib/installer-lib.pro index aed6b2a3..f442f140 100644 --- a/src/installer-lib/installer-lib.pro +++ b/src/installer-lib/installer-lib.pro @@ -6,7 +6,7 @@ include($$BASE_PRI) CONFIG += static create_prl -QT = core network +QT = core network qml qtHaveModule(dbus):QT *= dbus DEFINES *= AM_BUILD_APPMAN diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp index d9c487b6..566ca4b3 100644 --- a/src/manager-lib/applicationmanager.cpp +++ b/src/manager-lib/applicationmanager.cpp @@ -46,7 +46,7 @@ #include "jsonapplicationscanner.h" #include "executioncontainer.h" #include "dbus-utilities.h" - +#include "qml-utilities.h" #define AM_AUTHENTICATE_DBUS(RETURN_TYPE) \ do { \ @@ -269,6 +269,13 @@ ApplicationManager *ApplicationManager::instance() return s_instance; } +QObject *ApplicationManager::instanceForQml(QQmlEngine *qmlEngine, QJSEngine *) +{ + if (qmlEngine) + retakeSingletonOwnershipFromQmlEngine(qmlEngine, instance()); + return instance(); +} + ApplicationManager::ApplicationManager(ApplicationDatabase *adb, QObject *parent) : QAbstractListModel(parent) , d(new ApplicationManagerPrivate()) diff --git a/src/manager-lib/applicationmanager.h b/src/manager-lib/applicationmanager.h index a53899bb..d0a19c15 100644 --- a/src/manager-lib/applicationmanager.h +++ b/src/manager-lib/applicationmanager.h @@ -90,7 +90,7 @@ public: ~ApplicationManager(); static ApplicationManager *createInstance(ApplicationDatabase *adb, QString *error); static ApplicationManager *instance(); - static QObject *instanceForQml(QQmlEngine *, QJSEngine *) { return instance(); } + static QObject *instanceForQml(QQmlEngine *qmlEngine, QJSEngine *); bool isDummy() const { return false; } QVariantMap additionalConfiguration() const; diff --git a/src/manager-lib/manager-lib.pro b/src/manager-lib/manager-lib.pro index 28644eef..8bb790c0 100644 --- a/src/manager-lib/manager-lib.pro +++ b/src/manager-lib/manager-lib.pro @@ -6,7 +6,7 @@ include($$BASE_PRI) CONFIG += static create_prl -QT = core network qml +QT = core network qml qml-private !headless:QT *= gui quick qtHaveModule(dbus) { @@ -46,6 +46,7 @@ HEADERS += \ notificationmanager.h \ qmlinprocessruntime.h \ qmlinprocessapplicationinterface.h \ + qml-utilities.h !headless:HEADERS += \ fakepelagicorewindow.h \ @@ -72,6 +73,7 @@ SOURCES += \ notificationmanager.cpp \ qmlinprocessruntime.cpp \ qmlinprocessapplicationinterface.cpp \ + qml-utilities.cpp !headless:SOURCES += \ fakepelagicorewindow.cpp \ diff --git a/src/manager-lib/notificationmanager.cpp b/src/manager-lib/notificationmanager.cpp index 3e4c4b23..e026e80f 100644 --- a/src/manager-lib/notificationmanager.cpp +++ b/src/manager-lib/notificationmanager.cpp @@ -37,6 +37,7 @@ #include "application.h" #include "applicationmanager.h" #include "notificationmanager.h" +#include "qml-utilities.h" /*! \class NotificationManager @@ -271,6 +272,13 @@ NotificationManager *NotificationManager::instance() return s_instance; } +QObject *NotificationManager::instanceForQml(QQmlEngine *qmlEngine, QJSEngine *) +{ + if (qmlEngine) + retakeSingletonOwnershipFromQmlEngine(qmlEngine, instance()); + return instance(); +} + NotificationManager::NotificationManager(QObject *parent) : QAbstractListModel(parent) , d(new NotificationManagerPrivate()) diff --git a/src/manager-lib/notificationmanager.h b/src/manager-lib/notificationmanager.h index 296734d9..736a1aaf 100644 --- a/src/manager-lib/notificationmanager.h +++ b/src/manager-lib/notificationmanager.h @@ -47,7 +47,7 @@ public: ~NotificationManager(); static NotificationManager *createInstance(); static NotificationManager *instance(); - static QObject *instanceForQml(QQmlEngine *, QJSEngine *) { return instance(); } + static QObject *instanceForQml(QQmlEngine *qmlEngine, QJSEngine *); // the item model part int rowCount(const QModelIndex &parent = QModelIndex()) const; diff --git a/src/manager-lib/qml-utilities.cpp b/src/manager-lib/qml-utilities.cpp new file mode 100644 index 00000000..c3e692db --- /dev/null +++ b/src/manager-lib/qml-utilities.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pelagicore AG +** Contact: http://www.pelagicore.com/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Pelagicore Application Manager +** licenses may use this file in accordance with the commercial license +** agreement provided with the Software or, alternatively, in accordance +** with the terms contained in a written agreement between you and +** Pelagicore. For licensing terms and conditions, contact us at: +** http://www.pelagicore.com. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3 requirements will be +** met: http://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QTimer> +#include <private/qqmlmetatype_p.h> + +#include "qml-utilities.h" + +void retakeSingletonOwnershipFromQmlEngine(QQmlEngine *qmlEngine, QObject *singleton) +{ + // QQmlEngine is taking ownership of singletons after the first call to instanceForQml() and + // there is nothing to prevent this. This means that the singleton will be destroyed once the + // QQmlEngine is destroyed, which is not what we want. + // The workaround (until Qt has an API for that) is to remove the singleton QObject from QML's + // internal singleton registry *after* the instanceForQml() function has finished. + + QTimer::singleShot(0, qmlEngine, [qmlEngine, singleton]() { + foreach (const QQmlType *singletonType, QQmlMetaType::qmlSingletonTypes()) { + if (singletonType->singletonInstanceInfo()->qobjectApi(qmlEngine) == singleton) + singletonType->singletonInstanceInfo()->qobjectApis.remove(qmlEngine); + } + }); +} diff --git a/src/manager-lib/qml-utilities.h b/src/manager-lib/qml-utilities.h new file mode 100644 index 00000000..7cda41d4 --- /dev/null +++ b/src/manager-lib/qml-utilities.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pelagicore AG +** Contact: http://www.pelagicore.com/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Pelagicore Application Manager +** licenses may use this file in accordance with the commercial license +** agreement provided with the Software or, alternatively, in accordance +** with the terms contained in a written agreement between you and +** Pelagicore. For licensing terms and conditions, contact us at: +** http://www.pelagicore.com. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3 requirements will be +** met: http://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <QQmlEngine> + +void retakeSingletonOwnershipFromQmlEngine(QQmlEngine *qmlEngine, QObject *singleton); diff --git a/src/manager/main.cpp b/src/manager/main.cpp index 9ebb2d85..3deb6a31 100644 --- a/src/manager/main.cpp +++ b/src/manager/main.cpp @@ -486,8 +486,6 @@ int main(int argc, char *argv[]) //TODO: what should we do here? on the desktop this will obviously always fail qCCritical(LogSystem) << "WARNING:" << e.what(); } -#else - Q_UNUSED(nm) #endif // QT_DBUS_LIB #if defined(QT_PSHELLSERVER_LIB) @@ -558,11 +556,14 @@ int main(int argc, char *argv[]) // however dead-lock the process in Qt 5.2.1 with the main thread and the scene-graph // thread both waiting for each other. + delete nm; #if !defined(AM_HEADLESS) delete wm; #endif delete am; + delete engine; + #if defined(QT_PSSDP_LIB) if (ssdpOk) diff --git a/src/manager/windowmanager.cpp b/src/manager/windowmanager.cpp index 99fe1fc4..a3322303 100644 --- a/src/manager/windowmanager.cpp +++ b/src/manager/windowmanager.cpp @@ -46,6 +46,7 @@ #include "windowmanager.h" #include "waylandwindow.h" #include "inprocesswindow.h" +#include "qml-utilities.h" /*! \class WindowManager @@ -283,6 +284,13 @@ WindowManager *WindowManager::instance() return s_instance; } +QObject *WindowManager::instanceForQml(QQmlEngine *qmlEngine, QJSEngine *) +{ + if (qmlEngine) + retakeSingletonOwnershipFromQmlEngine(qmlEngine, instance()); + return instance(); +} + WindowManager::WindowManager(QQuickView *parent) : QAbstractListModel(parent) #ifndef AM_SINGLEPROCESS_MODE diff --git a/src/manager/windowmanager.h b/src/manager/windowmanager.h index 571e667d..fa03f106 100644 --- a/src/manager/windowmanager.h +++ b/src/manager/windowmanager.h @@ -72,7 +72,7 @@ public: ~WindowManager(); static WindowManager *createInstance(QQuickView* view); static WindowManager *instance(); - static QObject *instanceForQml(QQmlEngine *, QJSEngine *) { return instance(); } + static QObject *instanceForQml(QQmlEngine *qmlEngine, QJSEngine *); void enableWatchdog(bool enable); bool isWatchdogEnabled() const; |