18#include "xdgwatcher.h"
23#include <QStandardPaths>
26#include <gio/gdesktopappinfo.h>
28XdgWatcher::XdgWatcher(QObject* parent)
30 m_watcher(new QFileSystemWatcher(this))
32 connect(m_watcher, &QFileSystemWatcher::directoryChanged,
this, &XdgWatcher::onDirectoryChanged);
33 connect(m_watcher, &QFileSystemWatcher::fileChanged,
this, &XdgWatcher::onFileChanged);
35 const auto paths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
36 for (
const auto &path: paths) {
37 const auto qdir = QDir(path);
43 m_watcher->addPath(path);
46 const auto files = qdir.entryInfoList(QDir::Files);
47 for (
const auto &file: files) {
48 if (file.suffix() ==
"desktop") {
49 const auto path = file.absoluteFilePath();
50 m_watcher->addPath(path);
51 m_registry.insert(path, getAppId(file));
58const QString XdgWatcher::stripAppIdVersion(
const QString rawAppID)
const {
59 auto appIdComponents = rawAppID.split(
"_");
60 appIdComponents.removeLast();
61 return appIdComponents.join(
"_");
66const QString XdgWatcher::toStandardAppId(
const QFileInfo fileInfo)
const {
67 const auto paths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
68 for (
const auto &path: paths) {
69 if (fileInfo.absolutePath() == path) {
72 if (fileInfo.absolutePath().contains(path)) {
73 auto fileStr = fileInfo.absoluteFilePath();
74 fileStr.replace(path,
"");
75 fileStr.replace(
"/",
"-");
76 fileStr.replace(
".desktop",
"");
80 return fileInfo.completeBaseName();
83const QString XdgWatcher::getAppId(
const QFileInfo fileInfo)
const {
88 QFile qFile(fileInfo.absoluteFilePath());
89 qFile.open(QIODevice::ReadOnly);
90 QTextStream fileStream(&qFile);
92 while (fileStream.readLineInto(&line)) {
93 if (line.startsWith(
"X-Lomiri-Application-ID=")) {
94 auto rawAppID = line.replace(
"X-Lomiri-Application-ID=",
"");
96 return stripAppIdVersion(rawAppID);
102 return toStandardAppId(fileInfo);
106bool XdgWatcher::shouldShow(
const QFileInfo &file)
const {
107 GDesktopAppInfo *appinfo = g_desktop_app_info_new(file.fileName().toUtf8().constData());
109 bool show = g_app_info_should_show(G_APP_INFO(appinfo));
110 g_object_unref(appinfo);
113 qWarning() <<
"XdgWatcher: appinfo is NULL for" << file.absoluteFilePath();
119void XdgWatcher::onDirectoryChanged(
const QString &path) {
120 const auto files = QDir(path).entryInfoList(QDir::Files);
121 const auto watchedFiles = m_watcher->files();
122 for (
const auto &file: files) {
123 const auto appPath = file.absoluteFilePath();
124 if (file.suffix() ==
"desktop" && !watchedFiles.contains(appPath) && shouldShow(file)) {
125 m_watcher->addPath(appPath);
127 const auto appId = getAppId(file);
128 m_registry.insert(appPath, appId);
129 Q_EMIT appAdded(appId);
134void XdgWatcher::onFileChanged(
const QString &path) {
135 const auto watchedFiles = m_watcher->files();
136 if (watchedFiles.contains(path)) {
138 Q_EMIT appInfoChanged(m_registry.value(path));
142 Q_EMIT appRemoved(m_registry.take(path));