2023-07-10 10:18:33 +08:00
|
|
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
2023-08-21 16:02:26 +08:00
|
|
|
#include "applicationadaptor.h"
|
2023-08-07 14:25:22 +08:00
|
|
|
#include "dbus/applicationmanager1adaptor.h"
|
2023-08-21 16:02:26 +08:00
|
|
|
#include "applicationservice.h"
|
2023-08-18 10:01:52 +08:00
|
|
|
#include "dbus/AMobjectmanager1adaptor.h"
|
2023-08-10 14:32:09 +08:00
|
|
|
#include "systemdsignaldispatcher.h"
|
2023-09-08 10:58:41 +08:00
|
|
|
#include "propertiesForwarder.h"
|
2023-07-24 14:12:59 +08:00
|
|
|
#include <QFile>
|
2023-08-28 17:57:21 +08:00
|
|
|
#include <QDBusMessage>
|
2023-07-24 14:12:59 +08:00
|
|
|
#include <unistd.h>
|
2023-07-10 10:18:33 +08:00
|
|
|
|
2023-07-17 14:49:35 +08:00
|
|
|
ApplicationManager1Service::~ApplicationManager1Service() = default;
|
|
|
|
|
2023-09-13 11:47:04 +08:00
|
|
|
ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifier> ptr,
|
|
|
|
std::weak_ptr<ApplicationManager1Storage> storage) noexcept
|
2023-07-24 14:12:59 +08:00
|
|
|
: m_identifier(std::move(ptr))
|
2023-09-13 11:47:04 +08:00
|
|
|
, m_storage(std::move(storage))
|
2023-09-14 13:38:44 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ApplicationManager1Service::initService(QDBusConnection &connection) noexcept
|
2023-07-24 14:12:59 +08:00
|
|
|
{
|
|
|
|
if (!connection.registerService(DDEApplicationManager1ServiceName)) {
|
2023-08-21 16:02:26 +08:00
|
|
|
qFatal("%s", connection.lastError().message().toLocal8Bit().data());
|
2023-07-24 14:12:59 +08:00
|
|
|
}
|
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
if (auto *tmp = new (std::nothrow) ApplicationManager1Adaptor{this}; tmp == nullptr) {
|
|
|
|
qCritical() << "new Application Manager Adaptor failed.";
|
|
|
|
std::terminate();
|
|
|
|
}
|
2023-08-11 10:12:46 +08:00
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
if (auto *tmp = new (std::nothrow) AMObjectManagerAdaptor{this}; tmp == nullptr) {
|
|
|
|
qCritical() << "new Object Manager of Application Manager Adaptor failed.";
|
2023-08-18 10:01:52 +08:00
|
|
|
std::terminate();
|
|
|
|
}
|
|
|
|
|
2023-08-28 11:11:50 +08:00
|
|
|
if (!registerObjectToDBus(this, DDEApplicationManager1ObjectPath, ApplicationManagerInterface)) {
|
2023-07-24 14:12:59 +08:00
|
|
|
std::terminate();
|
|
|
|
}
|
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
m_jobManager.reset(new (std::nothrow) JobManager1Service(this));
|
|
|
|
|
|
|
|
if (!m_jobManager) {
|
|
|
|
qCritical() << "new JobManager failed.";
|
|
|
|
std::terminate();
|
|
|
|
}
|
2023-08-08 15:10:32 +08:00
|
|
|
|
|
|
|
auto &dispatcher = SystemdSignalDispatcher::instance();
|
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
connect(&dispatcher, &SystemdSignalDispatcher::SystemdUnitNew, this, &ApplicationManager1Service::addInstanceToApplication);
|
|
|
|
|
2023-08-08 15:10:32 +08:00
|
|
|
connect(&dispatcher,
|
2023-08-28 17:57:21 +08:00
|
|
|
&SystemdSignalDispatcher::SystemdUnitRemoved,
|
2023-08-08 15:10:32 +08:00
|
|
|
this,
|
2023-08-28 17:57:21 +08:00
|
|
|
&ApplicationManager1Service::removeInstanceFromApplication);
|
2023-08-08 15:10:32 +08:00
|
|
|
|
2023-09-06 16:15:00 +08:00
|
|
|
auto sysBus = QDBusConnection::systemBus();
|
|
|
|
if (!sysBus.connect("org.desktopspec.ApplicationUpdateNotifier1",
|
|
|
|
"/org/desktopspec/ApplicationUpdateNotifier1",
|
|
|
|
"org.desktopspec.ApplicationUpdateNotifier1",
|
|
|
|
"ApplicationUpdated",
|
|
|
|
this,
|
|
|
|
SLOT(ReloadApplications()))) {
|
|
|
|
qFatal("connect to ApplicationUpdated failed.");
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:18:20 +08:00
|
|
|
scanApplications();
|
2023-08-11 14:53:05 +08:00
|
|
|
|
2023-09-04 18:18:20 +08:00
|
|
|
scanInstances();
|
|
|
|
|
2023-09-12 09:58:14 +08:00
|
|
|
if (auto *ptr = new (std::nothrow) PropertiesForwarder{DDEApplicationManager1ObjectPath, this}; ptr == nullptr) {
|
|
|
|
qCritical() << "new PropertiesForwarder of Application Manager failed.";
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:39:09 +08:00
|
|
|
// TODO: This is a workaround, we will use database at the end.
|
2023-09-04 18:18:20 +08:00
|
|
|
auto runtimePath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
|
|
|
|
if (runtimePath.isEmpty()) {
|
2023-09-04 18:39:09 +08:00
|
|
|
runtimePath = QString{"/run/user/%1/"}.arg(getCurrentUID());
|
2023-09-04 18:18:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QDir runtimeDir{runtimePath};
|
2023-09-12 09:58:14 +08:00
|
|
|
const auto *filename = u8"deepin-application-manager";
|
|
|
|
QFile flag{runtimeDir.filePath(filename)};
|
|
|
|
|
|
|
|
auto sessionId = getCurrentSessionId();
|
|
|
|
if (flag.open(QFile::ReadOnly | QFile::ExistingOnly)) {
|
2023-09-12 10:04:41 +08:00
|
|
|
auto content = flag.read(sessionId.size());
|
2023-09-12 09:58:14 +08:00
|
|
|
if (!content.isEmpty() and !sessionId.isEmpty() and content == sessionId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
flag.close();
|
2023-09-04 18:39:09 +08:00
|
|
|
}
|
|
|
|
|
2023-09-12 09:58:14 +08:00
|
|
|
if (flag.open(QFile::WriteOnly | QFile::Truncate)) {
|
2023-09-12 10:04:41 +08:00
|
|
|
flag.write(sessionId, sessionId.size());
|
2023-09-04 18:18:20 +08:00
|
|
|
}
|
|
|
|
|
2023-09-15 17:14:58 +08:00
|
|
|
constexpr auto XSettings = "org.deepin.dde.XSettings1";
|
|
|
|
|
|
|
|
auto *watcher =
|
|
|
|
new QDBusServiceWatcher{XSettings, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this};
|
|
|
|
|
|
|
|
auto *sigCon = new QMetaObject::Connection{};
|
|
|
|
|
|
|
|
auto singleSlot = [this, watcher, sigCon]() {
|
|
|
|
QObject::disconnect(*sigCon);
|
|
|
|
delete sigCon;
|
|
|
|
qDebug() << XSettings << "is registered.";
|
|
|
|
scanAutoStart();
|
|
|
|
watcher->deleteLater();
|
|
|
|
};
|
|
|
|
|
|
|
|
*sigCon = connect(watcher, &QDBusServiceWatcher::serviceRegistered, std::move(singleSlot));
|
|
|
|
|
|
|
|
auto msg =
|
|
|
|
QDBusMessage::createMethodCall("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameHasOwner");
|
|
|
|
msg << XSettings;
|
|
|
|
|
|
|
|
auto reply = QDBusConnection::sessionBus().call(msg);
|
|
|
|
if (reply.type() != QDBusMessage::ReplyMessage) {
|
|
|
|
qWarning() << "call org.freedesktop.DBus::NameHasOwner failed, skip autostart:" << reply.errorMessage();
|
|
|
|
// ...
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reply.arguments().first().toBool()) {
|
|
|
|
singleSlot();
|
|
|
|
}
|
2023-08-28 17:57:21 +08:00
|
|
|
}
|
2023-08-11 14:53:05 +08:00
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
void ApplicationManager1Service::addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath)
|
|
|
|
{
|
2023-08-29 11:13:03 +08:00
|
|
|
if (!isApplication(systemdUnitPath)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
auto info = processUnitName(unitName);
|
|
|
|
auto appId = std::move(info.applicationID);
|
|
|
|
auto launcher = std::move(info.Launcher);
|
|
|
|
auto instanceId = std::move(info.instanceID);
|
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
if (appId.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
2023-08-11 14:53:05 +08:00
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
auto appIt = std::find_if(m_applicationList.cbegin(),
|
|
|
|
m_applicationList.cend(),
|
|
|
|
[&appId](const QSharedPointer<ApplicationService> &app) { return app->id() == appId; });
|
2023-08-08 15:10:32 +08:00
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
if (appIt == m_applicationList.cend()) [[unlikely]] {
|
|
|
|
qWarning() << "couldn't find app" << appId << "in application manager.";
|
|
|
|
return;
|
|
|
|
}
|
2023-08-08 15:10:32 +08:00
|
|
|
|
2023-09-14 17:16:10 +08:00
|
|
|
(*appIt)->updateAfterLaunch(sender() != nullptr); // activate by signal
|
2023-09-13 11:47:04 +08:00
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
const auto &applicationPath = (*appIt)->applicationPath().path();
|
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
if (!(*appIt)->addOneInstance(instanceId, applicationPath, systemdUnitPath.path(), launcher)) [[likely]] {
|
2023-08-28 17:57:21 +08:00
|
|
|
qCritical() << "add Instance failed:" << applicationPath << unitName << systemdUnitPath.path();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ApplicationManager1Service::removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath)
|
|
|
|
{
|
2023-08-29 11:13:03 +08:00
|
|
|
if (!isApplication(systemdUnitPath)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
auto info = processUnitName(unitName);
|
|
|
|
auto appId = std::move(info.applicationID);
|
|
|
|
auto launcher = std::move(info.Launcher);
|
|
|
|
auto instanceId = std::move(info.instanceID);
|
|
|
|
|
2023-08-28 17:57:21 +08:00
|
|
|
if (appId.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto appIt = std::find_if(m_applicationList.cbegin(),
|
|
|
|
m_applicationList.cend(),
|
|
|
|
[&appId](const QSharedPointer<ApplicationService> &app) { return app->id() == appId; });
|
|
|
|
|
|
|
|
if (appIt == m_applicationList.cend()) [[unlikely]] {
|
|
|
|
qWarning() << "couldn't find app" << appId << "in application manager.";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto &appIns = (*appIt)->applicationInstances();
|
|
|
|
|
|
|
|
auto instanceIt =
|
|
|
|
std::find_if(appIns.cbegin(), appIns.cend(), [&systemdUnitPath](const QSharedPointer<InstanceService> &value) {
|
2023-09-13 16:52:53 +08:00
|
|
|
return value->property("SystemdUnitPath") == systemdUnitPath;
|
2023-08-28 17:57:21 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
if (instanceIt != appIns.cend()) [[likely]] {
|
|
|
|
(*appIt)->removeOneInstance(instanceIt.key());
|
2023-09-13 16:52:53 +08:00
|
|
|
return;
|
2023-08-28 17:57:21 +08:00
|
|
|
}
|
2023-09-13 16:52:53 +08:00
|
|
|
|
|
|
|
orphanedInstances->removeIf([&systemdUnitPath](const QSharedPointer<InstanceService> &ptr) {
|
|
|
|
return (ptr->property("SystemdUnitPath").value<QDBusObjectPath>() == systemdUnitPath);
|
|
|
|
});
|
2023-08-28 17:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ApplicationManager1Service::scanApplications() noexcept
|
|
|
|
{
|
|
|
|
const auto &desktopFileDirs = getDesktopFileDirs();
|
|
|
|
|
|
|
|
applyIteratively(QList<QDir>(desktopFileDirs.cbegin(), desktopFileDirs.cend()), [this](const QFileInfo &info) -> bool {
|
|
|
|
DesktopErrorCode err{DesktopErrorCode::NoError};
|
|
|
|
auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
|
|
|
|
if (!ret.has_value()) {
|
|
|
|
qWarning() << "failed to search File:" << err;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!this->addApplication(std::move(ret).value())) {
|
|
|
|
qWarning() << "add Application failed, skip...";
|
|
|
|
}
|
|
|
|
return false; // means to apply this function to the rest of the files
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void ApplicationManager1Service::scanInstances() noexcept
|
|
|
|
{
|
|
|
|
auto &conn = ApplicationManager1DBus::instance().globalDestBus();
|
|
|
|
auto call_message = QDBusMessage::createMethodCall(SystemdService, SystemdObjectPath, SystemdInterfaceName, "ListUnits");
|
|
|
|
auto result = conn.call(call_message);
|
|
|
|
if (result.type() == QDBusMessage::ErrorMessage) {
|
|
|
|
qCritical() << "failed to scan existing instances: call to ListUnits failed:" << result.errorMessage();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto v = result.arguments().first();
|
|
|
|
QList<SystemdUnitDBusMessage> units;
|
|
|
|
v.value<QDBusArgument>() >> units;
|
|
|
|
for (const auto &unit : units) {
|
2023-08-29 11:13:03 +08:00
|
|
|
if (!isApplication(unit.objectPath)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (unit.subState == "running") {
|
|
|
|
this->addInstanceToApplication(unit.name, unit.objectPath);
|
|
|
|
}
|
2023-08-28 17:57:21 +08:00
|
|
|
}
|
2023-07-24 14:12:59 +08:00
|
|
|
}
|
2023-07-10 10:18:33 +08:00
|
|
|
|
2023-09-04 18:39:09 +08:00
|
|
|
void ApplicationManager1Service::scanAutoStart() noexcept
|
2023-09-04 18:18:20 +08:00
|
|
|
{
|
|
|
|
auto autostartDirs = getAutoStartDirs();
|
|
|
|
QStringList needToLaunch;
|
|
|
|
applyIteratively(QList<QDir>{autostartDirs.cbegin(), autostartDirs.cend()}, [&needToLaunch](const QFileInfo &info) {
|
|
|
|
if (info.isSymbolicLink()) {
|
|
|
|
needToLaunch.emplace_back(info.symLinkTarget());
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
while (!needToLaunch.isEmpty()) {
|
|
|
|
const auto &filePath = needToLaunch.takeFirst();
|
|
|
|
auto appIt =
|
|
|
|
std::find_if(m_applicationList.constKeyValueBegin(),
|
|
|
|
m_applicationList.constKeyValueEnd(),
|
|
|
|
[&filePath](const auto &pair) { return pair.second->m_desktopSource.sourcePath() == filePath; });
|
|
|
|
if (appIt != m_applicationList.constKeyValueEnd()) {
|
|
|
|
appIt->second->Launch({}, {}, {});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-21 14:47:40 +08:00
|
|
|
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
|
|
|
{
|
|
|
|
return m_applicationList.keys();
|
|
|
|
}
|
2023-07-10 10:18:33 +08:00
|
|
|
|
2023-08-20 18:25:59 +08:00
|
|
|
bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) noexcept
|
|
|
|
{
|
|
|
|
QSharedPointer<ApplicationService> application =
|
2023-09-13 11:47:04 +08:00
|
|
|
ApplicationService::createApplicationService(std::move(desktopFileSource), this, m_storage);
|
2023-08-20 18:25:59 +08:00
|
|
|
if (!application) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_applicationList.constFind(application->applicationPath()) != m_applicationList.cend()) {
|
2023-08-21 16:02:26 +08:00
|
|
|
qInfo() << "this application already exists."
|
|
|
|
<< "desktop source:" << application->desktopFileSource().sourcePath();
|
2023-08-20 18:25:59 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto *ptr = application.data();
|
|
|
|
|
|
|
|
if (auto *adaptor = new (std::nothrow) ApplicationAdaptor{ptr}; adaptor == nullptr) {
|
|
|
|
qCritical() << "new ApplicationAdaptor failed.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-08-28 11:11:50 +08:00
|
|
|
if (!registerObjectToDBus(ptr, application->applicationPath().path(), ApplicationInterface)) {
|
2023-08-20 18:25:59 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_applicationList.insert(application->applicationPath(), application);
|
2023-09-13 11:47:04 +08:00
|
|
|
|
2023-09-08 10:58:41 +08:00
|
|
|
emit listChanged();
|
2023-08-25 10:47:17 +08:00
|
|
|
emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr));
|
2023-08-20 18:25:59 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application) noexcept
|
2023-07-10 10:18:33 +08:00
|
|
|
{
|
2023-08-11 17:46:46 +08:00
|
|
|
if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) {
|
2023-08-25 10:47:17 +08:00
|
|
|
emit InterfacesRemoved(application, getChildInterfacesFromObject(it->data()));
|
2023-09-13 11:47:04 +08:00
|
|
|
if (auto ptr = m_storage.lock(); ptr) {
|
2023-09-14 17:16:10 +08:00
|
|
|
ptr->deleteApplication((*it)->id());
|
2023-09-13 11:47:04 +08:00
|
|
|
}
|
2023-08-11 17:46:46 +08:00
|
|
|
unregisterObjectFromDBus(application.path());
|
|
|
|
m_applicationList.remove(application);
|
2023-09-13 11:47:04 +08:00
|
|
|
|
2023-09-08 10:58:41 +08:00
|
|
|
emit listChanged();
|
2023-08-11 17:46:46 +08:00
|
|
|
}
|
2023-07-10 10:18:33 +08:00
|
|
|
}
|
|
|
|
|
2023-08-20 18:25:59 +08:00
|
|
|
void ApplicationManager1Service::removeAllApplication() noexcept
|
2023-07-21 14:47:40 +08:00
|
|
|
{
|
2023-08-10 14:32:09 +08:00
|
|
|
for (const auto &app : m_applicationList.keys()) {
|
|
|
|
removeOneApplication(app);
|
|
|
|
}
|
2023-07-21 14:47:40 +08:00
|
|
|
}
|
2023-07-17 14:49:35 +08:00
|
|
|
|
2023-07-10 10:18:33 +08:00
|
|
|
QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidfd,
|
2023-09-14 17:16:10 +08:00
|
|
|
QDBusObjectPath &instance,
|
|
|
|
ObjectInterfaceMap &application_instance_info) const noexcept
|
2023-07-10 10:18:33 +08:00
|
|
|
{
|
2023-07-24 14:12:59 +08:00
|
|
|
if (!pidfd.isValid()) {
|
|
|
|
qWarning() << "pidfd isn't a valid unix file descriptor";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_ASSERT_X(static_cast<bool>(m_identifier), "Identify", "Broken Identifier.");
|
|
|
|
|
|
|
|
QString fdFilePath = QString{"/proc/self/fdinfo/%1"}.arg(pidfd.fileDescriptor());
|
|
|
|
QFile fdFile{fdFilePath};
|
|
|
|
if (!fdFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
|
|
|
|
qWarning() << "open " << fdFilePath << "failed: " << fdFile.errorString();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
auto content = fdFile.readAll();
|
|
|
|
QTextStream stream{content};
|
|
|
|
QString appPid;
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
auto line = stream.readLine();
|
|
|
|
if (line.startsWith("Pid")) {
|
|
|
|
appPid = line.split(":").last().trimmed();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (appPid.isEmpty()) {
|
|
|
|
qWarning() << "can't find pid which corresponding with the instance of this application.";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
bool ok;
|
|
|
|
auto pid = appPid.toUInt(&ok);
|
|
|
|
if (!ok) {
|
|
|
|
qWarning() << "AppId is failed to convert to uint.";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto ret = m_identifier->Identify(pid);
|
|
|
|
|
2023-09-14 13:38:44 +08:00
|
|
|
if (ret.ApplicationId.isEmpty()) {
|
|
|
|
qInfo() << "Identify failed.";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2023-07-24 14:12:59 +08:00
|
|
|
auto app = std::find_if(m_applicationList.cbegin(), m_applicationList.cend(), [&ret](const auto &appPtr) {
|
|
|
|
return appPtr->id() == ret.ApplicationId;
|
|
|
|
});
|
2023-09-14 13:38:44 +08:00
|
|
|
|
2023-07-24 14:12:59 +08:00
|
|
|
if (app == m_applicationList.cend()) {
|
|
|
|
qWarning() << "can't find application:" << ret.ApplicationId;
|
|
|
|
return {};
|
|
|
|
}
|
2023-09-14 13:38:44 +08:00
|
|
|
|
2023-09-14 17:16:10 +08:00
|
|
|
auto instancePath = (*app)->findInstance(ret.InstanceId);
|
2023-09-14 13:38:44 +08:00
|
|
|
|
2023-09-14 17:16:10 +08:00
|
|
|
if (auto path = instancePath.path(); path.isEmpty()) {
|
2023-09-14 13:38:44 +08:00
|
|
|
qWarning() << "can't find instance:" << path;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2023-09-14 17:16:10 +08:00
|
|
|
instance = instancePath;
|
2023-09-14 13:38:44 +08:00
|
|
|
auto instanceObj = (*app)->m_Instances.constFind(instance);
|
2023-09-14 17:16:10 +08:00
|
|
|
application_instance_info = getChildInterfacesAndPropertiesFromObject(instanceObj->get());
|
2023-09-14 13:38:44 +08:00
|
|
|
|
2023-07-24 14:12:59 +08:00
|
|
|
return ret.ApplicationId;
|
2023-07-10 10:18:33 +08:00
|
|
|
}
|
|
|
|
|
2023-08-11 17:46:46 +08:00
|
|
|
void ApplicationManager1Service::updateApplication(const QSharedPointer<ApplicationService> &destApp,
|
2023-09-13 16:52:53 +08:00
|
|
|
DesktopFile desktopFile) noexcept
|
2023-08-10 14:32:09 +08:00
|
|
|
{
|
2023-09-06 12:06:34 +08:00
|
|
|
// TODO: add propertyChanged
|
2023-08-20 18:25:59 +08:00
|
|
|
if (auto app = m_applicationList.find(destApp->applicationPath()); app == m_applicationList.cend()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
auto *newEntry = new (std::nothrow) DesktopEntry{};
|
|
|
|
if (newEntry == nullptr) {
|
|
|
|
qCritical() << "new DesktopEntry failed.";
|
|
|
|
return;
|
|
|
|
}
|
2023-08-10 14:32:09 +08:00
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
auto err = newEntry->parse(desktopFile);
|
|
|
|
if (err != DesktopErrorCode::NoError) {
|
|
|
|
qWarning() << "update desktop file failed:" << err << ", content wouldn't change.";
|
|
|
|
return;
|
|
|
|
}
|
2023-08-20 18:25:59 +08:00
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
if (destApp->m_entry != newEntry) {
|
2023-08-20 18:25:59 +08:00
|
|
|
destApp->resetEntry(newEntry);
|
2023-09-14 17:16:10 +08:00
|
|
|
destApp->detachAllInstance();
|
2023-08-11 17:46:46 +08:00
|
|
|
}
|
2023-09-15 14:44:27 +08:00
|
|
|
|
|
|
|
if (destApp->m_desktopSource != desktopFile and destApp->isAutoStart()) {
|
|
|
|
destApp->setAutoStart(false);
|
|
|
|
destApp->m_desktopSource = std::move(desktopFile);
|
|
|
|
destApp->setAutoStart(true);
|
|
|
|
}
|
2023-08-11 17:46:46 +08:00
|
|
|
}
|
2023-08-10 14:32:09 +08:00
|
|
|
|
2023-09-06 12:06:34 +08:00
|
|
|
void ApplicationManager1Service::ReloadApplications()
|
2023-08-11 17:46:46 +08:00
|
|
|
{
|
2023-09-06 12:06:34 +08:00
|
|
|
const auto &desktopFileDirs = getDesktopFileDirs();
|
|
|
|
|
2023-09-06 17:47:31 +08:00
|
|
|
auto apps = m_applicationList.keys();
|
|
|
|
|
|
|
|
applyIteratively(QList<QDir>(desktopFileDirs.cbegin(), desktopFileDirs.cend()), [this, &apps](const QFileInfo &info) -> bool {
|
2023-09-06 12:06:34 +08:00
|
|
|
DesktopErrorCode err{DesktopErrorCode::NoError};
|
|
|
|
auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
|
|
|
|
if (!ret.has_value()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto file = std::move(ret).value();
|
|
|
|
|
|
|
|
auto destApp =
|
|
|
|
std::find_if(m_applicationList.cbegin(),
|
|
|
|
m_applicationList.cend(),
|
|
|
|
[&file](const QSharedPointer<ApplicationService> &app) { return file.desktopId() == app->id(); });
|
2023-08-11 17:46:46 +08:00
|
|
|
|
2023-09-06 17:47:31 +08:00
|
|
|
if (err != DesktopErrorCode::NoError) {
|
|
|
|
qWarning() << "error occurred:" << err << " skip this application.";
|
2023-09-06 12:06:34 +08:00
|
|
|
return false;
|
2023-08-11 17:46:46 +08:00
|
|
|
}
|
2023-08-10 14:32:09 +08:00
|
|
|
|
2023-09-13 16:52:53 +08:00
|
|
|
if (destApp != m_applicationList.cend() and apps.contains(destApp.key())) {
|
2023-09-06 17:47:31 +08:00
|
|
|
apps.removeOne(destApp.key());
|
2023-09-13 16:52:53 +08:00
|
|
|
updateApplication(destApp.value(), std::move(file));
|
2023-09-06 12:06:34 +08:00
|
|
|
return false;
|
2023-08-10 14:32:09 +08:00
|
|
|
}
|
2023-08-11 17:46:46 +08:00
|
|
|
|
2023-09-06 12:06:34 +08:00
|
|
|
addApplication(std::move(file));
|
|
|
|
return false;
|
|
|
|
});
|
2023-09-06 17:47:31 +08:00
|
|
|
|
|
|
|
for (const auto &key : apps) {
|
|
|
|
removeOneApplication(key);
|
|
|
|
}
|
2023-08-10 14:32:09 +08:00
|
|
|
}
|
2023-08-18 10:01:52 +08:00
|
|
|
|
|
|
|
ObjectMap ApplicationManager1Service::GetManagedObjects() const
|
|
|
|
{
|
2023-08-18 17:22:38 +08:00
|
|
|
return dumpDBusObject(m_applicationList);
|
2023-08-18 10:01:52 +08:00
|
|
|
}
|