feat: adjust dbus service structure

Log:
This commit is contained in:
heyuming 2023-07-17 14:49:35 +08:00 committed by Comix
parent 6f598ab52b
commit 3a278bec79
12 changed files with 338 additions and 117 deletions

View File

@ -8,6 +8,60 @@
Missing fields will be added later." Missing fields will be added later."
/> />
<property name="Actions" type="as" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="Names of all action identifiers of this application.
Check https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#extra-actions
for futher information."
/>
</property>
<property name="AutoStart" type="b" access="readwrite"/>
<property name="Instances" type="ao" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="All instances of this application."
/>
</property>
<property name="ID" type="s" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="The desktop file id of this application.
Check https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id
for futher infomation."
/>
</property>
<property name="Icons" type="a{sa{ua{sh}}}" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="The type of this property is
map[action(string)]map[size(uint)]map[format(string)]fd.
Format can be `png`, `svg`, `xpm`, `dci` or `icon`
refering to the png/svg/xpm/dci format of icon files,
as well as the `.icon` file contain the extra icon-data.
NOTE:
1. `action` is an action identifier
which is the id of
additional applications actions key.
When `action` is emtpy,
this method return icon of the main desktop entry.
Check https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s11.html#extra-actions-identifier
for futher infomation.
2. `.icon` is a text file with some metadata.
Check https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#file_formats
for futher infomation.
3. Check https://github.com/linuxdeepin/deepin-specifications
for futher infomation of dci icon format."
/>
<annotation name="org.qtproject.QtDBus.QtTypeName" value="IconMap"/>
</property>
<method name="Launch"> <method name="Launch">
<arg type="s" name="action" direction="in" /> <arg type="s" name="action" direction="in" />
<arg type="as" name="fields" direction="in" /> <arg type="as" name="fields" direction="in" />
@ -32,41 +86,6 @@
/> />
</method> </method>
<property type="a{sa{ua{sh}}}" name="Icons" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="The type of this property is
map[action(string)]map[size(uint)]map[format(string)]fd.
Format can be `png`, `svg`, `xpm`, `dci` or `icon`
refering to the png/svg/xpm/dci format of icon files,
as well as the `.icon` file contain the extra icon-data.
NOTE:
1. `action` is an action identifier
which is the id of
additional applications actions key.
When `action` is emtpy,
this method return icon of the main desktop entry.
Check https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s11.html#extra-actions-identifier
for futher infomation.
2. `.icon` is a text file with some metadata.
Check https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#file_formats
for futher infomation.
3. Check https://github.com/linuxdeepin/deepin-specifications
for futher infomation of dci icon format."
/>
</method>
<property name="Actions" type="as" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="Names of all action identifiers of this application.
Check https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#extra-actions
for futher information."
/>
</property>
<method name="GetActionName"> <method name="GetActionName">
<arg name="identifier" type="s" direction="in"/> <arg name="identifier" type="s" direction="in"/>
<arg name="env" type="as" direction="in"/> <arg name="env" type="as" direction="in"/>
@ -81,24 +100,5 @@
this method will use the locale config of that user." this method will use the locale config of that user."
/> />
</method> </method>
<property name="AutoStart" type="b" access="readwrite"/>
<property name="Instances" type="ao" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="All instances of this application."
/>
</property>
<property name="ID" type="s" access="read">
<annotation
name="org.freedesktop.DBus.Description"
value="The desktop file id of this application.
Check https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id
for futher infomation."
/>
</property>
</interface> </interface>
</node> </node>

View File

