feat: add desktopfilegenerator and method addUserApplication

1. change type of ActionName to 'a{sa{ss}}'
2. refactor the method of serialization

Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
ComixHe
2023-10-16 14:39:20 +08:00
committed by Comix
parent b71ceb5fc1
commit 1f73eea404
15 changed files with 458 additions and 41 deletions

View File

@ -8,6 +8,7 @@
#include "systemdsignaldispatcher.h"
#include "propertiesForwarder.h"
#include "applicationHooks.h"
#include "desktopfilegenerator.h"
#include <QFile>
#include <QDBusMessage>
#include <unistd.h>
@ -548,3 +549,67 @@ ApplicationManager1Service::findApplicationsByIds(const QStringList &appIds) con
return ret;
}
QString ApplicationManager1Service::addUserApplication(const QVariantMap &desktop_file, const QString &name) noexcept
{
if (name.isEmpty()) {
sendErrorReply(QDBusError::Failed, "file name is empty.");
return {};
}
QDir xdgDataHome{getXDGDataHome() + "/applications"};
const auto &filePath = xdgDataHome.filePath(name);
if (QFileInfo info{filePath}; info.exists() and info.isFile()) {
sendErrorReply(QDBusError::Failed, QString{"file already exists:%1"}.arg(info.absoluteFilePath()));
return {};
}
QFile file{filePath};
if (!file.open(QFile::NewOnly | QFile::WriteOnly | QFile::Text)) {
sendErrorReply(QDBusError::Failed, file.errorString());
return {};
}
QString errMsg;
auto fileContent = DesktopFileGenerator::generate(desktop_file, errMsg);
if (fileContent.isEmpty() or !errMsg.isEmpty()) {
file.remove();
sendErrorReply(QDBusError::Failed, errMsg);
return {};
}
auto writeContent = fileContent.toLocal8Bit();
if (file.write(writeContent) != writeContent.size()) {
file.remove();
sendErrorReply(QDBusError::Failed, "incomplete file content.this file will be removed.");
return {};
}
file.flush();
ParserError err{ParserError::NoError};
auto ret = DesktopFile::searchDesktopFileByPath(filePath, err);
if (err != ParserError::NoError) {
file.remove();
qDebug() << "add user's application failed:" << err;
sendErrorReply(QDBusError::Failed, "search failed.");
return {};
}
if (!ret) {
file.remove();
sendErrorReply(QDBusError::InternalError);
return {};
}
auto desktopSource = std::move(ret).value();
auto appId = desktopSource.desktopId();
if (!addApplication(std::move(desktopSource))) {
file.remove();
sendErrorReply(QDBusError::Failed, "add application to ApplicationManager failed.");
return {};
}
return appId;
}

View File

@ -20,7 +20,7 @@
class ApplicationService;
class ApplicationManager1Service final : public QObject
class ApplicationManager1Service final : public QObject, public QDBusContext
{
Q_OBJECT
public:
@ -54,6 +54,7 @@ public Q_SLOTS:
QDBusObjectPath &instance,
ObjectInterfaceMap &application_instance_info) const noexcept;
void ReloadApplications();
QString addUserApplication(const QVariantMap &desktop_file, const QString &name) noexcept;
[[nodiscard]] ObjectMap GetManagedObjects() const;
Q_SIGNALS:

View File

@ -384,59 +384,64 @@ QStringList ApplicationService::categories() const noexcept
PropMap ApplicationService::actionName() const noexcept
{
PropMap ret;
auto actionList = actions();
const auto &actionList = actions();
for (auto &action : actionList) {
action.prepend(DesktopFileActionKey);
auto value = m_entry->value(action, "Name");
for (const auto &action : actionList) {
auto rawActionKey = DesktopFileActionKey % action;
auto value = m_entry->value(rawActionKey, "Name");
if (!value.has_value()) {
continue;
}
ret.insert(action, std::move(value).value());
ret.insert(action, std::move(value).value().value<QStringMap>());
}
return ret;
}
PropMap ApplicationService::name() const noexcept
QStringMap ApplicationService::name() const noexcept
{
PropMap ret;
auto value = m_entry->value(DesktopFileEntryKey, "Name");
if (!value) {
return ret;
return {};
}
ret.insert(QString{"Name"}, {std::move(value).value()});
return ret;
if (!value->canConvert<QStringMap>()) {
return {};
}
return value->value<QStringMap>();
}
PropMap ApplicationService::genericName() const noexcept
QStringMap ApplicationService::genericName() const noexcept
{
PropMap ret;
auto value = m_entry->value(DesktopFileEntryKey, "GenericName");
if (!value) {
return ret;
return {};
}
ret.insert(QString{"GenericName"}, {std::move(value).value()});
return ret;
if (!value->canConvert<QStringMap>()) {
return {};
}
return value->value<QStringMap>();
}
PropMap ApplicationService::icons() const noexcept
QStringMap ApplicationService::icons() const noexcept
{
PropMap ret;
QStringMap ret;
auto actionList = actions();
for (const auto &action : actionList) {
auto value = m_entry->value(QString{action}.prepend(DesktopFileActionKey), "Icon");
const auto &actionKey = QString{action}.prepend(DesktopFileActionKey);
auto value = m_entry->value(actionKey, "Icon");
if (!value.has_value()) {
continue;
}
ret.insert(action, {std::move(value).value()});
ret.insert(actionKey, value->value<QString>());
}
auto mainIcon = m_entry->value(DesktopFileEntryKey, "Icon");
if (mainIcon.has_value()) {
ret.insert(defaultKeyStr, {std::move(mainIcon).value()});
ret.insert(DesktopFileEntryKey, mainIcon->value<QString>());
}
return ret;

View File

@ -50,14 +50,14 @@ public:
Q_PROPERTY(QString ID READ id CONSTANT)
[[nodiscard]] QString id() const noexcept;
Q_PROPERTY(PropMap Name READ name NOTIFY nameChanged)
[[nodiscard]] PropMap name() const noexcept;
Q_PROPERTY(QStringMap Name READ name NOTIFY nameChanged)
[[nodiscard]] QStringMap name() const noexcept;
Q_PROPERTY(PropMap GenericName READ genericName NOTIFY genericNameChanged)
[[nodiscard]] PropMap genericName() const noexcept;
Q_PROPERTY(QStringMap GenericName READ genericName NOTIFY genericNameChanged)
[[nodiscard]] QStringMap genericName() const noexcept;
Q_PROPERTY(PropMap Icons READ icons NOTIFY iconsChanged)
[[nodiscard]] PropMap icons() const noexcept;
Q_PROPERTY(QStringMap Icons READ icons NOTIFY iconsChanged)
[[nodiscard]] QStringMap icons() const noexcept;
Q_PROPERTY(qulonglong LastLaunchedTime READ lastLaunchedTime NOTIFY lastLaunchedTimeChanged)
[[nodiscard]] qulonglong lastLaunchedTime() const noexcept;