refact: change implementation of UpdateApplicationInfo

adjust the way of get XDG_DATA_DIRS.

Signed-off-by: ComixHe <heyuming@deepin.org>
Signed-off-by: black-desk <me@black-desk.cn>
This commit is contained in:
ComixHe 2023-08-11 17:46:46 +08:00 committed by Comix
parent 5183716873
commit 2fa74e40e5
10 changed files with 179 additions and 169 deletions

View File

@ -3,7 +3,7 @@
<interface name="org.desktopspec.ApplicationManager1"> <interface name="org.desktopspec.ApplicationManager1">
<property type="ao" access="read" name="List" /> <property type="ao" access="read" name="List" />
<method name="UpdateApplicationInfo"> <method name="UpdateApplicationInfo">
<arg type="as" name="app_id" direction="in" /> <arg type="as" name="app_ids" direction="in" />
<annotation <annotation
name="org.freedesktop.DBus.Description" name="org.freedesktop.DBus.Description"
value="This method is used to update the desktop file cache when needed. value="This method is used to update the desktop file cache when needed.

View File

@ -28,21 +28,11 @@ int main(int argc, char *argv[])
registerComplexDbusType(); registerComplexDbusType();
ApplicationManager1Service AMService{std::make_unique<CGroupsIdentifier>(), AMBus}; ApplicationManager1Service AMService{std::make_unique<CGroupsIdentifier>(), AMBus};
QList<DesktopFile> fileList{}; QList<DesktopFile> fileList{};
QByteArray XDGDataDirs; auto desktopFileDirs = getXDGDataDirs();
XDGDataDirs = qgetenv("XDG_DATA_DIRS");
if (XDGDataDirs.isEmpty()) {
XDGDataDirs.append("/usr/local/share/:/usr/share/");
qputenv("XDG_DATA_DIRS", XDGDataDirs);
}
auto desktopFileDirs = QString::fromLocal8Bit(XDGDataDirs).split(':', Qt::SkipEmptyParts);
std::for_each(desktopFileDirs.begin(), desktopFileDirs.end(), [](QString &str) {
str = QDir::cleanPath(str) + QDir::separator() + "applications";
});
applyIteratively(QList<QDir>(desktopFileDirs.begin(), desktopFileDirs.end()), [&AMService](const QFileInfo &info) -> bool { applyIteratively(QList<QDir>(desktopFileDirs.begin(), desktopFileDirs.end()), [&AMService](const QFileInfo &info) -> bool {
ParseError err{ParseError::NoError}; DesktopErrorCode err{DesktopErrorCode::NoError};
auto ret = DesktopFile::searchDesktopFile(info.absoluteFilePath(), err); auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
if (!ret.has_value()) { if (!ret.has_value()) {
qWarning() << "failed to search File:" << err; qWarning() << "failed to search File:" << err;
return false; return false;

View File

@ -132,9 +132,11 @@ QList<QDBusObjectPath> ApplicationManager1Service::list() const
void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application) void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application)
{ {
if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) {
unregisterObjectFromDBus(application.path()); unregisterObjectFromDBus(application.path());
m_applicationList.remove(application); m_applicationList.remove(application);
} }
}
void ApplicationManager1Service::removeAllApplication() void ApplicationManager1Service::removeAllApplication()
{ {
@ -221,80 +223,48 @@ QDBusObjectPath ApplicationManager1Service::Launch(const QString &id,
return value->Launch(actions, fields, options); return value->Launch(actions, fields, options);
} }
void ApplicationManager1Service::UpdateApplicationInfo(const QStringList &app_id) void ApplicationManager1Service::updateApplication(const QSharedPointer<ApplicationService> &destApp,
const DesktopFile &desktopFile) noexcept
{ {
auto XDGDataDirs = QString::fromLocal8Bit(qgetenv("XDG_DATA_DIRS")).split(':', Qt::SkipEmptyParts);
std::for_each(XDGDataDirs.begin(), XDGDataDirs.end(), [](QString &str) {
if (!str.endsWith(QDir::separator())) {
str.append(QDir::separator());
}
str.append("applications");
});
for (auto id : app_id) {
auto destApp = std::find_if(m_applicationList.begin(),
m_applicationList.end(),
[&id](const QSharedPointer<ApplicationService> &value) { return value->id() == id; });
if (destApp == m_applicationList.end()) { // new app
qInfo() << "add a new application:" << id;
do {
for (const auto &suffix : XDGDataDirs) {
QFileInfo info{suffix + id};
if (info.exists()) {
ParseError err;
auto file = DesktopFile::searchDesktopFile(info.absoluteFilePath(), err);
if (!file.has_value()) {
continue;
}
if (!addApplication(std::move(file).value())) {
id.clear();
break;
}
}
}
if (id.isEmpty()) {
break;
}
auto hyphenIndex = id.indexOf('-');
if (hyphenIndex == -1) {
break;
}
id[hyphenIndex] = QDir::separator();
} while (true);
} else { // remove or update
if (!(*destApp)->m_isPersistence) [[unlikely]] {
continue;
}
auto filePath = (*destApp)->m_desktopSource.m_file.filePath();
if (QFileInfo::exists(filePath)) { // update
qInfo() << "update application:" << id;
struct stat buf; struct stat buf;
if (auto ret = stat(filePath.toLatin1().data(), &buf); ret == -1) { const auto *filePath = desktopFile.filePath().toLocal8Bit().data();
qWarning() << "get file" << filePath << "state failed:" << std::strerror(errno) << ", skip..."; 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->m_desktopSource.m_file.modified(buf.st_mtim.tv_sec * secToNano + buf.st_mtim.tv_nsec)) {
auto newEntry = new DesktopEntry{};
auto err = newEntry->parse(destApp->m_desktopSource.m_file);
if (err != DesktopErrorCode::NoError and err != DesktopErrorCode::EntryKeyInvalid) {
qWarning() << "update desktop file failed:" << err << ", content wouldn't change.";
return;
}
destApp->m_entry.reset(newEntry);
}
}
void ApplicationManager1Service::UpdateApplicationInfo(const QStringList &appIdList)
{
for (const auto &appId : appIdList) {
DesktopErrorCode err{DesktopErrorCode::NotFound};
auto file = DesktopFile::searchDesktopFileById(appId, err);
auto destApp = std::find_if(m_applicationList.cbegin(),
m_applicationList.cend(),
[&appId](const QSharedPointer<ApplicationService> &app) { return appId == app->id(); });
if (err == DesktopErrorCode::NotFound) {
removeOneApplication(destApp.key());
continue; continue;
} }
if ((*destApp)->m_desktopSource.m_file.modified( if (destApp != m_applicationList.cend()) {
static_cast<std::size_t>(buf.st_mtim.tv_sec * 1e9 + buf.st_mtim.tv_nsec))) { updateApplication(destApp.value(), file.value());
auto newEntry = new DesktopEntry{};
auto err = newEntry->parse((*destApp)->m_desktopSource.m_file);
if (err != ParseError::NoError and err != ParseError::EntryKeyInvalid) {
qWarning() << "update desktop file failed:" << err << ", content wouldn't change.";
continue; continue;
} }
(*destApp)->m_entry.reset(newEntry);
} addApplication(std::move(file).value());
} else { // remove
qInfo() << "remove application:" << id;
removeOneApplication((*destApp)->m_applicationPath);
}
}
} }
} }

View File

@ -48,13 +48,15 @@ public:
void removeOneApplication(const QDBusObjectPath &application); void removeOneApplication(const QDBusObjectPath &application);
void removeAllApplication(); void removeAllApplication();
void updateApplication(const QSharedPointer<ApplicationService> &deskApp, const DesktopFile &desktopFile) noexcept;
JobManager1Service &jobManager() noexcept { return *m_jobManager; } JobManager1Service &jobManager() noexcept { return *m_jobManager; }
public Q_SLOTS: public Q_SLOTS:
[[nodiscard]] QDBusObjectPath Application(const QString &id) const; [[nodiscard]] QDBusObjectPath Application(const QString &id) const;
QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance); QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance);
QDBusObjectPath Launch(const QString &id, const QString &action, const QStringList &fields, const QVariantMap &options); QDBusObjectPath Launch(const QString &id, const QString &action, const QStringList &fields, const QVariantMap &options);
void UpdateApplicationInfo(const QStringList &app_id); void UpdateApplicationInfo(const QStringList &appIdList);
private: private:
std::unique_ptr<Identifier> m_identifier; std::unique_ptr<Identifier> m_identifier;

View File

@ -30,7 +30,7 @@ public:
ApplicationService &operator=(const ApplicationService &) = delete; ApplicationService &operator=(const ApplicationService &) = delete;
ApplicationService &operator=(ApplicationService &&) = delete; ApplicationService &operator=(ApplicationService &&) = delete;
Q_PROPERTY(QStringList Actions READ actions CONSTANT) Q_PROPERTY(QStringList Actions READ actions)
[[nodiscard]] QStringList actions() const noexcept; [[nodiscard]] QStringList actions() const noexcept;
Q_PROPERTY(QString ID READ id CONSTANT) Q_PROPERTY(QString ID READ id CONSTANT)
@ -89,8 +89,8 @@ private:
sourceStream.setString(&m_desktopSource.m_temp, QTextStream::ReadOnly | QTextStream::Text); sourceStream.setString(&m_desktopSource.m_temp, QTextStream::ReadOnly | QTextStream::Text);
} }
m_entry.reset(new DesktopEntry()); m_entry.reset(new DesktopEntry());
if (auto error = m_entry->parse(sourceStream); error != ParseError::NoError) { if (auto error = m_entry->parse(sourceStream); error != DesktopErrorCode::NoError) {
if (error != ParseError::EntryKeyInvalid) { if (error != DesktopErrorCode::EntryKeyInvalid) {
m_entry.reset(nullptr); m_entry.reset(nullptr);
return; return;
} }

View File

@ -23,10 +23,10 @@ auto DesktopEntry::parserGroupHeader(const QString &str) noexcept
return it; return it;
} }
ParseError DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator &currentGroup) noexcept DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator &currentGroup) noexcept
{ {
if (str.startsWith("#")) { if (str.startsWith("#")) {
return ParseError::NoError; return DesktopErrorCode::NoError;
} }
auto splitCharIndex = str.indexOf(']'); auto splitCharIndex = str.indexOf(']');
@ -57,7 +57,7 @@ ParseError DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::it
auto matcher = re.match(keyStr); auto matcher = re.match(keyStr);
if (!matcher.hasMatch()) { if (!matcher.hasMatch()) {
qWarning() << "invalid key: " << keyStr; qWarning() << "invalid key: " << keyStr;
return ParseError::EntryKeyInvalid; return DesktopErrorCode::EntryKeyInvalid;
} }
key = matcher.captured("MainKey"); key = matcher.captured("MainKey");
@ -69,110 +69,122 @@ ParseError DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::it
auto cur = currentGroup->find(key); auto cur = currentGroup->find(key);
if (cur == currentGroup->end()) { if (cur == currentGroup->end()) {
currentGroup->insert(keyStr, {{valueKey, valueStr}}); currentGroup->insert(keyStr, {{valueKey, valueStr}});
return ParseError::NoError; return DesktopErrorCode::NoError;
} }
auto value = cur->find(valueKey); auto value = cur->find(valueKey);
if (value == cur->end()) { if (value == cur->end()) {
cur->insert(valueKey, valueStr); cur->insert(valueKey, valueStr);
return ParseError::NoError; return DesktopErrorCode::NoError;
} }
qWarning() << "duplicated postfix and this line will be aborted, maybe format is invalid.\n" qWarning() << "duplicated postfix and this line will be aborted, maybe format is invalid.\n"
<< "exist: " << value.key() << "[" << value.value() << "]" << "exist: " << value.key() << "[" << value.value() << "]"
<< "current: " << str; << "current: " << str;
return ParseError::NoError; return DesktopErrorCode::NoError;
} }
std::optional<DesktopFile> DesktopFile::searchDesktopFile(const QString &desktopFile, ParseError &err) noexcept std::optional<DesktopFile> DesktopFile::searchDesktopFileByPath(const QString &desktopFile, DesktopErrorCode &err) noexcept
{ {
if (auto tmp = desktopFile.split("."); tmp.last() != "desktop") { constexpr decltype(auto) desktopPostfix = ".desktop";
qWarning() << "file isn't a desktop file";
err = ParseError::MismatchedFile; if (!desktopFile.endsWith(desktopPostfix)) {
qWarning() << "file isn't a desktop file:" << desktopFile;
err = DesktopErrorCode::MismatchedFile;
return std::nullopt; return std::nullopt;
} }
QString path; QFileInfo fileinfo{desktopFile};
if (!fileinfo.isAbsolute() or !fileinfo.exists()) {
qWarning() << "desktop file not found.";
err = DesktopErrorCode::NotFound;
return std::nullopt;
}
QString path{desktopFile};
QString id; QString id;
QFileInfo Fileinfo{desktopFile}; const auto &XDGDataDirs = getXDGDataDirs();
if (Fileinfo.isAbsolute() and Fileinfo.exists()) { auto idGen = std::any_of(XDGDataDirs.cbegin(), XDGDataDirs.cend(), [&desktopFile](const QString &suffixPath) {
path = desktopFile; return desktopFile.startsWith(suffixPath);
} else {
auto XDGDataDirs = QString::fromLocal8Bit(qgetenv("XDG_DATA_DIRS")).split(':', Qt::SkipEmptyParts);
std::for_each(XDGDataDirs.begin(), XDGDataDirs.end(), [](QString &str) {
str = QDir::cleanPath(str) + QDir::separator() + "applications";
}); });
auto fileName = Fileinfo.fileName();
applyIteratively(QList<QDir>{XDGDataDirs.begin(), XDGDataDirs.end()}, [&fileName, &path](const QFileInfo &file) -> bool { if (idGen) {
if (file.fileName() == fileName) { auto tmp = path.chopped(sizeof(desktopPostfix) - 1);
path = file.absoluteFilePath();
return true;
}
return false;
});
}
if (path.isEmpty()) {
qWarning() << "desktop file not found.";
err = ParseError::NotFound;
return std::nullopt;
}
auto tmp = path.chopped(8); // remove ".desktop"
auto components = tmp.split(QDir::separator()).toList(); auto components = tmp.split(QDir::separator()).toList();
auto it = std::find(components.cbegin(), components.cend(), "applications"); auto it = std::find(components.cbegin(), components.cend(), "applications");
if (it == components.cend()) {
qWarning() << "custom location detected, Id wouldn't be generated.";
} else {
QString FileId; QString FileId;
++it; ++it;
while (it != components.cend()) while (it != components.cend()) {
FileId += (*(it++) + "-"); FileId += (*(it++) + "-");
}
id = FileId.chopped(1); // remove extra "-"" id = FileId.chopped(1); // remove extra "-""
} }
struct stat buf; struct stat buf;
if (auto ret = stat(path.toLatin1().data(), &buf); ret == -1) { if (auto ret = stat(path.toLatin1().data(), &buf); ret == -1) {
err = ParseError::OpenFailed; err = DesktopErrorCode::OpenFailed;
qWarning() << "get file" << path << "state failed:" << std::strerror(errno); qWarning() << "get file" << path << "state failed:" << std::strerror(errno);
return std::nullopt; return std::nullopt;
} }
err = ParseError::NoError; err = DesktopErrorCode::NoError;
constexpr std::size_t nanoToSec = 1e9; constexpr std::size_t nanoToSec = 1e9;
return DesktopFile{std::move(path), std::move(id), buf.st_mtim.tv_sec * nanoToSec + buf.st_mtim.tv_nsec}; return DesktopFile{std::move(path), std::move(id), buf.st_mtim.tv_sec * nanoToSec + buf.st_mtim.tv_nsec};
} }
std::optional<DesktopFile> DesktopFile::searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept
{
auto XDGDataDirs = getXDGDataDirs();
for (const auto &dir : XDGDataDirs) {
auto app = QFileInfo{dir + QDir::separator() + appId};
while (!app.exists()) {
auto filePath = app.absoluteFilePath();
auto hyphenIndex = filePath.indexOf('-');
if (hyphenIndex == -1) {
break;
}
filePath.replace(hyphenIndex, 1, QDir::separator());
app.setFile(filePath);
}
if (app.exists()) {
return searchDesktopFileByPath(app.absoluteFilePath(), err);
}
}
return std::nullopt;
}
bool DesktopFile::modified(std::size_t time) const noexcept bool DesktopFile::modified(std::size_t time) const noexcept
{ {
return time != m_mtime; return time != m_mtime;
} }
ParseError DesktopEntry::parse(const DesktopFile &desktopFile) noexcept DesktopErrorCode DesktopEntry::parse(const DesktopFile &appId) noexcept
{ {
auto file = QFile(desktopFile.filePath()); auto file = QFile(appId.filePath());
if (!file.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) { if (!file.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
qWarning() << desktopFile.filePath() << "can't open."; qWarning() << appId.filePath() << "can't open.";
return ParseError::OpenFailed; return DesktopErrorCode::OpenFailed;
} }
QTextStream in{&file}; QTextStream in{&file};
return parse(in); return parse(in);
} }
ParseError DesktopEntry::parse(QTextStream &stream) noexcept DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept
{ {
if (stream.atEnd()) { if (stream.atEnd()) {
return ParseError::OpenFailed; return DesktopErrorCode::OpenFailed;
} }
stream.setEncoding(QStringConverter::Utf8); stream.setEncoding(QStringConverter::Utf8);
decltype(m_entryMap)::iterator currentGroup; decltype(m_entryMap)::iterator currentGroup;
ParseError err{ParseError::NoError}; DesktopErrorCode err{DesktopErrorCode::NoError};
while (!stream.atEnd()) { while (!stream.atEnd()) {
auto line = stream.readLine().trimmed(); auto line = stream.readLine().trimmed();
@ -182,13 +194,13 @@ ParseError DesktopEntry::parse(QTextStream &stream) noexcept
if (line.startsWith("[")) { if (line.startsWith("[")) {
if (!line.endsWith("]")) { if (!line.endsWith("]")) {
return ParseError::GroupHeaderInvalid; return DesktopErrorCode::GroupHeaderInvalid;
} }
currentGroup = parserGroupHeader(line); currentGroup = parserGroupHeader(line);
continue; continue;
} }
if (auto error = parseEntry(line, currentGroup); error != ParseError::NoError) { if (auto error = parseEntry(line, currentGroup); error != DesktopErrorCode::NoError) {
err = error; err = error;
qWarning() << "an error occurred,this line will be skipped:" << line; qWarning() << "an error occurred,this line will be skipped:" << line;
} }
@ -329,36 +341,36 @@ QDebug operator<<(QDebug debug, const DesktopEntry::Value &v)
return debug; return debug;
} }
QDebug operator<<(QDebug debug, const ParseError &v) QDebug operator<<(QDebug debug, const DesktopErrorCode &v)
{ {
QDebugStateSaver saver{debug}; QDebugStateSaver saver{debug};
QString errMsg; QString errMsg;
switch (v) { switch (v) {
case ParseError::NoError: { case DesktopErrorCode::NoError: {
errMsg = "no error."; errMsg = "no error.";
break; break;
} }
case ParseError::NotFound: { case DesktopErrorCode::NotFound: {
errMsg = "file not found."; errMsg = "file not found.";
break; break;
} }
case ParseError::MismatchedFile: { case DesktopErrorCode::MismatchedFile: {
errMsg = "file type is mismatched."; errMsg = "file type is mismatched.";
break; break;
} }
case ParseError::InvalidLocation: { case DesktopErrorCode::InvalidLocation: {
errMsg = "file location is invalid, please check $XDG_DATA_DIRS."; errMsg = "file location is invalid, please check $XDG_DATA_DIRS.";
break; break;
} }
case ParseError::OpenFailed: { case DesktopErrorCode::OpenFailed: {
errMsg = "couldn't open the file."; errMsg = "couldn't open the file.";
break; break;
} }
case ParseError::GroupHeaderInvalid: { case DesktopErrorCode::GroupHeaderInvalid: {
errMsg = "groupHead syntax is invalid."; errMsg = "groupHead syntax is invalid.";
break; break;
} }
case ParseError::EntryKeyInvalid: { case DesktopErrorCode::EntryKeyInvalid: {
errMsg = "key syntax is invalid."; errMsg = "key syntax is invalid.";
break; break;
} }

View File

@ -12,7 +12,15 @@
constexpr static auto defaultKeyStr = "default"; constexpr static auto defaultKeyStr = "default";
enum class ParseError { NoError, NotFound, MismatchedFile, InvalidLocation, OpenFailed, GroupHeaderInvalid, EntryKeyInvalid }; enum class DesktopErrorCode {
NoError,
NotFound,
MismatchedFile,
InvalidLocation,
OpenFailed,
GroupHeaderInvalid,
EntryKeyInvalid
};
struct DesktopFile struct DesktopFile
{ {
@ -25,7 +33,8 @@ struct DesktopFile
[[nodiscard]] const QString &filePath() const { return m_filePath; } [[nodiscard]] const QString &filePath() const { return m_filePath; }
[[nodiscard]] const QString &desktopId() const { return m_desktopId; } [[nodiscard]] const QString &desktopId() const { return m_desktopId; }
static std::optional<DesktopFile> searchDesktopFile(const QString &desktopFilePath, ParseError &err) noexcept; static std::optional<DesktopFile> searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept;
static std::optional<DesktopFile> searchDesktopFileByPath(const QString &desktopFilePath, DesktopErrorCode &err) noexcept;
[[nodiscard]] bool modified(std::size_t time) const noexcept; [[nodiscard]] bool modified(std::size_t time) const noexcept;
private: private:
@ -66,17 +75,17 @@ public:
DesktopEntry &operator=(DesktopEntry &&) = default; DesktopEntry &operator=(DesktopEntry &&) = default;
~DesktopEntry() = default; ~DesktopEntry() = default;
[[nodiscard]] ParseError parse(const DesktopFile &file) noexcept; [[nodiscard]] DesktopErrorCode parse(const DesktopFile &file) noexcept;
[[nodiscard]] ParseError 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;
private: private:
QMap<QString, QMap<QString, Value>> m_entryMap; QMap<QString, QMap<QString, Value>> m_entryMap;
auto parserGroupHeader(const QString &str) noexcept; auto parserGroupHeader(const QString &str) noexcept;
static ParseError parseEntry(const QString &str, decltype(m_entryMap)::iterator &currentGroup) noexcept; static DesktopErrorCode parseEntry(const QString &str, decltype(m_entryMap)::iterator &currentGroup) noexcept;
}; };
QDebug operator<<(QDebug debug, const DesktopEntry::Value &v); QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
QDebug operator<<(QDebug debug, const ParseError &v); QDebug operator<<(QDebug debug, const DesktopErrorCode &v);

View File

@ -25,13 +25,13 @@ using IconMap = QMap<QString, QMap<uint, QMap<QString, QDBusUnixFileDescriptor>>
inline QString getApplicationLauncherBinary() inline QString getApplicationLauncherBinary()
{ {
static const QString bin = []() -> QString { static const QString bin = []() {
auto value = qgetenv("DEEPIN_APPLICATION_MANAGER_APP_LAUNCH_HELPER_BIN"); auto value = qgetenv("DEEPIN_APPLICATION_MANAGER_APP_LAUNCH_HELPER_BIN");
if (value.isEmpty()) { if (value.isEmpty()) {
return ApplicationLaunchHelperBinary; return QString::fromLocal8Bit(ApplicationLaunchHelperBinary);
} }
qWarning() << "Using app launch helper defined in environment variable DEEPIN_APPLICATION_MANAGER_APP_LAUNCH_HELPER_BIN."; qWarning() << "Using app launch helper defined in environment variable DEEPIN_APPLICATION_MANAGER_APP_LAUNCH_HELPER_BIN.";
return value; return QString::fromLocal8Bit(value);
}(); }();
return bin; return bin;
} }
@ -303,4 +303,29 @@ inline QString getRelativePathFromAppId(const QString &id)
return path; return path;
} }
inline QStringList getXDGDataDirs()
{
const static auto XDGDataDirs = []() {
auto env = QString::fromLocal8Bit(qgetenv("XDG_DATA_DIRS")).split(':', Qt::SkipEmptyParts);
if (env.isEmpty()) {
env.append(QString{qgetenv("HOME")} + QDir::separator() + ".local/share");
env.append("/usr/local/share");
env.append("/usr/share");
qputenv("XDG_DATA_DIRS", env.join(':').toLocal8Bit());
}
std::for_each(env.begin(), env.end(), [](QString &str) {
if (!str.endsWith(QDir::separator())) {
str.append(QDir::separator());
}
str.append("applications");
});
return env;
}();
return XDGDataDirs;
}
#endif #endif

View File

@ -33,18 +33,20 @@ bool SystemdSignalDispatcher::connectToSignals() noexcept
void SystemdSignalDispatcher::onUnitNew(QString unitName, QDBusObjectPath systemdUnitPath) void SystemdSignalDispatcher::onUnitNew(QString unitName, QDBusObjectPath systemdUnitPath)
{ {
if (!unitName.startsWith("app-")) { constexpr decltype(auto) appPrefix = u8"app-";
if (!unitName.startsWith(appPrefix)) {
return; return;
} }
emit SystemdUnitNew(unitName.sliced(sizeof("app-") - 1), systemdUnitPath); emit SystemdUnitNew(unitName.sliced(sizeof(appPrefix) - 1), systemdUnitPath);
} }
void SystemdSignalDispatcher::onUnitRemoved(QString unitName, QDBusObjectPath systemdUnitPath) void SystemdSignalDispatcher::onUnitRemoved(QString unitName, QDBusObjectPath systemdUnitPath)
{ {
if (!unitName.startsWith("app-")) { constexpr decltype(auto) appPrefix = u8"app-";
if (!unitName.startsWith(appPrefix)) {
return; return;
} }
emit SystemdUnitRemoved(unitName.sliced(sizeof("app-") - 1), systemdUnitPath); emit SystemdUnitRemoved(unitName.sliced(sizeof(appPrefix) - 1), systemdUnitPath);
} }

View File

@ -17,8 +17,8 @@ public:
{ {
auto curDir = QDir::current(); auto curDir = QDir::current();
QString path{curDir.absolutePath() + "/data/desktopExample.desktop"}; QString path{curDir.absolutePath() + "/data/desktopExample.desktop"};
ParseError err; DesktopErrorCode err;
auto file = DesktopFile::searchDesktopFile(path, err); auto file = DesktopFile::searchDesktopFileByPath(path, err);
if (!file.has_value()) { if (!file.has_value()) {
qWarning() << "search " << path << "failed:" << err; qWarning() << "search " << path << "failed:" << err;
return; return;
@ -54,7 +54,7 @@ TEST_F(TestDesktopEntry, prase)
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);
ASSERT_EQ(err, ParseError::NoError); ASSERT_EQ(err, DesktopErrorCode::NoError);
auto group = entry.group("Desktop Entry"); auto group = entry.group("Desktop Entry");
ASSERT_TRUE(group); ASSERT_TRUE(group);