refact: DesktopFile's method and structure
Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
parent
65b6c9eaf0
commit
06ee5e5899
@ -27,7 +27,7 @@ public:
|
|||||||
u8"JobNew",
|
u8"JobNew",
|
||||||
this,
|
this,
|
||||||
SLOT(jobNewForward(QDBusObjectPath, QDBusObjectPath)))) {
|
SLOT(jobNewForward(QDBusObjectPath, QDBusObjectPath)))) {
|
||||||
qFatal() << "connect JobNew failed.";
|
qFatal("connect JobNew failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!con.connect(JobManager.service(),
|
if (!con.connect(JobManager.service(),
|
||||||
@ -36,7 +36,7 @@ public:
|
|||||||
u8"JobRemoved",
|
u8"JobRemoved",
|
||||||
this,
|
this,
|
||||||
SLOT(jobRemovedForward(QDBusObjectPath, QString, QVariantList)))) {
|
SLOT(jobRemovedForward(QDBusObjectPath, QString, QVariantList)))) {
|
||||||
qFatal() << "connect JobNew failed.";
|
qFatal("connect JobNew failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(this, &Demo::applicationLaunched, [](QList<QString> apps) {
|
connect(this, &Demo::applicationLaunched, [](QList<QString> apps) {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// 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 "applicationadaptor.h"
|
||||||
#include "dbus/applicationmanager1adaptor.h"
|
#include "dbus/applicationmanager1adaptor.h"
|
||||||
|
#include "applicationservice.h"
|
||||||
#include "dbus/AMobjectmanager1adaptor.h"
|
#include "dbus/AMobjectmanager1adaptor.h"
|
||||||
#include "systemdsignaldispatcher.h"
|
#include "systemdsignaldispatcher.h"
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
@ -10,17 +11,20 @@
|
|||||||
|
|
||||||
ApplicationManager1Service::~ApplicationManager1Service() = default;
|
ApplicationManager1Service::~ApplicationManager1Service() = default;
|
||||||
|
|
||||||
ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifier> ptr, QDBusConnection &connection)
|
ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifier> ptr, QDBusConnection &connection) noexcept
|
||||||
: m_identifier(std::move(ptr))
|
: m_identifier(std::move(ptr))
|
||||||
{
|
{
|
||||||
if (!connection.registerService(DDEApplicationManager1ServiceName)) {
|
if (!connection.registerService(DDEApplicationManager1ServiceName)) {
|
||||||
qFatal() << connection.lastError();
|
qFatal("%s", connection.lastError().message().toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
new ApplicationManager1Adaptor{this};
|
if (auto *tmp = new (std::nothrow) ApplicationManager1Adaptor{this}; tmp == nullptr) {
|
||||||
auto *tmp = new AMObjectManagerAdaptor{this};
|
qCritical() << "new Application Manager Adaptor failed.";
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
|
||||||
if (tmp == nullptr) {
|
if (auto *tmp = new (std::nothrow) AMObjectManagerAdaptor{this}; tmp == nullptr) {
|
||||||
|
qCritical() << "new Object Manager of Application Manager Adaptor failed.";
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +33,12 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
|||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_jobManager.reset(new JobManager1Service(this));
|
m_jobManager.reset(new (std::nothrow) JobManager1Service(this));
|
||||||
|
|
||||||
|
if (!m_jobManager) {
|
||||||
|
qCritical() << "new JobManager failed.";
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
|
||||||
auto &dispatcher = SystemdSignalDispatcher::instance();
|
auto &dispatcher = SystemdSignalDispatcher::instance();
|
||||||
|
|
||||||
@ -109,11 +118,8 @@ bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) n
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_applicationList.constFind(application->applicationPath()) != m_applicationList.cend()) {
|
if (m_applicationList.constFind(application->applicationPath()) != m_applicationList.cend()) {
|
||||||
auto info = qInfo();
|
qInfo() << "this application already exists."
|
||||||
info << "this application already exists.";
|
<< "desktop source:" << application->desktopFileSource().sourcePath();
|
||||||
if (application->desktopFileSource().persistence()) {
|
|
||||||
info << "desktop source:" << application->desktopFileSource().fileSource();
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,16 +215,9 @@ void ApplicationManager1Service::updateApplication(const QSharedPointer<Applicat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat buf;
|
auto mtime = getFileModifiedTime(desktopFile.sourceFileRef());
|
||||||
const auto *filePath = desktopFile.fileSource().toLocal8Bit().data();
|
|
||||||
if (auto ret = stat(filePath, &buf); ret == -1) {
|
|
||||||
qWarning() << "get file" << filePath << "state failed:" << std::strerror(errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::size_t secToNano = 1e9;
|
if (destApp->desktopFileSource().modified(mtime)) {
|
||||||
|
|
||||||
if (destApp->desktopFileSource().modified(buf.st_mtim.tv_sec * secToNano + buf.st_mtim.tv_nsec)) {
|
|
||||||
auto *newEntry = new (std::nothrow) DesktopEntry{};
|
auto *newEntry = new (std::nothrow) DesktopEntry{};
|
||||||
if (newEntry == nullptr) {
|
if (newEntry == nullptr) {
|
||||||
qCritical() << "new DesktopEntry failed.";
|
qCritical() << "new DesktopEntry failed.";
|
||||||
|
@ -13,15 +13,16 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include "dbus/jobmanager1service.h"
|
#include "dbus/jobmanager1service.h"
|
||||||
#include "dbus/APPobjectmanager1adaptor.h"
|
#include "desktopentry.h"
|
||||||
#include "dbus/applicationadaptor.h"
|
|
||||||
#include "identifier.h"
|
#include "identifier.h"
|
||||||
|
|
||||||
|
class ApplicationService;
|
||||||
|
|
||||||
class ApplicationManager1Service final : public QObject
|
class ApplicationManager1Service final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ApplicationManager1Service(std::unique_ptr<Identifier> ptr, QDBusConnection &connection);
|
explicit ApplicationManager1Service(std::unique_ptr<Identifier> ptr, QDBusConnection &connection) noexcept;
|
||||||
~ApplicationManager1Service() override;
|
~ApplicationManager1Service() override;
|
||||||
ApplicationManager1Service(const ApplicationManager1Service &) = delete;
|
ApplicationManager1Service(const ApplicationManager1Service &) = delete;
|
||||||
ApplicationManager1Service(ApplicationManager1Service &&) = delete;
|
ApplicationManager1Service(ApplicationManager1Service &&) = delete;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
#include "dbus/applicationservice.h"
|
#include "dbus/applicationservice.h"
|
||||||
|
#include "APPobjectmanager1adaptor.h"
|
||||||
#include "applicationmanager1service.h"
|
#include "applicationmanager1service.h"
|
||||||
#include "dbus/instanceadaptor.h"
|
#include "dbus/instanceadaptor.h"
|
||||||
#include "pwd.h"
|
#include "pwd.h"
|
||||||
@ -34,28 +35,24 @@ ApplicationService::~ApplicationService()
|
|||||||
QSharedPointer<ApplicationService> ApplicationService::createApplicationService(DesktopFile source,
|
QSharedPointer<ApplicationService> ApplicationService::createApplicationService(DesktopFile source,
|
||||||
ApplicationManager1Service *parent) noexcept
|
ApplicationManager1Service *parent) noexcept
|
||||||
{
|
{
|
||||||
QString objectPath;
|
QSharedPointer<ApplicationService> app{new (std::nothrow) ApplicationService{std::move(source), parent}};
|
||||||
QTextStream sourceStream;
|
if (!app) {
|
||||||
QFile sourceFile;
|
qCritical() << "new application service failed.";
|
||||||
QString tempSource;
|
|
||||||
QSharedPointer<ApplicationService> app{nullptr};
|
|
||||||
|
|
||||||
if (source.persistence()) {
|
|
||||||
objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + escapeToObjectPath(source.desktopId());
|
|
||||||
sourceFile.setFileName(source.fileSource());
|
|
||||||
if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
|
|
||||||
qCritical() << "desktop file can't open:" << source.fileSource() << sourceFile.errorString();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.reset(new (std::nothrow) ApplicationService{std::move(source), parent});
|
QString objectPath;
|
||||||
sourceStream.setDevice(&sourceFile);
|
QTextStream sourceStream;
|
||||||
|
|
||||||
|
auto appId = app->desktopFileSource().desktopId();
|
||||||
|
|
||||||
|
if (!appId.isEmpty()) {
|
||||||
|
objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + escapeToObjectPath(appId);
|
||||||
} else {
|
} else {
|
||||||
tempSource = source.fileSource();
|
|
||||||
objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + QUuid::createUuid().toString(QUuid::Id128);
|
objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + QUuid::createUuid().toString(QUuid::Id128);
|
||||||
app.reset(new (std::nothrow) ApplicationService{std::move(source), parent});
|
|
||||||
sourceStream.setString(&tempSource, QTextStream::ReadOnly | QTextStream::Text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceStream.setDevice(app->desktopFileSource().sourceFile());
|
||||||
std::unique_ptr<DesktopEntry> entry{std::make_unique<DesktopEntry>()};
|
std::unique_ptr<DesktopEntry> entry{std::make_unique<DesktopEntry>()};
|
||||||
auto error = entry->parse(sourceStream);
|
auto error = entry->parse(sourceStream);
|
||||||
|
|
||||||
@ -76,7 +73,11 @@ QSharedPointer<ApplicationService> ApplicationService::createApplicationService(
|
|||||||
app->m_applicationPath = QDBusObjectPath{std::move(objectPath)};
|
app->m_applicationPath = QDBusObjectPath{std::move(objectPath)};
|
||||||
|
|
||||||
// TODO: icon lookup
|
// TODO: icon lookup
|
||||||
new (std::nothrow) APPObjectManagerAdaptor{app.data()};
|
if (auto *ptr = new (std::nothrow) APPObjectManagerAdaptor{app.data()}; ptr == nullptr) {
|
||||||
|
qCritical() << "new Object Manager of Application failed.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,10 +253,7 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
|||||||
auto resourceFile = variantValue.toString();
|
auto resourceFile = variantValue.toString();
|
||||||
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
||||||
auto objectPath = m_applicationPath.path() + "/" + instanceRandomUUID;
|
auto objectPath = m_applicationPath.path() + "/" + instanceRandomUUID;
|
||||||
|
commands.push_front(QString{"--SourcePath=%1"}.arg(m_desktopSource.sourcePath()));
|
||||||
if (m_desktopSource.persistence()) {
|
|
||||||
commands.push_front(QString{"--SourcePath=%1"}.arg(m_desktopSource.fileSource()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resourceFile.isEmpty()) {
|
if (resourceFile.isEmpty()) {
|
||||||
commands.push_front(QString{R"(--unitName=app-DDE-%1@%2.service)"}.arg(
|
commands.push_front(QString{R"(--unitName=app-DDE-%1@%2.service)"}.arg(
|
||||||
@ -303,7 +301,7 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
|||||||
QStringList ApplicationService::actions() const noexcept
|
QStringList ApplicationService::actions() const noexcept
|
||||||
{
|
{
|
||||||
if (m_entry.isNull()) {
|
if (m_entry.isNull()) {
|
||||||
qWarning() << "desktop entry is empty, isPersistence:" << m_desktopSource.persistence();
|
qWarning() << "desktop entry is empty, source file:" << m_desktopSource.sourcePath();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,10 +330,7 @@ ObjectMap ApplicationService::GetManagedObjects() const
|
|||||||
|
|
||||||
QString ApplicationService::id() const noexcept
|
QString ApplicationService::id() const noexcept
|
||||||
{
|
{
|
||||||
if (m_desktopSource.persistence()) {
|
|
||||||
return m_desktopSource.desktopId();
|
return m_desktopSource.desktopId();
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IconMap ApplicationService::icons() const
|
IconMap ApplicationService::icons() const
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
void removeOneInstance(const QDBusObjectPath &instance) noexcept;
|
void removeOneInstance(const QDBusObjectPath &instance) noexcept;
|
||||||
void removeAllInstance() noexcept;
|
void removeAllInstance() noexcept;
|
||||||
[[nodiscard]] const QDBusObjectPath &applicationPath() const noexcept { return m_applicationPath; }
|
[[nodiscard]] const QDBusObjectPath &applicationPath() const noexcept { return m_applicationPath; }
|
||||||
[[nodiscard]] const DesktopFile &desktopFileSource() const noexcept { return m_desktopSource; }
|
[[nodiscard]] DesktopFile &desktopFileSource() noexcept { return m_desktopSource; }
|
||||||
[[nodiscard]] const QMap<QDBusObjectPath, QSharedPointer<InstanceService>> &applicationInstances() const noexcept
|
[[nodiscard]] const QMap<QDBusObjectPath, QSharedPointer<InstanceService>> &applicationInstances() const noexcept
|
||||||
{
|
{
|
||||||
return m_Instances;
|
return m_Instances;
|
||||||
|
@ -24,7 +24,11 @@ auto DesktopEntry::parserGroupHeader(const QString &str) noexcept
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void functest(QMap<QString, QString> p) {}
|
QString DesktopFile::sourcePath() const noexcept
|
||||||
|
{
|
||||||
|
QFileInfo info(*m_fileSource);
|
||||||
|
return info.absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept
|
DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept
|
||||||
{
|
{
|
||||||
@ -90,11 +94,14 @@ DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMa
|
|||||||
return DesktopErrorCode::NoError;
|
return DesktopErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<DesktopFile> DesktopFile::createTemporaryDesktopFile(QString content) noexcept
|
std::optional<DesktopFile> DesktopFile::createTemporaryDesktopFile(std::unique_ptr<QFile> temporaryFile) noexcept
|
||||||
{
|
{
|
||||||
auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
|
auto mtime = getFileModifiedTime(*temporaryFile);
|
||||||
auto nano = std::chrono::duration_cast<std::chrono::nanoseconds>(now);
|
if (mtime == 0) {
|
||||||
return DesktopFile{false, std::move(content), "", static_cast<size_t>(nano.count())};
|
qWarning() << "create temporary file failed.";
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return DesktopFile{std::move(temporaryFile), "", mtime};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<DesktopFile> DesktopFile::searchDesktopFileByPath(const QString &desktopFile, DesktopErrorCode &err) noexcept
|
std::optional<DesktopFile> DesktopFile::searchDesktopFileByPath(const QString &desktopFile, DesktopErrorCode &err) noexcept
|
||||||
@ -134,17 +141,17 @@ std::optional<DesktopFile> DesktopFile::searchDesktopFileByPath(const QString &d
|
|||||||
id = FileId.chopped(1); // remove extra "-""
|
id = FileId.chopped(1); // remove extra "-""
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat buf;
|
auto filePtr = std::make_unique<QFile>(std::move(path));
|
||||||
if (auto ret = stat(path.toLatin1().data(), &buf); ret == -1) {
|
|
||||||
|
auto mtime = getFileModifiedTime(*filePtr);
|
||||||
|
|
||||||
|
if (mtime == 0) {
|
||||||
err = DesktopErrorCode::OpenFailed;
|
err = DesktopErrorCode::OpenFailed;
|
||||||
qWarning() << "get file" << path << "state failed:" << std::strerror(errno);
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = DesktopErrorCode::NoError;
|
err = DesktopErrorCode::NoError;
|
||||||
constexpr std::size_t secToNano = 1e9;
|
return DesktopFile{std::move(filePtr), std::move(id), mtime};
|
||||||
|
|
||||||
return DesktopFile{true, std::move(path), std::move(id), buf.st_mtim.tv_sec * secToNano + buf.st_mtim.tv_nsec};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<DesktopFile> DesktopFile::searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept
|
std::optional<DesktopFile> DesktopFile::searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept
|
||||||
@ -178,21 +185,18 @@ bool DesktopFile::modified(std::size_t time) const noexcept
|
|||||||
return time != m_mtime;
|
return time != m_mtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
DesktopErrorCode DesktopEntry::parse(const DesktopFile &file) noexcept
|
DesktopErrorCode DesktopEntry::parse(DesktopFile &file) noexcept
|
||||||
{
|
{
|
||||||
QTextStream in;
|
DesktopFileGuard guard{file};
|
||||||
if (file.persistence()) {
|
|
||||||
auto sourceFile = QFile(file.fileSource());
|
if (!guard.try_open()) {
|
||||||
if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
|
qWarning() << file.sourcePath() << "can't open.";
|
||||||
qWarning() << file.fileSource() << "can't open.";
|
|
||||||
return DesktopErrorCode::OpenFailed;
|
return DesktopErrorCode::OpenFailed;
|
||||||
}
|
}
|
||||||
in.setDevice(&sourceFile);
|
|
||||||
} else {
|
|
||||||
in.setString(const_cast<QString *>(&file.fileSource()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return parse(in);
|
QTextStream stream;
|
||||||
|
stream.setDevice(file.sourceFile());
|
||||||
|
return parse(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept
|
DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef DESKTOPENTRY_H
|
||||||
|
#define DESKTOPENTRY_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sys/stat.h>
|
#include <QFile>
|
||||||
|
|
||||||
constexpr static auto defaultKeyStr = "default";
|
constexpr static auto defaultKeyStr = "default";
|
||||||
|
|
||||||
@ -22,38 +25,68 @@ enum class DesktopErrorCode {
|
|||||||
EntryKeyInvalid
|
EntryKeyInvalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DesktopFileGuard;
|
||||||
|
|
||||||
struct DesktopFile
|
struct DesktopFile
|
||||||
{
|
{
|
||||||
DesktopFile(const DesktopFile &) = default;
|
friend struct DesktopFileGuard;
|
||||||
|
DesktopFile(const DesktopFile &) = delete;
|
||||||
DesktopFile(DesktopFile &&) = default;
|
DesktopFile(DesktopFile &&) = default;
|
||||||
DesktopFile &operator=(const DesktopFile &) = default;
|
DesktopFile &operator=(const DesktopFile &) = delete;
|
||||||
DesktopFile &operator=(DesktopFile &&) = default;
|
DesktopFile &operator=(DesktopFile &&) = default;
|
||||||
~DesktopFile() = default;
|
~DesktopFile() = default;
|
||||||
|
|
||||||
[[nodiscard]] const QString &fileSource() const noexcept { return m_fileSource; }
|
[[nodiscard]] QString sourcePath() const noexcept;
|
||||||
|
// WARNING: This raw pointer's ownership belong to DesktopFile, DO NOT MODIFY!
|
||||||
|
[[nodiscard]] QFile *sourceFile() const noexcept { return &sourceFileRef(); };
|
||||||
|
[[nodiscard]] QFile &sourceFileRef() const noexcept { return *m_fileSource; };
|
||||||
[[nodiscard]] const QString &desktopId() const noexcept { return m_desktopId; }
|
[[nodiscard]] const QString &desktopId() const noexcept { return m_desktopId; }
|
||||||
[[nodiscard]] bool persistence() const noexcept { return m_isPersistence; }
|
|
||||||
[[nodiscard]] bool modified(std::size_t time) const noexcept;
|
[[nodiscard]] bool modified(std::size_t time) const noexcept;
|
||||||
|
|
||||||
static std::optional<DesktopFile> searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept;
|
static std::optional<DesktopFile> searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept;
|
||||||
static std::optional<DesktopFile> searchDesktopFileByPath(const QString &desktopFilePath, DesktopErrorCode &err) noexcept;
|
static std::optional<DesktopFile> searchDesktopFileByPath(const QString &desktopFilePath, DesktopErrorCode &err) noexcept;
|
||||||
static std::optional<DesktopFile> createTemporaryDesktopFile(QString content) noexcept;
|
static std::optional<DesktopFile> createTemporaryDesktopFile(std::unique_ptr<QFile> temporaryFile) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DesktopFile(bool persistence, QString &&source, QString &&fileId, std::size_t mtime)
|
DesktopFile(std::unique_ptr<QFile> source, QString fileId, std::size_t mtime)
|
||||||
: m_isPersistence(persistence)
|
: m_mtime(mtime)
|
||||||
, m_mtime(mtime)
|
|
||||||
, m_fileSource(std::move(source))
|
, m_fileSource(std::move(source))
|
||||||
, m_desktopId(std::move(fileId))
|
, m_desktopId(std::move(fileId))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_isPersistence;
|
|
||||||
std::size_t m_mtime;
|
std::size_t m_mtime;
|
||||||
QString m_fileSource{""};
|
std::unique_ptr<QFile> m_fileSource{nullptr};
|
||||||
QString m_desktopId{""};
|
QString m_desktopId{""};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DesktopFileGuard
|
||||||
|
{
|
||||||
|
DesktopFileGuard(const DesktopFileGuard &) = delete;
|
||||||
|
DesktopFileGuard(DesktopFileGuard &&other) noexcept
|
||||||
|
: fileRef(other.fileRef)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
DesktopFileGuard &operator=(const DesktopFileGuard &) = delete;
|
||||||
|
DesktopFileGuard &operator=(DesktopFileGuard &&) = delete;
|
||||||
|
|
||||||
|
explicit DesktopFileGuard(DesktopFile &file)
|
||||||
|
: fileRef(file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_open() { return fileRef.m_fileSource->open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text); }
|
||||||
|
~DesktopFileGuard()
|
||||||
|
{
|
||||||
|
if (fileRef.m_fileSource->isOpen()) {
|
||||||
|
fileRef.m_fileSource->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DesktopFile &fileRef;
|
||||||
|
};
|
||||||
|
|
||||||
class DesktopEntry
|
class DesktopEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -86,7 +119,7 @@ public:
|
|||||||
DesktopEntry &operator=(DesktopEntry &&) = default;
|
DesktopEntry &operator=(DesktopEntry &&) = default;
|
||||||
|
|
||||||
~DesktopEntry() = default;
|
~DesktopEntry() = default;
|
||||||
[[nodiscard]] DesktopErrorCode parse(const DesktopFile &file) noexcept;
|
[[nodiscard]] DesktopErrorCode parse(DesktopFile &file) noexcept;
|
||||||
[[nodiscard]] DesktopErrorCode parse(QTextStream &stream) noexcept;
|
[[nodiscard]] DesktopErrorCode parse(QTextStream &stream) noexcept;
|
||||||
[[nodiscard]] std::optional<QMap<QString, Value>> group(const QString &key) const noexcept;
|
[[nodiscard]] std::optional<QMap<QString, Value>> group(const QString &key) const noexcept;
|
||||||
[[nodiscard]] std::optional<Value> value(const QString &key, const QString &valueKey) const noexcept;
|
[[nodiscard]] std::optional<Value> value(const QString &key, const QString &valueKey) const noexcept;
|
||||||
@ -100,3 +133,5 @@ private:
|
|||||||
QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
|
QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const DesktopErrorCode &v);
|
QDebug operator<<(QDebug debug, const DesktopErrorCode &v);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
38
src/global.h
38
src/global.h
@ -19,6 +19,7 @@
|
|||||||
#include <QDBusObjectPath>
|
#include <QDBusObjectPath>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "constant.h"
|
#include "constant.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m_initFlag) {
|
if (!m_initFlag) {
|
||||||
qFatal() << "invoke init at first.";
|
qFatal("invoke init at first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_serverType) {
|
switch (m_serverType) {
|
||||||
@ -113,17 +114,17 @@ public:
|
|||||||
m_serverConnection.emplace(QDBusConnection::connectToBus(static_cast<QDBusConnection::BusType>(m_serverType),
|
m_serverConnection.emplace(QDBusConnection::connectToBus(static_cast<QDBusConnection::BusType>(m_serverType),
|
||||||
ApplicationManagerServerDBusName));
|
ApplicationManagerServerDBusName));
|
||||||
if (!m_serverConnection->isConnected()) {
|
if (!m_serverConnection->isConnected()) {
|
||||||
qFatal() << m_serverConnection->lastError();
|
qFatal("%s", m_serverConnection->lastError().message().toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
return m_serverConnection.value();
|
return m_serverConnection.value();
|
||||||
}
|
}
|
||||||
case DBusType::Custom: {
|
case DBusType::Custom: {
|
||||||
if (m_serverBusAddress.isEmpty()) {
|
if (m_serverBusAddress.isEmpty()) {
|
||||||
qFatal() << "connect to custom dbus must init this object by custom dbus address";
|
qFatal("connect to custom dbus must init this object by custom dbus address");
|
||||||
}
|
}
|
||||||
m_serverConnection.emplace(QDBusConnection::connectToBus(m_serverBusAddress, ApplicationManagerServerDBusName));
|
m_serverConnection.emplace(QDBusConnection::connectToBus(m_serverBusAddress, ApplicationManagerServerDBusName));
|
||||||
if (!m_serverConnection->isConnected()) {
|
if (!m_serverConnection->isConnected()) {
|
||||||
qFatal() << m_serverConnection->lastError();
|
qFatal("%s", m_serverConnection->lastError().message().toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
return m_serverConnection.value();
|
return m_serverConnection.value();
|
||||||
}
|
}
|
||||||
@ -140,7 +141,7 @@ public:
|
|||||||
QDBusConnection &globalDestBus()
|
QDBusConnection &globalDestBus()
|
||||||
{
|
{
|
||||||
if (!m_destConnection) {
|
if (!m_destConnection) {
|
||||||
qFatal() << "please set which bus should application manager to use to invoke other D-Bus service's method.";
|
qFatal("please set which bus should application manager to use to invoke other D-Bus service's method.");
|
||||||
}
|
}
|
||||||
return m_destConnection.value();
|
return m_destConnection.value();
|
||||||
}
|
}
|
||||||
@ -157,18 +158,18 @@ public:
|
|||||||
m_destConnection.emplace(
|
m_destConnection.emplace(
|
||||||
QDBusConnection::connectToBus(QDBusConnection::BusType::SessionBus, ApplicationManagerDestDBusName));
|
QDBusConnection::connectToBus(QDBusConnection::BusType::SessionBus, ApplicationManagerDestDBusName));
|
||||||
if (!m_destConnection->isConnected()) {
|
if (!m_destConnection->isConnected()) {
|
||||||
qFatal() << m_destConnection->lastError();
|
qFatal("%s", m_destConnection->lastError().message().toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_destBusAddress.isEmpty()) {
|
if (m_destBusAddress.isEmpty()) {
|
||||||
qFatal() << "connect to custom dbus must init this object by custom dbus address";
|
qFatal("connect to custom dbus must init this object by custom dbus address");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_destConnection.emplace(QDBusConnection::connectToBus(m_destBusAddress, ApplicationManagerDestDBusName));
|
m_destConnection.emplace(QDBusConnection::connectToBus(m_destBusAddress, ApplicationManagerDestDBusName));
|
||||||
if (!m_destConnection->isConnected()) {
|
if (!m_destConnection->isConnected()) {
|
||||||
qFatal() << m_destConnection->lastError();
|
qFatal("%s", m_destConnection->lastError().message().toLocal8Bit().data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,4 +375,25 @@ ObjectMap dumpDBusObject(const QMap<QDBusObjectPath, QSharedPointer<T>> &map)
|
|||||||
return objs;
|
return objs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::size_t getFileModifiedTime(QFile &file)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
QFileInfo info{file};
|
||||||
|
|
||||||
|
if (!file.isOpen()) {
|
||||||
|
if (auto ret = file.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text); !ret) {
|
||||||
|
qWarning() << "open file" << info.absoluteFilePath() << "failed.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto ret = stat(info.absoluteFilePath().toLocal8Bit().data(), &buf); ret == -1) {
|
||||||
|
qWarning() << "get file" << info.absoluteFilePath() << "state failed:" << std::strerror(errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::size_t secToNano = 1e9;
|
||||||
|
return buf.st_mtim.tv_sec * secToNano + buf.st_mtim.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,8 +32,8 @@ public:
|
|||||||
bus.setDestBus();
|
bus.setDestBus();
|
||||||
|
|
||||||
m_am = new ApplicationManager1Service{std::make_unique<CGroupsIdentifier>(), bus.globalServerBus()};
|
m_am = new ApplicationManager1Service{std::make_unique<CGroupsIdentifier>(), bus.globalServerBus()};
|
||||||
|
auto ptr = std::make_unique<QFile>(QString{"/usr/share/applications/test-Application.desktop"});
|
||||||
DesktopFile file{true, "/usr/share/applications/test-Application.desktop", "test-Application", 0};
|
DesktopFile file{std::move(ptr), "test-Application", 0};
|
||||||
QSharedPointer<ApplicationService> app = QSharedPointer<ApplicationService>::create(std::move(file), nullptr);
|
QSharedPointer<ApplicationService> app = QSharedPointer<ApplicationService>::create(std::move(file), nullptr);
|
||||||
QSharedPointer<InstanceService> instance =
|
QSharedPointer<InstanceService> instance =
|
||||||
QSharedPointer<InstanceService>::create(InstancePath.path().split('/').last(), ApplicationPath.path(), QString{"/"});
|
QSharedPointer<InstanceService>::create(InstancePath.path().split('/').last(), ApplicationPath.path(), QString{"/"});
|
||||||
|
@ -45,7 +45,7 @@ TEST_F(TestDesktopEntry, desktopFile)
|
|||||||
auto curDir = QDir::current();
|
auto curDir = QDir::current();
|
||||||
QString path{curDir.absolutePath() + QDir::separator() + "data" + QDir::separator() + "applications" + QDir::separator() +
|
QString path{curDir.absolutePath() + QDir::separator() + "data" + QDir::separator() + "applications" + QDir::separator() +
|
||||||
"deepin-editor.desktop"};
|
"deepin-editor.desktop"};
|
||||||
EXPECT_EQ(exampleFile->fileSource().toStdString(), path.toStdString());
|
EXPECT_EQ(exampleFile->sourcePath(), path);
|
||||||
EXPECT_EQ(exampleFile->desktopId().toStdString(), "deepin-editor");
|
EXPECT_EQ(exampleFile->desktopId().toStdString(), "deepin-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ TEST_F(TestDesktopEntry, prase)
|
|||||||
const auto &exampleFile = file();
|
const auto &exampleFile = file();
|
||||||
ASSERT_FALSE(exampleFile.isNull());
|
ASSERT_FALSE(exampleFile.isNull());
|
||||||
DesktopEntry entry;
|
DesktopEntry entry;
|
||||||
QFile in{exampleFile->fileSource()};
|
QFile in{exampleFile->sourcePath()};
|
||||||
ASSERT_TRUE(in.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text));
|
ASSERT_TRUE(in.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text));
|
||||||
QTextStream fs{&in};
|
QTextStream fs{&in};
|
||||||
auto err = entry.parse(fs);
|
auto err = entry.parse(fs);
|
||||||
|
Loading…
Reference in New Issue
Block a user