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 | #ifndef KPARTS_PARTLOADER_H |
9 | #define KPARTS_PARTLOADER_H |
10 | |
11 | #include <KPluginFactory> |
12 | #include <KPluginMetaData> |
13 | #include <QList> |
14 | #include <QObject> |
15 | #include <kparts/kparts_export.h> |
16 | |
17 | namespace KParts |
18 | { |
19 | Q_NAMESPACE_EXPORT(KPARTS_EXPORT) |
20 | |
21 | /*! |
22 | * Enum for standardized capabilities of KParts |
23 | * |
24 | * \code |
25 | * { |
26 | * "KPlugin": {...}, |
27 | * "KParts": { |
28 | * "Capabilities": [ |
29 | * "ReadOnly" |
30 | * ], |
31 | * "InitialPreference": 42 |
32 | * } |
33 | * } |
34 | * \endcode |
35 | * |
36 | * \value ReadOnly |
37 | * \value ReadWrite |
38 | * \value BrowserView |
39 | */ |
40 | enum class PartCapability { |
41 | ReadOnly = 1, |
42 | ReadWrite = 2, |
43 | BrowserView = 4, |
44 | }; |
45 | Q_ENUM_NS(PartCapability) |
46 | Q_DECLARE_FLAGS(PartCapabilities, PartCapability) |
47 | Q_FLAG_NS(PartCapabilities) |
48 | Q_DECLARE_OPERATORS_FOR_FLAGS(PartCapabilities) |
49 | |
50 | /*! |
51 | * \namespace KParts::PartLoader |
52 | * \inheaderfile KParts/PartLoader |
53 | * \inmodule KParts |
54 | * |
55 | * \brief Helper methods for locating and loading parts. |
56 | * |
57 | * This is based upon KPluginFactory, but it takes |
58 | * care of querying by mimetype, sorting the available parts by builtin |
59 | * preference and by user preference. |
60 | * \since KParts 5.69 |
61 | */ |
62 | namespace PartLoader |
63 | { |
64 | namespace Private |
65 | { |
66 | |
67 | enum ErrorType { |
68 | CouldNotLoadPlugin, |
69 | NoPartFoundForMimeType, |
70 | NoPartInstantiatedForMimeType, |
71 | }; |
72 | |
73 | /*! |
74 | * \internal |
75 | * \a errorString translated, user-visible error string |
76 | * \a errorText untranslated error text |
77 | * \a argument argument for the text |
78 | */ |
79 | KPARTS_EXPORT void getErrorStrings(QString *errorString, QString *errorText, const QString &argument, ErrorType type); |
80 | |
81 | } |
82 | |
83 | /*! |
84 | * Parses the associated capabilities from the KPart. This parses the deprecated "ServiceTypes" array of the "KPlugin" object |
85 | * |
86 | * \since KParts 6.4 |
87 | */ |
88 | KPARTS_EXPORT PartCapabilities partCapabilities(const KPluginMetaData &data); |
89 | |
90 | /*! |
91 | * Locate all available KParts using KPluginMetaData::findPlugins for a mimetype. |
92 | * Returns a list of plugin metadata, sorted by preference. |
93 | * This takes care both of the builtin preference (set by developers) |
94 | * and of user preference (stored in mimeapps.list). |
95 | * |
96 | * To load a part from one of the KPluginMetaData instances returned here, |
97 | * use instantiatePart() |
98 | * |
99 | * \since 5.69 |
100 | */ |
101 | KPARTS_EXPORT QList<KPluginMetaData> partsForMimeType(const QString &mimeType); |
102 | |
103 | /*! |
104 | * Attempts to create a KPart from the given metadata. |
105 | * |
106 | * \code |
107 | * if (auto result = KParts::PartLoader::instantiatePart<MyPart>(metaData, parentWidget, parent, args)) { |
108 | * // result.plugin is valid and can be accessed |
109 | * } else { |
110 | * // result contains information about the error |
111 | * } |
112 | * \endcode |
113 | * |
114 | * \a data KPluginMetaData from which the plugin should be loaded |
115 | * |
116 | * \a parentWidget The parent widget |
117 | * |
118 | * \a parent The parent object |
119 | * |
120 | * \a args A list of arguments to be passed to the part |
121 | * |
122 | * Returns a Result object which contains the plugin instance and potentially error information |
123 | * |
124 | * \since 5.100 |
125 | */ |
126 | template<typename T> |
127 | static KPluginFactory::Result<T> |
128 | instantiatePart(const KPluginMetaData &data, QWidget *parentWidget = nullptr, QObject *parent = nullptr, const QVariantList &args = {}) |
129 | { |
130 | KPluginFactory::Result<T> result; |
131 | KPluginFactory::Result<KPluginFactory> factoryResult = KPluginFactory::loadFactory(data); |
132 | if (!factoryResult.plugin) { |
133 | result.errorString = factoryResult.errorString; |
134 | result.errorReason = factoryResult.errorReason; |
135 | return result; |
136 | } |
137 | T *instance = factoryResult.plugin->create<T>(parentWidget, parent, args); |
138 | if (!instance) { |
139 | const QString fileName = data.fileName(); |
140 | Private::getErrorStrings(errorString: &result.errorString, errorText: &result.errorText, argument: fileName, type: Private::CouldNotLoadPlugin); |
141 | result.errorReason = KPluginFactory::INVALID_KPLUGINFACTORY_INSTANTIATION; |
142 | } else { |
143 | result.plugin = instance; |
144 | } |
145 | return result; |
146 | } |
147 | |
148 | /*! |
149 | * Use this method to create a KParts part. It will try to create an object which inherits |
150 | * \a T. |
151 | * |
152 | * \code |
153 | * if (auto result = KParts::PartLoader::instantiatePartForMimeType<KParts::ReadOnlyPart>(mimeType, parentWidget, parent, args)) { |
154 | * // result.plugin is valid and can be accessed |
155 | * } else { |
156 | * // result contains information about the error |
157 | * } |
158 | * \endcode |
159 | * |
160 | * \a T The interface for which an object should be created. The object will inherit \a T. |
161 | * |
162 | * \a mimeType The mimetype for which we need a KParts. |
163 | * |
164 | * \a parentWidget The parent widget for the part's widget. |
165 | * |
166 | * \a parent The parent of the part. |
167 | * |
168 | * Returns a Result object which contains the plugin instance and potentially error information |
169 | * |
170 | * \since 5.100 |
171 | */ |
172 | template<class T> |
173 | static KPluginFactory::Result<T> |
174 | instantiatePartForMimeType(const QString &mimeType, QWidget *parentWidget = nullptr, QObject *parent = nullptr, const QVariantList &args = {}) |
175 | { |
176 | const QList<KPluginMetaData> plugins = KParts::PartLoader::partsForMimeType(mimeType); |
177 | if (plugins.isEmpty()) { |
178 | KPluginFactory::Result<T> errorResult; |
179 | errorResult.errorReason = KPluginFactory::ResultErrorReason::INVALID_PLUGIN; |
180 | Private::getErrorStrings(errorString: &errorResult.errorString, errorText: &errorResult.errorText, argument: mimeType, type: Private::NoPartFoundForMimeType); |
181 | |
182 | return errorResult; |
183 | } |
184 | |
185 | for (const KPluginMetaData &plugin : plugins) { |
186 | if (const auto result = instantiatePart<T>(plugin, parentWidget, parent, args)) { |
187 | return result; |
188 | } |
189 | } |
190 | |
191 | KPluginFactory::Result<T> errorResult; |
192 | errorResult.errorReason = KPluginFactory::ResultErrorReason::INVALID_PLUGIN; |
193 | Private::getErrorStrings(errorString: &errorResult.errorString, errorText: &errorResult.errorText, argument: mimeType, type: Private::NoPartInstantiatedForMimeType); |
194 | |
195 | return errorResult; |
196 | } |
197 | |
198 | } // namespace |
199 | } // namespace |
200 | |
201 | Q_DECLARE_METATYPE(KParts::PartCapabilities) |
202 | |
203 | #endif |
204 | |