diff --git a/api/dbus/org.desktopspec.ApplicationManager1.Application.xml b/api/dbus/org.desktopspec.ApplicationManager1.Application.xml
index 9298ca7..476cf87 100644
--- a/api/dbus/org.desktopspec.ApplicationManager1.Application.xml
+++ b/api/dbus/org.desktopspec.ApplicationManager1.Application.xml
@@ -17,6 +17,10 @@
+
+
+
+
-
-
-
-
-
@@ -36,22 +31,5 @@
/>
-
-
-
-
-
-
-
-
-
diff --git a/src/constant.h b/src/constant.h
index bffef65..ccf5161 100644
--- a/src/constant.h
+++ b/src/constant.h
@@ -16,10 +16,7 @@ constexpr auto DDEApplicationManager1ServiceName =
#endif
constexpr auto DDEApplicationManager1ObjectPath = u8"/org/deepin/dde/ApplicationManager1";
-constexpr auto DDEApplicationManager1ApplicationObjectPath = u8"/org/deepin/dde/ApplicationManager1/Application/";
-constexpr auto DDEApplicationManager1InstanceObjectPath = u8"/org/deepin/dde/ApplicationManager1/Instance/";
constexpr auto DDEApplicationManager1JobManagerObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1";
-constexpr auto DDEApplicationManager1JobObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1/Job/";
constexpr auto DesktopFileEntryKey = u8"Desktop Entry";
constexpr auto DesktopFileActionKey = u8"Desktop Action ";
diff --git a/src/dbus/applicationmanager1service.cpp b/src/dbus/applicationmanager1service.cpp
index dc28b02..19ef5d3 100644
--- a/src/dbus/applicationmanager1service.cpp
+++ b/src/dbus/applicationmanager1service.cpp
@@ -110,18 +110,6 @@ void ApplicationManager1Service::removeAllApplication()
}
}
-QDBusObjectPath ApplicationManager1Service::Application(const QString &id) const
-{
- auto ret = std::find_if(m_applicationList.cbegin(), m_applicationList.cend(), [&id](const auto &app) {
- return static_cast(app->id() == id);
- });
-
- if (ret != m_applicationList.cend()) {
- return ret.key();
- }
- return {};
-}
-
QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidfd,
QDBusObjectPath &application,
QDBusObjectPath &application_instance)
@@ -174,20 +162,6 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
return ret.ApplicationId;
}
-QDBusObjectPath ApplicationManager1Service::Launch(const QString &id,
- const QString &actions,
- const QStringList &fields,
- const QVariantMap &options)
-{
- auto app = Application(id);
- if (app.path().isEmpty()) {
- qWarning() << "No such application.";
- return {};
- }
- const auto &value = m_applicationList.value(app);
- return value->Launch(actions, fields, options);
-}
-
void ApplicationManager1Service::updateApplication(const QSharedPointer &destApp,
const DesktopFile &desktopFile) noexcept
{
diff --git a/src/dbus/applicationmanager1service.h b/src/dbus/applicationmanager1service.h
index 52bdbc2..d798d85 100644
--- a/src/dbus/applicationmanager1service.h
+++ b/src/dbus/applicationmanager1service.h
@@ -30,15 +30,18 @@ public:
Q_PROPERTY(QList List READ list)
[[nodiscard]] QList list() const;
+
template
bool addApplication(T &&desktopFileSource)
{
- QSharedPointer application{new ApplicationService{std::forward(desktopFileSource), this}};
+ QSharedPointer application = makeApplication(std::forward(desktopFileSource), this);
if (!application) {
return false;
}
+
auto *ptr = application.data();
new ApplicationAdaptor{ptr};
+
if (!registerObjectToDBus(ptr, application->m_applicationPath.path(), getDBusInterface())) {
return false;
}
@@ -53,9 +56,7 @@ public:
JobManager1Service &jobManager() noexcept { return *m_jobManager; }
public Q_SLOTS:
- [[nodiscard]] QDBusObjectPath Application(const QString &id) const;
QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance);
- QDBusObjectPath Launch(const QString &id, const QString &action, const QStringList &fields, const QVariantMap &options);
void UpdateApplicationInfo(const QStringList &appIdList);
private:
diff --git a/src/dbus/applicationservice.cpp b/src/dbus/applicationservice.cpp
index 69ed66a..52f61e1 100644
--- a/src/dbus/applicationservice.cpp
+++ b/src/dbus/applicationservice.cpp
@@ -19,7 +19,9 @@ ApplicationService::~ApplicationService()
m_desktopSource.destruct(m_isPersistence);
for (auto &instance : m_Instances.values()) {
instance->m_Application = QDBusObjectPath{"/"};
- instance->setParent(qApp); // detach all instances to qApp
+ auto *ptr = instance.get();
+ instance.reset(nullptr);
+ ptr->setParent(qApp); // detach all instances to qApp
}
}
@@ -132,8 +134,10 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
m_applicationPath.path(),
[this, binary = std::move(bin), commands = std::move(cmds)](QVariant variantValue) mutable -> QVariant {
auto resourceFile = variantValue.toString();
+ auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
+ auto objectPath = m_applicationPath.path() + "/" + instanceRandomUUID;
+
if (resourceFile.isEmpty()) {
- auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
commands.push_front(QString{R"(--unitName=app-DDE-%1@%2.service)"}.arg(
escapeApplicationId(this->id()), instanceRandomUUID)); // launcher should use this instanceId
QProcess process;
@@ -143,7 +147,7 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
qWarning() << "Launch Application Failed. exitCode:" << code;
return QString{""};
}
- return DDEApplicationManager1InstanceObjectPath + instanceRandomUUID;
+ return objectPath;
}
int location{0};
@@ -163,7 +167,6 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
// resourceFile must be available in the following contexts
auto tmp = commands;
tmp.insert(location, resourceFile);
- auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
tmp.push_front(QString{R"(--unitName=DDE-%1@%2.service)"}.arg(this->id(), instanceRandomUUID));
QProcess process;
process.start(getApplicationLauncherBinary(), tmp);
@@ -173,7 +176,7 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
qWarning() << "Launch Application Failed:" << binary << tmp;
return QString{""};
}
- return DDEApplicationManager1InstanceObjectPath + instanceRandomUUID;
+ return objectPath;
},
std::move(res));
}
@@ -239,11 +242,55 @@ QList ApplicationService::instances() const noexcept
return m_Instances.keys();
}
+QString ApplicationService::iconName() const noexcept
+{
+ if (m_entry.isNull()) {
+ qWarning() << "desktop entry is empty, isPersistence:" << m_isPersistence;
+ return {};
+ }
+
+ const auto &actions = m_entry->value(DesktopFileEntryKey, "Icon");
+ if (!actions) {
+ return {};
+ }
+
+ bool ok{false};
+ const auto &icon = actions->toIconString(ok);
+ if (!ok) {
+ qWarning() << "Icon convert to String failed.";
+ return {};
+ }
+
+ return icon;
+}
+
+QString ApplicationService::displayName() const noexcept
+{
+ if (m_entry.isNull()) {
+ qWarning() << "desktop entry is empty, isPersistence:" << m_isPersistence;
+ return {};
+ }
+
+ const auto &actions = m_entry->value(DesktopFileEntryKey, "Name");
+ if (!actions) {
+ return {};
+ }
+
+ bool ok{false};
+ const auto &name = actions->toString(ok);
+ if (!ok) {
+ qWarning() << "Icon convert to String failed.";
+ return {};
+ }
+
+ return name;
+}
+
bool ApplicationService::addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath)
{
auto service = new InstanceService{instanceId, application, systemdUnitPath};
auto adaptor = new InstanceAdaptor(service);
- QString objectPath{DDEApplicationManager1InstanceObjectPath + instanceId};
+ QString objectPath{m_applicationPath.path() + "/" + instanceId};
if (registerObjectToDBus(service, objectPath, getDBusInterface())) {
m_Instances.insert(QDBusObjectPath{objectPath}, QSharedPointer{service});
diff --git a/src/dbus/applicationservice.h b/src/dbus/applicationservice.h
index de98e5f..1cccf57 100644
--- a/src/dbus/applicationservice.h
+++ b/src/dbus/applicationservice.h
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include "dbus/instanceservice.h"
#include "global.h"
#include "desktopentry.h"
@@ -47,6 +48,12 @@ public:
Q_PROPERTY(QList Instances READ instances)
[[nodiscard]] QList instances() const noexcept;
+ Q_PROPERTY(QString IconName READ iconName CONSTANT)
+ [[nodiscard]] QString iconName() const noexcept;
+
+ Q_PROPERTY(QString DisplayName READ displayName CONSTANT)
+ [[nodiscard]] QString displayName() const noexcept;
+
[[nodiscard]] QDBusObjectPath findInstance(const QString &instanceId) const;
[[nodiscard]] const QString &getLauncher() const noexcept { return m_launcher; }
@@ -64,45 +71,13 @@ public Q_SLOTS:
private:
friend class ApplicationManager1Service;
template
- explicit ApplicationService(T &&source, ApplicationManager1Service *parent = nullptr)
- : m_parent(parent)
+ friend QSharedPointer makeApplication(T &&source, ApplicationManager1Service *parent);
+
+ template
+ explicit ApplicationService(T &&source)
+ : m_isPersistence(static_cast(std::is_same_v))
, m_desktopSource(std::forward(source))
{
- static_assert(std::is_same_v or std::is_same_v, "param type must be QString or DesktopFile.");
- QString objectPath{DDEApplicationManager1ApplicationObjectPath};
- QTextStream sourceStream;
- QFile sourceFile;
- auto dbusAppid = m_desktopSource.m_file.desktopId();
-
- if constexpr (std::is_same_v) {
- m_applicationPath =
-#ifdef DEBUG_MODE
- QDBusObjectPath{objectPath + escapeToObjectPath(dbusAppid)};
-#else
- QDBusObjectPath{objectPath + QUuid::createUuid().toString(QUuid::Id128)};
-#endif
- m_isPersistence = true;
- sourceFile.setFileName(m_desktopSource.m_file.filePath());
- if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
-#ifndef DEBUG_MODE
- qCritical() << "desktop file can't open:" << m_desktopSource.m_file.filePath() << sourceFile.errorString();
-#endif
- return;
- }
- sourceStream.setDevice(&sourceFile);
- } else if (std::is_same_v) {
- m_applicationPath = QDBusObjectPath{objectPath + QUuid::createUuid().toString(QUuid::Id128)};
- m_isPersistence = false;
- sourceStream.setString(&m_desktopSource.m_temp, QTextStream::ReadOnly | QTextStream::Text);
- }
- m_entry.reset(new DesktopEntry());
- if (auto error = m_entry->parse(sourceStream); error != DesktopErrorCode::NoError) {
- if (error != DesktopErrorCode::EntryKeyInvalid) {
- m_entry.reset(nullptr);
- return;
- }
- }
- // TODO: icon lookup
}
bool m_AutoStart{false};
@@ -143,4 +118,58 @@ private:
[[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
};
+template
+QSharedPointer makeApplication(T &&source, ApplicationManager1Service *parent)
+{
+ static_assert(std::is_same_v or std::is_same_v, "param type must be QString or DesktopFile.");
+ QString objectPath;
+ QTextStream sourceStream;
+ QFile sourceFile;
+ QSharedPointer app{nullptr};
+
+ if constexpr (std::is_same_v) {
+ DesktopFile in{std::forward(source)};
+ objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + escapeToObjectPath(in.desktopId());
+ sourceFile.setFileName(in.filePath());
+
+ if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
+ qCritical() << "desktop file can't open:" << in.filePath() << sourceFile.errorString();
+ return nullptr;
+ }
+
+ app.reset(new ApplicationService{std::move(in)});
+ sourceStream.setDevice(&sourceFile);
+ } else if (std::is_same_v) {
+ QString in{std::forward(source)};
+ objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + QUuid::createUuid().toString(QUuid::Id128);
+
+ app.reset(new ApplicationService{std::move(in)});
+ sourceStream.setString(&in, QTextStream::ReadOnly | QTextStream::Text);
+ }
+
+ std::unique_ptr entry{std::make_unique()};
+ auto error = entry->parse(sourceStream);
+
+ if (error != DesktopErrorCode::NoError) {
+ if (error != DesktopErrorCode::EntryKeyInvalid) {
+ return nullptr;
+ }
+ }
+
+ if (auto val = entry->value(DesktopFileEntryKey, "Hidden"); val.has_value()) {
+ bool ok{false};
+ if (auto hidden = val.value().toBoolean(ok); ok and hidden) {
+ return nullptr;
+ }
+ }
+
+ app->m_parent = parent;
+ app->m_entry.reset(entry.release());
+ app->m_applicationPath = QDBusObjectPath{std::move(objectPath)};
+
+ // TODO: icon lookup
+
+ return app;
+}
+
#endif
diff --git a/src/dbus/jobmanager1service.h b/src/dbus/jobmanager1service.h
index b64291e..23801aa 100644
--- a/src/dbus/jobmanager1service.h
+++ b/src/dbus/jobmanager1service.h
@@ -50,7 +50,8 @@ public:
{
static_assert(std::is_invocable_v, "param type must be QVariant.");
- QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString(QUuid::Id128)};
+ QString objectPath =
+ QString{"%1/%2"}.arg(DDEApplicationManager1JobManagerObjectPath).arg(QUuid::createUuid().toString(QUuid::Id128));
QFuture future = QtConcurrent::mappedReduced(std::move(args),
func,
qOverload(&QVariantList::append),
diff --git a/src/dbus/jobservice.cpp b/src/dbus/jobservice.cpp
index e80368f..4549195 100644
--- a/src/dbus/jobservice.cpp
+++ b/src/dbus/jobservice.cpp
@@ -11,7 +11,7 @@ JobService::JobService(const QFuture &job)
JobService::~JobService() = default;
-QString JobService::status() const
+QString JobService::status() const // FIXME: job status aren't mutually exclusive
{
if (m_job.isFinished()) {
return "finished";
diff --git a/src/desktopentry.cpp b/src/desktopentry.cpp
index 881d135..52c3141 100644
--- a/src/desktopentry.cpp
+++ b/src/desktopentry.cpp
@@ -56,7 +56,9 @@ DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMa
re.optimize();
auto matcher = re.match(keyStr);
if (!matcher.hasMatch()) {
+#ifdef DEBUG_MODE
qWarning() << "invalid key: " << keyStr;
+#endif
return DesktopErrorCode::EntryKeyInvalid;
}
@@ -205,7 +207,9 @@ DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept
if (auto error = parseEntry(line, currentGroup); error != DesktopErrorCode::NoError) {
err = error;
+#ifdef DEBUG_MODE
qWarning() << "an error occurred,this line will be skipped:" << line;
+#endif
}
}
return err;
@@ -223,13 +227,17 @@ std::optional DesktopEntry::value(const QString &groupKey,
{
const auto &destGroup = group(groupKey);
if (!destGroup) {
+#ifdef DEBUG_MODE
qWarning() << "group " << groupKey << " can't be found.";
+#endif
return std::nullopt;
}
auto it = destGroup->find(valueKey);
if (it == destGroup->cend()) {
+#ifdef DEBUG_MODE
qWarning() << "value " << valueKey << " can't be found.";
+#endif
return std::nullopt;
}
return *it;
diff --git a/tests/ut_applicationmanager.cpp b/tests/ut_applicationmanager.cpp
index d44caf8..adec108 100644
--- a/tests/ut_applicationmanager.cpp
+++ b/tests/ut_applicationmanager.cpp
@@ -44,23 +44,11 @@ public:
static void TearDownTestCase() { m_am->deleteLater(); }
static inline ApplicationManager1Service *m_am{nullptr};
- const static inline QDBusObjectPath ApplicationPath{DDEApplicationManager1ApplicationObjectPath +
+ const static inline QDBusObjectPath ApplicationPath{QString{DDEApplicationManager1ObjectPath} + "/" +
QUuid::createUuid().toString(QUuid::Id128)};
- const static inline QDBusObjectPath InstancePath{DDEApplicationManager1InstanceObjectPath +
- QUuid::createUuid().toString(QUuid::Id128)};
+ const static inline QDBusObjectPath InstancePath{ApplicationPath.path() + "/" + QUuid::createUuid().toString(QUuid::Id128)};
};
-TEST_F(TestApplicationManager, list)
-{
- auto lists = m_am->list();
- EXPECT_EQ(lists.first(), ApplicationPath);
-}
-
-TEST_F(TestApplicationManager, application)
-{
- EXPECT_EQ(m_am->Application("test-Application"), ApplicationPath);
-}
-
TEST_F(TestApplicationManager, identifyService)
{
using namespace std::chrono_literals;