File indexing completed on 2024-05-12 16:23:46
0001 // SPDX-FileCopyrightText: 2021 Jonah Brüchert <jbb@kaidan.im> 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 #include "webappmanager.h" 0006 0007 #include <QImage> 0008 #include <QStandardPaths> 0009 #include <QStringBuilder> 0010 0011 #include <KConfigGroup> 0012 #include <KDesktopFile> 0013 #include <KSandbox> 0014 0015 WebAppManager::WebAppManager(QObject *parent) 0016 : QObject(parent) 0017 , m_desktopFileDirectory(desktopFileDirectory()) 0018 { 0019 const auto fileInfos = m_desktopFileDirectory.entryInfoList(QDir::Files); 0020 0021 // Likely almost all files in the directory are webapps, so this should be worth it 0022 m_webApps.reserve(fileInfos.size()); 0023 0024 for (const auto &file : fileInfos) { 0025 // Make sure to only parse desktop files 0026 if (file.fileName().contains(QStringView(u".desktop"))) { 0027 KDesktopFile desktopFile(file.filePath()); 0028 0029 // Only handle desktop files referencing angelfish-webapp 0030 if (desktopFile.group(QStringLiteral("Desktop Entry")).readEntry("Exec").contains(QStringView(u"angelfish-webapp"))) { 0031 WebApp app{desktopFile.readName(), desktopFile.readIcon(), desktopFile.readUrl()}; 0032 0033 m_webApps.push_back(std::move(app)); 0034 } 0035 } 0036 } 0037 } 0038 0039 QString WebAppManager::desktopFileDirectory() 0040 { 0041 auto dir = []() -> QString { 0042 if (KSandbox::isFlatpak()) { 0043 return qEnvironmentVariable("HOME") % u"/.local/share/applications/"; 0044 } 0045 return QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation); 0046 }(); 0047 0048 QDir(dir).mkpath(QStringLiteral(".")); 0049 0050 return dir; 0051 } 0052 0053 QString WebAppManager::iconDirectory() 0054 { 0055 auto dir = []() -> QString { 0056 if (KSandbox::isFlatpak()) { 0057 return qEnvironmentVariable("HOME") % u"/.local/share/icons/hicolor/16x16/apps/"; 0058 } 0059 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/icons/hicolor/16x16/apps/"); 0060 }(); 0061 0062 QDir(dir).mkpath(QStringLiteral(".")); 0063 0064 return dir; 0065 } 0066 0067 const std::vector<WebApp> &WebAppManager::applications() const 0068 { 0069 return m_webApps; 0070 } 0071 0072 void WebAppManager::addApp(const QString &name, const QString &url, const QImage &icon) 0073 { 0074 const QString filename = generateFileName(name); 0075 const QString desktopFileName = generateDesktopFileName(name); 0076 0077 icon.save(iconDirectory() % QDir::separator() % filename % u".png", "PNG"); 0078 KConfig desktopFile(desktopFileDirectory() % QDir::separator() % desktopFileName, KConfig::SimpleConfig); 0079 0080 auto desktopEntry = desktopFile.group(QStringLiteral("Desktop Entry")); 0081 desktopEntry.writeEntry(QStringLiteral("Type"), QStringLiteral("Application")); 0082 desktopEntry.writeEntry(QStringLiteral("URL"), url); 0083 desktopEntry.writeEntry(QStringLiteral("Name"), name); 0084 desktopEntry.writeEntry(QStringLiteral("Exec"), QString(webAppCommand() % u' ' % desktopFileName)); 0085 desktopEntry.writeEntry(QStringLiteral("Icon"), filename); 0086 0087 m_webApps.push_back(WebApp{name, filename, url}); 0088 0089 desktopFile.sync(); 0090 0091 Q_EMIT applicationsChanged(); 0092 } 0093 0094 bool WebAppManager::exists(const QString &name) 0095 { 0096 const QString location = desktopFileDirectory(); 0097 const QString filename = generateDesktopFileName(name); 0098 0099 return QFile::exists(location % QDir::separator() % filename); 0100 } 0101 0102 bool WebAppManager::removeApp(const QString &name) 0103 { 0104 const QString location = desktopFileDirectory(); 0105 const QString filename = generateDesktopFileName(name); 0106 0107 auto it = std::remove_if(m_webApps.begin(), m_webApps.end(), [&name](const WebApp &app) { 0108 return app.name == name; 0109 }); 0110 0111 m_webApps.erase(it); 0112 0113 bool success = QFile::remove(location % QDir::separator() % filename); 0114 Q_EMIT applicationsChanged(); 0115 return success; 0116 } 0117 0118 WebAppManager &WebAppManager::instance() 0119 { 0120 static WebAppManager instance; 0121 return instance; 0122 } 0123 0124 QString WebAppManager::generateFileName(const QString &name) 0125 { 0126 QString filename = name.toLower(); 0127 filename.replace(QChar(u' '), QChar(u'_')); 0128 filename.remove(u'/'); 0129 filename.remove(u'"'); 0130 filename.remove(u'\''); 0131 filename.remove(u','); 0132 filename.remove(u'.'); 0133 filename.remove(u'|'); 0134 return filename; 0135 } 0136 0137 QString WebAppManager::generateDesktopFileName(const QString &name) 0138 { 0139 return generateFileName(name) % u".desktop"; 0140 } 0141 0142 QString WebAppManager::webAppCommand() 0143 { 0144 if (KSandbox::isFlatpak()) { 0145 return QStringLiteral( 0146 "flatpak run " 0147 "--command=angelfish-webapp " 0148 "--filesystem=%1 " 0149 "org.kde.angelfish") 0150 .arg(desktopFileDirectory()); 0151 } 0152 0153 return QStringLiteral("angelfish-webapp"); 0154 } 0155 0156 #include "moc_webappmanager.cpp"