summaryrefslogtreecommitdiffstats
path: root/examples/applicationmanager
diff options
context:
space:
mode:
authorDaniel d'Andrada <daniel.dandrada@luxoft.com>2018-07-10 14:40:25 +0200
committerRobert Griebl <robert.griebl@pelagicore.com>2018-07-11 11:57:12 +0000
commitba2a7ede9e1689c03099cd0ef619bc18cda29ef4 (patch)
tree043a0d1581988a56b5fd9956814defa774f3a031 /examples/applicationmanager
parentc414cb25d0cc2f7ce33e21e15ff52bc14d6421ad (diff)
Fix installation of the examples
- Only the project files and wrapper scripts were being installed - They were being put directly into Qt's example dir. They should be grouped into a applicationmanager subdirectory there, similarly to what other modules do. Task-number: AUTOSUITE-591 Change-Id: I1da6b28a8fe2e9210ad109309d30dfc1ad0d1e99 Reviewed-by: Robert Griebl <robert.griebl@pelagicore.com>
Diffstat (limited to 'examples/applicationmanager')
-rw-r--r--examples/applicationmanager/applicationmanager.pro14
-rw-r--r--examples/applicationmanager/custom-appman/custom-appman.cpp90
-rw-r--r--examples/applicationmanager/custom-appman/custom-appman.pro22
-rw-r--r--examples/applicationmanager/custom-appman/doc/images/custom-appman.pngbin0 -> 25621 bytes
-rw-r--r--examples/applicationmanager/custom-appman/doc/src/custom-appman.qdoc104
-rw-r--r--examples/applicationmanager/minidesk/am-config.yaml37
-rw-r--r--examples/applicationmanager/minidesk/apps/tld.minidesk.app1/app1.qml101
-rw-r--r--examples/applicationmanager/minidesk/apps/tld.minidesk.app1/icon.pngbin0 -> 5138 bytes
-rw-r--r--examples/applicationmanager/minidesk/apps/tld.minidesk.app1/info.yaml9
-rw-r--r--examples/applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml94
-rw-r--r--examples/applicationmanager/minidesk/apps/tld.minidesk.app2/icon.pngbin0 -> 5597 bytes
-rw-r--r--examples/applicationmanager/minidesk/apps/tld.minidesk.app2/info.yaml9
-rw-r--r--examples/applicationmanager/minidesk/doc/images/minidesk.pngbin0 -> 96692 bytes
-rw-r--r--examples/applicationmanager/minidesk/doc/src/minidesk.qdoc256
-rw-r--r--examples/applicationmanager/minidesk/minidesk.pro27
-rw-r--r--examples/applicationmanager/minidesk/minidesk.qmlproject17
-rw-r--r--examples/applicationmanager/minidesk/system-ui/Readme.qml91
-rw-r--r--examples/applicationmanager/minidesk/system-ui/main.qml238
-rw-r--r--examples/applicationmanager/monitor/am-config.yaml33
-rw-r--r--examples/applicationmanager/monitor/apps/tld.monitor.app/ApplicationWindow.qml80
-rw-r--r--examples/applicationmanager/monitor/apps/tld.monitor.app/app.qml83
-rw-r--r--examples/applicationmanager/monitor/apps/tld.monitor.app/dummyicon0
-rw-r--r--examples/applicationmanager/monitor/apps/tld.monitor.app/info.yaml9
-rw-r--r--examples/applicationmanager/monitor/doc/images/monitor.pngbin0 -> 31783 bytes
-rw-r--r--examples/applicationmanager/monitor/doc/src/monitor.qdoc109
-rw-r--r--examples/applicationmanager/monitor/monitor.pro23
-rw-r--r--examples/applicationmanager/monitor/monitor.qmlproject17
-rw-r--r--examples/applicationmanager/monitor/system-ui/MonitorChart.qml97
-rw-r--r--examples/applicationmanager/monitor/system-ui/MonitorText.qml58
-rw-r--r--examples/applicationmanager/monitor/system-ui/Switch.qml72
-rw-r--r--examples/applicationmanager/monitor/system-ui/Tile.qml58
-rw-r--r--examples/applicationmanager/monitor/system-ui/WindowContainer.qml77
-rw-r--r--examples/applicationmanager/monitor/system-ui/main.qml267
-rw-r--r--examples/applicationmanager/multi-views/am-config.yaml37
-rw-r--r--examples/applicationmanager/multi-views/apps/tld.multi-views.app/app1.qml79
-rw-r--r--examples/applicationmanager/multi-views/apps/tld.multi-views.app/icon.pngbin0 -> 5138 bytes
-rw-r--r--examples/applicationmanager/multi-views/apps/tld.multi-views.app/info.yaml9
-rw-r--r--examples/applicationmanager/multi-views/multi-views.pro21
-rw-r--r--examples/applicationmanager/multi-views/system-ui/Readme.qml71
-rw-r--r--examples/applicationmanager/multi-views/system-ui/main.qml227
-rw-r--r--examples/applicationmanager/softwarecontainer-plugin/README.md71
-rw-r--r--examples/applicationmanager/softwarecontainer-plugin/service-manifest.d/io.qt.ApplicationManager.Application.json58
-rw-r--r--examples/applicationmanager/softwarecontainer-plugin/softwarecontainer-plugin.pro21
-rw-r--r--examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.cpp585
-rw-r--r--examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.h140
-rw-r--r--examples/applicationmanager/startup-plugin/startup-plugin.cpp85
-rw-r--r--examples/applicationmanager/startup-plugin/startup-plugin.h75
-rw-r--r--examples/applicationmanager/startup-plugin/startup-plugin.pro14
48 files changed, 3585 insertions, 0 deletions
diff --git a/examples/applicationmanager/applicationmanager.pro b/examples/applicationmanager/applicationmanager.pro
new file mode 100644
index 00000000..bf10ac2c
--- /dev/null
+++ b/examples/applicationmanager/applicationmanager.pro
@@ -0,0 +1,14 @@
+TEMPLATE = subdirs
+
+SUBDIRS = \
+ minidesk \
+ monitor \
+ multi-views \
+ startup-plugin \
+
+# remove the !headless and handle this in the example when we switch to the new configure system
+!headless:SUBDIRS += \
+ custom-appman \
+
+linux:!android:SUBDIRS += \
+ softwarecontainer-plugin \
diff --git a/examples/applicationmanager/custom-appman/custom-appman.cpp b/examples/applicationmanager/custom-appman/custom-appman.cpp
new file mode 100644
index 00000000..decccd08
--- /dev/null
+++ b/examples/applicationmanager/custom-appman/custom-appman.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+#include <QtAppManCommon/global.h>
+#include <QtAppManCommon/logging.h>
+#include <QtAppManMain/main.h>
+#include <QtAppManMain/defaultconfiguration.h>
+#include <QtAppManPackage/package.h>
+#include <QtAppManInstaller/sudo.h>
+
+
+QT_USE_NAMESPACE_AM
+
+Q_DECL_EXPORT int main(int argc, char *argv[])
+{
+ QCoreApplication::setApplicationName(qSL("Custom ApplicationManager"));
+ QCoreApplication::setApplicationVersion("0.1");
+
+ Logging::initialize(argc, argv);
+
+ Package::ensureCorrectLocale();
+
+ try {
+ QStringList deploymentWarnings;
+ Sudo::forkServer(Sudo::DropPrivilegesPermanently, &deploymentWarnings);
+
+ Main a(argc, argv);
+
+ DefaultConfiguration cfg;
+ cfg.parse();
+
+ a.setup(&cfg, deploymentWarnings);
+ a.loadQml(cfg.loadDummyData());
+ a.showWindow(cfg.fullscreen() && !cfg.noFullscreen());
+
+ return MainBase::exec();
+ } catch (const std::exception &e) {
+ qCCritical(LogSystem) << "ERROR:" << e.what();
+ return 2;
+ }
+}
diff --git a/examples/applicationmanager/custom-appman/custom-appman.pro b/examples/applicationmanager/custom-appman/custom-appman.pro
new file mode 100644
index 00000000..e1ebab9e
--- /dev/null
+++ b/examples/applicationmanager/custom-appman/custom-appman.pro
@@ -0,0 +1,22 @@
+TEMPLATE = app
+TARGET = custom-appman
+
+CONFIG += c++11 link_pkgconfig exceptions console
+CONFIG -= app_bundle qml_debug
+
+DEFINES += QT_MESSAGELOGCONTEXT
+
+QT = appman_main-private
+
+SOURCES = custom-appman.cpp
+
+OTHER_FILES += \
+ doc/src/*.qdoc \
+ doc/images/*.png \
+
+target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/custom-appman
+INSTALLS += target
+
+example_sources.path = $$target.path
+example_sources.files = $SOURCES doc
+INSTALLS += example_sources
diff --git a/examples/applicationmanager/custom-appman/doc/images/custom-appman.png b/examples/applicationmanager/custom-appman/doc/images/custom-appman.png
new file mode 100644
index 00000000..64bae006
--- /dev/null
+++ b/examples/applicationmanager/custom-appman/doc/images/custom-appman.png
Binary files differ
diff --git a/examples/applicationmanager/custom-appman/doc/src/custom-appman.qdoc b/examples/applicationmanager/custom-appman/doc/src/custom-appman.qdoc
new file mode 100644
index 00000000..5ea6d44f
--- /dev/null
+++ b/examples/applicationmanager/custom-appman/doc/src/custom-appman.qdoc
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:FDL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\example custom-appman
+\title Implementing a Custom Application-Manager Example
+\image custom-appman.png Screenshot
+\brief Basic structure and starting point for a custom application-manager executable.
+\ingroup applicationmanager-examples
+
+\section1 Introduction
+
+The application-manager is compiled as a self-contained executable that can be configured
+in large parts through the YAML based config file system and startup plugins. However it may still
+be necessary to implement a custom application-manager executable to have more influence over the
+startup behavior.
+
+\note Please note however, that all C++ classes in the application-manager modules are considered private
+API at the moment, so there are no compatibility guarantees at all.
+
+If you still desire to go down that road however, this example will provide you with an starting
+point to build your custom implementation upon.
+
+Keep in mind though, that this custom application-manager executable will need a System-UI to
+display something on the screen, just as the standard \c appman executable.
+
+\section1 Walkthrough
+
+Following is a breakdown of the minimal code needed for such a custom implementation:
+
+\quotefromfile custom-appman/custom-appman.cpp
+\skipto #include
+\printuntil QT_USE_NAMESPACE_AM
+
+The application-manager is split into functional building blocks/libraries. These includes will
+pull in the basic set of classes needed.
+In order to avoid possible clashes with QML plugins, all of the application-manager's symbols are
+namespaced - \c QT_USE_NAMESPACE_AM will expand to the matching \c using statement.
+
+\skipto QCoreApplication::setApplicationName
+\printuntil QCoreApplication::setApplicationVersion
+
+Not application-manager specific, but having an application name and version set is generally
+a good idea.
+
+\printline Logging::init
+
+We want the logging part of the application-manager initialized as early as possible, especially
+when dealing with DLT logging.
+
+\printline Package::ensure
+
+If you are using the installer part of the application-manager, this function needs to be called
+\e before the QApplication constructor to make sure your C locale is an UTF-8 variant (this is a
+requirement in order to get deterministic results when using \c libarchive with non-ASCII filenames).
+
+\printto try
+
+Again, for the installer part only, an additional setup step is necessary before running the
+QApplication constructor: if the executable is setuid-root, this call will \c fork of a child
+process which keeps the root privileges while the main process permanently drop them.
+
+\printuntil return 2
+\printline }
+
+This \c try block is the heart of the custom application-manager. You need to create a \c Main
+(which is a class derived from QGuiApplication) object plus a suitable configuration object: in
+this simple case we just use the application-manager's default YAML parsing, so we instantiate
+a \c DefaultConfiguration object.
+The rest of the function consists of parsing the configuration and then calling the relevant
+setup routines on the \c Main object.
+Since \c Main can be derived differently depending on your application-manager configuration
+(headless, with widgets or standard), you would need to know the correct base-class for the exec()
+call - the \c MainBase typedef will circumvent that problem though.
+
+Keep in mind that most functions in the application-manager will throw exceptions that are
+derived from \c std::exception, so a \c catch handler is a must.
+
+*/
diff --git a/examples/applicationmanager/minidesk/am-config.yaml b/examples/applicationmanager/minidesk/am-config.yaml
new file mode 100644
index 00000000..269e20c7
--- /dev/null
+++ b/examples/applicationmanager/minidesk/am-config.yaml
@@ -0,0 +1,37 @@
+formatVersion: 1
+formatType: am-configuration
+---
+installationLocations:
+- id: "internal-0"
+ installationPath: "/tmp/minidesk/apps"
+ documentPath: "/tmp/minidesk/docs"
+ mountPoint: "/tmp"
+ isDefault: true
+
+applications:
+ builtinAppsManifestDir: "${CONFIG_PWD}/apps"
+ installedAppsManifestDir: "/tmp/minidesk/manifests"
+ appImageMountDir: "/tmp/minidesk/image-mounts"
+ database: "/tmp/minidesk/apps.db"
+
+logging:
+ rules:
+ - "*=false"
+ - "qt.*=false"
+ - "am.*=false"
+ - "qml*=true"
+ - "*.warning=true"
+ - "*.critical=true"
+
+ui:
+ fullscreen: no
+ mainQml: "${CONFIG_PWD}/system-ui/main.qml"
+
+systemProperties:
+ protected:
+ light: on
+
+# development setup:
+flags:
+ noSecurity: yes
+ noUiWatchdog: yes
diff --git a/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/app1.qml b/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/app1.qml
new file mode 100644
index 00000000..76ab5dc0
--- /dev/null
+++ b/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/app1.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtApplicationManager 1.0
+
+ApplicationManagerWindow {
+ id: root
+ color: "peachpuff"
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 180; height: 180; radius: width/4
+ color: "peru"
+
+ Image {
+ source: ApplicationInterface.icon
+ anchors.centerIn: parent
+ }
+
+ RotationAnimation on rotation {
+ id: rotation
+ from: 0; to: 360; loops: Animation.Infinite; duration: 4000
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (rotation.paused) {
+ rotation.resume();
+ } else {
+ rotation.pause();
+ root.setWindowProperty("rotation", parent.rotation);
+ }
+ popUp.visible = rotation.paused;
+ }
+ }
+ }
+
+ ApplicationManagerWindow {
+ id: popUp
+ visible: false
+ color: "lightcoral"
+
+ Text {
+ anchors.centerIn: parent
+ text: "App1 paused!"
+ }
+
+ Component.onCompleted: setWindowProperty("type", "pop-up");
+ }
+}
diff --git a/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/icon.png b/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/icon.png
new file mode 100644
index 00000000..adb840ce
--- /dev/null
+++ b/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/icon.png
Binary files differ
diff --git a/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/info.yaml b/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/info.yaml
new file mode 100644
index 00000000..953e852f
--- /dev/null
+++ b/examples/applicationmanager/minidesk/apps/tld.minidesk.app1/info.yaml
@@ -0,0 +1,9 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'tld.minidesk.app1'
+icon: 'icon.png'
+code: 'app1.qml'
+runtime: 'qml'
+name:
+ en: 'App1'
diff --git a/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml b/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml
new file mode 100644
index 00000000..88b1f745
--- /dev/null
+++ b/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/app2.qml
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtApplicationManager 1.0
+
+ApplicationManagerWindow {
+ color: ApplicationInterface.systemProperties.light ? "peachpuff" : "black"
+
+ Image {
+ anchors.centerIn: parent
+ source: ApplicationInterface.icon
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ var notification = ApplicationInterface.createNotification();
+ notification.summary = "Let there be light!"
+ notification.show();
+ }
+ }
+ }
+
+ onWindowPropertyChanged: console.log("App2: onWindowPropertyChanged - " + name + ": " + value);
+
+ Connections {
+ target: ApplicationInterface
+ onOpenDocument: console.log("App2: onOpenDocument - " + documentUrl);
+ onQuit: target.acknowledgeQuit();
+ }
+
+ ApplicationInterfaceExtension {
+ id: extension
+ name: "tld.minidesk.interface"
+
+ onReadyChanged: console.log("App2: circumference function returned: "
+ + object.circumference(2.0, "plate") + ", it used pi = " + object.pi);
+ }
+
+ Connections {
+ target: extension.object
+ onComputed: console.log("App2: " + what + " has been computed");
+ onPiChanged: console.log("App2: pi changed: " + target.pi);
+ }
+}
diff --git a/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/icon.png b/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/icon.png
new file mode 100644
index 00000000..3f8caa42
--- /dev/null
+++ b/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/icon.png
Binary files differ
diff --git a/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/info.yaml b/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/info.yaml
new file mode 100644
index 00000000..65759aa8
--- /dev/null
+++ b/examples/applicationmanager/minidesk/apps/tld.minidesk.app2/info.yaml
@@ -0,0 +1,9 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'tld.minidesk.app2'
+icon: 'icon.png'
+code: 'app2.qml'
+runtime: 'qml'
+name:
+ en: 'App2'
diff --git a/examples/applicationmanager/minidesk/doc/images/minidesk.png b/examples/applicationmanager/minidesk/doc/images/minidesk.png
new file mode 100644
index 00000000..0a16982a
--- /dev/null
+++ b/examples/applicationmanager/minidesk/doc/images/minidesk.png
Binary files differ
diff --git a/examples/applicationmanager/minidesk/doc/src/minidesk.qdoc b/examples/applicationmanager/minidesk/doc/src/minidesk.qdoc
new file mode 100644
index 00000000..ad85c36e
--- /dev/null
+++ b/examples/applicationmanager/minidesk/doc/src/minidesk.qdoc
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:FDL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\example minidesk
+\title Desktop System-UI Example
+\image minidesk.png Screenshot
+\brief Minimal Desktop System-UI in pure QML
+\ingroup applicationmanager-examples
+
+\section1 Introduction
+
+The \e {Desktop System-UI Example} showcases the application-manager API in a simple fashion. The
+focus is on the concepts, less on elegance or completeness, for instance no error checking is done.
+Some features will only print debug messages without further functionality. A classic desktop with
+server-side window decorations is emulated.
+
+The following features are supported:
+\list
+\li Start applications by clicking an icon on the top left
+\li Stop applications by clicking on the top/left window decoration rectangle
+\li Raise applications by clicking on the decoration
+\li Drag windows by pressing on the window decoration and moving
+\li System-UI sends 'propA' change when an app is started
+\li System-UI and App2 react on window property changes with a debug message
+\li App1 animation can be stopped and restarted by a click
+\li App1 sends 'rotation' property to System-UI on stop
+\li App1 shows a pop-up on the System-UI while it is paused
+\li App2 will make use of an IPC extension when it is started
+\li App2 logs the document URL it has been started with
+\li App2 triggers a notification in the System-UI when the bulb icon is clicked
+\li A separate (\"wayland\") process started outside of appman will be shown as App1
+\endlist
+
+\note The example can be run in single- and multi-process mode. In the following, multi-process is
+assumed and corresponding terminology is used. The terms \e client and \e application, respectively
+\e server and \e {System-UI} are used interchangeably. The System-UI comprises compositing and
+generic inter-process communication (IPC).
+
+\section2 Invocation
+The example can be started from within the minidesk folder with:
+\badcode
+path/to/bin/appman -c am-config.yaml -r
+\endcode
+
+\note The application-manager attempts to register a \c freedesktop.org compliant notification
+server. DBus errors might occur if it conflicts with the server running on the host desktop
+environment. In this case, a private session bus needs to be started by adding the
+\c --start-session-dbus option:
+\badcode
+path/to/bin/appman -c am-config.yaml -r --start-session-dbus
+\endcode
+
+\section1 Walkthrough
+
+\section2 System-UI Window
+
+\quotefromfile minidesk/system-ui/main.qml
+\skipto import Qt
+\printuntil text:
+\printline }
+\dots
+
+The \l{QtApplicationManager} module has to be imported to be able to access the application-manager
+APIs. The System-UI window has a fixed size and linen background color. Instead of a \l{Rectangle},
+the root element could as well be a \l{Window}. On top of the background the
+\l{minidesk/system-ui/Readme.qml}{Readme} element is shown that displays a usage how-to. At the
+bottom left there is a textual indication for whether the application-manager runs in single- or
+multi-process mode.
+
+\section2 Launcher
+
+\printto System-UI chrome for applications
+
+A \l{Repeater} provides the application icons arranged in a \l{Column} on the top-left corner of
+the System-UI. This is achieved by using the \l{ApplicationManager} element as the model. Amongst
+others, it provides the \c icon role which is used as the \l{Image} source URL. The \c icon URL is
+defined in the \l{Manifest Definition}{info.yaml} file of the application. To indicate that an
+application has been launched, the opacity of the corresponding application's icon is decreased
+through a binding to the \c isRunning role.
+
+Clicking on an application icon will launch the corresponding application through a call to
+\l {ApplicationManager::startApplication()}{ApplicationManager.startApplication()}. The first
+argument, \c applicationId, is provided by the ApplicationManager model (e.g. "tld.minidesk.app1"
+for the first application). Both applications will be started with the (optional) document URL
+"documentUrl". Subsequent clicks on an already launched icon will still call
+\l{ApplicationManager::}{startApplication()}, but will be silently ignored. The content of the
+\c appContainter will be set below in the \c onWindowReady handler. The content is provided by the
+two applications in an \l{ApplicationManagerWindow} root element.
+
+\section2 Application Windows in the System-UI
+
+\printto System-UI for a pop-up and notification
+
+This second \l{Repeater} provides the window chrome for the actual applications in its delegate.
+The model is the same as for the first \l{Repeater}, essentially the \l{ApplicationManager}
+element. The chrome consists of:
+\list
+\li A fixed size window \l{Rectangle} with a "tan" color. The default location depends on the
+ \c model.index, hence each application has a different location.
+\li The name of the application, prefixed with "Decoration" on the top horizontal center. The name
+ is also provided by the \l{ApplicationManager} model and read from the application's
+ \l{Manifest Definition}{info.yaml} file.
+\li A \l{MouseArea} for dragging the window and setting the z-order. The \l{MouseArea} fills the
+ entire window, though the application container is placed on top of it and hence it will not
+ handle dragging. Simply increasing the z-order on each click is only done to keep the code to
+ a minimum.
+\li A small chocolate-colored \l Rectangle on the top left corner for closing the window chrome and
+ stopping the actual application (see
+ \l{ApplicationManager::stopApplication()}{stopApplication()}).
+\li A container \l{Item} where the actual application will be placed in. The \c appContainer is
+ exposed, so it can later be referenced to place the actual application window in it.
+\endlist
+
+\section2 Pop-ups
+
+Two approaches are implemented to display pop-ups in the System-UI:
+\list
+\li Through a window rendered by the client application
+\li Through the notification API provided by the application-manager
+\endlist
+This is the corresponding System-UI code:
+\printto Handler for WindowManager signals
+
+\section3 Client Application Rendering
+The \c popUpContainer \l{Item} provides a System-UI recipient for the pop-up rendered
+by App1. App1 instantiates another \l{ApplicationManagerWindow} for the pop-up within its
+\l{ApplicationManagerWindow} root element, as shown here:
+\quotefromfile minidesk/apps/tld.minidesk.app1/app1.qml
+\skipto Rectangle
+\skipto ApplicationManagerWindow
+\printuntil Component.onCompleted
+\printline }
+The \l{ApplicationManagerWindow::setWindowProperty}{ApplicationManagerWindow.setWindowProperty()}
+method is used to set a freely selectable shared property. Here we choose \c{type: "pop-up"} to
+indicate that the window is supposed to be shown as a pop-up. In the \c onWindowReady handler below
+the System-UI checks for this property and handles the window appropriately as a pop-up.
+
+\section3 Notification API Usage
+
+An alternative to the above approach is to use the application-manager's \l{Notification} API on
+the application (client) side and the \l{NotificationManager} API on the System-UI (server) side.
+The following code is invoked when the \e bulb icon of App2 is clicked:
+
+\quotefromfile minidesk/apps/tld.minidesk.app2/app2.qml
+\skipto var notification
+\printuntil notification.show();
+
+App2 creates a new \l{Notification} element, sets its \l{Notification::summary}{summary} property
+and calls \l{Notification::show()}{show()} on it. This call will increase the
+\l{NotificationManager::count}{NotificationManager.count} on the System-UI side, and subsequently
+the \l{Text} element's text property will be set to the \c summary string of the first
+notification. Presenting the first notification only is a simplification to keep the code short.
+
+\section2 WindowManager Signal Handler
+
+\quotefromfile minidesk/system-ui/main.qml
+\skipto Handler for WindowManager signals
+\printto IPC extension
+This is the vital part of the System-UI, where the window surfaces of the applications are mapped
+to items in the System-UI. The \l {WindowManager::windowReady}{onWindowReady} handler is invoked
+when a new application window is shown (visibility set to true). The \c index parameter references
+into the \l{WindowManager} model, which holds the window surfaces. The first line translates this
+index to the application index of the \l{ApplicationManager} model and assigns it to \c appIndex.
+
+Only the "pop-up" ApplicationManagerWindow of App1 has the user-defined \c type property set. All
+other windows don't have the \c type property. In the latter case, the application's \c window
+passed to \c onWindowReady is re-parented to the System-UI's \c winChrome. Also the size of the
+window is set to fill the entire \c appContainer.
+
+There is a special treatment for an invalid \c appIndex for demonstration purposes: it is assumed
+that the window surface is from an external application that follows the Wayland protocol. For
+example a Qt application could be started on the command line as follows:
+
+\badcode
+QT_WAYLAND_DISABLE_WINDOWDECORATION=1 ./qtapp -platform wayland
+\endcode
+
+This application will then be shown inside the App1 container.
+\c QT_WAYLAND_DISABLE_WINDOWDECORATION is set to disable client side window decorations, since they
+are provided by the System-UI. Note, that an application started in this way, can just as well be
+closed only from the command line.
+
+Pop-ups (windows with type "pop-up") are re-parented to their respective \c popUpContainer.
+
+The \c onWindowClosing handler determines if the window is a top-level application window. If so,
+the applications's \c winChrome is set to invisible and the corresponding application icon is set
+to fully opaque to indicate that the application is not running. The \c onWindowLost handler calls
+\l{WindowManager::releaseWindow()}{WindowManager.releaseWindow()} to free all resources associated
+with the \c window.
+
+
+\section2 IPC Extension
+The following snippet demonstrates how the \l{ApplicationIPCInterface} can be used to define an IPC
+extension. The IPC interface has to be defined in the System-UI, for instance:
+\printuntil Component.onCompleted
+\printline }
+
+Here, a property \c pi is defined, as well as a signal \c computed and a function \c circumference.
+After registering this interface with
+\l{ApplicationIPCManager::registerInterface()}{ApplicationIPCManager.registerInterface()}, it can
+be used from the application processes.
+
+On the application side, the \l{ApplicationInterfaceExtension} type has to be used. Here is how
+App2 makes use of this interface extension:
+
+\quotefromfile minidesk/apps/tld.minidesk.app2/app2.qml
+\skipto ApplicationInterfaceExtension
+\printuntil onPiChanged
+\printline }
+
+The interface is used here immediately when it becomes ready. It can, of course, be accessed from
+elsewhere, too. The \l{ApplicationInterfaceExtension::name}{ApplicationInterfaceExtension.name} has
+to match the name it was registered with in
+\l{ApplicationIPCManager::registerInterface()}{ApplicationIPCManager.registerInterface()}.
+
+\section2 Application Termination
+When an application is stopped from the System-UI through
+\l{ApplicationManager::stopApplication()}{ApplicationManager.stopApplication()}, it will be sent
+the \l{ApplicationInterface::quit()}{ApplicationInterface.quit()} signal. The application can do
+some clean-up and must subsequently confirm with
+\l{ApplicationInterface::acknowledgeQuit()}{ApplicationInterface.acknowledgeQuit()}, like App2 does:
+\quotefromfile minidesk/apps/tld.minidesk.app2/app2.qml
+\skipto Connections
+\printuntil onQuit
+\printline }
+
+Note that App1 is not well-behaved: it does not acknowledge the \c quit signal and will hence simply
+be terminated by the application-manager.
+
+*/
diff --git a/examples/applicationmanager/minidesk/minidesk.pro b/examples/applicationmanager/minidesk/minidesk.pro
new file mode 100644
index 00000000..d12a6917
--- /dev/null
+++ b/examples/applicationmanager/minidesk/minidesk.pro
@@ -0,0 +1,27 @@
+TEMPLATE = app
+CONFIG += am-systemui
+
+OTHER_FILES += \
+ am-config.yaml \
+ minidesk.qmlproject \
+ doc/src/*.qdoc \
+ doc/images/*.png \
+ system-ui/*.qml \
+ apps/tld.minidesk.app1/*.yaml \
+ apps/tld.minidesk.app1/*.qml \
+ apps/tld.minidesk.app1/*.png \
+ apps/tld.minidesk.app2/*.yaml \
+ apps/tld.minidesk.app2/*.qml \
+ apps/tld.minidesk.app2/*.png \
+
+target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/minidesk
+INSTALLS += target
+
+AM_COPY_DIRECTORIES += apps system-ui
+AM_COPY_FILES += am-config.yaml
+
+AM_DEFAULT_ARGS=-c am-config.yaml --start-session-dbus --verbose
+
+example_sources.path = $$target.path
+example_sources.files = $$AM_COPY_FILES $$AM_COPY_DIRECTORIES doc
+INSTALLS += example_sources
diff --git a/examples/applicationmanager/minidesk/minidesk.qmlproject b/examples/applicationmanager/minidesk/minidesk.qmlproject
new file mode 100644
index 00000000..5ce6345e
--- /dev/null
+++ b/examples/applicationmanager/minidesk/minidesk.qmlproject
@@ -0,0 +1,17 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "system-ui/main.qml"
+
+ QmlFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "apps"
+ }
+ Files {
+ directory: "."
+ filter: "*.yaml"
+ }
+}
+
diff --git a/examples/applicationmanager/minidesk/system-ui/Readme.qml b/examples/applicationmanager/minidesk/system-ui/Readme.qml
new file mode 100644
index 00000000..01144436
--- /dev/null
+++ b/examples/applicationmanager/minidesk/system-ui/Readme.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ anchors.fill: parent
+
+ Column {
+ width: paragraph.implicitWidth
+ height: heading.implicitHeight + paragraph.implicitHeight + 80
+ anchors.centerIn: parent
+ spacing: 10
+
+ Text {
+ id: heading
+ color: "cornflowerblue"
+ font { pixelSize: 20; weight: Font.Bold }
+ text: "Minimal Desktop System-UI in pure QML"
+ }
+
+ Text {
+ id: paragraph
+ color: "grey"
+ font.pixelSize: 16
+ text: "The following features are supported:\n" +
+ "\u2022 Start applications by clicking an icon on the top left\n" +
+ "\u2022 Stop applications by clicking on the top/left window decoration rectangle\n" +
+ "\u2022 Raise applications by clicking on the decoration\n" +
+ "\u2022 Drag windows by pressing on the window decoration and moving\n" +
+ "\u2022 System-UI sends 'propA' change when an app is started\n" +
+ "\u2022 System-UI and App2 react on window property changes with a debug message\n" +
+ "\u2022 App1 animation can be stopped and restarted by a click\n" +
+ "\u2022 App1 sends 'rotation' property to System-UI on stop\n" +
+ "\u2022 App1 shows a pop-up on the System-UI while it is paused\n" +
+ "\u2022 App2 will make use of an IPC extension when it is started\n" +
+ "\u2022 App2 logs the document URL it has been started with\n" +
+ "\u2022 App2 triggers a notification in the System-UI when the bulb icon is clicked\n" +
+ "\u2022 A separate (\"wayland\") process started outside of appman will be shown as App1"
+ }
+ }
+}
diff --git a/examples/applicationmanager/minidesk/system-ui/main.qml b/examples/applicationmanager/minidesk/system-ui/main.qml
new file mode 100644
index 00000000..1ba08ddc
--- /dev/null
+++ b/examples/applicationmanager/minidesk/system-ui/main.qml
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtApplicationManager 1.0
+
+Rectangle {
+ width: 1024
+ height: 640
+ color: "linen"
+
+ Readme {}
+
+ Text {
+ anchors.bottom: parent.bottom
+ text: (ApplicationManager.singleProcess ? "Single" : "Multi") + "-Process Mode"
+ }
+
+ // Application launcher panel
+ Column {
+ id: launcher
+ Repeater {
+ id: menuItems
+ model: ApplicationManager
+
+ Image {
+ source: icon
+ opacity: isRunning ? 0.3 : 1.0
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: application.start();
+ }
+ }
+ }
+ }
+
+ // System-UI chrome for applications
+ Repeater {
+ model: ListModel { id: topLevelWindowsModel }
+
+ delegate: Rectangle {
+ id: winChrome
+
+ width: 400; height: 320
+ z: model.index
+ color: "tan"
+
+ property bool manuallyClosed: false
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Decoration: " + model.window.application.name("en")
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ drag.target: parent
+ onPressed: topLevelWindowsModel.move(model.index, topLevelWindowsModel.count-1, 1);
+ }
+
+ Rectangle {
+ width: 25; height: 25
+ color: "chocolate"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ winChrome.manuallyClosed = true;
+ model.window.application.stop();
+ }
+ }
+ }
+
+ WindowItem {
+ anchors.fill: parent
+ anchors.margins: 3
+ anchors.topMargin: 25
+ window: model.window
+ }
+
+ Component.onCompleted: {
+ winChrome.x = 300 + model.index * 50;
+ winChrome.y = 10 + model.index * 30;
+ }
+
+ states: [
+ State {
+ name: "open"
+ when: model.window && model.window.contentState === WindowObject.SurfaceWithContent && !manuallyClosed
+ PropertyChanges {
+ target: winChrome
+ opacity: 1
+ scale: 1
+ visible: true
+ }
+ }
+ ]
+
+ opacity: 0.25
+ scale: 0.50
+ visible: false
+
+ transitions: [
+ Transition {
+ to: "open"
+ NumberAnimation { target: winChrome; properties: "opacity,scale"; duration: 500; easing.type: Easing.OutQuad}
+ },
+ Transition {
+ from: "open"
+ SequentialAnimation {
+ PropertyAction { target: winChrome; property: "visible"; value: true } // we wanna see the window during the closing animation
+ NumberAnimation { target: winChrome; properties: "opacity,scale"; duration: 500; easing.type: Easing.InQuad}
+ ScriptAction { script: {
+ if (model.window.contentState === WindowObject.NoSurface)
+ topLevelWindowsModel.remove(model.index, 1);
+ } }
+ }
+ }
+ ]
+ }
+ }
+
+ // System-UI for pop-ups
+ Repeater {
+ model: ListModel { id: popupsModel }
+ delegate: WindowItem {
+ z: 100 + model.index
+ width: 200; height: 60
+ anchors.centerIn: parent
+ window: model.window
+ Connections {
+ target: model.window
+ onContentStateChanged: {
+ if (model.window.contentState === WindowObject.NoSurface)
+ popupsModel.remove(model.index, 1);
+ }
+ }
+ Rectangle {
+ width: 25
+ height: 25
+ anchors.horizontalCenter: parent.right
+ anchors.verticalCenter: parent.top
+ color: "chocolate"
+ Text { text: "X"; anchors.centerIn: parent }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: model.window.close()
+ }
+ }
+ }
+ }
+
+ // System-UI for a notification
+ Text {
+ z: 30001
+ font.pixelSize: 46
+ anchors.centerIn: parent
+ text: NotificationManager.count > 0 ? NotificationManager.get(0).summary : ""
+ }
+
+ // Handler for WindowManager signals
+ Connections {
+ target: WindowManager
+ onWindowAdded: {
+ // separate windows by their type, adding them to their respective model
+ var model = window.windowProperty("type") === "pop-up" ? popupsModel : topLevelWindowsModel;
+ model.append({"window":window});
+ }
+ }
+
+ // IPC extension
+ ApplicationIPCInterface {
+ id: extension
+
+ property double pi
+ signal computed(string what)
+ readonly property var _decltype_circumference: { "double": [ "double", "string" ] }
+ function circumference(radius, thing) {
+ console.log("SystemUI: circumference(" + radius + ", \"" + thing + "\") has been called");
+ pi = 3.14;
+ var circ = 2 * pi * radius;
+ computed("circumference for " + thing);
+ return circ;
+ }
+
+ Component.onCompleted: ApplicationIPCManager.registerInterface(extension, "tld.minidesk.interface", {});
+ }
+}
diff --git a/examples/applicationmanager/monitor/am-config.yaml b/examples/applicationmanager/monitor/am-config.yaml
new file mode 100644
index 00000000..5212d8fb
--- /dev/null
+++ b/examples/applicationmanager/monitor/am-config.yaml
@@ -0,0 +1,33 @@
+formatVersion: 1
+formatType: am-configuration
+---
+
+installationLocations:
+- id: "internal-0"
+ installationPath: "/tmp/am/apps"
+ documentPath: "/tmp/am/docs"
+ mountPoint: "/tmp"
+ isDefault: true
+
+applications:
+ builtinAppsManifestDir: "apps"
+ installedAppsManifestDir: "/tmp/am/manifests"
+ appImageMountDir: "/tmp/am/image-mounts"
+ database: "/tmp/am/apps.db"
+
+logging:
+ rules:
+ - "*=false"
+ - "qt.*=false"
+ - "am.*=false"
+ - "qml*=true"
+ - "*.warning=true"
+ - "*.critical=true"
+
+ui:
+ mainQml: "system-ui/main.qml"
+
+# development setup:
+flags:
+ noSecurity: yes
+ noUiWatchdog: yes
diff --git a/examples/applicationmanager/monitor/apps/tld.monitor.app/ApplicationWindow.qml b/examples/applicationmanager/monitor/apps/tld.monitor.app/ApplicationWindow.qml
new file mode 100644
index 00000000..d326205a
--- /dev/null
+++ b/examples/applicationmanager/monitor/apps/tld.monitor.app/ApplicationWindow.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtApplicationManager 1.0
+
+ApplicationManagerWindow {
+ id: root
+
+ property alias title: title.text
+ property alias idle: pause.duration
+ property string windowType
+
+ color: "darkgreen"
+
+ Text{
+ id: title
+ color: "white"
+ anchors.centerIn: parent
+ }
+
+ SequentialAnimation on color {
+ loops: Animation.Infinite
+ ColorAnimation { to: "darkolivegreen"; duration: 500 }
+ PauseAnimation { id: pause; duration: 0 }
+ ColorAnimation { to: "darkgreen"; duration: 500 }
+ PauseAnimation { duration: pause.duration }
+ }
+
+ onWindowTypeChanged: root.setWindowProperty("windowType", windowType)
+}
diff --git a/examples/applicationmanager/monitor/apps/tld.monitor.app/app.qml b/examples/applicationmanager/monitor/apps/tld.monitor.app/app.qml
new file mode 100644
index 00000000..e8c57e0a
--- /dev/null
+++ b/examples/applicationmanager/monitor/apps/tld.monitor.app/app.qml
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtApplicationManager 1.0
+
+ApplicationWindow {
+ title: "Primary Window"
+ windowType: "primary"
+
+ ApplicationWindow {
+ title: "Secondary Window"
+ windowType: "secondary"
+ visible: true
+ idle: 500
+ }
+
+ Timer {
+ property int count: 0
+ running: true
+ repeat: true
+ onTriggered: {
+ if (count < 100) {
+ var arr = [];
+ var idx = 200000;
+ while (idx > 0)
+ arr[idx] = idx--;
+ count++;
+ } else {
+ repeat = false;
+ }
+ }
+ }
+}
diff --git a/examples/applicationmanager/monitor/apps/tld.monitor.app/dummyicon b/examples/applicationmanager/monitor/apps/tld.monitor.app/dummyicon
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/examples/applicationmanager/monitor/apps/tld.monitor.app/dummyicon
diff --git a/examples/applicationmanager/monitor/apps/tld.monitor.app/info.yaml b/examples/applicationmanager/monitor/apps/tld.monitor.app/info.yaml
new file mode 100644
index 00000000..cd0a58c8
--- /dev/null
+++ b/examples/applicationmanager/monitor/apps/tld.monitor.app/info.yaml
@@ -0,0 +1,9 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'tld.monitor.app'
+icon: 'dummyicon'
+code: 'app.qml'
+runtime: 'qml'
+name:
+ en: 'Application'
diff --git a/examples/applicationmanager/monitor/doc/images/monitor.png b/examples/applicationmanager/monitor/doc/images/monitor.png
new file mode 100644
index 00000000..d3b3cddd
--- /dev/null
+++ b/examples/applicationmanager/monitor/doc/images/monitor.png
Binary files differ
diff --git a/examples/applicationmanager/monitor/doc/src/monitor.qdoc b/examples/applicationmanager/monitor/doc/src/monitor.qdoc
new file mode 100644
index 00000000..603f6b36
--- /dev/null
+++ b/examples/applicationmanager/monitor/doc/src/monitor.qdoc
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:FDL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\example monitor
+\title Performance Monitoring Example
+\image monitor.png Screenshot
+\brief A resource and performance monitor
+\ingroup applicationmanager-examples
+
+\section1 Introduction
+
+This example shows the basic usage of system and process monitoring APIs offered by the
+application-manager:
+ \list
+ \li SystemMonitor
+ \li ProcessMonitor
+ \endlist
+
+The example monitors performance (frame rate), as well as rescource usage (memory and CPU).
+
+\section2 Invocation
+The example can be started from within the "monitor" folder with:
+\badcode
+path/to/bin/appman -c am-config.yaml -r
+\endcode
+
+\note The application-manager attempts to register a \c freedesktop.org compliant notification
+server. DBus errors might occur if it conflicts with the server running on the host desktop
+environment. In this case, a private session bus needs to be started by adding the
+\c --start-session-dbus option.
+
+\section1 Walkthrough
+
+We will start from the bottom, because this is the essential part.
+
+\section2 SystemMonitor and ProcessMonitor Usage
+
+\quotefromfile monitor/system-ui/main.qml
+\skipto ProcessMonitor
+\printuntil ApplicationManager.startApplication
+\printline }
+The ProcessMonitor is an instantiatable type that will monitor the process that is associated with
+its \l {ProcessMonitor::applicationId}{applicationId} property. An empty applicationId string means
+that the System-UI process is monitored. By clicking the "Switch Process" button, the monitored
+process can be changed to the \c tld.monitor.app application. Measurements will be performed each
+second (1000 ms) and 12 reading points will be kept in the model (the ProcessMonitor is a model).
+The model is used below to display the bar charts.
+
+Memory and frame rate reporting need to be enabled, since we are interested in both. For frame rate
+measurements the list of \c monitoredWindows has to be filled with windows that we are interested
+in. For the System-UI this is the single root window itself and for the tld.monitor.app process it
+is the currently selected window. Hence the list will always include just one element. The memory
+and frame rate changed signal handlers will update the current values of the corresponding views.
+
+The Connections type is used to implement signal handlers for the property changes of the
+SystemMonitor. The current values of the corresponding views are updated, as well.
+
+The SystemMonitor is a singleton type. It is set-up in the Component.onCompleted handler. Like
+above, measurements will be performed each second (1000 ms) and 12 reading points will be kept in
+the model (the SystemMonitor is a model, as well).
+
+The very last line will start the only application that is provided by this example. Note that, if
+the application-manager is running in single-process mode, the application will run within the
+System-UI process and consequently the ProcessMonitor will not report anything and the associated
+ProcessMonitor::processId will be set to 0.
+
+\section2 The User Interface
+
+\quotefromfile monitor/system-ui/main.qml
+\skipto import Qt
+\printto ProcessMonitor
+\dots
+
+We won't go into much detail, because it's rather conventional QML code. The MonitorChart is a
+ListView that uses either an instance of a ProcessMonitor or the SystemMonitor singleton as its
+model. The reading values are represented as bars. Their height is determined by the
+corresponding model role, e.g. for the PSS memory consumption it is \c memoryPss.total.
+
+When the tld.monitor.app process is monitored, its two windows will be shown (primary and
+secondary). The window that is monitored in terms of frame rate can be selected and is highlighted
+with a white border.
+
+*/
diff --git a/examples/applicationmanager/monitor/monitor.pro b/examples/applicationmanager/monitor/monitor.pro
new file mode 100644
index 00000000..8a93c3bd
--- /dev/null
+++ b/examples/applicationmanager/monitor/monitor.pro
@@ -0,0 +1,23 @@
+TEMPLATE = app
+CONFIG += am-systemui
+
+OTHER_FILES += \
+ am-config.yaml \
+ monitor.qmlproject \
+ doc/src/*.qdoc \
+ doc/images/*.png \
+ system-ui/*.qml \
+ apps/tld.monitor.app/*.yaml \
+ apps/tld.monitor.app/*.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/monitor
+INSTALLS += target
+
+AM_COPY_DIRECTORIES += apps system-ui
+AM_COPY_FILES += am-config.yaml
+
+AM_DEFAULT_ARGS=-c am-config.yaml --start-session-dbus --verbose
+
+example_sources.path = $$target.path
+example_sources.files = $$AM_COPY_FILES $$AM_COPY_DIRECTORIES doc
+INSTALLS += example_sources
diff --git a/examples/applicationmanager/monitor/monitor.qmlproject b/examples/applicationmanager/monitor/monitor.qmlproject
new file mode 100644
index 00000000..5ce6345e
--- /dev/null
+++ b/examples/applicationmanager/monitor/monitor.qmlproject
@@ -0,0 +1,17 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "system-ui/main.qml"
+
+ QmlFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "apps"
+ }
+ Files {
+ directory: "."
+ filter: "*.yaml"
+ }
+}
+
diff --git a/examples/applicationmanager/monitor/system-ui/MonitorChart.qml b/examples/applicationmanager/monitor/system-ui/MonitorChart.qml
new file mode 100644
index 00000000..0d49e346
--- /dev/null
+++ b/examples/applicationmanager/monitor/system-ui/MonitorChart.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+
+Rectangle {
+ property alias title: title.text
+ property alias reading: reading.text
+ property alias model: listview.model
+ property alias delegate: listview.delegate
+
+ width: 185
+ height: 250
+ color: "black"
+ border { width: 1; color: "white" }
+
+ Rectangle {
+ width: parent.width
+ height: 30
+ color: "black"
+ border { width: 1; color: "white" }
+
+ MonitorText {
+ id: title
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ MonitorText {
+ id: reading
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ ListView {
+ id: listview
+ anchors.fill: parent
+ anchors.margins: 10
+ anchors.topMargin: 40
+ orientation: ListView.Horizontal
+ layoutDirection: Qt.RightToLeft
+ spacing: 3
+ clip: true
+ }
+}
diff --git a/examples/applicationmanager/monitor/system-ui/MonitorText.qml b/examples/applicationmanager/monitor/system-ui/MonitorText.qml
new file mode 100644
index 00000000..263a22ec
--- /dev/null
+++ b/examples/applicationmanager/monitor/system-ui/MonitorText.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+
+Text {
+ font.pixelSize: 14
+ color: "white"
+}
diff --git a/examples/applicationmanager/monitor/system-ui/Switch.qml b/examples/applicationmanager/monitor/system-ui/Switch.qml
new file mode 100644
index 00000000..6ed638fb
--- /dev/null
+++ b/examples/applicationmanager/monitor/system-ui/Switch.qml
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+
+Rectangle {
+ signal toggle()
+
+ width: 180; height: 30; radius: 4
+ color: 'white'
+
+ MonitorText {
+ anchors.centerIn: parent
+ text: 'Switch Process'
+ font.bold: true
+ color: 'black'
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: toggle();
+ }
+}
diff --git a/examples/applicationmanager/monitor/system-ui/Tile.qml b/examples/applicationmanager/monitor/system-ui/Tile.qml
new file mode 100644
index 00000000..d3a06b18
--- /dev/null
+++ b/examples/applicationmanager/monitor/system-ui/Tile.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+
+Item {
+ width: 225
+ height: 300
+}
diff --git a/examples/applicationmanager/monitor/system-ui/WindowContainer.qml b/examples/applicationmanager/monitor/system-ui/WindowContainer.qml
new file mode 100644
index 00000000..3b292cda
--- /dev/null
+++ b/examples/applicationmanager/monitor/system-ui/WindowContainer.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+
+Rectangle {
+ property bool active: false
+ property alias container: container
+ signal activated()
+
+ width: 180; height: 65
+
+ color: active ? "white" : "transparent"
+
+ Item {
+ id: container
+ anchors.margins: 2
+ anchors.fill: parent
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ active = true;
+ activated();
+ }
+ }
+}
diff --git a/examples/applicationmanager/monitor/system-ui/main.qml b/examples/applicationmanager/monitor/system-ui/main.qml
new file mode 100644
index 00000000..5343a55d
--- /dev/null
+++ b/examples/applicationmanager/monitor/system-ui/main.qml
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Window 2.0
+import QtApplicationManager 1.0
+
+
+Window {
+ id: root
+
+ property var primaryWindow
+ property var secondaryWindow
+
+ width: 720
+ height: 600
+ color: "black"
+
+ Column {
+ x: 10
+ padding: 20
+
+ Tile {
+ Column {
+ id: systemOverview
+ spacing: 10
+
+ MonitorText { text: "System"; font.pixelSize: 26 }
+ MonitorText { text: "CPU Cores: " + SystemMonitor.cpuCores }
+ MonitorText { text: "Total Memory: " + (SystemMonitor.totalMemory / 1e9).toFixed(1) + " GB" }
+ MonitorText { id: systemMem; text: "Used Memory:" }
+ MonitorText { text: "Idle Threshold: " + SystemMonitor.idleLoadThreshold * 100 + " %" }
+ MonitorText { text: "Idle: " + SystemMonitor.idle }
+ MonitorText { text: "GPU Load: " + SystemMonitor.gpuLoad * 100 + " %" }
+ }
+ }
+
+ Tile {
+ MonitorChart {
+ id: systemLoad
+ title: "CPU Load"
+ model: SystemMonitor
+ delegate: Rectangle {
+ width: 11
+ height: parent.height
+ gradient: Gradient {
+ GradientStop { position: 0.5; color: "#FF0000" }
+ GradientStop { position: 1.0; color: "#00FF00" }
+ }
+ Rectangle {
+ width: parent.width
+ height: parent.height - cpuLoad * parent.height
+ color: "black"
+ }
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ x: 246; y: 25
+ width: 1; height: root.height - 50
+ color: "white"
+ }
+
+ Grid {
+ columns: 2
+ padding: 20
+ x: 260
+
+ Tile {
+ Column {
+ spacing: 20
+
+ MonitorText {
+ text: processMon.applicationId === "" ? "System-UI" : processMon.applicationId
+ font.pixelSize: 26
+ }
+ MonitorText { text: "Process ID: " + processMon.processId }
+
+ Switch {
+ onToggle: {
+ processMon.applicationId = processMon.applicationId === ""
+ ? ApplicationManager.application(0).id : ""
+ if (processMon.applicationId !== "") {
+ if (ApplicationManager.singleProcess)
+ console.warn("There is no dedicated application process in single-process mode");
+
+ if (primaryWindow && secondaryWindow) {
+ processMon.monitoredWindows = primary.active ? [primaryWindow] : [secondaryWindow]
+ } else {
+ processMon.monitoredWindows = []
+ console.warn("No application window available. Please check your QtWayland configuration.");
+ }
+ } else {
+ processMon.monitoredWindows = [root]
+ }
+ }
+ }
+ }
+ }
+
+ Tile {
+ Column {
+ visible: processMon.applicationId !== ""
+ spacing: 20
+ Item {
+ width: 200; height: 65
+ MonitorText { anchors.bottom: parent.bottom; text: "Application Windows:" }
+ }
+
+ WindowContainer {
+ id: primary
+ active: true
+ onActivated: {
+ processMon.monitoredWindows = [primaryWindow];
+ secondary.active = false;
+ }
+ }
+
+ WindowContainer {
+ id: secondary
+ onActivated: {
+ processMon.monitoredWindows = [secondaryWindow];
+ primary.active = false;
+ }
+ }
+ }
+ }
+
+ Tile {
+ MonitorChart {
+ id: processPss
+ title: "Memory PSS"
+ model: processMon
+ delegate: Rectangle {
+ width: 11
+ height: memoryPss.total / 5e6
+ anchors.bottom: parent.bottom
+ color: "lightsteelblue"
+ }
+ }
+ }
+
+ Tile {
+ MonitorChart {
+ id: frameChart
+ title: "Frame rate"
+ model: processMon
+ delegate: Rectangle {
+ width: 11
+ height: frameRate[0] ? frameRate[0].average * 3 : 0
+ anchors.bottom: parent.bottom
+ color.r: frameRate[0] ? (frameRate[0].average >= 60 ? 0 : 1 - frameRate[0].average / 60) : 0
+ color.g: frameRate[0] ? (frameRate[0].average >= 60 ? 1 : frameRate[0].average / 60) : 0
+ color.b: 0
+
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: WindowManager
+ onWindowReady: {
+ if (WindowManager.windowProperty(window, "windowType") === "primary") {
+ primaryWindow = window
+ window.parent = primary.container
+ window.anchors.fill = primary.container
+ } else {
+ secondaryWindow = window
+ window.parent = secondary.container
+ window.anchors.fill = secondary.container
+ }
+ }
+
+ onWindowLost: {
+ processMon.monitoredWindows = []
+ WindowManager.releaseWindow(window);
+ }
+ }
+
+ ProcessMonitor {
+ id: processMon
+ applicationId: ""
+ reportingInterval: 1000
+ count: 12
+
+ memoryReportingEnabled: true
+ frameRateReportingEnabled: true
+ monitoredWindows: [root]
+
+ onMemoryReportingChanged: processPss.reading = (memoryPss.total / 1e6).toFixed(0) + " MB";
+ onFrameRateReportingChanged: {
+ if (frameRate[0])
+ frameChart.reading = frameRate[0].average.toFixed(0) + " fps";
+ }
+ }
+
+ Connections {
+ target: SystemMonitor
+ onCpuLoadReportingChanged: systemLoad.reading = (load * 100).toFixed(1) + " %";
+ onMemoryReportingChanged: systemMem.text = "Used Memory: " + (used / 1e9).toFixed(1) + " GB"
+ }
+
+
+ Component.onCompleted: {
+ SystemMonitor.reportingInterval = 1000;
+ SystemMonitor.count = 12;
+
+ SystemMonitor.idleLoadThreshold = 0.05;
+ SystemMonitor.cpuLoadReportingEnabled = true;
+ SystemMonitor.gpuLoadReportingEnabled = true;
+ SystemMonitor.memoryReportingEnabled = true;
+
+ ApplicationManager.startApplication(ApplicationManager.application(0).id);
+ }
+}
diff --git a/examples/applicationmanager/multi-views/am-config.yaml b/examples/applicationmanager/multi-views/am-config.yaml
new file mode 100644
index 00000000..1fa63b8a
--- /dev/null
+++ b/examples/applicationmanager/multi-views/am-config.yaml
@@ -0,0 +1,37 @@
+formatVersion: 1
+formatType: am-configuration
+---
+installationLocations:
+- id: "internal-0"
+ installationPath: "/tmp/multi-views/apps"
+ documentPath: "/tmp/multi-views/docs"
+ mountPoint: "/tmp"
+ isDefault: true
+
+applications:
+ builtinAppsManifestDir: "${CONFIG_PWD}/apps"
+ installedAppsManifestDir: "/tmp/multi-views/manifests"
+ appImageMountDir: "/tmp/multi-views/image-mounts"
+ database: "/tmp/multi-views/apps.db"
+
+logging:
+ rules:
+ - "*=false"
+ - "qt.*=false"
+ - "am.*=false"
+ - "qml*=true"
+ - "*.warning=true"
+ - "*.critical=true"
+
+ui:
+ fullscreen: no
+ mainQml: "${CONFIG_PWD}/system-ui/main.qml"
+
+systemProperties:
+ protected:
+ light: on
+
+# development setup:
+flags:
+ noSecurity: yes
+ noUiWatchdog: yes
diff --git a/examples/applicationmanager/multi-views/apps/tld.multi-views.app/app1.qml b/examples/applicationmanager/multi-views/apps/tld.multi-views.app/app1.qml
new file mode 100644
index 00000000..dff73e7a
--- /dev/null
+++ b/examples/applicationmanager/multi-views/apps/tld.multi-views.app/app1.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtApplicationManager 1.0
+
+ApplicationManagerWindow {
+ id: root
+ color: mouseArea.pressed ? "red" : "peachpuff"
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 180; height: 180; radius: width/4
+ color: "peru"
+
+ Image {
+ source: ApplicationInterface.icon
+ anchors.centerIn: parent
+ }
+
+ RotationAnimation on rotation {
+ from: 0; to: 360; loops: Animation.Infinite; duration: 4000
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ }
+}
diff --git a/examples/applicationmanager/multi-views/apps/tld.multi-views.app/icon.png b/examples/applicationmanager/multi-views/apps/tld.multi-views.app/icon.png
new file mode 100644
index 00000000..adb840ce
--- /dev/null
+++ b/examples/applicationmanager/multi-views/apps/tld.multi-views.app/icon.png
Binary files differ
diff --git a/examples/applicationmanager/multi-views/apps/tld.multi-views.app/info.yaml b/examples/applicationmanager/multi-views/apps/tld.multi-views.app/info.yaml
new file mode 100644
index 00000000..36ace0e1
--- /dev/null
+++ b/examples/applicationmanager/multi-views/apps/tld.multi-views.app/info.yaml
@@ -0,0 +1,9 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'tld.multi-views.app'
+icon: 'icon.png'
+code: 'app1.qml'
+runtime: 'qml'
+name:
+ en: 'App1'
diff --git a/examples/applicationmanager/multi-views/multi-views.pro b/examples/applicationmanager/multi-views/multi-views.pro
new file mode 100644
index 00000000..82c6fece
--- /dev/null
+++ b/examples/applicationmanager/multi-views/multi-views.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+CONFIG += am-systemui
+
+OTHER_FILES += \
+ am-config.yaml \
+ system-ui/*.qml \
+ apps/tld.multi-views.app/*.yaml \
+ apps/tld.multi-views.app/*.qml \
+ apps/tld.multi-views.app/*.png \
+
+target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/multi-views
+INSTALLS += target
+
+AM_COPY_DIRECTORIES += apps system-ui
+AM_COPY_FILES += am-config.yaml
+
+AM_DEFAULT_ARGS=-c am-config.yaml --start-session-dbus --verbose -r
+
+example_sources.path = $$target.path
+example_sources.files = $$AM_COPY_FILES $$AM_COPY_DIRECTORIES
+INSTALLS += example_sources
diff --git a/examples/applicationmanager/multi-views/system-ui/Readme.qml b/examples/applicationmanager/multi-views/system-ui/Readme.qml
new file mode 100644
index 00000000..000e5fdf
--- /dev/null
+++ b/examples/applicationmanager/multi-views/system-ui/Readme.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ anchors.fill: parent
+
+ Column {
+ width: heading.implicitWidth
+ height: heading.implicitHeight + 80
+ anchors.centerIn: parent
+ spacing: 10
+
+ Text {
+ id: heading
+ color: "cornflowerblue"
+ font { pixelSize: 20; weight: Font.Bold }
+ text: "Multiple WindowItems displaying the same WindowObject"
+ }
+ }
+}
diff --git a/examples/applicationmanager/multi-views/system-ui/main.qml b/examples/applicationmanager/multi-views/system-ui/main.qml
new file mode 100644
index 00000000..64d5ce4f
--- /dev/null
+++ b/examples/applicationmanager/multi-views/system-ui/main.qml
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtApplicationManager 1.0
+
+Rectangle {
+ width: 1024
+ height: 640
+ color: "linen"
+
+ Readme {}
+
+ Text {
+ anchors.bottom: parent.bottom
+ text: (ApplicationManager.singleProcess ? "Single" : "Multi") + "-Process Mode"
+ }
+
+ // Application launcher panel
+ Column {
+ id: launcher
+ Repeater {
+ id: menuItems
+ model: ApplicationManager
+
+ Image {
+ source: icon
+
+ Text {
+ anchors.fill: parent
+ fontSizeMode: Text.Fit; minimumPixelSize: 10; font.pixelSize: height
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: model.isRunning ? "Stop" : "Start"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (model.isRunning)
+ application.stop();
+ else
+ application.start();
+ }
+ }
+ }
+ }
+ }
+
+ // System-UI chrome for applications
+ Repeater {
+ model: ListModel { id: topLevelWindowsModel }
+
+ delegate: Rectangle {
+ id: winChrome
+
+ width: 400; height: 320
+ z: model.index
+ color: "tan"
+
+ property bool manuallyClosed: false
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: (windowItem.primary ? "Primary: " : "Secondary: ") + model.window.application.name("en")
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ drag.target: parent
+ onPressed: topLevelWindowsModel.move(model.index, topLevelWindowsModel.count-1, 1);
+ }
+
+ Rectangle {
+ width: 25; height: 25
+ color: "chocolate"
+ Text {
+ anchors.fill: parent
+ fontSizeMode: Text.Fit; minimumPixelSize: 10; font.pixelSize: 25
+ horizontalAlignment: Text.AlignHCenter
+ text: "-"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ winChrome.manuallyClosed = true;
+ }
+ }
+ }
+
+ Text {
+ width: 25; height: 25
+ anchors.right: addWindowItemButton.left
+ fontSizeMode: Text.Fit; minimumPixelSize: 10; font.pixelSize: 25
+
+ text: "P"
+ visible: !windowItem.primary
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: windowItem.makePrimary()
+ }
+ }
+ Text {
+ id: addWindowItemButton
+ width: 25; height: 25
+ anchors.right: parent.right
+ fontSizeMode: Text.Fit; minimumPixelSize: 10; font.pixelSize: 25
+
+ text: "+"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ topLevelWindowsModel.append({"window":model.window});
+ }
+ }
+ }
+
+ WindowItem {
+ id: windowItem
+ anchors.fill: parent
+ anchors.margins: 3
+ anchors.topMargin: 25
+ window: model.window
+ }
+
+ Component.onCompleted: {
+ winChrome.x = 300 + model.index * 50;
+ winChrome.y = 10 + model.index * 30;
+ }
+
+ states: [
+ State {
+ name: "open"
+ when: model.window && model.window.contentState === WindowObject.SurfaceWithContent && !manuallyClosed
+ PropertyChanges {
+ target: winChrome
+ opacity: 1
+ scale: 1
+ visible: true
+ }
+ }
+ ]
+
+ opacity: 0.25
+ scale: 0.50
+ visible: false
+
+ transitions: [
+ Transition {
+ to: "open"
+ NumberAnimation { target: winChrome; properties: "opacity,scale"; duration: 500; easing.type: Easing.OutQuad}
+ },
+ Transition {
+ from: "open"
+ SequentialAnimation {
+ PropertyAction { target: winChrome; property: "visible"; value: true } // we wanna see the window during the closing animation
+ NumberAnimation { target: winChrome; properties: "opacity,scale"; duration: 500; easing.type: Easing.InQuad}
+ ScriptAction { script: {
+ if (model.window.contentState === WindowObject.NoSurface || winChrome.manuallyClosed)
+ topLevelWindowsModel.remove(model.index, 1);
+ } }
+ }
+ }
+ ]
+ }
+ }
+
+ // Handler for WindowManager signals
+ Connections {
+ target: WindowManager
+ onWindowAdded: {
+ topLevelWindowsModel.append({"window":window});
+ }
+ }
+}
diff --git a/examples/applicationmanager/softwarecontainer-plugin/README.md b/examples/applicationmanager/softwarecontainer-plugin/README.md
new file mode 100644
index 00000000..57d7eb3b
--- /dev/null
+++ b/examples/applicationmanager/softwarecontainer-plugin/README.md
@@ -0,0 +1,71 @@
+# SoftwareContainer Plugin
+
+This is a very basic PoC integration of Pelagicore's Software-Containers
+
+[https://github.com/Pelagicore/softwarecontainer][]
+
+Please also read the "Containers" page in the official Qt Application Manager
+documentation:
+[https://doc-snapshots.qt.io/qtapplicationmanager/containers.html]
+
+Parts of the container configuration are hardcoded in `softwarecontainer.cpp`,
+while all of the capability definition is in the JSON manifest at
+`service-manifest.d/io.qt.ApplicationManager.Application/`.
+
+The Wayland/OpenGL pass-through is tested against Intel GPUs and VMware's
+virtual GPU.
+
+The softwarecontainer-agent needs to be started as root. By default it will
+register itself on the system D-Bus, so a policy file must be in place,
+allowing it to register itself on the system-bus. If you want to run the
+agent on the session bus instead (via the `--session-bus` parameter), you
+have to add the following to one of your config.yaml files:
+```
+containers:
+ softwarecontainer:
+ dbus: 'session'
+```
+
+Passing the service-manifest directory that comes with the plugin via
+`-m` is mandatory - otherwise the container setup will fail due to the
+missing `io.qt.ApplicationManager.Application` capability.
+
+You have to make sure that the agent has access to the same session-bus
+that the application-manager is using, if you intend on forwarding this
+bus. This is a bit tricky if the agent is run as root and the application-
+manager as non-root user, since the default session-bus policy in most
+distros disallows root to access user session-busses: the workaround is to
+add a `<allow user="root"/>` policy in `/etc/dbus-1/session.conf`.
+
+Please do also not forget to tell the agent about your environment, when
+running it via sudo:
+```
+sudo XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR
+DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS softwarecontainer-agent -m
+/path/to/application-manager/examples/softwarecontainer-plugin/service-manifest.d/
+```
+
+On the AM side, you need to activate the plugin by adding something like
+this to one of your config.yaml files:
+```
+plugins:
+ container: [ "/path/to/libsoftwarecontainer-plugin.so" ]
+```
+In order to actually run apps within softwarecontainers, you have to add a
+container selection configuration:
+[https://doc-snapshots.qt.io/qtapplicationmanager/containers.html#container-selection-configuration][]
+
+
+Please be aware that for easier development on the desktop, you normally want
+your $HOME directory mounted into the container in read-only mode, so you do
+not have to install your application-manager into /usr/ after every build
+(given that your build directory is somewhere in $HOME, the container would
+not see the appman-launcher-qml binary).
+This is *not* done by default, but you can activate this behavior by adding
+this to one of your config.yaml files:
+
+```
+containers:
+ softwarecontainer:
+ bindMountHome: yes
+```
diff --git a/examples/applicationmanager/softwarecontainer-plugin/service-manifest.d/io.qt.ApplicationManager.Application.json b/examples/applicationmanager/softwarecontainer-plugin/service-manifest.d/io.qt.ApplicationManager.Application.json
new file mode 100644
index 00000000..68592c08
--- /dev/null
+++ b/examples/applicationmanager/softwarecontainer-plugin/service-manifest.d/io.qt.ApplicationManager.Application.json
@@ -0,0 +1,58 @@
+{
+ "version": "1",
+ "capabilities": [
+ {
+ "name": "io.qt.ApplicationManager.Application",
+ "gateways": [
+ {
+ "id": "dbus",
+ "config": [
+ {
+ "dbus-gateway-config-session": [
+ {
+ "direction": "*",
+ "interface": "*",
+ "object-path": "*",
+ "method": "*"
+ }
+ ],
+ "dbus-gateway-config-system": [
+ {
+ "direction": "*",
+ "interface": "*",
+ "object-path": "*",
+ "method": "*"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "wayland",
+ "config": [
+ {
+ "enabled": true
+ }
+ ]
+ },
+ {
+ "id": "devicenode",
+ "config": [
+ {
+ "name": "/dev/dri/card0"
+ },
+ {
+ "name": "/dev/dri/renderD128"
+ },
+ {
+ "name": "/dev/tty0"
+ },
+ {
+ "name": "/dev/tty1"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer-plugin.pro b/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer-plugin.pro
new file mode 100644
index 00000000..2e8febc8
--- /dev/null
+++ b/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer-plugin.pro
@@ -0,0 +1,21 @@
+requires(linux:!android)
+
+TEMPLATE = lib
+CONFIG += plugin c++11
+TARGET = softwarecontainer-plugin
+
+QT = core dbus appman_common-private appman_plugininterfaces-private
+
+HEADERS += \
+ softwarecontainer.h
+
+SOURCES += \
+ softwarecontainer.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/softwarecontainer-plugin
+INSTALLS += target
+
+DISTFILES += \
+ service-manifest.d/io.qt.ApplicationManager.Application.json
+
+OTHER_FILES += README.md
diff --git a/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.cpp b/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.cpp
new file mode 100644
index 00000000..7e34bd86
--- /dev/null
+++ b/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.cpp
@@ -0,0 +1,585 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include <tuple>
+
+#include <QtDBus/QtDBus>
+#include <QtAppManCommon/global.h>
+#include <QJsonDocument>
+#include <QSocketNotifier>
+#include <qplatformdefs.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include "softwarecontainer.h"
+
+
+QT_BEGIN_NAMESPACE
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QMap<QString,QString> &map)
+{
+ argument.beginMap(QMetaType::QString, QMetaType::QString);
+ for (auto it = map.cbegin(); it != map.cend(); ++it) {
+ argument.beginMapEntry();
+ argument << it.key() << it.value();
+ argument.endMapEntry();
+ }
+ argument.endMap();
+
+ return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, QMap<QString,QString> &map)
+{
+ argument.beginMap();
+ while (!argument.atEnd()) {
+ argument.beginMapEntry();
+ QString key, value;
+ argument >> key >> value;
+ map.insert(key, value);
+ argument.endMapEntry();
+ }
+ argument.endMap();
+
+ return argument;
+}
+
+QT_END_NAMESPACE
+
+
+QT_USE_NAMESPACE_AM
+
+// unfortunately, this is a copy of the code from debugwrapper.cpp
+static QStringList substituteCommand(const QStringList &debugWrapperCommand, const QString &program,
+ const QStringList &arguments)
+{
+ QString stringifiedArguments = arguments.join(qL1C(' '));
+ QStringList result;
+
+ for (const QString &s : debugWrapperCommand) {
+ if (s == qSL("%arguments%")) {
+ result << arguments;
+ } else {
+ QString str(s);
+ str.replace(qL1S("%program%"), program);
+ str.replace(qL1S("%arguments%"), stringifiedArguments);
+ result << str;
+ }
+ }
+ return result;
+}
+
+SoftwareContainerManager::SoftwareContainerManager()
+{
+ static bool once = false;
+ if (!once) {
+ once = true;
+ qDBusRegisterMetaType<QMap<QString, QString>>();
+ }
+}
+
+QString SoftwareContainerManager::identifier() const
+{
+ return QStringLiteral("softwarecontainer");
+}
+
+bool SoftwareContainerManager::supportsQuickLaunch() const
+{
+ return false;
+}
+
+void SoftwareContainerManager::setConfiguration(const QVariantMap &configuration)
+{
+ m_configuration = configuration;
+}
+
+ContainerInterface *SoftwareContainerManager::create(bool isQuickLaunch, const QVector<int> &stdioRedirections,
+ const QMap<QString, QString> &debugWrapperEnvironment,
+ const QStringList &debugWrapperCommand)
+{
+ if (!m_interface) {
+ QString dbus = configuration().value(QStringLiteral("dbus")).toString();
+ QDBusConnection conn(QStringLiteral("sc-bus"));
+
+ if (dbus.isEmpty())
+ dbus = QStringLiteral("system");
+
+ if (dbus == QLatin1String("system"))
+ conn = QDBusConnection::systemBus();
+ else if (dbus == QLatin1String("session"))
+ conn = QDBusConnection::sessionBus();
+ else
+ conn = QDBusConnection::connectToBus(dbus, QStringLiteral("sc-bus"));
+
+ if (!conn.isConnected()) {
+ qWarning() << "The" << dbus << "D-Bus is not available to connect to the SoftwareContainer agent.";
+ return nullptr;
+ }
+ m_interface = new QDBusInterface(QStringLiteral("com.pelagicore.SoftwareContainerAgent"),
+ QStringLiteral("/com/pelagicore/SoftwareContainerAgent"),
+ QStringLiteral("com.pelagicore.SoftwareContainerAgent"),
+ conn, this);
+ if (m_interface->lastError().isValid()) {
+ qWarning() << "Could not connect to com.pelagicore.SoftwareContainerAgent, "
+ "/com/pelagicore/SoftwareContainerAgent on the" << dbus << "D-Bus";
+ delete m_interface;
+ m_interface = nullptr;
+ return nullptr;
+ }
+
+ if (!connect(m_interface, SIGNAL(ProcessStateChanged(int,uint,bool,uint)), this, SLOT(processStateChanged(int,uint,bool,uint)))) {
+ qWarning() << "Could not connect to the com.pelagicore.SoftwareContainerAgent.ProcessStateChanged "
+ "signal on the" << dbus << "D-Bus";
+ delete m_interface;
+ m_interface = nullptr;
+ return nullptr;
+ }
+ }
+
+ QString config = qSL("[]");
+ QVariant v = configuration().value("createConfig");
+ if (v.isValid())
+ config = QString::fromUtf8(QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact));
+
+ QDBusMessage reply = m_interface->call(QDBus::Block, "Create", config);
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning() << "SoftwareContainer failed to create a new container:" << reply.errorMessage()
+ << "(config was:" << config << ")";
+ return nullptr;
+ }
+
+ int containerId = reply.arguments().at(0).toInt();
+
+ if (containerId < 0) {
+ qCritical() << "SoftwareContainer failed to create a new container. (config was:" << config << ")";
+ return nullptr;
+ }
+
+ // calculate where to dump stdout/stderr
+ int outputFd = stdioRedirections.value(STDERR_FILENO, -1);
+ if (outputFd < 0)
+ outputFd = stdioRedirections.value(STDOUT_FILENO, -1);
+ if ((::fcntl(outputFd, F_GETFD) < 0) && (errno == EBADF))
+ outputFd = STDOUT_FILENO;
+
+ SoftwareContainer *container = new SoftwareContainer(this, isQuickLaunch, containerId,
+ outputFd, debugWrapperEnvironment,
+ debugWrapperCommand);
+ m_containers.insert(containerId, container);
+ connect(container, &QObject::destroyed, this, [this, containerId]() { m_containers.remove(containerId); });
+ return container;
+}
+
+QDBusInterface *SoftwareContainerManager::interface() const
+{
+ return m_interface;
+}
+
+QVariantMap SoftwareContainerManager::configuration() const
+{
+ return m_configuration;
+}
+
+void SoftwareContainerManager::processStateChanged(int containerId, uint processId, bool isRunning, uint exitCode)
+{
+ Q_UNUSED(processId)
+
+ SoftwareContainer *container = m_containers.value(containerId);
+ if (!container) {
+ qWarning() << "Received a processStateChanged signal for unknown container" << containerId;
+ return;
+ }
+
+ if (!isRunning)
+ container->containerExited(exitCode);
+}
+
+
+
+SoftwareContainer::SoftwareContainer(SoftwareContainerManager *manager, bool isQuickLaunch, int containerId,
+ int outputFd, const QMap<QString, QString> &debugWrapperEnvironment,
+ const QStringList &debugWrapperCommand)
+ : m_manager(manager)
+ , m_isQuickLaunch(isQuickLaunch)
+ , m_id(containerId)
+ , m_outputFd(outputFd)
+ , m_debugWrapperEnvironment(debugWrapperEnvironment)
+ , m_debugWrapperCommand(debugWrapperCommand)
+{ }
+
+SoftwareContainer::~SoftwareContainer()
+{
+ if (m_fifoFd >= 0)
+ QT_CLOSE(m_fifoFd);
+ if (!m_fifoPath.isEmpty())
+ ::unlink(m_fifoPath);
+ if (m_outputFd > STDERR_FILENO)
+ QT_CLOSE(m_outputFd);
+}
+
+SoftwareContainerManager *SoftwareContainer::manager() const
+{
+ return m_manager;
+}
+
+bool SoftwareContainer::attachApplication(const QVariantMap &application)
+{
+
+ // In normal launch attachApplication is called first, then the start()
+ // method is called. During quicklaunch start() is called first and then
+ // attachApplication. In this case we need to configure the container
+ // with any extra capabilities etc.
+
+ m_state = QProcess::Starting;
+ m_application = application;
+
+ m_hostPath = application.value(qSL("codeDir")).toString();
+ if (m_hostPath.isEmpty())
+ m_hostPath = QDir::currentPath();
+
+ m_appRelativeCodePath = application.value(qSL("codeFilePath")).toString();
+ m_containerPath = qSL("/app");
+
+ // If this is a quick launch instance, we need to renew the capabilities
+ // and send the bindmounts.
+ if (m_isQuickLaunch) {
+ if (!sendCapabilities())
+ return false;
+
+ if (!sendBindMounts())
+ return false;
+ }
+
+ m_ready = true;
+ emit ready();
+ return true;
+}
+
+QString SoftwareContainer::controlGroup() const
+{
+ return QString();
+}
+
+bool SoftwareContainer::setControlGroup(const QString &groupName)
+{
+ Q_UNUSED(groupName)
+ return false;
+}
+
+bool SoftwareContainer::setProgram(const QString &program)
+{
+ m_program = program;
+ return true;
+}
+
+void SoftwareContainer::setBaseDirectory(const QString &baseDirectory)
+{
+ m_baseDir = baseDirectory;
+}
+
+bool SoftwareContainer::isReady() const
+{
+ return m_ready;
+}
+
+QString SoftwareContainer::mapContainerPathToHost(const QString &containerPath) const
+{
+ return containerPath;
+}
+
+QString SoftwareContainer::mapHostPathToContainer(const QString &hostPath) const
+{
+ return hostPath;
+}
+
+bool SoftwareContainer::sendCapabilities()
+{
+ auto iface = manager()->interface();
+ if (!iface)
+ return false;
+
+ // this is the one and only capability in io.qt.ApplicationManager.Application.json
+ static const QStringList capabilities { qSL("io.qt.ApplicationManager.Application") };
+
+ QDBusMessage reply = iface->call(QDBus::Block, "SetCapabilities", m_id, QVariant::fromValue(capabilities));
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning() << "SoftwareContainer failed to set capabilities to" << capabilities << ":" << reply.errorMessage();
+ return false;
+ }
+ return true;
+}
+
+bool SoftwareContainer::sendBindMounts()
+{
+ auto iface = manager()->interface();
+ if (!iface)
+ return false;
+
+ QFileInfo fontCacheInfo(qSL("/var/cache/fontconfig"));
+
+ QVector<std::tuple<QString, QString, bool>> bindMounts; // bool == isReadOnly
+ // the private P2P D-Bus
+ bindMounts.append(std::make_tuple(m_dbusP2PInfo.absoluteFilePath(), m_dbusP2PInfo.absoluteFilePath(), false));
+
+ // we need to share the fontconfig cache - otherwise the container startup might take a long time
+ bindMounts.append(std::make_tuple(fontCacheInfo.absoluteFilePath(), fontCacheInfo.absoluteFilePath(), false));
+
+ // the actual path to the application
+ bindMounts.append(std::make_tuple(m_hostPath, m_containerPath, true));
+
+ // for development only - mount the user's $HOME dir into the container as read-only. Otherwise
+ // you would have to `make install` the AM into /usr on every rebuild
+ if (manager()->configuration().value(QStringLiteral("bindMountHome")).toBool())
+ bindMounts.append(std::make_tuple(QDir::homePath(), QDir::homePath(), true));
+
+ // do all the bind-mounts in parallel to waste as little time as possible
+ QList<QDBusPendingReply<>> bindMountResults;
+
+ for (auto it = bindMounts.cbegin(); it != bindMounts.cend(); ++it)
+ bindMountResults << iface->asyncCall("BindMount", m_id, std::get<0>(*it), std::get<1>(*it), std::get<2>(*it));
+
+ for (const auto &pending : qAsConst(bindMountResults))
+ QDBusPendingCallWatcher(pending).waitForFinished();
+
+ for (int i = 0; i < bindMounts.size(); ++i) {
+ if (bindMountResults.at(i).isError()) {
+ qWarning() << "SoftwareContainer failed to bind-mount the directory" << std::get<0>(bindMounts.at(i))
+ << "into the container at" << std::get<1>(bindMounts.at(i)) << ":" << bindMountResults.at(i).error().message();
+ return false;
+ }
+ }
+
+ return true;
+
+}
+
+bool SoftwareContainer::start(const QStringList &arguments, const QMap<QString, QString> &runtimeEnvironment)
+{
+ auto iface = manager()->interface();
+ if (!iface)
+ return false;
+
+ if (!QFile::exists(m_program))
+ return false;
+
+ // Send initial capabilities even if this is a quick-launch instance
+ if (!sendCapabilities())
+ return false;
+
+ // parse out the actual socket file name from the DBus specification
+ QString dbusP2PSocket = runtimeEnvironment.value(QStringLiteral("AM_DBUS_PEER_ADDRESS"));
+ dbusP2PSocket = dbusP2PSocket.mid(dbusP2PSocket.indexOf(QLatin1Char('=')) + 1);
+ dbusP2PSocket = dbusP2PSocket.left(dbusP2PSocket.indexOf(QLatin1Char(',')));
+ QFileInfo dbusP2PInfo(dbusP2PSocket);
+ m_dbusP2PInfo = dbusP2PInfo;
+
+ // Only send the bindmounts if this is not a quick-launch instance.
+ if (!m_isQuickLaunch && !sendBindMounts())
+ return false;
+
+ // create an unique fifo name in /tmp
+ m_fifoPath = QDir::tempPath().toLocal8Bit() + "/sc-" + QUuid::createUuid().toByteArray().mid(1,36) + ".fifo";
+ if (mkfifo(m_fifoPath, 0600) != 0) {
+ qWarning() << "Failed to create FIFO at" << m_fifoPath << "to redirect stdout/stderr out of the container:" << strerror(errno);
+ m_fifoPath.clear();
+ return false;
+ }
+
+ // open fifo for reading
+ // due to QTBUG-15261 (bytesAvailable() on a fifo always returns 0) we use a raw fd
+ m_fifoFd = QT_OPEN(m_fifoPath, O_RDONLY | O_NONBLOCK);
+ if (m_fifoFd < 0) {
+ qWarning() << "Failed to open FIFO at" << m_fifoPath << "for reading:" << strerror(errno);
+ return false;
+ }
+
+ // read from fifo and dump to message handler
+ QSocketNotifier *sn = new QSocketNotifier(m_fifoFd, QSocketNotifier::Read, this);
+ int outputFd = m_outputFd;
+ connect(sn, &QSocketNotifier::activated, this, [sn, outputFd](int fifoFd) {
+ int bytesAvailable = 0;
+ if (ioctl(fifoFd, FIONREAD, &bytesAvailable) == 0) {
+ static const int bufferSize = 4096;
+ static QByteArray buffer(bufferSize, 0);
+
+ while (bytesAvailable > 0) {
+ auto bytesRead = QT_READ(fifoFd, buffer.data(), std::min(bytesAvailable, bufferSize));
+ if (bytesRead < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ sn->setEnabled(false);
+ return;
+ } else if (bytesRead > 0) {
+ (void) QT_WRITE(outputFd, buffer.constData(), bytesRead);
+ bytesAvailable -= bytesRead;
+ }
+ }
+ }
+ });
+
+ // Calculate the exact command to run
+ QStringList command;
+ if (!m_debugWrapperCommand.isEmpty()) {
+ command = substituteCommand(m_debugWrapperCommand, m_program, arguments);
+ } else {
+ command = arguments;
+ command.prepend(m_program);
+ }
+
+ // SC expects a plain string instead of individual args
+ QString cmdLine;
+ for (const auto &part : qAsConst(command)) {
+ if (!cmdLine.isEmpty())
+ cmdLine.append(QLatin1Char(' '));
+ cmdLine.append(QLatin1Char('\"'));
+ cmdLine.append(part);
+ cmdLine.append(QLatin1Char('\"'));
+ }
+ //cmdLine.prepend(QStringLiteral("/usr/bin/strace ")); // useful if things go wrong...
+
+ // we start with a copy of the AM's environment, but some variables would overwrite important
+ // redirections set by SC gateways.
+ static const QStringList forbiddenVars = {
+ qSL("XDG_RUNTIME_DIR"),
+ qSL("DBUS_SESSION_BUS_ADDRESS"),
+ qSL("DBUS_SYSTEM_BUS_ADDRESS"),
+ qSL("PULSE_SERVER")
+ };
+
+ // since we have to translate between a QProcessEnvironment and a QMap<>, we cache the result
+ static QMap<QString, QString> baseEnvVars;
+ if (baseEnvVars.isEmpty()) {
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ const auto keys = env.keys();
+ for (const auto key : keys) {
+ if (!key.isEmpty() && !forbiddenVars.contains(key))
+ baseEnvVars.insert(key, env.value(key));
+ }
+ }
+
+ QMap<QString, QString> envVars = baseEnvVars;
+
+ // set the env. variables coming from the runtime
+ for (auto it = runtimeEnvironment.cbegin(); it != runtimeEnvironment.cend(); ++it) {
+ if (it.value().isEmpty())
+ envVars.remove(it.key());
+ else
+ envVars.insert(it.key(), it.value());
+ }
+ // set the env. variables coming from a debug wrapper
+ for (auto it = m_debugWrapperEnvironment.cbegin(); it != m_debugWrapperEnvironment.cend(); ++it) {
+ if (it.value().isEmpty())
+ envVars.remove(it.key());
+ else
+ envVars.insert(it.key(), it.value());
+ }
+
+ QVariant venvVars = QVariant::fromValue(envVars);
+
+ qDebug () << "SoftwareContainer is trying to launch application" << m_id
+ << "\n * command ..." << cmdLine
+ << "\n * directory ." << m_containerPath
+ << "\n * output ...." << m_fifoPath
+ << "\n * environment" << envVars;
+
+#if 0
+ qWarning() << "Attach to container now!";
+ qWarning().nospace() << " sudo lxc-attach -n SC-" << m_id;
+ sleep(10000000);
+#endif
+
+ auto reply = iface->call(QDBus::Block, "Execute", m_id, cmdLine, m_containerPath, QString::fromLocal8Bit(m_fifoPath), venvVars);
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning() << "SoftwareContainer failed to execute application" << m_id << "in directory" << m_containerPath << "in the container:" << reply.errorMessage();
+ return false;
+ }
+
+ m_pid = reply.arguments().at(0).value<int>();
+
+ m_state = QProcess::Running;
+ QTimer::singleShot(0, this, [this]() {
+ emit stateChanged(m_state);
+ emit started();
+ });
+ return true;
+}
+
+qint64 SoftwareContainer::processId() const
+{
+ return m_pid;
+}
+
+QProcess::ProcessState SoftwareContainer::state() const
+{
+ return m_state;
+}
+
+void SoftwareContainer::kill()
+{
+ auto iface = manager()->interface();
+
+ if (iface) {
+ QDBusMessage reply = iface->call(QDBus::Block, "Destroy", m_id);
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning() << "SoftwareContainer failed to destroy container" << reply.errorMessage();
+ }
+
+ if (!reply.arguments().at(0).toBool()) {
+ qWarning() << "SoftwareContainer failed to destroy container.";
+ }
+ }
+}
+
+void SoftwareContainer::terminate()
+{
+ //TODO: handle graceful shutdown
+ kill();
+}
+
+void SoftwareContainer::containerExited(uint exitCode)
+{
+ m_state = QProcess::NotRunning;
+ emit stateChanged(m_state);
+ emit finished(WEXITSTATUS(exitCode), WIFEXITED(exitCode) ? QProcess::NormalExit : QProcess::CrashExit);
+ deleteLater();
+}
diff --git a/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.h b/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.h
new file mode 100644
index 00000000..50d47312
--- /dev/null
+++ b/examples/applicationmanager/softwarecontainer-plugin/softwarecontainer.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QVariantMap>
+#include <QFileInfo>
+
+#include <QtAppManPluginInterfaces/containerinterface.h>
+
+QT_FORWARD_DECLARE_CLASS(QDBusInterface)
+
+class SoftwareContainerManager;
+
+class SoftwareContainer : public ContainerInterface
+{
+ Q_OBJECT
+
+public:
+ SoftwareContainer(SoftwareContainerManager *manager, bool isQuickLaunch, int containerId,
+ int outputFd, const QMap<QString, QString> &debugWrapperEnvironment,
+ const QStringList &debugWrapperCommand);
+ ~SoftwareContainer();
+
+ SoftwareContainerManager *manager() const;
+
+ bool attachApplication(const QVariantMap &application) override;
+
+ QString controlGroup() const override;
+ bool setControlGroup(const QString &groupName) override;
+
+ bool setProgram(const QString &program) override;
+ void setBaseDirectory(const QString &baseDirectory) override;
+
+ bool isReady() const override;
+
+ QString mapContainerPathToHost(const QString &containerPath) const override;
+ QString mapHostPathToContainer(const QString &hostPath) const override;
+
+ bool start(const QStringList &arguments, const QMap<QString, QString> &runtimeEnvironment) override;
+
+ qint64 processId() const override;
+ QProcess::ProcessState state() const override;
+
+ void kill() override;
+ void terminate() override;
+
+ void containerExited(uint exitCode);
+
+private:
+ bool sendCapabilities();
+ bool sendBindMounts();
+
+ SoftwareContainerManager *m_manager;
+ bool m_isQuickLaunch;
+ int m_id;
+ QString m_program;
+ QString m_baseDir;
+ bool m_ready = false;
+ qint64 m_pid = 0;
+ QProcess::ProcessState m_state = QProcess::NotRunning;
+ QVariantMap m_application;
+ QString m_appRelativeCodePath;
+ QString m_hostPath;
+ QString m_containerPath;
+ QByteArray m_fifoPath;
+ int m_fifoFd = -1;
+ int m_outputFd;
+ QMap<QString, QString> m_debugWrapperEnvironment;
+ QStringList m_debugWrapperCommand;
+ QFileInfo m_dbusP2PInfo;
+};
+
+class SoftwareContainerManager : public QObject, public ContainerManagerInterface
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID AM_ContainerManagerInterface_iid)
+ Q_INTERFACES(ContainerManagerInterface)
+
+public:
+ SoftwareContainerManager();
+
+ QString identifier() const override;
+ bool supportsQuickLaunch() const override;
+ void setConfiguration(const QVariantMap &configuration) override;
+
+ ContainerInterface *create(bool isQuickLaunch,
+ const QVector<int> &stdioRedirections,
+ const QMap<QString, QString> &debugWrapperEnvironment,
+ const QStringList &debugWrapperCommand) override;
+public:
+ QDBusInterface *interface() const;
+ QVariantMap configuration() const;
+
+private slots:
+ void processStateChanged(int containerId, uint processId, bool isRunning, uint exitCode);
+
+private:
+ QVariantMap m_configuration;
+ QDBusInterface *m_interface = nullptr;
+ QMap<int, SoftwareContainer *> m_containers;
+};
diff --git a/examples/applicationmanager/startup-plugin/startup-plugin.cpp b/examples/applicationmanager/startup-plugin/startup-plugin.cpp
new file mode 100644
index 00000000..15bdd175
--- /dev/null
+++ b/examples/applicationmanager/startup-plugin/startup-plugin.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+#include "startup-plugin.h"
+
+Q_LOGGING_CATEGORY(LogMe, "am.start")
+
+void TestStartupInterface::initialize(const QVariantMap &systemProperties) Q_DECL_NOEXCEPT_EXPR(false)
+{
+ qCWarning(LogMe) << "Startup initialize - systemProperties:" << systemProperties;
+}
+
+void TestStartupInterface::afterRuntimeRegistration() Q_DECL_NOEXCEPT_EXPR(false)
+{
+ qCWarning(LogMe) << "Startup afterRuntimeRegistration";
+}
+
+void TestStartupInterface::beforeQmlEngineLoad(QQmlEngine *engine) Q_DECL_NOEXCEPT_EXPR(false)
+{
+ qCWarning(LogMe) << "Startup beforeQmlEngineLoad - engine:" << engine;
+}
+
+void TestStartupInterface::afterQmlEngineLoad(QQmlEngine *engine) Q_DECL_NOEXCEPT_EXPR(false)
+{
+ qCWarning(LogMe) << "Startup afterQmlEngineLoad - engine:" << engine;
+}
+
+void TestStartupInterface::beforeWindowShow(QWindow *window) Q_DECL_NOEXCEPT_EXPR(false)
+{
+ qCWarning(LogMe) << "Startup beforeWindowShow - window:" << window;
+}
+
+void TestStartupInterface::afterWindowShow(QWindow *window) Q_DECL_NOEXCEPT_EXPR(false)
+{
+ qCWarning(LogMe) << "Startup afterWindowShow - window:" << window;
+}
diff --git a/examples/applicationmanager/startup-plugin/startup-plugin.h b/examples/applicationmanager/startup-plugin/startup-plugin.h
new file mode 100644
index 00000000..c1fe0b05
--- /dev/null
+++ b/examples/applicationmanager/startup-plugin/startup-plugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:BSD-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: BSD-3-Clause
+**
+****************************************************************************/
+
+#include <QLoggingCategory>
+#include <QtAppManPluginInterfaces>
+#include <QtAppManCommon/global.h>
+
+Q_DECLARE_LOGGING_CATEGORY(LogMe)
+
+class TestStartupInterface : public QObject, public StartupInterface
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID AM_StartupInterface_iid)
+ Q_INTERFACES(StartupInterface)
+
+public:
+ // StartupInterface
+ void initialize(const QVariantMap &systemProperties) Q_DECL_NOEXCEPT_EXPR(false) override;
+ void afterRuntimeRegistration() Q_DECL_NOEXCEPT_EXPR(false) override;
+
+ void beforeQmlEngineLoad(QQmlEngine *engine) Q_DECL_NOEXCEPT_EXPR(false) override;
+ void afterQmlEngineLoad(QQmlEngine *engine) Q_DECL_NOEXCEPT_EXPR(false) override;
+
+ void beforeWindowShow(QWindow *window) Q_DECL_NOEXCEPT_EXPR(false) override;
+ void afterWindowShow(QWindow *window) Q_DECL_NOEXCEPT_EXPR(false) override;
+};
diff --git a/examples/applicationmanager/startup-plugin/startup-plugin.pro b/examples/applicationmanager/startup-plugin/startup-plugin.pro
new file mode 100644
index 00000000..3cfdd7e3
--- /dev/null
+++ b/examples/applicationmanager/startup-plugin/startup-plugin.pro
@@ -0,0 +1,14 @@
+TEMPLATE = lib
+CONFIG += plugin c++11
+TARGET = startup-plugin
+
+QT = core appman_plugininterfaces-private
+
+HEADERS += \
+ startup-plugin.h
+
+SOURCES += \
+ startup-plugin.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/startup-plugin
+INSTALLS += target