diff --git a/src/core/desktopentry.cpp b/src/core/desktopentry.cpp index 46738812..35824313 100644 --- a/src/core/desktopentry.cpp +++ b/src/core/desktopentry.cpp @@ -1,4 +1,5 @@ #include "desktopentry.hpp" +#include #include #include @@ -108,6 +109,7 @@ void DesktopEntry::parseEntry(const QString& text) { if (key == "Name") this->mName = value; else if (key == "GenericName") this->mGenericName = value; + else if (key == "StartupWMClass") this->mStartupClass = value; else if (key == "NoDisplay") this->mNoDisplay = value == "true"; else if (key == "Comment") this->mComment = value; else if (key == "Icon") this->mIcon = value; @@ -384,6 +386,25 @@ DesktopEntry* DesktopEntryManager::byId(const QString& id) { } } +DesktopEntry* DesktopEntryManager::heuristicLookup(const QString& name) { + if (auto* entry = DesktopEntryManager::byId(name)) return entry; + + auto& list = this->mApplications.valueList(); + + auto iter = std::ranges::find_if(list, [&](const DesktopEntry* entry) { + return name == entry->mStartupClass; + }); + + if (iter != list.end()) return *iter; + + iter = std::ranges::find_if(list, [&](const DesktopEntry* entry) { + return name.toLower() == entry->mStartupClass.toLower(); + }); + + if (iter != list.end()) return *iter; + return nullptr; +} + ObjectModel* DesktopEntryManager::applications() { return &this->mApplications; } DesktopEntries::DesktopEntries() { DesktopEntryManager::instance(); } @@ -392,6 +413,10 @@ DesktopEntry* DesktopEntries::byId(const QString& id) { return DesktopEntryManager::instance()->byId(id); } +DesktopEntry* DesktopEntries::heuristicLookup(const QString& name) { + return DesktopEntryManager::instance()->heuristicLookup(name); +} + ObjectModel* DesktopEntries::applications() { return DesktopEntryManager::instance()->applications(); } diff --git a/src/core/desktopentry.hpp b/src/core/desktopentry.hpp index ee8f5112..34137728 100644 --- a/src/core/desktopentry.hpp +++ b/src/core/desktopentry.hpp @@ -22,6 +22,9 @@ class DesktopEntry: public QObject { Q_PROPERTY(QString name MEMBER mName CONSTANT); /// Short description of the application, such as "Web Browser". May be empty. Q_PROPERTY(QString genericName MEMBER mGenericName CONSTANT); + /// Initial class or app id the app intends to use. May be useful for matching running apps + /// to desktop entries. + Q_PROPERTY(QString startupClass MEMBER mStartupClass CONSTANT); /// If true, this application should not be displayed in menus and launchers. Q_PROPERTY(bool noDisplay MEMBER mNoDisplay CONSTANT); /// Long description of the application, such as "View websites on the internet". May be empty. @@ -81,6 +84,7 @@ public: QString mId; QString mName; QString mGenericName; + QString mStartupClass; bool mNoDisplay = false; QString mComment; QString mIcon; @@ -151,6 +155,7 @@ public: void scanDesktopEntries(); [[nodiscard]] DesktopEntry* byId(const QString& id); + [[nodiscard]] DesktopEntry* heuristicLookup(const QString& name); [[nodiscard]] ObjectModel* applications(); @@ -186,7 +191,14 @@ public: explicit DesktopEntries(); /// Look up a desktop entry by name. Includes NoDisplay entries. May return null. + /// + /// While this function requires an exact match, @@heuristicLookup() will correctly + /// find an entry more often and is generally more useful. Q_INVOKABLE [[nodiscard]] static DesktopEntry* byId(const QString& id); + /// Look up a desktop entry by name using heuristics. Unline @@byId(), + /// if no exact matches are found this function will try to guess - potentially incorrectly. + /// May return null. + Q_INVOKABLE [[nodiscard]] static DesktopEntry* heuristicLookup(const QString& name); [[nodiscard]] static ObjectModel* applications(); };