File indexing completed on 2024-05-19 03:59:07
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "partloader.h" 0009 0010 #include "kparts_logging.h" 0011 0012 #include <KConfigGroup> 0013 #include <KLocalizedString> 0014 #include <KService> 0015 #include <KSharedConfig> 0016 0017 #include <QMimeDatabase> 0018 #include <QMimeType> 0019 0020 static QList<KPluginMetaData> partsFromUserPreference(const QString &mimeType) 0021 { 0022 auto config = KSharedConfig::openConfig(QStringLiteral("kpartsrc"), KConfig::NoGlobals); 0023 const QStringList pluginIds = config->group(QStringLiteral("Added KDE Part Associations")).readXdgListEntry(mimeType); 0024 QList<KPluginMetaData> plugins; 0025 plugins.reserve(pluginIds.size()); 0026 for (const QString &pluginId : pluginIds) { 0027 if (KPluginMetaData data(QLatin1String("kf6/parts/") + pluginId); data.isValid()) { 0028 plugins << data; 0029 } 0030 } 0031 return plugins; 0032 } 0033 0034 // A plugin can support N mimetypes. Pick the one that is closest to @parent in the inheritance tree 0035 // and return how far it is from that parent (0 = same mimetype, 1 = direct child, etc.) 0036 static int pluginDistanceToMimeType(const KPluginMetaData &md, const QString &parent) 0037 { 0038 QMimeDatabase db; 0039 auto distanceToMimeType = [&](const QString &mime) { 0040 if (mime == parent) { 0041 return 0; 0042 } 0043 const QStringList ancestors = db.mimeTypeForName(mime).allAncestors(); 0044 const int dist = ancestors.indexOf(parent); 0045 return dist == -1 ? 50 : dist + 1; 0046 }; 0047 const QStringList mimes = md.mimeTypes(); 0048 int minDistance = 50; 0049 for (const QString &mime : mimes) { 0050 minDistance = std::min(minDistance, distanceToMimeType(mime)); 0051 } 0052 return minDistance; 0053 } 0054 0055 QList<KPluginMetaData> KParts::PartLoader::partsForMimeType(const QString &mimeType) 0056 { 0057 auto supportsMime = [&mimeType](const KPluginMetaData &md) { 0058 if (md.supportsMimeType(mimeType)) { 0059 return true; 0060 } 0061 auto pluginJson = md.rawData(); 0062 auto pluginNamespace = pluginJson.value(QLatin1String("KParts")).toObject().value(QLatin1String("PluginNamespace")).toString(); 0063 if (pluginNamespace.isEmpty()) { 0064 return false; 0065 } 0066 auto plugins = KPluginMetaData::findPlugins(pluginNamespace, [&mimeType](const KPluginMetaData &pluginMd) { 0067 return pluginMd.supportsMimeType(mimeType); 0068 }); 0069 return !plugins.isEmpty(); 0070 }; 0071 QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/parts"), supportsMime); 0072 auto orderPredicate = [&](const KPluginMetaData &left, const KPluginMetaData &right) { 0073 // We filtered based on "supports mimetype", but this didn't order from most-specific to least-specific. 0074 const int leftDistance = pluginDistanceToMimeType(left, mimeType); 0075 const int rightDistance = pluginDistanceToMimeType(right, mimeType); 0076 if (leftDistance < rightDistance) { 0077 return true; 0078 } 0079 if (leftDistance > rightDistance) { 0080 return false; 0081 } 0082 // Plugins who support the same mimetype are then sorted by initial preference 0083 const auto getInitialPreference = [](const KPluginMetaData &data) { 0084 return data.rawData().value(QLatin1String("KPlugin")).toObject().value(QLatin1String("InitialPreference")).toInt(); 0085 }; 0086 return getInitialPreference(left) > getInitialPreference(right); 0087 }; 0088 std::sort(plugins.begin(), plugins.end(), orderPredicate); 0089 0090 const QList<KPluginMetaData> userParts = partsFromUserPreference(mimeType); 0091 if (!userParts.isEmpty()) { 0092 plugins = userParts; 0093 } 0094 0095 // for (const KPluginMetaData &plugin : plugins) { 0096 // qDebug() << plugin.fileName() << plugin.initialPreference(); 0097 //} 0098 return plugins; 0099 } 0100 0101 void KParts::PartLoader::Private::getErrorStrings(QString *errorString, QString *errorText, const QString &argument, ErrorType type) 0102 { 0103 switch (type) { 0104 case CouldNotLoadPlugin: 0105 *errorString = i18n("KPluginFactory could not load the plugin: %1", argument); 0106 *errorText = QStringLiteral("KPluginFactory could not load the plugin: %1").arg(argument); 0107 break; 0108 case NoPartFoundForMimeType: 0109 *errorString = i18n("No part was found for mimeType %1", argument); 0110 *errorText = QStringLiteral("No part was found for mimeType %1").arg(argument); 0111 break; 0112 case NoPartInstantiatedForMimeType: 0113 *errorString = i18n("No part could be instantiated for mimeType %1", argument); 0114 *errorText = QStringLiteral("No part could be instantiated for mimeType %1").arg(argument); 0115 break; 0116 default: 0117 qCWarning(KPARTSLOG) << "PartLoader::Private::getErrorStrings got unexpected error type" << type; 0118 break; 0119 } 0120 };