File indexing completed on 2024-04-28 09:31:36
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de> 0003 * SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include <KAuthorized> 0009 #include <KCModuleData> 0010 #include <KFileUtils> 0011 #include <KPluginFactory> 0012 #include <KPluginMetaData> 0013 #include <KService> 0014 #include <QGuiApplication> 0015 #include <QStandardPaths> 0016 0017 #include <set> 0018 0019 #include "../systemsettings_app_debug.h" 0020 0021 enum MetaDataSource { 0022 SystemSettings = 1, 0023 KInfoCenter = 2, 0024 All = SystemSettings | KInfoCenter, 0025 }; 0026 0027 inline QList<KPluginMetaData> findExternalKCMModules(MetaDataSource source) 0028 { 0029 const auto findExternalModulesInFilesystem = [](const QString &sourceNamespace) { 0030 const QString sourceNamespaceDirName = QStringLiteral("plasma/%1/externalmodules").arg(sourceNamespace); 0031 const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, sourceNamespaceDirName, QStandardPaths::LocateDirectory); 0032 const QStringList files = KFileUtils::findAllUniqueFiles(dirs, QStringList{QStringLiteral("*.desktop")}); 0033 0034 QList<KPluginMetaData> metaDataList; 0035 for (const QString &file : files) { 0036 KService service(file); 0037 QJsonObject kplugin; 0038 kplugin.insert(QLatin1String("Name"), service.name()); 0039 kplugin.insert(QLatin1String("Icon"), service.icon()); 0040 kplugin.insert(QLatin1String("Description"), service.comment()); 0041 0042 QJsonObject root; 0043 root.insert(QLatin1String("KPlugin"), kplugin); 0044 root.insert(QLatin1String("X-KDE-Weight"), service.property<int>(QStringLiteral("X-KDE-Weight"))); 0045 root.insert(QLatin1String("X-KDE-KInfoCenter-Category"), service.property<QString>(QStringLiteral("X-KDE-KInfoCenter-Category"))); 0046 root.insert(QLatin1String("X-KDE-System-Settings-Category"), service.property<QString>(QStringLiteral("X-KDE-System-Settings-Category"))); 0047 root.insert(QLatin1String("IsExternalApp"), true); 0048 0049 metaDataList << KPluginMetaData(root, file); 0050 } 0051 return metaDataList; 0052 }; 0053 0054 QList<KPluginMetaData> metaDataList; 0055 if (source & SystemSettings) { 0056 metaDataList << findExternalModulesInFilesystem(QStringLiteral("systemsettings")); 0057 } 0058 0059 if (source & KInfoCenter) { 0060 metaDataList << findExternalModulesInFilesystem(QStringLiteral("kinfocenter")); 0061 } 0062 0063 return metaDataList; 0064 } 0065 0066 inline QList<KPluginMetaData> findKCMsMetaData(MetaDataSource source) 0067 { 0068 QList<KPluginMetaData> modules; 0069 std::set<QString> uniquePluginIds; 0070 0071 auto filter = [](const KPluginMetaData &data) { 0072 const auto supportedPlatforms = data.value(QStringLiteral("X-KDE-OnlyShowOnQtPlatforms"), QStringList()); 0073 return supportedPlatforms.isEmpty() || supportedPlatforms.contains(qGuiApp->platformName()); 0074 }; 0075 0076 // We need the exist calls because otherwise the trader language aborts if the property doesn't exist and the second part of the or is not evaluated 0077 QList<KPluginMetaData> metaDataList = KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms"), filter); 0078 if (source & SystemSettings) { 0079 metaDataList << KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms/systemsettings"), filter); 0080 metaDataList << KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms/systemsettings_qwidgets"), filter); 0081 } 0082 if (source & KInfoCenter) { 0083 metaDataList << KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms/kinfocenter"), filter); 0084 } 0085 for (const auto &m : std::as_const(metaDataList)) { 0086 // We check both since porting a module to loading view KPluginMetaData drops ".desktop" from the pluginId() 0087 if (!KAuthorized::authorizeControlModule(m.pluginId())) { 0088 continue; 0089 } 0090 modules << m; 0091 const bool inserted = uniquePluginIds.insert(m.pluginId()).second; 0092 if (!inserted) { 0093 qWarning() << "the plugin" << m.pluginId() << " was found in multiple namespaces"; 0094 } 0095 } 0096 std::stable_sort(modules.begin(), modules.end(), [](const KPluginMetaData &m1, const KPluginMetaData &m2) { 0097 return QString::compare(m1.pluginId(), m2.pluginId(), Qt::CaseInsensitive) < 0; 0098 }); 0099 return modules; 0100 } 0101 0102 inline bool isKinfoCenterKcm(const KPluginMetaData &data) 0103 { 0104 // external module or a KCM in the namespace 0105 return data.fileName().contains(QLatin1String("/kinfocenter/")); 0106 } 0107 0108 inline KCModuleData *loadModuleData(const KPluginMetaData &data) 0109 { 0110 if (auto factory = KPluginFactory::loadFactory(data).plugin) { 0111 return factory->create<KCModuleData>(); 0112 } 0113 return nullptr; 0114 }