@ -1,21 +1,23 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
// //
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
#include "applicationmanager1service.h" #include "applicationmanager1service.h"
#include "applicationmanager1adaptor.h"
#include "applicationadaptor.h"
#include "global.h"
ApplicationManager1Service::ApplicationManager1Service(QObject *parent) ApplicationManager1Service::~ApplicationManager1Service() = default;
: QObject(parent)
ApplicationManager1Service::ApplicationManager1Service() = default;
QList<QDBusObjectPath> ApplicationManager1Service::list() const { return m_applicationList.keys(); }
bool ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application)
{ {
return m_applicationList.remove(application) != 0;
} }
ApplicationManager1Service::~ApplicationManager1Service() {} void ApplicationManager1Service::removeAllApplication() { m_applicationList.clear(); }
QList<QDBusObjectPath> ApplicationManager1Service::list() const
{
// TODO: impl
return {};
}
QDBusObjectPath ApplicationManager1Service::Application(const QString &id) QDBusObjectPath ApplicationManager1Service::Application(const QString &id)
{ {
@ -32,10 +34,22 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
} }
QDBusObjectPath ApplicationManager1Service::Launch(const QString &id, QDBusObjectPath ApplicationManager1Service::Launch(const QString &id,
const QString &action, const QString &actions,
const QStringList &fields, const QStringList &fields,
const QVariantMap &options) const QVariantMap &options)
{ {
// TODO: impl // TODO: impl reset of Launch
QString objectPath;
if (id.contains('.')) {
objectPath = id.split('.').first();
}
objectPath.prepend(DDEApplicationManager1ApplicationObjectPath);
QSharedPointer<ApplicationService> app{new ApplicationService{id}};
auto *ptr = app.data();
if (registerObjectToDbus<decltype(ptr), ApplicationAdaptor>(ptr, objectPath, getDBusInterface<ApplicationAdaptor>())) {
QDBusObjectPath path{objectPath};
m_applicationList.insert(path, app);
return path;
}
return {}; return {};
} }

View File

@ -8,22 +8,36 @@
#include <QObject> #include <QObject>
#include <QDBusObjectPath> #include <QDBusObjectPath>
#include <QDBusUnixFileDescriptor> #include <QDBusUnixFileDescriptor>
#include <QSharedPointer>
#include <QMap>
#include "applicationservice.h"
class ApplicationManager1Service : public QObject class ApplicationManager1Service final : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ApplicationManager1Service(QObject *parent = nullptr); ApplicationManager1Service();
virtual ~ApplicationManager1Service(); ~ApplicationManager1Service() override;
ApplicationManager1Service(const ApplicationManager1Service &) = delete;
ApplicationManager1Service(ApplicationManager1Service &&) = delete;
ApplicationManager1Service &operator=(const ApplicationManager1Service &) = delete;
ApplicationManager1Service &operator=(ApplicationManager1Service&&) = delete;
public:
Q_PROPERTY(QList<QDBusObjectPath> List READ list) Q_PROPERTY(QList<QDBusObjectPath> List READ list)
QList<QDBusObjectPath> list() const; QList<QDBusObjectPath> list() const;
void addApplication(const QString &ID,
const QStringList &actions,
bool AutoStart = false);
bool removeOneApplication(const QDBusObjectPath &application);
void removeAllApplication();
public Q_SLOTS: public Q_SLOTS:
QDBusObjectPath Application(const QString &id); QDBusObjectPath Application(const QString &id);
QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance); QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance);
QDBusObjectPath Launch(const QString &id, const QString &action, const QStringList &fields, const QVariantMap &options); QDBusObjectPath Launch(const QString &id, const QString &action, const QStringList &fields, const QVariantMap &options);
private:
QMap<QDBusObjectPath,QSharedPointer<ApplicationService>> m_applicationList;
}; };
#endif #endif

View File

