summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@pelagicore.com>2015-10-29 01:12:27 +0100
committerRobert Griebl <robert.griebl@pelagicore.com>2015-11-02 10:14:00 +0000
commitc606a37aa4c8968a92d0fcaf27cedbf311397754 (patch)
tree467134131b21d85de38c6c0ffa2de593d560a96a
parent5a4d9e558c02a32114e98dcae2307eef688a7eb4 (diff)
downloadqtapplicationmanager-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.cpp5
-rw-r--r--src/installer-lib/applicationinstaller.h2
-rw-r--r--src/installer-lib/installer-lib.pro2
-rw-r--r--src/manager-lib/applicationmanager.cpp9
-rw-r--r--src/manager-lib/applicationmanager.h2
-rw-r--r--src/manager-lib/manager-lib.pro4
-rw-r--r--src/manager-lib/notificationmanager.cpp8
-rw-r--r--src/manager-lib/notificationmanager.h2
-rw-r--r--src/manager-lib/qml-utilities.cpp48
-rw-r--r--src/manager-lib/qml-utilities.h33
-rw-r--r--src/manager/main.cpp5
-rw-r--r--src/manager/windowmanager.cpp8
-rw-r--r--src/manager/windowmanager.h2
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;