summaryrefslogtreecommitdiffstats
path: root/src/manager-lib/application.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/manager-lib/application.cpp')
-rw-r--r--src/manager-lib/application.cpp385
1 files changed, 118 insertions, 267 deletions
diff --git a/src/manager-lib/application.cpp b/src/manager-lib/application.cpp
index bc2c7e4f..432cc86e 100644
--- a/src/manager-lib/application.cpp
+++ b/src/manager-lib/application.cpp
@@ -4,7 +4,7 @@
** Copyright (C) 2018 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the Luxoft Application Manager.
+** This file is part of the Qt Application Manager.
**
** $QT_BEGIN_LICENSE:LGPL-QTAS$
** Commercial License Usage
@@ -43,14 +43,12 @@
#include "application.h"
#include "abstractruntime.h"
#include "applicationinfo.h"
+#include "package.h"
#include "exception.h"
#include "logging.h"
#include <QDebug>
-#if defined(Q_OS_UNIX)
-# include <signal.h>
-#endif
/*!
\qmltype ApplicationObject
@@ -90,9 +88,12 @@
/*!
\qmlproperty string ApplicationObject::documentUrl
\readonly
+ \obsolete
- This property always returns the default \c documentUrl specified in the manifest file, even if
- a different URL was used to start the application.
+ This was used to distinguish between application aliases, which have been replaced by the
+ intents mechanism.
+
+ Always returns an empty string.
*/
/*!
\qmlproperty bool ApplicationObject::builtIn
@@ -104,22 +105,22 @@
/*!
\qmlproperty bool ApplicationObject::alias
\readonly
+ \obsolete
- Will return \c true if this ApplicationObject object is an alias to another one.
+ This was used to distinguish between application aliases, which have been replaced by the
+ intents mechanism.
- \sa nonAliased
+ Always returns \c false.
*/
/*!
\qmlproperty ApplicationObject ApplicationObject::nonAliased
\readonly
+ \obsolete
- If this ApplicationObject is an alias, then you can access the non-alias, base ApplicationObject
- via this property, otherwise it contains a reference to itself. This means that if you're interested
- in accessing the base application regardless of whether the object at hand is just an alias, you
- can always safely refer to this property.
+ This was used to distinguish between application aliases, which have been replaced by the
+ intents mechanism.
- If you want to know whether this object is an alias or a base ApplicationObject, use
- ApplicationObject::alias instead.
+ Always returns the object itself.
*/
/*!
\qmlproperty list<string> ApplicationObject::capabilities
@@ -190,10 +191,7 @@
\qmlproperty string ApplicationObject::codeDir
\readonly
- The absolute path to the application's installation directory. Please note this directory might
- not always be available for applications that were installed onto removable media.
-
- \sa {Installation Locations}
+ The absolute path to the application's installation directory.
*/
/*!
\qmlproperty enumeration ApplicationObject::state
@@ -272,237 +270,162 @@
QT_BEGIN_NAMESPACE_AM
+
///////////////////////////////////////////////////////////////////////////////////////////////////
-// AbstractApplication
+// Application
///////////////////////////////////////////////////////////////////////////////////////////////////
-AbstractApplication::AbstractApplication(AbstractApplicationInfo *info)
+Application::Application(ApplicationInfo *info, Package *package)
: m_info(info)
+ , m_package(package)
{
+ Q_ASSERT(info);
+ Q_ASSERT(package);
+
+ // handle package blocking: all apps have to be stopped and the stop state has to be reported
+ // back to the package
+ connect(package, &Package::blockedChanged, this, [this](bool blocked) {
+ emit blockedChanged(blocked);
+ if (blocked && (runState() == Am::NotRunning))
+ this->package()->applicationStoppedDueToBlock(id());
+ else if (blocked)
+ stop(true);
+ });
+ connect(this, &Application::runStateChanged, this, [this](Am::RunState runState) {
+ if (isBlocked() && (runState == Am::NotRunning))
+ this->package()->applicationStoppedDueToBlock(id());
+ });
}
-QString AbstractApplication::id() const
+bool Application::start(const QString &documentUrl)
{
- return m_info->id();
+ if (requests.startRequested)
+ return requests.startRequested(documentUrl);
+ else
+ return false;
}
-QUrl AbstractApplication::icon() const
+bool Application::debug(const QString &debugWrapper, const QString &documentUrl)
{
- if (info()->icon().isEmpty())
- return QUrl();
-
- auto appInfo = this->nonAliasedInfo();
- QDir dir;
- switch (state()) {
- default:
- case Installed:
- dir.setPath(appInfo->manifestDir());
- break;
- case BeingInstalled:
- case BeingUpdated:
- dir.setPath(appInfo->codeDir().absolutePath() + QLatin1Char('+'));
- break;
- case BeingRemoved:
- dir.setPath(appInfo->codeDir().absolutePath() + QLatin1Char('-'));
- break;
- }
- return QUrl::fromLocalFile(dir.absoluteFilePath(info()->icon()));
+ if (requests.debugRequested)
+ return requests.debugRequested(debugWrapper, documentUrl);
+ else
+ return false;
}
-QString AbstractApplication::documentUrl() const
+void Application::stop(bool forceKill)
{
- return info()->documentUrl();
+ if (requests.stopRequested)
+ requests.stopRequested(forceKill);
}
-bool AbstractApplication::isBuiltIn() const
+ApplicationInfo *Application::info() const
{
- return nonAliasedInfo()->isBuiltIn();
+ return m_info.data();
}
-bool AbstractApplication::isAlias() const
+PackageInfo *Application::packageInfo() const
{
- return info()->isAlias();
+ return m_info->packageInfo();
}
-QStringList AbstractApplication::capabilities() const
+Package *Application::package() const
{
- return nonAliasedInfo()->capabilities();
+ return m_package;
}
-QStringList AbstractApplication::supportedMimeTypes() const
+QString Application::id() const
{
- return nonAliasedInfo()->supportedMimeTypes();
+ return m_info->id();
}
-QStringList AbstractApplication::categories() const
+bool Application::isBuiltIn() const
{
- return nonAliasedInfo()->categories();
+ return packageInfo()->isBuiltIn();
}
-QVariantMap AbstractApplication::applicationProperties() const
+QString Application::runtimeName() const
{
- return info()->applicationProperties();
+ return m_info->runtimeName();
}
-bool AbstractApplication::supportsApplicationInterface() const
+QVariantMap Application::runtimeParameters() const
{
- return nonAliasedInfo()->supportsApplicationInterface();
+ return m_info->runtimeParameters();
}
-QString AbstractApplication::version() const
+QStringList Application::capabilities() const
{
- return nonAliasedInfo()->version();
+ return m_info->capabilities();
}
-QString AbstractApplication::codeDir() const
+QStringList Application::categories() const
{
- switch (state()) {
- default:
- case Installed:
- return nonAliasedInfo()->codeDir().absolutePath();
- case BeingInstalled:
- case BeingUpdated:
- return nonAliasedInfo()->codeDir().absolutePath() + QLatin1Char('+');
- case BeingRemoved:
- return nonAliasedInfo()->codeDir().absolutePath() + QLatin1Char('-');
- }
+ return package()->categories();
}
-QString AbstractApplication::name(const QString &language) const
+QUrl Application::icon() const
{
- return info()->name(language);
+ return package()->icon();
}
-bool AbstractApplication::start(const QString &documentUrl)
+QStringList Application::supportedMimeTypes() const
{
- if (requests.startRequested)
- return requests.startRequested(documentUrl);
- else
- return false;
+ return info()->supportedMimeTypes();
}
-bool AbstractApplication::debug(const QString &debugWrapper, const QString &documentUrl)
+QString Application::name() const
{
- if (requests.debugRequested)
- return requests.debugRequested(debugWrapper, documentUrl);
- else
- return false;
+ return package()->name();
}
-void AbstractApplication::stop(bool forceKill)
+QString Application::name(const QString &language) const
{
- if (requests.stopRequested)
- requests.stopRequested(forceKill);
+ return package()->names().value(language).toString();
}
-QVector<AbstractApplication *> AbstractApplication::fromApplicationInfoVector(
- QVector<AbstractApplicationInfo *> &appInfoVector)
+bool Application::isBlocked() const
{
- QVector<AbstractApplication *> apps;
-
- auto findAppWithId = [&apps] (const QString &id) -> AbstractApplication*
- {
- for (AbstractApplication *app : apps) {
- if (app->id() == id)
- return app;
- }
- return nullptr;
- };
-
- auto extractBaseId = [] (const QString &id) -> QString
- {
- return id.section(qL1C('@'), 0, 0);
- };
-
- for (auto *appInfo : appInfoVector) {
- QScopedPointer<AbstractApplication> app;
- if (appInfo->isAlias()) {
- auto *originalApp = findAppWithId(extractBaseId(appInfo->id()));
- if (!originalApp)
- throw Exception(Error::Parse, "Could not find base app for alias id %2").arg(appInfo->id());
- Q_ASSERT(!originalApp->isAlias());
- app.reset(new ApplicationAlias(static_cast<Application*>(originalApp),
- static_cast<ApplicationAliasInfo*>(appInfo)));
- } else {
- AbstractApplication *otherAbsApp = findAppWithId(appInfo->id());
- if (otherAbsApp) {
- // There's already another ApplicationInfo with the same id. It's probably an update for a
- // built-in app, in which case we use the same Application instance to hold both
- // ApplicationInfo instances.
- bool merged = false;
-
- if (!otherAbsApp->isAlias()) {
- auto otherApp = static_cast<Application*>(otherAbsApp);
- auto fullAppInfo = static_cast<ApplicationInfo*>(appInfo);
- if (otherApp->isBuiltIn() && !fullAppInfo->isBuiltIn() && !otherApp->updatedInfo()) {
- otherApp->setUpdatedInfo(static_cast<ApplicationInfo*>(appInfo));
- merged = true;
- } else if (!otherApp->isBuiltIn() && fullAppInfo->isBuiltIn() && !otherApp->updatedInfo()) {
- auto currentBaseInfo = otherApp->takeBaseInfo();
- otherApp->setBaseInfo(static_cast<ApplicationInfo*>(appInfo));
- otherApp->setUpdatedInfo(currentBaseInfo);
- merged = true;
- }
- }
-
- if (!merged)
- qCWarning(LogSystem).nospace() << "Found a second application with id "
- << appInfo->id() << " which is not an update for a built-in one. Ignoring it.";
- } else {
- app.reset(new Application(static_cast<ApplicationInfo*>(appInfo)));
- }
- }
-
- if (!app.isNull())
- apps << app.take();
- }
-
- return apps;
+ return package()->isBlocked();
}
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Application
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-Application::Application(ApplicationInfo *info, State initialState)
- : AbstractApplication(info)
- , m_state(initialState)
+QVariantMap Application::applicationProperties() const
{
+ return info()->applicationProperties();
}
-void Application::setCurrentRuntime(AbstractRuntime *rt)
+bool Application::supportsApplicationInterface() const
{
- if (m_runtime == rt)
- return;
-
- if (m_runtime)
- disconnect(m_runtime, nullptr, this, nullptr);
-
- m_runtime = rt;
- emit runtimeChanged();
+ return info()->supportsApplicationInterface();
+}
- if (m_runtime) {
- connect(m_runtime, &AbstractRuntime::finished, this, &Application::setLastExitCodeAndStatus);
- connect(m_runtime, &QObject::destroyed, this, [this]() {
- this->setCurrentRuntime(nullptr);
- });
- } else
- setRunState(Am::NotRunning);
+QString Application::codeDir() const
+{
+ switch (package()->state()) {
+ default:
+ case Package::Installed:
+ return packageInfo()->baseDir().absolutePath();
+ case Package::BeingInstalled:
+ case Package::BeingUpdated:
+ return packageInfo()->baseDir().absolutePath() + QLatin1Char('+');
+ case Package::BeingRemoved:
+ return packageInfo()->baseDir().absolutePath() + QLatin1Char('-');
+ }
}
-bool Application::isBlocked() const
+QString Application::version() const
{
- return m_blocked.load() == 1;
+ return packageInfo()->version();
}
-bool Application::block()
+Application::State Application::state() const
{
- return m_blocked.testAndSetOrdered(0, 1);
+ return static_cast<State>(package()->state());
}
-bool Application::unblock()
+qreal Application::progress() const
{
- return m_blocked.testAndSetOrdered(1, 0);
+ return package()->progress();
}
void Application::setRunState(Am::RunState runState)
@@ -513,24 +436,25 @@ void Application::setRunState(Am::RunState runState)
}
}
-QString Application::runtimeName() const
+void Application::setCurrentRuntime(AbstractRuntime *runtime)
{
- return Application::nonAliasedInfo()->runtimeName();
-}
+ if (m_runtime == runtime)
+ return;
-QVariantMap Application::runtimeParameters() const
-{
- return Application::nonAliasedInfo()->runtimeParameters();
-}
+ if (m_runtime)
+ disconnect(m_runtime, nullptr, this, nullptr);
-AbstractApplicationInfo *Application::info() const
-{
- return m_updatedInfo ? m_updatedInfo.data() : m_info.data();
-}
+ m_runtime = runtime;
+ emit runtimeChanged();
-ApplicationInfo *Application::nonAliasedInfo() const
-{
- return static_cast<ApplicationInfo*>(Application::info());
+ if (m_runtime) {
+ connect(m_runtime, &AbstractRuntime::finished, this, &Application::setLastExitCodeAndStatus);
+ connect(m_runtime, &QObject::destroyed, this, [this]() {
+ this->setCurrentRuntime(nullptr);
+ });
+ } else {
+ setRunState(Am::NotRunning);
+ }
}
void Application::setLastExitCodeAndStatus(int exitCode, Am::ExitStatus exitStatus)
@@ -540,88 +464,15 @@ void Application::setLastExitCodeAndStatus(int exitCode, Am::ExitStatus exitStat
emit lastExitCodeChanged();
}
- Am::ExitStatus newStatus;
- if (exitStatus == Am::CrashExit) {
-#if defined(Q_OS_UNIX)
- newStatus = (exitCode == SIGTERM || exitCode == SIGKILL) ? Am::ForcedExit : Am::CrashExit;
-#else
- newStatus = Am::CrashExit;
-#endif
- } else {
- newStatus = Am::NormalExit;
- }
-
- if (m_lastExitStatus != newStatus) {
- m_lastExitStatus = newStatus;
+ if (m_lastExitStatus != exitStatus) {
+ m_lastExitStatus = exitStatus;
emit lastExitStatusChanged();
}
}
-void Application::setBaseInfo(ApplicationInfo *info)
-{
- m_info.reset(info);
- emit bulkChange();
-}
-
-ApplicationInfo *Application::takeBaseInfo()
-{
- return static_cast<ApplicationInfo*>(m_info.take());
-}
-
-void Application::setUpdatedInfo(ApplicationInfo* info)
-{
- Q_ASSERT(!info || (m_info && info->id() == m_info->id()));
-
- m_updatedInfo.reset(info);
- emit bulkChange();
-}
-
-void Application::setState(State state)
-{
- if (m_state != state) {
- m_state = state;
- emit stateChanged(m_state);
- }
-}
-
-void Application::setProgress(qreal value)
-{
- m_progress = value;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// ApplicationAlias
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-ApplicationAlias::ApplicationAlias(Application* app, ApplicationAliasInfo* info)
- : AbstractApplication(info)
- , m_application(app)
-{
- connect(m_application, &AbstractApplication::runtimeChanged, this, &AbstractApplication::runtimeChanged);
- connect(m_application, &AbstractApplication::lastExitCodeChanged, this, &AbstractApplication::lastExitCodeChanged);
- connect(m_application, &AbstractApplication::lastExitStatusChanged, this, &AbstractApplication::lastExitStatusChanged);
- connect(m_application, &AbstractApplication::stateChanged, this, &AbstractApplication::stateChanged);
- connect(m_application, &AbstractApplication::runStateChanged, this, &AbstractApplication::runStateChanged);
-}
-
-QString ApplicationAlias::runtimeName() const
-{
- return m_application->runtimeName();
-}
-
-QVariantMap ApplicationAlias::runtimeParameters() const
-{
- return m_application->runtimeParameters();
-}
-
-ApplicationInfo *ApplicationAlias::nonAliasedInfo() const
-{
- return m_application->nonAliasedInfo();
-}
-
QT_END_NAMESPACE_AM
-QDebug operator<<(QDebug debug, const QT_PREPEND_NAMESPACE_AM(AbstractApplication) *app)
+QDebug operator<<(QDebug debug, const QT_PREPEND_NAMESPACE_AM(Application) *app)
{
debug << "Application Object:";
if (app)