feat: add dde-am tool to launch application

add dde-am tool.
This commit is contained in:
Ye ShanShan 2024-03-22 16:29:33 +08:00 committed by yeshanshan
parent b9d92f1254
commit 703a27c1ee
12 changed files with 292 additions and 0 deletions

View File

@ -23,11 +23,13 @@ set(DDE_AM_USE_DEBUG_DBUS_NAME OFF CACHE BOOL "build a dbus service using a diff
set(PROFILING_MODE OFF CACHE BOOL "run a valgrind performance profiling.") set(PROFILING_MODE OFF CACHE BOOL "run a valgrind performance profiling.")
find_package(Qt6 REQUIRED COMPONENTS Core DBus Concurrent) find_package(Qt6 REQUIRED COMPONENTS Core DBus Concurrent)
find_package(Dtk6 REQUIRED COMPONENTS Core)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
set(APP_LAUNCH_HELPER_BIN app-launch-helper) set(APP_LAUNCH_HELPER_BIN app-launch-helper)
set(APP_UPDATE_NOTIFIER_BIN app-update-notifier) set(APP_UPDATE_NOTIFIER_BIN app-update-notifier)
set(AM_LIBEXEC_DIR ${CMAKE_INSTALL_LIBEXECDIR}/deepin/application-manager) set(AM_LIBEXEC_DIR ${CMAKE_INSTALL_LIBEXECDIR}/deepin/application-manager)
set(APPLICATION_SERVICEID "org.deepin.dde.application-manager")
if(DDE_AM_USE_DEBUG_DBUS_NAME) if(DDE_AM_USE_DEBUG_DBUS_NAME)
add_compile_definitions(-DDDE_AM_USE_DEBUG_DBUS_NAME) add_compile_definitions(-DDDE_AM_USE_DEBUG_DBUS_NAME)

View File

@ -2,3 +2,4 @@ add_subdirectory(dde-application-manager)
add_subdirectory(app-launch-helper) add_subdirectory(app-launch-helper)
add_subdirectory(app-update-notifier) add_subdirectory(app-update-notifier)
add_subdirectory(app-identifier) add_subdirectory(app-identifier)
add_subdirectory(dde-am)

View File

@ -0,0 +1 @@
add_subdirectory(src)

View File

@ -0,0 +1,17 @@
set(BIN_NAME dde-am)
add_executable(${BIN_NAME} main.cpp
launcher.h launcher.cpp
)
target_link_libraries(${BIN_NAME} PRIVATE
dde_am_static
Dtk6::Core
)
target_include_directories(${BIN_NAME} PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src
)
install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@ -0,0 +1,150 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "launcher.h"
#include "global.h"
#include <QDBusConnection>
#include <QDBusMetaType>
#include <DConfig>
DCORE_USE_NAMESPACE
namespace {
void registerComplexDbusType()
{
qRegisterMetaType<ObjectInterfaceMap>();
qDBusRegisterMetaType<ObjectInterfaceMap>();
qRegisterMetaType<ObjectMap>();
qDBusRegisterMetaType<ObjectMap>();
qDBusRegisterMetaType<QStringMap>();
qRegisterMetaType<QStringMap>();
qRegisterMetaType<PropMap>();
qDBusRegisterMetaType<PropMap>();
qDBusRegisterMetaType<QDBusObjectPath>();
}
template<class T>
DExpected<T> parseDBusField(const QVariantMap &map, const QString &key)
{
if (!map.contains(key))
return DUnexpected{emplace_tag::USE_EMPLACE, -1, QString("%1 doesn't exist.").arg(key)};
const auto value = map.value(key);
return DExpected<T>{qdbus_cast<T>(value)};
}
ObjectMap getManagedObjects()
{
registerComplexDbusType();
auto con = QDBusConnection::sessionBus();
auto msg = QDBusMessage::createMethodCall(
DDEApplicationManager1ServiceName, DDEApplicationManager1ObjectPath, ObjectManagerInterface, "GetManagedObjects");
auto reply = con.call(msg);
if (reply.type() != QDBusMessage::ReplyMessage) {
qFatal() << "Failed to fetch application infos" << reply.errorMessage();
}
const auto &arguments = reply.arguments();
Q_ASSERT_X(!arguments.isEmpty(), "", "Incorrect reply argument for GetManagedObjects call.");
return qdbus_cast<ObjectMap>(arguments.first());
}
} // namespace
DExpected<QStringList> Launcher::appIds()
{
QStringList appIds;
const auto objects = getManagedObjects();
for (auto iter = objects.cbegin(); iter != objects.cend(); ++iter) {
const auto &objPath = iter.key().path();
const ObjectInterfaceMap &objs = iter.value();
const QVariantMap appInfo = objs.value("org.desktopspec.ApplicationManager1.Application");
if (appInfo.isEmpty())
continue;
if (auto value = parseDBusField<QString>(appInfo, u8"ID")) {
appIds.append(value.value());
} else {
qFatal() << "Failed to parse application ID";
}
}
return appIds;
}
void Launcher::setPath(const QString &path)
{
m_path = path;
}
void Launcher::setAction(const QString &action)
{
m_action = action;
}
void Launcher::setLaunchedType(LaunchedType type)
{
m_launchedType = type;
}
DExpected<void> Launcher::run()
{
if (auto value = launch(); !value)
return value;
if (m_launchedType == ByUser)
if (auto ret = updateLaunchedTimes(); !ret)
return ret;
return {};
}
DExpected<void> Launcher::launch()
{
auto con = QDBusConnection::sessionBus();
auto msg = QDBusMessage::createMethodCall(
DDEApplicationManager1ServiceName, m_path, ApplicationInterface, "Launch");
const QList<QVariant> arguments {
m_action,
QStringList{},
QVariantMap{}
};
msg.setArguments(arguments);
auto reply = con.call(msg);
if (reply.type() != QDBusMessage::ReplyMessage) {
return DUnexpected{emplace_tag::USE_EMPLACE,
static_cast<int>(reply.type()),
QString("Failed to launch: %1, error: %2").arg(appId(), reply.errorMessage())};
}
return {};
}
DExpected<void> Launcher::updateLaunchedTimes()
{
std::unique_ptr<DConfig> config(DConfig::create(ApplicationServiceID, ApplicationManagerToolsConfig));
if (!config->isValid())
return DUnexpected{emplace_tag::USE_EMPLACE, -1,
"DConfig is invalid when updating launched times."};
const QString AppsLaunchedTimes(u8"appsLaunchedTimes");
QVariantMap launchedTimes = config->value(AppsLaunchedTimes).toMap();
const auto appKey = appId();
if (appKey.isEmpty())
return DUnexpected{emplace_tag::USE_EMPLACE, -1, QString("Empty appId for the path: %1").arg(m_path)};
launchedTimes[appKey] = launchedTimes[appKey].toLongLong() + 1;
config->setValue(AppsLaunchedTimes, launchedTimes);
return {};
}
QString Launcher::appId() const
{
if (m_path.isEmpty()) return {};
const auto startIndex = QString(DDEApplicationManager1ObjectPath).size();
auto endIndex = m_path.indexOf("/", startIndex + 1);
const auto id = endIndex <= -1 ? m_path.mid(startIndex + 1) :
m_path.sliced(startIndex + 1, endIndex - (startIndex + 1));
return unescapeFromObjectPath(id);
}

View File

@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#pragma once
#include <QString>
#include <DExpected>
class Launcher {
public:
enum LaunchedType{
Unknown,
ByUser,
};
void setPath(const QString &path);
void setAction(const QString &action);
void setLaunchedType(LaunchedType type);
Dtk::Core::DExpected<void> run();
static Dtk::Core::DExpected<QStringList> appIds();
private:
Dtk::Core::DExpected<void> launch();
Dtk::Core::DExpected<void> updateLaunchedTimes();
QString appId() const;
QString m_path;
QString m_action;
LaunchedType m_launchedType = Unknown;
};

64
apps/dde-am/src/main.cpp Normal file
View File

@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include <QCoreApplication>
#include <QCommandLineOption>
#include <QCommandLineParser>
#include "launcher.h"
#include "global.h"
int main(int argc, char *argv[])
{
QCoreApplication app{argc, argv};
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption listOption("list", "List all appId.");
parser.addOption(listOption);
QCommandLineOption launchedByUserOption("by-user",
"Launched by user, it's useful for counting launched times.");
parser.addOption(launchedByUserOption);
parser.addPositionalArgument("appId", "Application's ID.");
parser.addPositionalArgument("action", "Name of the action identifiers for the application, optionally.");
parser.process(app);
if (parser.isSet(listOption)) {
const auto apps = Launcher::appIds();
if (!apps) {
qWarning() << apps.error();
return apps.error().getErrorCode();
}
for (const auto &item :apps.value()) {
qDebug() << qPrintable(item);
}
return 0;
}
auto arguments = parser.positionalArguments();
if (arguments.size() < 1)
parser.showHelp();
Launcher launcher;
if (parser.isSet(launchedByUserOption))
launcher.setLaunchedType(Launcher::ByUser);
const auto pos1 = arguments.takeFirst();
QString appPath = pos1.startsWith("/") ? pos1 :
QString("%1/%2").arg(DDEApplicationManager1ObjectPath, escapeToObjectPath(pos1));
launcher.setPath(appPath);
if (arguments.size() >= 1) {
const auto action = arguments.takeFirst();
launcher.setAction(action);
}
auto ret = launcher.run();
if (!ret) {
qWarning() << ret.error();
return ret.error().getErrorCode();
}
return 0;
}

2
debian/control vendored
View File

@ -7,6 +7,8 @@ Build-Depends: debhelper-compat ( =12), cmake,
libsystemd-dev, libsystemd-dev,
pkg-config, pkg-config,
qt6-base-dev, qt6-base-dev,
libdtkcommon-dev,
libdtk6core-dev,
Standards-Version: 4.5.0 Standards-Version: 4.5.0
Homepage: https://github.com/linuxdeepin/dde-application-manager Homepage: https://github.com/linuxdeepin/dde-application-manager

View File

@ -74,3 +74,7 @@ set(DCONFIG_FILES
) )
install(FILES ${DCONFIG_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/dsg/configs/dde-application-manager) install(FILES ${DCONFIG_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/dsg/configs/dde-application-manager)
dtk_add_config_meta_files(APPID ${APPLICATION_SERVICEID}
FILES ${CMAKE_CURRENT_LIST_DIR}/dsg/configs/dde-application-manager/org.deepin.dde.am.json
)

View File

@ -0,0 +1,16 @@
{
"magic": "dsg.config.meta",
"version": "1.0",
"contents": {
"appsLaunchedTimes": {
"value": {},
"serial": 0,
"flags": [],
"name": "launched times of all apps",
"name[zh_CN]": "所有应用的启动次数",
"description": "launched times of all apps",
"permissions": "readwrite",
"visibility": "public"
}
}
}

View File

@ -8,4 +8,7 @@
constexpr auto ApplicationLaunchHelperBinary = constexpr auto ApplicationLaunchHelperBinary =
u8"@CMAKE_INSTALL_FULL_LIBEXECDIR@/deepin/application-manager/@APP_LAUNCH_HELPER_BIN@"; u8"@CMAKE_INSTALL_FULL_LIBEXECDIR@/deepin/application-manager/@APP_LAUNCH_HELPER_BIN@";
const auto ApplicationServiceID =
u8"@APPLICATION_SERVICEID@";
#endif #endif

View File

@ -63,4 +63,6 @@ constexpr auto InstalledTime = u8"InstalledTime";
constexpr auto ApplicationManagerHookDir = u8"/deepin/dde-application-manager/hooks.d"; constexpr auto ApplicationManagerHookDir = u8"/deepin/dde-application-manager/hooks.d";
constexpr auto ApplicationManagerToolsConfig = u8"org.deepin.dde.am";
#endif #endif