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 | /** |
20 | * Helper methods for locating and loading parts. |
21 | * This is based upon KPluginFactory, but it takes |
22 | * care of querying by mimetype, sorting the available parts by builtin |
23 | * preference and by user preference. |
24 | * @since 5.69 |
25 | */ |
26 | namespace PartLoader |
27 | { |
28 | namespace Private |
29 | { |
30 | |
31 | enum ErrorType { |
32 | CouldNotLoadPlugin, |
33 | NoPartFoundForMimeType, |
34 | NoPartInstantiatedForMimeType, |
35 | }; |
36 | |
37 | /** |
38 | * @internal |
39 | * @param errorString translated, user-visible error string |
40 | * @param errorText untranslated error text |
41 | * @param argument argument for the text |
42 | */ |
43 | KPARTS_EXPORT void getErrorStrings(QString *errorString, QString *errorText, const QString &argument, ErrorType type); |
44 | |
45 | } |
46 | |
47 | /** |
48 | * Locate all available KParts using KPluginMetaData::findPlugins for a mimetype. |
49 | * @return a list of plugin metadata, sorted by preference. |
50 | * This takes care both of the builtin preference (set by developers) |
51 | * and of user preference (stored in mimeapps.list). |
52 | * |
53 | * To load a part from one of the KPluginMetaData instances returned here, |
54 | * use \ref instantiatePart() |
55 | * |
56 | * @since 5.69 |
57 | */ |
58 | KPARTS_EXPORT QList<KPluginMetaData> partsForMimeType(const QString &mimeType); |
59 | |
60 | /** |
61 | * Attempts to create a KPart from the given metadata. |
62 | * |
63 | * @code |
64 | * if (auto result = KParts::PartLoader::instantiatePart<MyPart>(metaData, parentWidget, parent, args)) { |
65 | * // result.plugin is valid and can be accessed |
66 | * } else { |
67 | * // result contains information about the error |
68 | * } |
69 | * @endcode |
70 | * @param data KPluginMetaData from which the plugin should be loaded |
71 | * @param parentWidget The parent widget |
72 | * @param parent The parent object |
73 | * @param args A list of arguments to be passed to the part |
74 | * @return Result object which contains the plugin instance and potentially error information |
75 | * @since 5.100 |
76 | */ |
77 | template<typename T> |
78 | static KPluginFactory::Result<T> |
79 | instantiatePart(const KPluginMetaData &data, QWidget *parentWidget = nullptr, QObject *parent = nullptr, const QVariantList &args = {}) |
80 | { |
81 | KPluginFactory::Result<T> result; |
82 | KPluginFactory::Result<KPluginFactory> factoryResult = KPluginFactory::loadFactory(data); |
83 | if (!factoryResult.plugin) { |
84 | result.errorString = factoryResult.errorString; |
85 | result.errorReason = factoryResult.errorReason; |
86 | return result; |
87 | } |
88 | T *instance = factoryResult.plugin->create<T>(parentWidget, parent, args); |
89 | if (!instance) { |
90 | const QString fileName = data.fileName(); |
91 | Private::getErrorStrings(errorString: &result.errorString, errorText: &result.errorText, argument: fileName, type: Private::CouldNotLoadPlugin); |
92 | result.errorReason = KPluginFactory::INVALID_KPLUGINFACTORY_INSTANTIATION; |
93 | } else { |
94 | result.plugin = instance; |
95 | } |
96 | return result; |
97 | } |
98 | |
99 | /** |
100 | * Use this method to create a KParts part. It will try to create an object which inherits |
101 | * @p T. |
102 | * |
103 | * @code |
104 | * if (auto result = KParts::PartLoader::instantiatePartForMimeType<KParts::ReadOnlyPart>(mimeType, parentWidget, parent, args)) { |
105 | * // result.plugin is valid and can be accessed |
106 | * } else { |
107 | * // result contains information about the error |
108 | * } |
109 | * @endcode |
110 | * |
111 | * @tparam T The interface for which an object should be created. The object will inherit @p T. |
112 | * @param mimeType The mimetype for which we need a KParts. |
113 | * @param parentWidget The parent widget for the part's widget. |
114 | * @param parent The parent of the part. |
115 | * @return Result object which contains the plugin instance and potentially error information |
116 | * @since 5.100 |
117 | */ |
118 | template<class T> |
119 | static KPluginFactory::Result<T> |
120 | instantiatePartForMimeType(const QString &mimeType, QWidget *parentWidget = nullptr, QObject *parent = nullptr, const QVariantList &args = {}) |
121 | { |
122 | const QList<KPluginMetaData> plugins = KParts::PartLoader::partsForMimeType(mimeType); |
123 | if (plugins.isEmpty()) { |
124 | KPluginFactory::Result<T> errorResult; |
125 | errorResult.errorReason = KPluginFactory::ResultErrorReason::INVALID_PLUGIN; |
126 | Private::getErrorStrings(errorString: &errorResult.errorString, errorText: &errorResult.errorText, argument: mimeType, type: Private::NoPartFoundForMimeType); |
127 | |
128 | return errorResult; |
129 | } |
130 | |
131 | for (const KPluginMetaData &plugin : plugins) { |
132 | if (const auto result = instantiatePart<T>(plugin, parentWidget, parent, args)) { |
133 | return result; |
134 | } |
135 | } |
136 | |
137 | KPluginFactory::Result<T> errorResult; |
138 | errorResult.errorReason = KPluginFactory::ResultErrorReason::INVALID_PLUGIN; |
139 | Private::getErrorStrings(errorString: &errorResult.errorString, errorText: &errorResult.errorText, argument: mimeType, type: Private::NoPartInstantiatedForMimeType); |
140 | |
141 | return errorResult; |
142 | } |
143 | |
144 | } // namespace |
145 | } // namespace |
146 | |
147 | #endif |
148 | |