@ -3,16 +3,53 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
#include "applicationservice.h" #include "applicationservice.h"
#include "instanceadaptor.h"
#include <QUuid>
ApplicationService::ApplicationService(QObject *parent) ApplicationService::ApplicationService(QString ID)
: QObject(parent) : m_AutoStart(false)
, m_ID(std::move(ID))
, m_applicationPath(DDEApplicationManager1ApplicationObjectPath + m_ID)
{ {
} }
ApplicationService::~ApplicationService() {} ApplicationService::~ApplicationService() = default;
QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options) QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env)
{ {
// TODO: impl // TODO: impl
return {}; return {};
} }
QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options)
{
// TODO: impl launch app from systemd.
QString objectPath{m_applicationPath.path() + "/" + QUuid::createUuid().toString()};
QSharedPointer<InstanceService> ins{new InstanceService{objectPath, ""}};
auto *ptr = ins.data();
if (registerObjectToDbus<decltype(ptr), InstanceAdaptor>(ptr, objectPath, getDBusInterface<InstanceAdaptor>())) {
m_Instances.insert(QDBusObjectPath{objectPath}, ins);
return QDBusObjectPath{objectPath};
}
return {};
}
QStringList ApplicationService::actions() const noexcept { return m_actions; }
QStringList& ApplicationService::actionsRef() noexcept { return m_actions; }
QString ApplicationService::iD() const noexcept { return m_ID; }
IconMap ApplicationService::icons() const { return m_Icons; }
IconMap& ApplicationService::iconsRef() { return m_Icons; }
bool ApplicationService::isAutoStart() const noexcept { return m_AutoStart; }
void ApplicationService::setAutoStart(bool autostart) noexcept { m_AutoStart = autostart; }
QList<QDBusObjectPath> ApplicationService::instances() const noexcept { return m_Instances.keys(); }
bool ApplicationService::removeOneInstance(const QDBusObjectPath &instance) { return m_Instances.remove(instance) != 0; }
void ApplicationService::removeAllInstance() { m_Instances.clear();}

View File

@ -7,16 +7,58 @@
#include <QObject> #include <QObject>
#include <QDBusObjectPath> #include <QDBusObjectPath>
#include <QMap>
#include <QString>
#include <QDBusUnixFileDescriptor>
#include <QSharedPointer>
#include "instanceservice.h"
#include "global.h"
class ApplicationService : public QObject class ApplicationService : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ApplicationService(QObject *parent = nullptr); ~ApplicationService() override;
virtual ~ApplicationService(); ApplicationService(const ApplicationService&) = delete;
ApplicationService(ApplicationService &&) = delete;
ApplicationService& operator=(const ApplicationService&) = delete;
ApplicationService &operator=(ApplicationService &&) = delete;
Q_PROPERTY(QStringList Actions READ actions CONSTANT)
QStringList actions() const noexcept;
QStringList& actionsRef() noexcept;
Q_PROPERTY(QString ID READ iD CONSTANT)
QString iD() const noexcept;
Q_PROPERTY(IconMap Icons READ icons)
IconMap icons() const;
IconMap& iconsRef();
Q_PROPERTY(bool AutoStart READ isAutoStart WRITE setAutoStart)
bool isAutoStart() const noexcept;
void setAutoStart(bool autostart) noexcept;
Q_PROPERTY(QList<QDBusObjectPath> Instances READ instances)
QList<QDBusObjectPath> instances() const noexcept;
void recoverInstances(const QList<QDBusObjectPath>) noexcept;
bool removeOneInstance(const QDBusObjectPath &instance);
void removeAllInstance();
public Q_SLOTS: public Q_SLOTS:
QString GetActionName(const QString &identifier, const QStringList &env);
QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options); QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options);
private:
friend class ApplicationManager1Service;
explicit ApplicationService(QString ID);
bool m_AutoStart;
QString m_ID;
QDBusObjectPath m_applicationPath;
QStringList m_actions;
QMap<QDBusObjectPath,QSharedPointer<InstanceService>> m_Instances;
IconMap m_Icons;
}; };
#endif #endif

View File

@ -4,21 +4,13 @@
#include "instanceservice.h" #include "instanceservice.h"
InstanceService::InstanceService(QObject *parent) InstanceService::InstanceService(QString application, QString systemdUnitPath)
: QObject(parent) : m_Application(std::move(application)), m_SystemdUnitPath(std::move(systemdUnitPath))
{ {
} }
InstanceService::~InstanceService() {} InstanceService::~InstanceService() = default;
QDBusObjectPath InstanceService::application() const QDBusObjectPath InstanceService::application() const { return m_Application; }
{
// TODO: impl
return {};
}
QDBusObjectPath InstanceService::systemdUnitPath() const QDBusObjectPath InstanceService::systemdUnitPath() const { return m_SystemdUnitPath; }
{
// TODO: impl
return {};
}

