feat: watch systemd unit new and remove to sync state
add default values to XDG_DATA_DIRS if it dosen't set Signed-off-by: ComixHe <heyuming@deepin.org> Signed-off-by: black-desk <me@black-desk.cn>
This commit is contained in:
@ -22,6 +22,105 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
||||
}
|
||||
|
||||
m_jobManager.reset(new JobManager1Service(this));
|
||||
|
||||
auto &dispatcher = SystemdSignalDispatcher::instance();
|
||||
|
||||
connect(&dispatcher,
|
||||
&SystemdSignalDispatcher::SystemdUnitNew,
|
||||
this,
|
||||
[this](QString serviceName, QDBusObjectPath systemdUnitPath) {
|
||||
auto [appId, instanceId] = processServiceName(serviceName);
|
||||
if (appId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &app : m_applicationList) {
|
||||
if (app->id() == appId) [[unlikely]] {
|
||||
const auto &applicationPath = app->m_applicationPath.path();
|
||||
if (!app->addOneInstance(instanceId, applicationPath, systemdUnitPath.path())) {
|
||||
qWarning() << "add Instance failed:" << applicationPath << serviceName << systemdUnitPath.path();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "couldn't find application:" << serviceName << "in application manager.";
|
||||
});
|
||||
|
||||
connect(&dispatcher,
|
||||
&SystemdSignalDispatcher::SystemdUnitRemoved,
|
||||
this,
|
||||
[this](QString serviceName, QDBusObjectPath systemdUnitPath) {
|
||||
auto pair = processServiceName(serviceName);
|
||||
auto appId = pair.first, instanceId = pair.second;
|
||||
if (appId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto appIt = std::find_if(m_applicationList.cbegin(),
|
||||
m_applicationList.cend(),
|
||||
[&appId](const QSharedPointer<ApplicationService> &app) {
|
||||
if (app->id() == appId) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (appIt == m_applicationList.cend()) [[unlikely]] {
|
||||
qWarning() << "couldn't find app" << appId << "in application manager.";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &appRef = *appIt;
|
||||
|
||||
auto instanceIt = std::find_if(appRef->m_Instances.cbegin(),
|
||||
appRef->m_Instances.cend(),
|
||||
[&systemdUnitPath](const QSharedPointer<InstanceService> &value) {
|
||||
if (value->systemdUnitPath() == systemdUnitPath) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (instanceIt != appRef->m_Instances.cend()) [[likely]] {
|
||||
appRef->removeOneInstance(instanceIt.key());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QPair<QString, QString> ApplicationManager1Service::processServiceName(const QString &serviceName)
|
||||
{
|
||||
QString instanceId;
|
||||
QString applicationId;
|
||||
|
||||
if (serviceName.endsWith(".service")) {
|
||||
auto lastDotIndex = serviceName.lastIndexOf('.');
|
||||
auto app = serviceName.sliced(0, lastDotIndex - 1); // remove suffix
|
||||
|
||||
if (app.contains('@')) {
|
||||
auto atIndex = app.indexOf('@');
|
||||
instanceId = app.sliced(atIndex + 1);
|
||||
app.remove(atIndex, instanceId.length() + 1);
|
||||
}
|
||||
|
||||
applicationId = app.split('-').last(); // drop launcher if it exists.
|
||||
} else if (serviceName.endsWith(".scope")) {
|
||||
auto lastDotIndex = serviceName.lastIndexOf('.');
|
||||
auto app = serviceName.sliced(0, lastDotIndex - 1);
|
||||
|
||||
auto components = app.split('-');
|
||||
instanceId = components.takeLast();
|
||||
applicationId = components.takeLast();
|
||||
} else {
|
||||
qDebug() << "it's not service or slice or scope.";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (instanceId.isEmpty()) {
|
||||
instanceId = QUuid::createUuid().toString(QUuid::Id128);
|
||||
}
|
||||
|
||||
return qMakePair(std::move(applicationId), std::move(instanceId));
|
||||
}
|
||||
|
||||
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
||||
|
@ -60,6 +60,8 @@ private:
|
||||
std::unique_ptr<Identifier> m_identifier;
|
||||
QScopedPointer<JobManager1Service> m_jobManager{nullptr};
|
||||
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList;
|
||||
|
||||
QPair<QString, QString> processServiceName(const QString &serviceName);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,16 @@ ApplicationService::~ApplicationService()
|
||||
m_desktopSource.destruct(m_isPersistence);
|
||||
}
|
||||
|
||||
qsizetype ApplicationService::applicationCheck(const QString &serviceName)
|
||||
{
|
||||
const auto &ApplicationId = id();
|
||||
if (!serviceName.startsWith(ApplicationId)) [[likely]] {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ApplicationId.size();
|
||||
}
|
||||
|
||||
QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env)
|
||||
{
|
||||
const auto &supportedActions = actions();
|
||||
@ -130,16 +140,16 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
|
||||
auto resourceFile = variantValue.toString();
|
||||
if (resourceFile.isEmpty()) {
|
||||
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
||||
commands.push_front(QString{R"(--unitName=DDE-%1@%2.service)"}.arg(
|
||||
commands.push_front(QString{R"(--unitName=app-DDE-%1@%2.service)"}.arg(
|
||||
this->id(), instanceRandomUUID)); // launcher should use this instanceId
|
||||
QProcess process;
|
||||
process.start(m_launcher, commands);
|
||||
process.waitForFinished();
|
||||
if (auto code = process.exitCode(); code != 0) {
|
||||
qWarning() << "Launch Application Failed. exitCode:" << code;
|
||||
return false;
|
||||
return QString{""};
|
||||
}
|
||||
return addOneInstance(instanceRandomUUID, m_applicationPath.path()); // TODO: pass correct Systemd Unit Path
|
||||
return DDEApplicationManager1InstanceObjectPath + instanceRandomUUID;
|
||||
}
|
||||
|
||||
int location{0};
|
||||
@ -167,8 +177,9 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
|
||||
auto exitCode = process.exitCode();
|
||||
if (exitCode != 0) {
|
||||
qWarning() << "Launch Application Failed:" << binary << tmp;
|
||||
return QString{""};
|
||||
}
|
||||
return addOneInstance(instanceRandomUUID, m_applicationPath.path());
|
||||
return DDEApplicationManager1InstanceObjectPath + instanceRandomUUID;
|
||||
},
|
||||
std::move(res));
|
||||
}
|
||||
@ -254,8 +265,8 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
|
||||
|
||||
void ApplicationService::removeOneInstance(const QDBusObjectPath &instance)
|
||||
{
|
||||
m_Instances.remove(instance);
|
||||
unregisterObjectFromDBus(instance.path());
|
||||
m_Instances.remove(instance);
|
||||
}
|
||||
|
||||
void ApplicationService::removeAllInstance()
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "global.h"
|
||||
#include "desktopentry.h"
|
||||
#include "desktopicons.h"
|
||||
#include "systemdsignaldispatcher.h"
|
||||
#include "dbus/jobmanager1service.h"
|
||||
|
||||
class ApplicationService : public QObject
|
||||
@ -52,9 +53,9 @@ public:
|
||||
const QString &getLauncher() const noexcept { return m_launcher; }
|
||||
void setLauncher(const QString &launcher) noexcept { m_launcher = launcher; }
|
||||
|
||||
bool addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath = "/");
|
||||
bool addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath);
|
||||
void recoverInstances(const QList<QDBusObjectPath>) noexcept;
|
||||
void removeOneInstance(const QDBusObjectPath &instance); // TODO: remove instance when app closed
|
||||
void removeOneInstance(const QDBusObjectPath &instance);
|
||||
void removeAllInstance();
|
||||
|
||||
public Q_SLOTS:
|
||||
@ -133,6 +134,7 @@ private:
|
||||
QSharedPointer<DesktopIcons> m_Icons{nullptr};
|
||||
QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
|
||||
QString userNameLookup(uid_t uid);
|
||||
qsizetype applicationCheck(const QString &serviceName);
|
||||
[[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QtConcurrent>
|
||||
#include <QDBusError>
|
||||
#include <QFuture>
|
||||
#include <QUuid>
|
||||
#include "global.h"
|
||||
@ -76,7 +77,7 @@ public:
|
||||
|
||||
QString result{job->status()};
|
||||
for (const auto &val : future.result()) {
|
||||
if (val.canConvert<QDBusError>()) {
|
||||
if (val.metaType().id() == QMetaType::fromType<QDBusError>().id()) {
|
||||
result = "failed";
|
||||
}
|
||||
break;
|
||||
|
Reference in New Issue
Block a user