/* * Copyright (C) 2020 ~ 2021 CyberOS Team. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "systemappmonitor.h" #include #include #include #include #include #define SystemApplicationsFolder "/usr/share/applications" static SystemAppMonitor *SELF = nullptr; static QByteArray detectDesktopEnvironment() { const QByteArray desktop = qgetenv("XDG_CURRENT_DESKTOP"); if (!desktop.isEmpty()) return desktop.toUpper(); return QByteArray("UNKNOWN"); } SystemAppMonitor *SystemAppMonitor::self() { if (SELF == nullptr) SELF = new SystemAppMonitor; return SELF; } SystemAppMonitor::SystemAppMonitor(QObject *parent) : QObject(parent) { QFileSystemWatcher *watcher = new QFileSystemWatcher(this); watcher->addPath(SystemApplicationsFolder); connect(watcher, &QFileSystemWatcher::directoryChanged, this, &SystemAppMonitor::refresh); refresh(); } SystemAppMonitor::~SystemAppMonitor() { while (!m_items.isEmpty()) delete m_items.takeFirst(); } SystemAppItem *SystemAppMonitor::find(const QString &filePath) { for (SystemAppItem *item : m_items) if (item->path == filePath) return item; return nullptr; } void SystemAppMonitor::refresh() { QStringList addedEntries; for (SystemAppItem *item : m_items) addedEntries.append(item->path); QStringList allEntries; QDirIterator it(SystemApplicationsFolder, { "*.desktop" }, QDir::NoFilter, QDirIterator::Subdirectories); while (it.hasNext()) { const QString &filePath = it.next(); if (!QFile::exists(filePath)) continue; allEntries.append(filePath); } for (const QString &filePath : allEntries) { if (!addedEntries.contains(filePath)) { addApplication(filePath); } } for (SystemAppItem *item : m_items) { if (!allEntries.contains(item->path)) { removeApplication(item); } } emit refreshed(); } void SystemAppMonitor::addApplication(const QString &filePath) { if (find(filePath)) return; QSettings desktop(filePath, QSettings::IniFormat); desktop.setIniCodec("UTF-8"); desktop.beginGroup("Desktop Entry"); if (desktop.contains("OnlyShowIn")) { const QString &value = desktop.value("OnlyShowIn").toString(); if (!value.contains(detectDesktopEnvironment(), Qt::CaseInsensitive)) { return; } } if (desktop.value("NoDisplay").toBool() || desktop.value("Hidden").toBool()) { return; } QString appName = desktop.value(QString("Name[%1]").arg(QLocale::system().name())).toString(); QString appExec = desktop.value("Exec").toString(); if (appName.isEmpty()) appName = desktop.value("Name").toString(); appExec.remove(QRegularExpression("%.")); appExec.remove(QRegularExpression("^\"")); // appExec.remove(QRegularExpression(" *$")); appExec = appExec.simplified(); SystemAppItem *item = new SystemAppItem; item->path = filePath; item->name = appName; item->genericName = desktop.value("GenericName").toString(); item->comment = desktop.value("Comment").toString(); item->iconName = desktop.value("Icon").toString(); item->startupWMClass = desktop.value("StartupWMClass").toString(); item->exec = appExec; item->args = appExec.split(" "); m_items.append(item); } void SystemAppMonitor::removeApplication(SystemAppItem *item) { m_items.removeOne(item); item->deleteLater(); }