KParts

partloader.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "partloader.h"
9
10#include "kparts_logging.h"
11
12#include <KConfigGroup>
13#include <KLocalizedString>
14#include <KService>
15#include <KSharedConfig>
16
17#include <QMimeDatabase>
18#include <QMimeType>
19
20static QList<KPluginMetaData> partsFromUserPreference(const QString &mimeType)
21{
22 auto config = KSharedConfig::openConfig(QStringLiteral("kpartsrc"), KConfig::NoGlobals);
23 const QStringList pluginIds = config->group(QStringLiteral("Added KDE Part Associations")).readXdgListEntry(mimeType);
25 plugins.reserve(pluginIds.size());
26 for (const QString &pluginId : pluginIds) {
27 if (KPluginMetaData data(QLatin1String("kf6/parts/") + pluginId); data.isValid()) {
28 plugins << data;
29 }
30 }
31 return plugins;
32}
33
34// A plugin can support N mimetypes. Pick the one that is closest to @parent in the inheritance tree
35// and return how far it is from that parent (0 = same mimetype, 1 = direct child, etc.)
36static int pluginDistanceToMimeType(const KPluginMetaData &md, const QString &parent)
37{
39 auto distanceToMimeType = [&](const QString &mime) {
40 if (mime == parent) {
41 return 0;
42 }
43 const QStringList ancestors = db.mimeTypeForName(mime).allAncestors();
44 const int dist = ancestors.indexOf(parent);
45 return dist == -1 ? 50 : dist + 1;
46 };
47 const QStringList mimes = md.mimeTypes();
48 int minDistance = 50;
49 for (const QString &mime : mimes) {
50 minDistance = std::min(minDistance, distanceToMimeType(mime));
51 }
52 return minDistance;
53}
54
56{
57 auto supportsMime = [&mimeType](const KPluginMetaData &md) {
58 if (md.supportsMimeType(mimeType)) {
59 return true;
60 }
61 auto pluginJson = md.rawData();
62 auto pluginNamespace = pluginJson.value(QLatin1String("KParts")).toObject().value(QLatin1String("PluginNamespace")).toString();
63 if (pluginNamespace.isEmpty()) {
64 return false;
65 }
66 auto plugins = KPluginMetaData::findPlugins(pluginNamespace, [&mimeType](const KPluginMetaData &pluginMd) {
67 return pluginMd.supportsMimeType(mimeType);
68 });
69 return !plugins.isEmpty();
70 };
71 QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/parts"), supportsMime);
72 auto orderPredicate = [&](const KPluginMetaData &left, const KPluginMetaData &right) {
73 // We filtered based on "supports mimetype", but this didn't order from most-specific to least-specific.
74 const int leftDistance = pluginDistanceToMimeType(left, mimeType);
75 const int rightDistance = pluginDistanceToMimeType(right, mimeType);
76 if (leftDistance < rightDistance) {
77 return true;
78 }
79 if (leftDistance > rightDistance) {
80 return false;
81 }
82 // Plugins who support the same mimetype are then sorted by initial preference
83 const auto getInitialPreference = [](const KPluginMetaData &data) {
84 return data.rawData().value(QLatin1String("KPlugin")).toObject().value(QLatin1String("InitialPreference")).toInt();
85 };
86 return getInitialPreference(left) > getInitialPreference(right);
87 };
88 std::sort(plugins.begin(), plugins.end(), orderPredicate);
89
90 const QList<KPluginMetaData> userParts = partsFromUserPreference(mimeType);
91 if (!userParts.isEmpty()) {
92 plugins = userParts;
93 }
94
95 // for (const KPluginMetaData &plugin : plugins) {
96 // qDebug() << plugin.fileName() << plugin.initialPreference();
97 //}
98 return plugins;
99}
100
101void KParts::PartLoader::Private::getErrorStrings(QString *errorString, QString *errorText, const QString &argument, ErrorType type)
102{
103 switch (type) {
104 case CouldNotLoadPlugin:
105 *errorString = i18n("KPluginFactory could not load the plugin: %1", argument);
106 *errorText = QStringLiteral("KPluginFactory could not load the plugin: %1").arg(argument);
107 break;
108 case NoPartFoundForMimeType:
109 *errorString = i18n("No part was found for mimeType %1", argument);
110 *errorText = QStringLiteral("No part was found for mimeType %1").arg(argument);
111 break;
112 case NoPartInstantiatedForMimeType:
113 *errorString = i18n("No part could be instantiated for mimeType %1", argument);
114 *errorText = QStringLiteral("No part could be instantiated for mimeType %1").arg(argument);
115 break;
116 default:
117 qCWarning(KPARTSLOG) << "PartLoader::Private::getErrorStrings got unexpected error type" << type;
118 break;
119 }
120};
QStringList mimeTypes() const
QJsonObject rawData() const
static QList< KPluginMetaData > findPlugins(const QString &directory, std::function< bool(const KPluginMetaData &)> filter={}, KPluginMetaDataOptions options={})
bool isValid() const
bool supportsMimeType(const QString &mimeType) const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QString i18n(const char *text, const TYPE &arg...)
KPARTS_EXPORT QList< KPluginMetaData > partsForMimeType(const QString &mimeType)
Locate all available KParts using KPluginMetaData::findPlugins for a mimetype.
QJsonValue value(QLatin1StringView key) const const
iterator begin()
iterator end()
bool isEmpty() const const
void reserve(qsizetype size)
qsizetype size() const const
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
QString arg(Args &&... args) const const
qsizetype indexOf(const QRegularExpression &re, qsizetype from) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:54 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.