View File

@ -12,15 +12,23 @@ class InstanceService : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceService(QObject *parent = nullptr); ~InstanceService() override;
virtual ~InstanceService(); InstanceService(const InstanceService &) = delete;
InstanceService(InstanceService &&) = delete;
InstanceService &operator=(const InstanceService &) = delete;
InstanceService &operator=(InstanceService&&) = delete;
public: Q_PROPERTY(QDBusObjectPath Application READ application CONSTANT)
Q_PROPERTY(QDBusObjectPath Application READ application)
QDBusObjectPath application() const; QDBusObjectPath application() const;
Q_PROPERTY(QDBusObjectPath SystemdUnitPath READ systemdUnitPath) Q_PROPERTY(QDBusObjectPath SystemdUnitPath READ systemdUnitPath CONSTANT)
QDBusObjectPath systemdUnitPath() const; QDBusObjectPath systemdUnitPath() const;
private:
friend class ApplicationService;
InstanceService(QString application, QString systemdUnitPath);
const QDBusObjectPath m_Application;
const QDBusObjectPath m_SystemdUnitPath;
}; };
#endif #endif

View File

@ -3,10 +3,24 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
#include "jobmanager1service.h" #include "jobmanager1service.h"
#include <QUuid>
#include "global.h"
JobManager1Service::JobManager1Service(QObject *parent) JobManager1Service::JobManager1Service() = default;
: QObject(parent)
JobManager1Service::~JobManager1Service() = default;
template <typename F, typename... Args>
void addJob(const QDBusObjectPath &source, F func, Args &&...args)
{ {
// TODO: impl
} }
JobManager1Service::~JobManager1Service() {} bool JobManager1Service::removeJob(const QDBusObjectPath &job,
const QString &status,
const QString &message,
const QDBusVariant &result)
{
// TODO: impl
return false;
}

View File

@ -6,18 +6,31 @@
#define JOBMANAGER1SERVICE_H #define JOBMANAGER1SERVICE_H
#include <QObject> #include <QObject>
#include <QMap>
#include <QDBusObjectPath> #include <QDBusObjectPath>
#include <QSharedPointer>
class JobManager1Service : public QObject #include "jobservice.h"
class JobManager1Service final : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit JobManager1Service(QObject *parent = nullptr); JobManager1Service();
virtual ~JobManager1Service(); JobManager1Service(const JobManager1Service &) = delete;
JobManager1Service(JobManager1Service&&) = delete;
JobManager1Service &operator=(const JobManager1Service &) = delete;
JobManager1Service &operator=(JobManager1Service &&) = delete;
~JobManager1Service() override;
template<typename F,typename ...Args>
void addJob(const QDBusObjectPath &source,F func, Args&& ...args);
bool removeJob(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result);
Q_SIGNALS: Q_SIGNALS:
void JobNew(const QDBusObjectPath &job, const QDBusObjectPath &source); void JobNew(const QDBusObjectPath &job, const QDBusObjectPath &source);
void JobRemoved(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result); void JobRemoved(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result);
private:
QMap<QDBusObjectPath, QSharedPointer<JobService>> m_jobs;
}; };
#endif #endif

View File

@ -4,41 +4,47 @@
#include "jobservice.h" #include "jobservice.h"
JobService::JobService(QObject *parent) JobService::JobService(const QFuture<QVariant>& job)
: QObject(parent) : m_job(job)
{ {
} }
JobService::~JobService() {} JobService::~JobService() = default;
QString JobService::status() const QString JobService::status() const
{ {
if (job.isFinished()) if (m_job.isFinished()) {
return "finished"; return "finished";
if (job.isCanceled()) }
if (m_job.isCanceled()) {
return "canceled"; return "canceled";
if (job.isSuspended()) }
if (m_job.isSuspended()) {
return "suspended"; return "suspended";
if (job.isSuspending()) }
if (m_job.isSuspending()) {
return "suspending"; return "suspending";
if (job.isStarted()) }
if (m_job.isStarted()) {
return "started"; return "started";
if (job.isRunning()) }
if (m_job.isRunning()) {
return "running"; return "running";
}
return "failed"; return "failed";
} }
void JobService::Cancel() void JobService::Cancel()
{ {
job.cancel(); m_job.cancel();
} }
void JobService::Pause() void JobService::Pause()
{ {
job.suspend(); m_job.suspend();
} }
void JobService::Resume() void JobService::Resume()
{ {
job.resume(); m_job.resume();
} }

