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
17namespace 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 */
26namespace PartLoader
27{
28namespace Private
29{
30
31enum 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 */
43KPARTS_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 */
58KPARTS_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 */
77template<typename T>
78static KPluginFactory::Result<T>
79instantiatePart(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 */
118template<class T>
119static KPluginFactory::Result<T>
120instantiatePartForMimeType(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

source code of kparts/src/partloader.h