example: add launch application example
fix some bug while testing the example Signed-off-by: ComixHe <heyuming@deepin.org> Signed-off-by: black-desk <me@black-desk.cn>
This commit is contained in:
parent
8a74802c84
commit
bc2bdf559e
@ -13,6 +13,8 @@ set(CMAKE_AUTORCC ON)
|
|||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
|
||||||
|
set(BUILD_EXAMPLES ON CACHE BOOL "Whether to build examples or not.")
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core DBus Concurrent)
|
find_package(Qt6 REQUIRED COMPONENTS Core DBus Concurrent)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
@ -22,10 +24,13 @@ add_subdirectory(src)
|
|||||||
add_subdirectory(plugins)
|
add_subdirectory(plugins)
|
||||||
add_subdirectory(apps)
|
add_subdirectory(apps)
|
||||||
|
|
||||||
# add_subdirectory(docs)
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
add_subdirectory(examples)
|
||||||
|
endif()
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface)
|
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface)
|
||||||
{
|
{
|
||||||
auto &con = ApplicationManager1DBus::instance().globalServerBus();
|
auto &con = ApplicationManager1DBus::instance().globalServerBus();
|
||||||
if (!con.registerObject(path, interface, o, QDBusConnection::RegisterOption::ExportAllContents)) {
|
if (!con.registerObject(path, interface, o, QDBusConnection::RegisterOption::ExportAdaptors)) {
|
||||||
qFatal() << "register object failed:" << path << interface << con.lastError();
|
qFatal() << "register object failed:" << path << interface << con.lastError();
|
||||||
} else {
|
} else {
|
||||||
qInfo() << "register object:" << path << interface;
|
qInfo() << "register object:" << path << interface;
|
||||||
|
1
examples/CMakeLists.txt
Normal file
1
examples/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
add_subdirectory(launchApp)
|
8
examples/launchApp/CMakeLists.txt
Normal file
8
examples/launchApp/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
set(LAUNCHAPP_BIN launchApp)
|
||||||
|
|
||||||
|
add_executable(${LAUNCHAPP_BIN} main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(${LAUNCHAPP_BIN} PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::DBus
|
||||||
|
)
|
76
examples/launchApp/main.cpp
Normal file
76
examples/launchApp/main.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QVariantMap>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class Demo : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Demo()
|
||||||
|
: ApplicationManager(u8"org.deepin.dde.ApplicationManager1",
|
||||||
|
u8"/org/deepin/dde/ApplicationManager1",
|
||||||
|
u8"org.desktopspec.ApplicationManager1")
|
||||||
|
, JobManager(u8"org.deepin.dde.ApplicationManager1",
|
||||||
|
u8"/org/deepin/dde/ApplicationManager1/JobManager1",
|
||||||
|
u8"org.desktopspec.JobManager1")
|
||||||
|
{
|
||||||
|
auto con = JobManager.connection();
|
||||||
|
if (!con.connect(JobManager.service(),
|
||||||
|
JobManager.path(),
|
||||||
|
JobManager.interface(),
|
||||||
|
u8"JobNew",
|
||||||
|
this,
|
||||||
|
SLOT(onJobNew(QDBusObjectPath, QDBusObjectPath)))) {
|
||||||
|
qFatal() << "connect JobNew failed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!con.connect(JobManager.service(),
|
||||||
|
JobManager.path(),
|
||||||
|
JobManager.interface(),
|
||||||
|
u8"JobRemoved",
|
||||||
|
this,
|
||||||
|
SLOT(onJobRemoved(QDBusObjectPath, QString, QVariantList)))) {
|
||||||
|
qFatal() << "connect JobNew failed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void launchApp(const QString &appId)
|
||||||
|
{
|
||||||
|
auto msg =
|
||||||
|
ApplicationManager.callWithArgumentList(QDBus::Block, "Launch", {appId, QString{""}, QStringList{}, QVariantMap{}});
|
||||||
|
qInfo() << "reply message:" << msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void onJobNew(QDBusObjectPath job, QDBusObjectPath source)
|
||||||
|
{
|
||||||
|
qInfo() << "Job New ["
|
||||||
|
<< "Job Path:" << job.path() << source.path() << "add this job].";
|
||||||
|
}
|
||||||
|
|
||||||
|
void onJobRemoved(QDBusObjectPath job, QString status, QVariantList result)
|
||||||
|
{
|
||||||
|
qInfo() << "Job Removed ["
|
||||||
|
<< "Job Path:" << job.path() << "Job Status:" << status << "result:" << result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusInterface ApplicationManager;
|
||||||
|
QDBusInterface JobManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication app{argc, argv};
|
||||||
|
Demo demo;
|
||||||
|
demo.launchApp("google-chrome");
|
||||||
|
return QCoreApplication::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "main.moc"
|
@ -16,9 +16,9 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
|||||||
qFatal() << connection.lastError();
|
qFatal() << connection.lastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!registerObjectToDBus(new ApplicationManager1Adaptor{this},
|
new ApplicationManager1Adaptor{this};
|
||||||
DDEApplicationManager1ObjectPath,
|
|
||||||
getDBusInterface<ApplicationManager1Adaptor>())) {
|
if (!registerObjectToDBus(this, DDEApplicationManager1ObjectPath, getDBusInterface<ApplicationManager1Adaptor>())) {
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ QPair<QString, QString> ApplicationManager1Service::processServiceName(const QSt
|
|||||||
instanceId = components.takeLast();
|
instanceId = components.takeLast();
|
||||||
applicationId = components.takeLast();
|
applicationId = components.takeLast();
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "it's not service or slice or scope.";
|
qDebug() << "it's not service or scope:" << serviceName << "ignore.";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ QPair<QString, QString> ApplicationManager1Service::processServiceName(const QSt
|
|||||||
instanceId = QUuid::createUuid().toString(QUuid::Id128);
|
instanceId = QUuid::createUuid().toString(QUuid::Id128);
|
||||||
}
|
}
|
||||||
|
|
||||||
return qMakePair(std::move(applicationId), std::move(instanceId));
|
return qMakePair(unescapeApplicationId(applicationId), std::move(instanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
||||||
|
@ -37,9 +37,9 @@ public:
|
|||||||
if (!application) {
|
if (!application) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!registerObjectToDBus(new ApplicationAdaptor{application.data()},
|
auto *ptr = application.data();
|
||||||
application->m_applicationPath.path(),
|
new ApplicationAdaptor{ptr};
|
||||||
getDBusInterface<ApplicationAdaptor>())) {
|
if (!registerObjectToDBus(ptr, application->m_applicationPath.path(), getDBusInterface<ApplicationAdaptor>())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_applicationList.insert(application->m_applicationPath, application);
|
m_applicationList.insert(application->m_applicationPath, application);
|
||||||
|
@ -145,7 +145,7 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
|
|||||||
if (resourceFile.isEmpty()) {
|
if (resourceFile.isEmpty()) {
|
||||||
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
||||||
commands.push_front(QString{R"(--unitName=app-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
|
escapeApplicationId(this->id()), instanceRandomUUID)); // launcher should use this instanceId
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start(m_launcher, commands);
|
process.start(m_launcher, commands);
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
@ -255,7 +255,7 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
|
|||||||
auto adaptor = new InstanceAdaptor(service);
|
auto adaptor = new InstanceAdaptor(service);
|
||||||
QString objectPath{DDEApplicationManager1InstanceObjectPath + instanceId};
|
QString objectPath{DDEApplicationManager1InstanceObjectPath + instanceId};
|
||||||
|
|
||||||
if (registerObjectToDBus(adaptor, objectPath, getDBusInterface<InstanceAdaptor>())) {
|
if (registerObjectToDBus(service, objectPath, getDBusInterface<InstanceAdaptor>())) {
|
||||||
m_Instances.insert(QDBusObjectPath{objectPath}, QSharedPointer<InstanceService>{service});
|
m_Instances.insert(QDBusObjectPath{objectPath}, QSharedPointer<InstanceService>{service});
|
||||||
service->moveToThread(this->thread());
|
service->moveToThread(this->thread());
|
||||||
adaptor->moveToThread(this->thread());
|
adaptor->moveToThread(this->thread());
|
||||||
|
@ -5,18 +5,14 @@
|
|||||||
#include "dbus/jobmanager1service.h"
|
#include "dbus/jobmanager1service.h"
|
||||||
#include "dbus/jobmanager1adaptor.h"
|
#include "dbus/jobmanager1adaptor.h"
|
||||||
|
|
||||||
LaunchTask::LaunchTask()
|
|
||||||
{
|
|
||||||
qRegisterMetaType<LaunchTask>();
|
|
||||||
}
|
|
||||||
|
|
||||||
JobManager1Service::JobManager1Service(ApplicationManager1Service *parent)
|
JobManager1Service::JobManager1Service(ApplicationManager1Service *parent)
|
||||||
: m_parent(parent)
|
: m_parent(parent)
|
||||||
{
|
{
|
||||||
if (!registerObjectToDBus(
|
new JobManager1Adaptor{this};
|
||||||
new JobManager1Adaptor{this}, DDEApplicationManager1JobManagerObjectPath, getDBusInterface<JobManager1Adaptor>())) {
|
if (!registerObjectToDBus(this, DDEApplicationManager1JobManagerObjectPath, getDBusInterface<JobManager1Adaptor>())) {
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
qRegisterMetaType<LaunchTask>();
|
||||||
}
|
}
|
||||||
|
|
||||||
JobManager1Service::~JobManager1Service() = default;
|
JobManager1Service::~JobManager1Service() = default;
|
||||||
|
@ -22,7 +22,7 @@ class ApplicationManager1Service;
|
|||||||
|
|
||||||
struct LaunchTask
|
struct LaunchTask
|
||||||
{
|
{
|
||||||
LaunchTask();
|
LaunchTask() = default;
|
||||||
~LaunchTask() = default;
|
~LaunchTask() = default;
|
||||||
LaunchTask(const LaunchTask &) = default;
|
LaunchTask(const LaunchTask &) = default;
|
||||||
LaunchTask(LaunchTask &&) = default;
|
LaunchTask(LaunchTask &&) = default;
|
||||||
@ -57,7 +57,10 @@ public:
|
|||||||
QVariantList{},
|
QVariantList{},
|
||||||
QtConcurrent::ReduceOption::OrderedReduce);
|
QtConcurrent::ReduceOption::OrderedReduce);
|
||||||
QSharedPointer<JobService> job{new JobService{future}};
|
QSharedPointer<JobService> job{new JobService{future}};
|
||||||
if (!registerObjectToDBus(new JobAdaptor(job.data()), objectPath, getDBusInterface<JobAdaptor>())) {
|
|
||||||
|
auto *ptr = job.data();
|
||||||
|
new JobAdaptor(ptr);
|
||||||
|
if (!registerObjectToDBus(ptr, objectPath, getDBusInterface<JobAdaptor>())) {
|
||||||
qCritical() << "can't register job to dbus.";
|
qCritical() << "can't register job to dbus.";
|
||||||
future.cancel();
|
future.cancel();
|
||||||
return {};
|
return {};
|
||||||
|
35
src/global.h
35
src/global.h
@ -254,13 +254,46 @@ inline QString unescapeFromObjectPath(const QString &str)
|
|||||||
for (qsizetype i = 0; i < str.size(); ++i) {
|
for (qsizetype i = 0; i < str.size(); ++i) {
|
||||||
if (str[i] == '_' and i + 2 < str.size()) {
|
if (str[i] == '_' and i + 2 < str.size()) {
|
||||||
auto hexStr = str.sliced(i + 1, 2);
|
auto hexStr = str.sliced(i + 1, 2);
|
||||||
ret.replace(hexStr, QChar::fromLatin1(hexStr.toUInt(nullptr, 16)));
|
ret.replace(QString{"_%1"}.arg(hexStr), QChar::fromLatin1(hexStr.toUInt(nullptr, 16)));
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QString escapeApplicationId(const QString &id)
|
||||||
|
{
|
||||||
|
if (id.isEmpty()) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = id;
|
||||||
|
QRegularExpression re{R"([^a-zA-Z0-9])"};
|
||||||
|
auto matcher = re.globalMatch(ret);
|
||||||
|
while (matcher.hasNext()) {
|
||||||
|
auto replaceList = matcher.next().capturedTexts();
|
||||||
|
replaceList.removeDuplicates();
|
||||||
|
for (const auto &c : replaceList) {
|
||||||
|
auto hexStr = QString::number(static_cast<uint>(c.front().toLatin1()), 16);
|
||||||
|
ret.replace(c, QString{R"(\x%1)"}.arg(hexStr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString unescapeApplicationId(const QString &id)
|
||||||
|
{
|
||||||
|
auto ret = id;
|
||||||
|
for (qsizetype i = 0; i < id.size(); ++i) {
|
||||||
|
if (id[i] == '\\' and i + 3 < id.size()) {
|
||||||
|
auto hexStr = id.sliced(i + 2, 2);
|
||||||
|
ret.replace(QString{R"(\x%1)"}.arg(hexStr), QChar::fromLatin1(hexStr.toUInt(nullptr, 16)));
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline QString getRelativePathFromAppId(const QString &id)
|
inline QString getRelativePathFromAppId(const QString &id)
|
||||||
{
|
{
|
||||||
QString path;
|
QString path;
|
||||||
|
Loading…
Reference in New Issue
Block a user