View File

@ -13,10 +13,8 @@ class JobService : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit JobService(QObject *parent = nullptr); ~JobService() override;
virtual ~JobService();
public:
Q_PROPERTY(QString Status READ status) Q_PROPERTY(QString Status READ status)
QString status() const; QString status() const;
@ -26,7 +24,8 @@ public Q_SLOTS:
void Resume(); void Resume();
private: private:
QFuture<QVariant> job; explicit JobService(const QFuture<QVariant>& job);
QFuture<QVariant> m_job;
}; };
#endif #endif

82
src/include/global.h Normal file
View File

@ -0,0 +1,82 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef GLOBAL_H
#define GLOBAL_H
#include <QString>
#include <QMap>
#include <QDBusUnixFileDescriptor>
#include <QDBusConnection>
#include <optional>
#include <QDBusError>
#include <QMetaType>
#include <QMetaClassInfo>
using IconMap = QMap<QString, QMap<uint, QMap<QString, QDBusUnixFileDescriptor>>>;
constexpr auto DDEApplicationManager1ServiceName = u8"org.deepin.dde.ApplicationManager1";
constexpr auto DDEApplicationManager1ObjectPath = u8"/org/deepin/dde/ApplicationManager1";
constexpr auto DDEApplicationManager1ApplicationObjectPath = u8"/org/deepin/dde/ApplicationManager1/Application/";
constexpr auto DDEApplicationManager1JobManagerObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1";
constexpr auto DDEApplicationManager1JobObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1/Job/";
class ApplicationManager1DBus
{
public:
ApplicationManager1DBus(const ApplicationManager1DBus &) = delete;
ApplicationManager1DBus(ApplicationManager1DBus &&) = delete;
ApplicationManager1DBus &operator=(const ApplicationManager1DBus &) = delete;
ApplicationManager1DBus &operator=(ApplicationManager1DBus&&) = delete;
const QString &BusAddress() { return m_busAddress; }
void setBusAddress(const QString &address) { m_busAddress = address; }
QDBusConnection& CustomBus()
{
static auto con = QDBusConnection::connectToBus(m_busAddress, "org.deepin.dde.ApplicationManager1");
if (!con.isConnected()) {
qWarning() << con.lastError();
std::terminate();
}
return con;
}
static ApplicationManager1DBus &instance()
{
static ApplicationManager1DBus dbus;
return dbus;
}
private:
ApplicationManager1DBus() = default;
~ApplicationManager1DBus() = default;
QString m_busAddress;
};
template <typename T, typename U>
bool registerObjectToDbus(T parent, const QString &path, const QString &interface)
{
using service_type = std::remove_const_t<T>;
static_assert(std::is_pointer_v<service_type>, "param type must be a pointer");
static_assert(std::is_base_of_v<QObject, std::remove_pointer_t<T>> and
std::is_base_of_v<QObject, U>,
"param type must derive QObject");
auto &con = ApplicationManager1DBus::instance().CustomBus();
if (!con.registerObject(path, interface, new U{parent})) {
qWarning() << "register object failed:" << path << interface << con.lastError();
return false;
}
return true;
}
template <typename T>
QString getDBusInterface()
{
auto meta = QMetaType::fromType<T>();
auto infoObject = meta.metaObject();
if (auto infoIndex = infoObject->indexOfClassInfo("D-Bus Interface"); infoIndex != -1) {
return infoObject->classInfo(infoIndex).value();
}
return {};
}
#endif