diff --git a/api/dbus/org.desktopspec.ApplicationManager1.Application.xml b/api/dbus/org.desktopspec.ApplicationManager1.Application.xml
index af2b1e7..5eec181 100644
--- a/api/dbus/org.desktopspec.ApplicationManager1.Application.xml
+++ b/api/dbus/org.desktopspec.ApplicationManager1.Application.xml
@@ -61,6 +61,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -84,38 +108,5 @@
This option might request a polikit authentication."
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/api/dbus/org.desktopspec.ObjectManager1.xml b/api/dbus/org.desktopspec.ObjectManager1.xml
index c1fbe2a..9c58842 100644
--- a/api/dbus/org.desktopspec.ObjectManager1.xml
+++ b/api/dbus/org.desktopspec.ObjectManager1.xml
@@ -2,13 +2,14 @@
-
+
-
+
+
diff --git a/apps/dde-application-manager/src/main.cpp b/apps/dde-application-manager/src/main.cpp
index 419a3ed..a5c33e4 100644
--- a/apps/dde-application-manager/src/main.cpp
+++ b/apps/dde-application-manager/src/main.cpp
@@ -19,7 +19,13 @@ void registerComplexDbusType()
qDBusRegisterMetaType>();
qDBusRegisterMetaType>>();
qDBusRegisterMetaType();
+ qRegisterMetaType();
+ qDBusRegisterMetaType();
+ qRegisterMetaType();
qDBusRegisterMetaType();
+ qDBusRegisterMetaType>();
+ qRegisterMetaType();
+ qDBusRegisterMetaType();
}
} // namespace
@@ -48,7 +54,7 @@ int main(int argc, char *argv[])
return false;
}
if (!AMService.addApplication(std::move(ret).value())) {
- qWarning() << "add Application failed:" << ret->sourcePath() << "skip...";
+ qWarning() << "add Application failed, skip...";
}
return false; // means to apply this function to the rest of the files
});
diff --git a/src/constant.h b/src/constant.h
index ccf5161..b85e92e 100644
--- a/src/constant.h
+++ b/src/constant.h
@@ -16,6 +16,7 @@ constexpr auto DDEApplicationManager1ServiceName =
#endif
constexpr auto DDEApplicationManager1ObjectPath = u8"/org/deepin/dde/ApplicationManager1";
+constexpr auto DDEAutoStartManager1ObjectPath = u8"/org/deepin/dde/AutoStartManager1";
constexpr auto DDEApplicationManager1JobManagerObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1";
constexpr auto DesktopFileEntryKey = u8"Desktop Entry";
constexpr auto DesktopFileActionKey = u8"Desktop Action ";
diff --git a/src/dbus/applicationmanager1service.cpp b/src/dbus/applicationmanager1service.cpp
index 0475795..57b6951 100644
--- a/src/dbus/applicationmanager1service.cpp
+++ b/src/dbus/applicationmanager1service.cpp
@@ -135,7 +135,7 @@ bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) n
return false;
}
m_applicationList.insert(application->applicationPath(), application);
- emit InterfacesAdded(application->applicationPath(), getInterfacesListFromObject(ptr));
+ emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr));
return true;
}
@@ -143,7 +143,7 @@ bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) n
void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application) noexcept
{
if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) {
- emit InterfacesRemoved(application, getInterfacesListFromObject(it->data()));
+ emit InterfacesRemoved(application, getChildInterfacesFromObject(it->data()));
unregisterObjectFromDBus(application.path());
m_applicationList.remove(application);
}
@@ -225,7 +225,7 @@ void ApplicationManager1Service::updateApplication(const QSharedPointerparse(destApp->desktopFileSource());
- if (err != DesktopErrorCode::NoError and err != DesktopErrorCode::EntryKeyInvalid) {
+ if (err != DesktopErrorCode::NoError) {
qWarning() << "update desktop file failed:" << err << ", content wouldn't change.";
return;
}
diff --git a/src/dbus/applicationmanager1service.h b/src/dbus/applicationmanager1service.h
index 4154efd..69276f0 100644
--- a/src/dbus/applicationmanager1service.h
+++ b/src/dbus/applicationmanager1service.h
@@ -46,7 +46,7 @@ public Q_SLOTS:
[[nodiscard]] ObjectMap GetManagedObjects() const;
Q_SIGNALS:
- void InterfacesAdded(const QDBusObjectPath &object_path, const QStringList &interfaces);
+ void InterfacesAdded(const QDBusObjectPath &object_path, const ObjectInterfaceMap &interfaces);
void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
private:
diff --git a/src/dbus/applicationservice.cpp b/src/dbus/applicationservice.cpp
index 1ea2dfb..fcc17d9 100644
--- a/src/dbus/applicationservice.cpp
+++ b/src/dbus/applicationservice.cpp
@@ -63,10 +63,8 @@ QSharedPointer ApplicationService::createApplicationService(
auto error = entry->parse(sourceStream);
if (error != DesktopErrorCode::NoError) {
- if (error != DesktopErrorCode::EntryKeyInvalid) {
- qWarning() << "parse failed:" << error;
- return nullptr;
- }
+ qWarning() << "parse failed:" << error << app->desktopFileSource().sourcePath();
+ return nullptr;
}
if (auto val = entry->value(DesktopFileEntryKey, "Hidden"); val.has_value()) {
@@ -89,110 +87,6 @@ QSharedPointer ApplicationService::createApplicationService(
return app;
}
-QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env) const
-{
- const auto &supportedActions = actions();
- if (supportedActions.isEmpty()) {
- return {};
- }
- if (auto index = supportedActions.indexOf(identifier); index == -1) {
- qWarning() << "can't find " << identifier << " in supported actions List.";
- return {};
- }
-
- const auto &actionHeader = QString{"%1%2"}.arg(DesktopFileActionKey, identifier);
- const auto &actionName = m_entry->value(actionHeader, "Name");
- if (!actionName) {
- return {};
- }
-
- QString locale{""};
- bool ok;
- if (!env.isEmpty()) {
- QString lcStr;
- for (const auto &lc : env) {
- if (lc.startsWith("LANG")) {
- locale = lc.split('=').last();
- }
-
- if (lc.startsWith("LC_ALL")) {
- locale = lc.split('=').last();
- break;
- }
- }
- }
-
- QLocale lc = locale.isEmpty() ? getUserLocale() : QLocale{locale};
-
- const auto &name = actionName->toLocaleString(lc, ok);
- if (!ok) {
- qWarning() << "convert to locale string failed, dest locale:" << lc;
- return {};
- }
- return name;
-}
-
-QString ApplicationService::GetDisplayName(const QStringList &env) const
-{
- const auto &displayName = m_entry->value(DesktopFileEntryKey, "Name");
- if (!displayName) {
- return {};
- }
-
- QString locale{""};
- bool ok;
- if (!env.isEmpty()) {
- QString lcStr;
- for (const auto &lc : env) {
- if (lc.startsWith("LANG")) {
- locale = lc.split('=').last();
- }
-
- if (lc.startsWith("LC_ALL")) {
- locale = lc.split('=').last();
- break;
- }
- }
- }
-
- QLocale lc = locale.isEmpty() ? getUserLocale() : QLocale{locale};
-
- const auto &name = displayName->toLocaleString(lc, ok);
- if (!ok) {
- qWarning() << "convert to locale string failed, dest locale:" << lc;
- return {};
- }
- return name;
-}
-
-QString ApplicationService::GetIconName(const QString &action) const
-{
- std::optional iconName{std::nullopt};
-
- if (action.isEmpty()) {
- iconName = m_entry->value(DesktopFileEntryKey, "Icon");
-
- } else {
- const auto &supportedActions = actions();
-
- if (auto index = supportedActions.indexOf(action); index == -1) {
- qWarning() << "can't find " << action << " in supported actions List.";
- return {};
- }
-
- const auto &actionHeader = QString{"%1%2"}.arg(DesktopFileActionKey, action);
- iconName = m_entry->value(actionHeader, "Icon");
- }
-
- if (!iconName) {
- return {};
- }
-
- bool ok{false};
- const auto &name = iconName->toIconString(ok);
- return ok ? name : "";
-}
-
QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options)
{
QString execStr;
@@ -325,12 +219,55 @@ QStringList ApplicationService::actions() const noexcept
return {};
}
- auto actionList = str.split(";");
- actionList.removeAll("");
-
+ auto actionList = str.split(";", Qt::SkipEmptyParts);
return actionList;
}
+PropMap ApplicationService::actionName() const noexcept
+{
+ PropMap ret;
+ auto actionList = actions();
+
+ for (auto &action : actionList) {
+ action.prepend(DesktopFileActionKey);
+ auto value = m_entry->value(action, "Name");
+ if (!value.has_value()) {
+ continue;
+ }
+ ret.insert(action, {std::move(value).value()});
+ }
+
+ return ret;
+}
+
+PropMap ApplicationService::displayName() const noexcept
+{
+ PropMap ret;
+ auto value = std::move(m_entry->value(DesktopFileEntryKey, "Name")).value();
+ ret.insert(QString{"Name"}, {std::move(value)});
+ return ret;
+}
+
+PropMap ApplicationService::iconName() const noexcept
+{
+ PropMap ret;
+ auto actionList = actions();
+ for (const auto &action : actionList) {
+ auto value = m_entry->value(QString{action}.prepend(DesktopFileActionKey), "Icon");
+ if (!value.has_value()) {
+ continue;
+ }
+ ret.insert(action, {std::move(value).value()});
+ }
+
+ auto mainIcon = m_entry->value(DesktopFileEntryKey, "Icon");
+ if (mainIcon.has_value()) {
+ ret.insert(defaultKeyStr, {std::move(mainIcon).value()});
+ }
+
+ return ret;
+}
+
ObjectMap ApplicationService::GetManagedObjects() const
{
return dumpDBusObject(m_Instances);
@@ -384,7 +321,7 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
m_Instances.insert(QDBusObjectPath{objectPath}, QSharedPointer{service});
service->moveToThread(this->thread());
adaptor->moveToThread(this->thread());
- emit InterfacesAdded(QDBusObjectPath{objectPath}, getInterfacesListFromObject(service));
+ emit InterfacesAdded(QDBusObjectPath{objectPath}, getChildInterfacesAndPropertiesFromObject(service));
return true;
}
@@ -396,7 +333,7 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
void ApplicationService::removeOneInstance(const QDBusObjectPath &instance) noexcept
{
if (auto it = m_Instances.find(instance); it != m_Instances.cend()) {
- emit InterfacesRemoved(instance, getInterfacesListFromObject(it->data()));
+ emit InterfacesRemoved(instance, getChildInterfacesFromObject(it->data()));
unregisterObjectFromDBus(instance.path());
m_Instances.remove(instance);
}
diff --git a/src/dbus/applicationservice.h b/src/dbus/applicationservice.h
index f49352a..c8f5a15 100644
--- a/src/dbus/applicationservice.h
+++ b/src/dbus/applicationservice.h
@@ -36,9 +36,18 @@ public:
Q_PROPERTY(QStringList Actions READ actions)
[[nodiscard]] QStringList actions() const noexcept;
+ Q_PROPERTY(PropMap ActionName READ actionName)
+ [[nodiscard]] PropMap actionName() const noexcept;
+
Q_PROPERTY(QString ID READ id CONSTANT)
[[nodiscard]] QString id() const noexcept;
+ Q_PROPERTY(PropMap DisplayName READ displayName)
+ [[nodiscard]] PropMap displayName() const noexcept;
+
+ Q_PROPERTY(PropMap IconName READ iconName)
+ [[nodiscard]] PropMap iconName() const noexcept;
+
Q_PROPERTY(qulonglong LastLaunchedTime READ lastLaunchedTime)
[[nodiscard]] qulonglong lastLaunchedTime() const noexcept;
@@ -71,14 +80,11 @@ public:
void resetEntry(DesktopEntry *newEntry) noexcept;
public Q_SLOTS:
- [[nodiscard]] QString GetActionName(const QString &identifier, const QStringList &env) const;
QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options);
- [[nodiscard]] QString GetIconName(const QString &action) const;
- [[nodiscard]] QString GetDisplayName(const QStringList &env) const;
[[nodiscard]] ObjectMap GetManagedObjects() const;
Q_SIGNALS:
- void InterfacesAdded(const QDBusObjectPath &object_path, const QStringList &interfaces);
+ void InterfacesAdded(const QDBusObjectPath &object_path, const ObjectInterfaceMap &interfaces);
void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
private:
diff --git a/src/desktopentry.cpp b/src/desktopentry.cpp
index 9a41816..199f2cc 100644
--- a/src/desktopentry.cpp
+++ b/src/desktopentry.cpp
@@ -17,26 +17,52 @@
auto DesktopEntry::parserGroupHeader(const QString &str) noexcept
{
- auto groupHeader = str.sliced(1, str.size() - 2);
- auto it = m_entryMap.find(groupHeader);
- if (it == m_entryMap.cend()) {
- return m_entryMap.insert(groupHeader, {});
+ auto groupHeader = str.sliced(1, str.size() - 2).trimmed();
+ decltype(m_entryMap)::iterator it{m_entryMap.end()};
+
+ QRegularExpression re{R"([^\x20-\x5a-\x5e-\x7e\x5c])"};
+ auto matcher = re.match(groupHeader);
+ if (matcher.hasMatch()) {
+ return it;
}
+
+ auto tmp = m_entryMap.find(groupHeader);
+ if (tmp == m_entryMap.end()) {
+ it = m_entryMap.insert(groupHeader, {});
+ }
+
return it;
}
QString DesktopFile::sourcePath() const noexcept
{
+ if (!m_fileSource) {
+ return "";
+ }
+
QFileInfo info(*m_fileSource);
return info.absoluteFilePath();
}
-DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept
+bool DesktopEntry::isInvalidLocaleString(const QString &str) noexcept
{
- if (str.startsWith("#")) {
- return DesktopErrorCode::NoError;
- }
+ constexpr auto Language = R"((?:[a-z]+))"; // language of locale postfix. eg.(en, zh)
+ constexpr auto Country = R"((?:_[A-Z]+))"; // country of locale postfix. eg.(US, CN)
+ constexpr auto Encoding = R"((?:\.[0-9A-Z-]+))"; // encoding of locale postfix. eg.(UFT-8)
+ constexpr auto Modifier = R"((?:@[a-z=;]+))"; // modifier of locale postfix. eg.(euro;collation=traditional)
+ const static auto validKey = QString(R"(^%1%2?%3?%4?$)").arg(Language, Country, Encoding, Modifier);
+ // example: https://regex101.com/r/hylOay/2
+ static QRegularExpression re = []() -> QRegularExpression {
+ QRegularExpression tmp{validKey};
+ tmp.optimize();
+ return tmp;
+ }();
+ return re.match(str).hasMatch();
+}
+
+QPair DesktopEntry::processEntry(const QString &str) noexcept
+{
auto splitCharIndex = str.indexOf(']');
if (splitCharIndex != -1) {
for (; splitCharIndex < str.size(); ++splitCharIndex) {
@@ -49,56 +75,97 @@ DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMa
}
auto keyStr = str.first(splitCharIndex).trimmed();
auto valueStr = str.sliced(splitCharIndex + 1).trimmed();
+ return qMakePair(std::move(keyStr), std::move(valueStr));
+}
+
+std::optional> DesktopEntry::processEntryKey(const QString &keyStr) noexcept
+{
QString key;
- QString valueKey{defaultKeyStr};
-
- constexpr auto MainKey = R"re((?[0-9a-zA-Z-]+))re"; // main key. eg.(Name, X-CUSTOM-KEY).
- constexpr auto Language = R"re((?:[a-z]+))re"; // language of locale postfix. eg.(en, zh)
- constexpr auto Country = R"re((?:_[A-Z]+))re"; // country of locale postfix. eg.(US, CN)
- constexpr auto Encoding = R"re((?:\.[0-9A-Z-]+))re"; // encoding of locale postfix. eg.(UFT-8)
- constexpr auto Modifier = R"re((?:@[a-z=;]+))re"; // modifier of locale postfix. eg(euro;collation=traditional)
- const static auto validKey =
- QString("^%1(?:\\[(?%2%3?%4?%5?)\\])?$").arg(MainKey).arg(Language).arg(Country).arg(Encoding).arg(Modifier);
- // example: https://regex101.com/r/hylOay/1
- static QRegularExpression re = []() -> QRegularExpression {
- QRegularExpression tmp{validKey};
- tmp.optimize();
- return tmp;
- }();
-
- auto matcher = re.match(keyStr);
- if (!matcher.hasMatch()) {
-#ifdef DEBUG_MODE
- qWarning() << "invalid key: " << keyStr;
-#endif
- return DesktopErrorCode::EntryKeyInvalid;
+ QString localeStr;
+ if (auto index = keyStr.indexOf('['); index != -1) {
+ key = keyStr.sliced(0, index);
+ localeStr = keyStr.sliced(index + 1, keyStr.length() - 1 - index - 1); // strip '[' and ']'
+ } else {
+ key = keyStr;
}
- key = matcher.captured("MainKey");
-
- if (auto locale = matcher.captured("LOCALE"); !locale.isEmpty()) {
- valueKey = locale;
+ QRegularExpression re{"R([^A-Za-z0-9-])"};
+ if (re.match(key).hasMatch()) {
+ qWarning() << "keyName's format is invalid.";
+ return std::nullopt;
}
- auto cur = currentGroup->find(key);
- if (cur == currentGroup->end()) {
- currentGroup->insert(keyStr, {{valueKey, valueStr}});
+ return qMakePair(std::move(key), std::move(localeStr));
+}
+
+DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept
+{
+ auto [key, value] = processEntry(str);
+ auto keyPair = processEntryKey(key);
+
+ if (!keyPair.has_value()) {
+ return DesktopErrorCode::InvalidFormat;
+ }
+
+ auto [keyName, localeStr] = std::move(keyPair).value();
+ if (localeStr.isEmpty()) {
+ localeStr = defaultKeyStr;
+ }
+
+ auto valueIt = currentGroup->find(keyName);
+ if (valueIt == currentGroup->end()) {
+ currentGroup->insert(keyName, {{localeStr, value}});
return DesktopErrorCode::NoError;
}
- auto value = cur->find(valueKey);
- if (value == cur->end()) {
- cur->insert(valueKey, valueStr);
+ auto innerIt = valueIt->find(localeStr);
+ if (innerIt == valueIt->end()) {
+ valueIt->insert(localeStr, value);
return DesktopErrorCode::NoError;
}
qWarning() << "duplicated postfix and this line will be aborted, maybe format is invalid.\n"
- << "exist: " << value.key() << "[" << value.value() << "]"
- << "current: " << str;
+ << "exist: " << innerIt.key() << "[" << innerIt.value() << "]"
+ << "current: " << keyName << "[" << localeStr << "]";
return DesktopErrorCode::NoError;
}
+bool DesktopEntry::checkMainEntryValidation() const noexcept
+{
+ auto it = m_entryMap.find(DesktopFileEntryKey);
+ if (it == m_entryMap.end()) {
+ return false;
+ }
+
+ if (auto name = it->find("Name"); name == it->end()) {
+ qWarning() << "No Name.";
+ return false;
+ }
+
+ auto type = it->find("Type");
+ if (type == it->end()) {
+ qWarning() << "No Type.";
+ for (const auto &[k, v] : it->asKeyValueRange()) {
+ qInfo() << "keyName:" << k;
+ for (const auto &[key, value] : v.asKeyValueRange()) {
+ qInfo() << key << value;
+ }
+ }
+ return false;
+ }
+
+ const auto &typeStr = *type->find(defaultKeyStr);
+
+ if (typeStr == "Link") {
+ if (it->find("URL") == it->end()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
std::optional DesktopFile::createTemporaryDesktopFile(std::unique_ptr temporaryFile) noexcept
{
auto mtime = getFileModifiedTime(*temporaryFile);
@@ -228,9 +295,17 @@ DesktopErrorCode DesktopEntry::parse(DesktopFile &file) noexcept
return parse(stream);
}
+bool DesktopEntry::skipCheck(const QString &line) noexcept
+{
+ return line.startsWith('#') or line.isEmpty();
+}
+
DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept
{
if (stream.atEnd()) {
+ if (m_context == EntryContext::Done) {
+ return DesktopErrorCode::NoError;
+ }
return DesktopErrorCode::OpenFailed;
}
@@ -238,28 +313,74 @@ DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept
decltype(m_entryMap)::iterator currentGroup;
DesktopErrorCode err{DesktopErrorCode::NoError};
+ bool mainEntryParsed{false};
+ QString line;
+
while (!stream.atEnd()) {
- auto line = stream.readLine().trimmed();
+ switch (m_context) {
+ case EntryContext::Unknown: {
+ qWarning() << "entry context is unknown,abort.";
+ err = DesktopErrorCode::InvalidFormat;
+ return err;
+ } break;
+ case EntryContext::EntryOuter: {
+ if (skipCheck(line)) {
+ line = stream.readLine().trimmed();
+ continue;
+ }
- if (line.isEmpty()) {
- continue;
- }
+ if (line.startsWith('[')) {
+ auto group = parserGroupHeader(line);
- if (line[0] == '[') {
- if (!(line[line.size() - 1] == ']')) {
- return DesktopErrorCode::GroupHeaderInvalid;
- }
- currentGroup = parserGroupHeader(line);
- continue;
- }
+ if (group == m_entryMap.end()) {
+ qWarning() << "groupName format error or already exists:" << line;
+ return DesktopErrorCode::InvalidFormat;
+ }
+ currentGroup = group;
+ bool isMainEntry = (currentGroup.key() == DesktopFileEntryKey);
- if (auto error = parseEntry(line, currentGroup); error != DesktopErrorCode::NoError) {
- err = error;
-#ifdef DEBUG_MODE
- qWarning() << "an error occurred,this line will be skipped:" << line;
-#endif
+ if ((!mainEntryParsed and isMainEntry) or (mainEntryParsed and !isMainEntry)) {
+ m_context = EntryContext::Entry;
+ continue;
+ }
+ }
+ qWarning() << "groupName format error:" << line;
+ err = DesktopErrorCode::InvalidFormat;
+ return err;
+ } break;
+ case EntryContext::Entry: {
+ line = stream.readLine().trimmed();
+
+ if (skipCheck(line)) {
+ continue;
+ }
+
+ if (line.startsWith('[')) {
+ m_context = EntryContext::EntryOuter;
+
+ if (currentGroup.key() == DesktopFileEntryKey) {
+ mainEntryParsed = true;
+ }
+ continue;
+ }
+
+ err = parseEntry(line, currentGroup);
+ if (err != DesktopErrorCode::NoError) {
+ qWarning() << "Entry format error:" << line;
+ return err;
+ }
+ } break;
+ case EntryContext::Done:
+ break;
}
}
+
+ m_context = EntryContext::Done;
+ if (!checkMainEntryValidation()) {
+ qWarning() << "invalid MainEntry, abort.";
+ err = DesktopErrorCode::MissingInfo;
+ }
+
return err;
}
@@ -425,12 +546,12 @@ QDebug operator<<(QDebug debug, const DesktopErrorCode &v)
errMsg = "couldn't open the file.";
break;
}
- case DesktopErrorCode::GroupHeaderInvalid: {
- errMsg = "groupHead syntax is invalid.";
+ case DesktopErrorCode::InvalidFormat: {
+ errMsg = "the format of desktopEntry file is invalid.";
break;
}
- case DesktopErrorCode::EntryKeyInvalid: {
- errMsg = "key syntax is invalid.";
+ case DesktopErrorCode::MissingInfo: {
+ errMsg = "missing required infomation.";
break;
}
}
diff --git a/src/desktopentry.h b/src/desktopentry.h
index b86f8e6..c3ffec5 100644
--- a/src/desktopentry.h
+++ b/src/desktopentry.h
@@ -15,15 +15,9 @@
constexpr static auto defaultKeyStr = "default";
-enum class DesktopErrorCode {
- NoError,
- NotFound,
- MismatchedFile,
- InvalidLocation,
- OpenFailed,
- GroupHeaderInvalid,
- EntryKeyInvalid
-};
+enum class DesktopErrorCode { NoError, NotFound, MismatchedFile, InvalidLocation, InvalidFormat, OpenFailed, MissingInfo };
+
+enum class EntryContext { Unknown, EntryOuter, Entry, Done };
struct DesktopFileGuard;
@@ -104,18 +98,10 @@ private:
class DesktopEntry
{
public:
- class Value final : private QMap
+ class Value final : public QMap
{
public:
using QMap::QMap;
- using QMap::find;
- using QMap::insert;
- using QMap::cbegin;
- using QMap::cend;
- using QMap::begin;
- using QMap::end;
- using QMap::asKeyValueRange;
-
QString toString(bool &ok) const noexcept;
bool toBoolean(bool &ok) const noexcept;
QString toIconString(bool &ok) const noexcept;
@@ -138,11 +124,18 @@ public:
[[nodiscard]] DesktopErrorCode parse(QTextStream &stream) noexcept;
[[nodiscard]] std::optional> group(const QString &key) const noexcept;
[[nodiscard]] std::optional value(const QString &key, const QString &valueKey) const noexcept;
+ static bool isInvalidLocaleString(const QString &str) noexcept;
private:
+ EntryContext m_context{EntryContext::EntryOuter};
QMap> m_entryMap;
+
auto parserGroupHeader(const QString &str) noexcept;
+ [[nodiscard]] bool checkMainEntryValidation() const noexcept;
+ static bool skipCheck(const QString &line) noexcept;
static DesktopErrorCode parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept;
+ static QPair processEntry(const QString &str) noexcept;
+ static std::optional> processEntryKey(const QString &keyStr) noexcept;
};
QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
diff --git a/src/global.h b/src/global.h
index f118f9a..a955791 100644
--- a/src/global.h
+++ b/src/global.h
@@ -27,7 +27,13 @@
Q_DECLARE_LOGGING_CATEGORY(DDEAMProf)
using IconMap = QMap>>;
-using ObjectMap = QMap;
+using ObjectInterfaceMap = QMap;
+using ObjectMap = QMap;
+using PropMap = QMap>;
+
+Q_DECLARE_METATYPE(ObjectInterfaceMap)
+Q_DECLARE_METATYPE(ObjectMap)
+Q_DECLARE_METATYPE(PropMap)
inline QString getApplicationLauncherBinary()
{
@@ -200,17 +206,39 @@ inline QString getDBusInterface(const QMetaType &meta)
return {};
}
-inline QStringList getInterfacesListFromObject(QObject *o)
+inline ObjectInterfaceMap getChildInterfacesAndPropertiesFromObject(QObject *o)
{
auto childs = o->children();
- QStringList interfaces;
- std::for_each(childs.cbegin(), childs.cend(), [&interfaces](QObject *app) {
+ ObjectInterfaceMap ret;
+
+ std::for_each(childs.cbegin(), childs.cend(), [&ret](QObject *app) {
if (app->inherits("QDBusAbstractAdaptor")) {
- interfaces.emplace_back(getDBusInterface(app->metaObject()->metaType()));
+ auto interface = getDBusInterface(app->metaObject()->metaType());
+ QVariantMap properties;
+ const auto *mo = app->metaObject();
+ for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
+ auto prop = mo->property(i);
+ properties.insert(prop.name(), prop.read(app));
+ }
+ ret.insert(interface, properties);
}
});
- return interfaces;
+ return ret;
+}
+
+inline QStringList getChildInterfacesFromObject(QObject *o)
+{
+ auto childs = o->children();
+ QStringList ret;
+
+ std::for_each(childs.cbegin(), childs.cend(), [&ret](QObject *app) {
+ if (app->inherits("QDBusAbstractAdaptor")) {
+ ret.append(getDBusInterface(app->metaObject()->metaType()));
+ }
+ });
+
+ return ret;
}
inline uid_t getCurrentUID()
@@ -399,8 +427,8 @@ ObjectMap dumpDBusObject(const QMap> &map)
ObjectMap objs;
for (const auto &[key, value] : map.asKeyValueRange()) {
- auto interfaces = getInterfacesListFromObject(value.data());
- objs.insert(key, interfaces);
+ auto interAndProps = getChildInterfacesAndPropertiesFromObject(value.data());
+ objs.insert(key, interAndProps);
}
return objs;