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."
/>
<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">
<arg type="s" name="action" direction="in" />
<arg type="as" name="fields" direction="in" />
@ -32,41 +86,6 @@
/>
</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">
<arg name="identifier" type="s" direction="in"/>
<arg name="env" type="as" direction="in"/>
@ -81,24 +100,5 @@
this method will use the locale config of that user."
/>
</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>
</node>

View File

@ -1,21 +1,23 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "applicationmanager1service.h"
#include "applicationmanager1adaptor.h"
#include "applicationadaptor.h"
#include "global.h"
ApplicationManager1Service::ApplicationManager1Service(QObject *parent)
: QObject(parent)
ApplicationManager1Service::~ApplicationManager1Service() = default;
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() {}
QList<QDBusObjectPath> ApplicationManager1Service::list() const
{
// TODO: impl
return {};
}
void ApplicationManager1Service::removeAllApplication() { m_applicationList.clear(); }
QDBusObjectPath ApplicationManager1Service::Application(const QString &id)
{
@ -32,10 +34,22 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
}
QDBusObjectPath ApplicationManager1Service::Launch(const QString &id,
const QString &action,
const QString &actions,
const QStringList &fields,
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 {};
}

View File

@ -8,22 +8,36 @@
#include <QObject>
#include <QDBusObjectPath>
#include <QDBusUnixFileDescriptor>
#include <QSharedPointer>
#include <QMap>
#include "applicationservice.h"
class ApplicationManager1Service : public QObject
class ApplicationManager1Service final : public QObject
{
Q_OBJECT
public:
explicit ApplicationManager1Service(QObject *parent = nullptr);
virtual ~ApplicationManager1Service();
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)
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:
QDBusObjectPath Application(const QString &id);
QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance);
QDBusObjectPath Launch(const QString &id, const QString &action, const QStringList &fields, const QVariantMap &options);
private:
QMap<QDBusObjectPath,QSharedPointer<ApplicationService>> m_applicationList;
};
#endif

View File

@ -3,16 +3,53 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "applicationservice.h"
#include "instanceadaptor.h"
#include <QUuid>
ApplicationService::ApplicationService(QObject *parent)
: QObject(parent)
ApplicationService::ApplicationService(QString ID)
: 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
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 <QDBusObjectPath>
#include <QMap>
#include <QString>
#include <QDBusUnixFileDescriptor>
#include <QSharedPointer>
#include "instanceservice.h"
#include "global.h"
class ApplicationService : public QObject
{
Q_OBJECT
public:
explicit ApplicationService(QObject *parent = nullptr);
virtual ~ApplicationService();
~ApplicationService() override;
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:
QString GetActionName(const QString &identifier, const QStringList &env);
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

View File

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

View File

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

View File

@ -3,10 +3,24 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "jobmanager1service.h"
#include <QUuid>
#include "global.h"
JobManager1Service::JobManager1Service(QObject *parent)
: QObject(parent)
JobManager1Service::JobManager1Service() = default;
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
#include <QObject>
#include <QMap>
#include <QDBusObjectPath>
class JobManager1Service : public QObject
#include <QSharedPointer>
#include "jobservice.h"
class JobManager1Service final : public QObject
{
Q_OBJECT
public:
explicit JobManager1Service(QObject *parent = nullptr);
virtual ~JobManager1Service();
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:
void JobNew(const QDBusObjectPath &job, const QDBusObjectPath &source);
void JobRemoved(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result);
private:
QMap<QDBusObjectPath, QSharedPointer<JobService>> m_jobs;
};
#endif

View File

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

View File

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