#include "ApplicationModel.hpp" #include #include ApplicationModel::ApplicationModel(QObject *parent) : QAbstractListModel(parent) { } int ApplicationModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return m_entries.size(); } int ApplicationModel::count() const { return m_entries.size(); } QVariant ApplicationModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= m_entries.size()) return {}; const DesktopEntry &entry = m_entries.at(index.row()); switch (role) { case DesktopIdRole: case Qt::UserRole: return entry.desktopId; case NameRole: case Qt::DisplayRole: return entry.name; case GenericNameRole: return entry.genericName; case CommentRole: return entry.comment; case IconNameRole: return entry.icon; case CategoriesRole: return entry.categories; case TerminalRole: return entry.terminal; default: return {}; } } QHash ApplicationModel::roleNames() const { return { {DesktopIdRole, QByteArrayLiteral("desktopId")}, {NameRole, QByteArrayLiteral("name")}, {GenericNameRole, QByteArrayLiteral("genericName")}, {CommentRole, QByteArrayLiteral("comment")}, {IconNameRole, QByteArrayLiteral("iconName")}, {CategoriesRole, QByteArrayLiteral("categories")}, {TerminalRole, QByteArrayLiteral("terminal")}, }; } void ApplicationModel::setEntries(QVector entries) { std::sort(entries.begin(), entries.end(), [](const DesktopEntry &left, const DesktopEntry &right) { const int order = QString::localeAwareCompare(left.name, right.name); if (order != 0) return order < 0; return left.desktopId < right.desktopId; }); beginResetModel(); m_entries = std::move(entries); endResetModel(); emit countChanged(); } const DesktopEntry *ApplicationModel::entryAt(int row) const { if (row < 0 || row >= m_entries.size()) return nullptr; return &m_entries.at(row); } const DesktopEntry *ApplicationModel::entryById(const QString &desktopId) const { for (const DesktopEntry &entry : m_entries) { if (entry.desktopId == desktopId) return &entry; } return nullptr; } const DesktopEntry *ApplicationModel::entryMatchingWindow(const QString &appId, const QString &windowClass) const { auto stem = [](QString value) { if (value.endsWith(QLatin1String(".desktop"), Qt::CaseInsensitive)) value.chop(8); return value.toLower(); }; const QString app = stem(appId); const QString cls = stem(windowClass); const QString appLast = app.contains(QLatin1Char('.')) ? app.section(QLatin1Char('.'), -1) : app; const QString classLast = cls.contains(QLatin1Char('.')) ? cls.section(QLatin1Char('.'), -1) : cls; const DesktopEntry *wmClassMatch = nullptr; const DesktopEntry *lastComponentMatch = nullptr; for (const DesktopEntry &entry : m_entries) { const QString id = stem(entry.desktopId); if (!app.isEmpty() && id == app) return &entry; if (!cls.isEmpty() && id == cls) return &entry; if (!entry.startupWmClass.isEmpty()) { const QString wm = stem(entry.startupWmClass); if ((!app.isEmpty() && wm == app) || (!cls.isEmpty() && wm == cls) || (!appLast.isEmpty() && wm == appLast) || (!classLast.isEmpty() && wm == classLast)) { if (!wmClassMatch) wmClassMatch = &entry; } } if (!lastComponentMatch) { const QString idLast = id.contains(QLatin1Char('.')) ? id.section(QLatin1Char('.'), -1) : id; if (appLast.size() >= 3 && (id == appLast || idLast == appLast)) lastComponentMatch = &entry; else if (classLast.size() >= 3 && (id == classLast || idLast == classLast)) lastComponentMatch = &entry; } } if (wmClassMatch) return wmClassMatch; return lastComponentMatch; }