File indexing completed on 2024-05-12 03:57:42

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 #ifndef KPARTS_PARTLOADER_H
0009 #define KPARTS_PARTLOADER_H
0010 
0011 #include <KPluginFactory>
0012 #include <KPluginMetaData>
0013 #include <QList>
0014 #include <QObject>
0015 #include <kparts/kparts_export.h>
0016 
0017 namespace KParts
0018 {
0019 /**
0020  * Helper methods for locating and loading parts.
0021  * This is based upon KPluginFactory, but it takes
0022  * care of querying by mimetype, sorting the available parts by builtin
0023  * preference and by user preference.
0024  * @since 5.69
0025  */
0026 namespace PartLoader
0027 {
0028 namespace Private
0029 {
0030 
0031 enum ErrorType {
0032     CouldNotLoadPlugin,
0033     NoPartFoundForMimeType,
0034     NoPartInstantiatedForMimeType,
0035 };
0036 
0037 /**
0038  * @internal
0039  * @param errorString translated, user-visible error string
0040  * @param errorText untranslated error text
0041  * @param argument argument for the text
0042  */
0043 KPARTS_EXPORT void getErrorStrings(QString *errorString, QString *errorText, const QString &argument, ErrorType type);
0044 
0045 }
0046 
0047 /**
0048  * Locate all available KParts using KPluginMetaData::findPlugins for a mimetype.
0049  * @return a list of plugin metadata, sorted by preference.
0050  * This takes care both of the builtin preference (set by developers)
0051  * and of user preference (stored in mimeapps.list).
0052  *
0053  * To load a part from one of the KPluginMetaData instances returned here,
0054  * use \ref instantiatePart()
0055  *
0056  * @since 5.69
0057  */
0058 KPARTS_EXPORT QList<KPluginMetaData> partsForMimeType(const QString &mimeType);
0059 
0060 /**
0061  * Attempts to create a KPart from the given metadata.
0062  *
0063  * @code
0064  * if (auto result = KParts::PartLoader::instantiatePart<MyPart>(metaData, parentWidget, parent, args)) {
0065  *     // result.plugin is valid and can be accessed
0066  * } else {
0067  *     // result contains information about the error
0068  * }
0069  * @endcode
0070  * @param data KPluginMetaData from which the plugin should be loaded
0071  * @param parentWidget The parent widget
0072  * @param parent The parent object
0073  * @param args A list of arguments to be passed to the part
0074  * @return Result object which contains the plugin instance and potentially error information
0075  * @since 5.100
0076  */
0077 template<typename T>
0078 static KPluginFactory::Result<T>
0079 instantiatePart(const KPluginMetaData &data, QWidget *parentWidget = nullptr, QObject *parent = nullptr, const QVariantList &args = {})
0080 {
0081     KPluginFactory::Result<T> result;
0082     KPluginFactory::Result<KPluginFactory> factoryResult = KPluginFactory::loadFactory(data);
0083     if (!factoryResult.plugin) {
0084         result.errorString = factoryResult.errorString;
0085         result.errorReason = factoryResult.errorReason;
0086         return result;
0087     }
0088     T *instance = factoryResult.plugin->create<T>(parentWidget, parent, args);
0089     if (!instance) {
0090         const QString fileName = data.fileName();
0091         Private::getErrorStrings(&result.errorString, &result.errorText, fileName, Private::CouldNotLoadPlugin);
0092         result.errorReason = KPluginFactory::INVALID_KPLUGINFACTORY_INSTANTIATION;
0093     } else {
0094         result.plugin = instance;
0095     }
0096     return result;
0097 }
0098 
0099 /**
0100  * Use this method to create a KParts part. It will try to create an object which inherits
0101  * @p T.
0102  *
0103  * @code
0104  * if (auto result = KParts::PartLoader::instantiatePartForMimeType<KParts::ReadOnlyPart>(mimeType, parentWidget, parent, args)) {
0105  *     // result.plugin is valid and can be accessed
0106  * } else {
0107  *     // result contains information about the error
0108  * }
0109  * @endcode
0110  *
0111  * @tparam T The interface for which an object should be created. The object will inherit @p T.
0112  * @param mimeType The mimetype for which we need a KParts.
0113  * @param parentWidget The parent widget for the part's widget.
0114  * @param parent The parent of the part.
0115  * @return Result object which contains the plugin instance and potentially error information
0116  * @since 5.100
0117  */
0118 template<class T>
0119 static KPluginFactory::Result<T>
0120 instantiatePartForMimeType(const QString &mimeType, QWidget *parentWidget = nullptr, QObject *parent = nullptr, const QVariantList &args = {})
0121 {
0122     const QList<KPluginMetaData> plugins = KParts::PartLoader::partsForMimeType(mimeType);
0123     if (plugins.isEmpty()) {
0124         KPluginFactory::Result<T> errorResult;
0125         errorResult.errorReason = KPluginFactory::ResultErrorReason::INVALID_PLUGIN;
0126         Private::getErrorStrings(&errorResult.errorString, &errorResult.errorText, mimeType, Private::NoPartFoundForMimeType);
0127 
0128         return errorResult;
0129     }
0130 
0131     for (const KPluginMetaData &plugin : plugins) {
0132         if (const auto result = instantiatePart<T>(plugin, parentWidget, parent, args)) {
0133             return result;
0134         }
0135     }
0136 
0137     KPluginFactory::Result<T> errorResult;
0138     errorResult.errorReason = KPluginFactory::ResultErrorReason::INVALID_PLUGIN;
0139     Private::getErrorStrings(&errorResult.errorString, &errorResult.errorText, mimeType, Private::NoPartInstantiatedForMimeType);
0140 
0141     return errorResult;
0142 }
0143 
0144 } // namespace
0145 } // namespace
0146 
0147 #endif