File indexing completed on 2024-04-28 04:36:30

0001 /*
0002     SPDX-FileCopyrightText: 2004, 2007 Alexander Dymo <adymo@kdevelop.org>
0003     SPDX-FileCopyrightText: 2006 Matt Rogers <mattr@kde.org>
0004     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0005 
0006     Based on code from Kopete
0007     SPDX-FileCopyrightText: 2002-2003 Martijn Klingens <klingens@kde.org>
0008 
0009     SPDX-License-Identifier: LGPL-2.0-or-later
0010 */
0011 
0012 #ifndef KDEVPLATFORM_IPLUGINCONTROLLER_H
0013 #define KDEVPLATFORM_IPLUGINCONTROLLER_H
0014 
0015 #include <QObject>
0016 #include <QList>
0017 #include <QVector>
0018 #include <QVariant>
0019 
0020 #include <KPluginMetaData>
0021 
0022 #include "iplugin.h"
0023 #include "interfacesexport.h"
0024 
0025 class QExtensionManager;
0026 
0027 namespace KDevelop
0028 {
0029 class ProfileEngine;
0030 
0031 /**
0032  * The KDevelop plugin controller.
0033  * The Plugin controller is responsible for querying, loading and unloading
0034  * available plugins.
0035  *
0036  * Most of the time if you want to get at a plugin you should be using
0037  * extensionForPlugin with the extension interface name. If you need to get at
0038  * the actual \c IPlugin* pointer to connect signals/slots you should use
0039  * \c pluginForExtension() and then the IPlugin's extension member function to get
0040  * at the extension interface if necessary.
0041  *
0042  * If you have the need to load a specific plugin for a given extension both
0043  * functions have an optional second parameter that allows one to specify the
0044  * name of the plugin as declared in the \c .desktop file under the
0045  * \c X-KDE-PluginInfo-Name property. This should be used only very seldomly in
0046  * real code and is mostly meant for testing and for implementation in the
0047  * shell as it makes the code dependent on the plugin name which may change and
0048  * also the actual plugin implementation so users cannot exchange one plugin
0049  * with another also implementing the same interface.
0050  *
0051  */
0052 class KDEVPLATFORMINTERFACES_EXPORT IPluginController : public QObject
0053 {
0054 
0055 Q_OBJECT
0056 
0057 public:
0058     /**
0059      * \brief Indicates the plugin type
0060      * This is used to determine how the plugin is loaded
0061      */
0062     enum PluginType {
0063         Global = 0, ///< Indicates that the plugin is loaded at startup
0064         Project ///< Indicates that the plugin is loaded with the first opened project
0065     };
0066 
0067     explicit IPluginController( QObject* parent = nullptr );
0068 
0069     ~IPluginController() override;
0070 
0071     /**
0072      * Get the plugin info for a loaded plugin
0073      */
0074     virtual KPluginMetaData pluginInfo(const IPlugin*) const = 0;
0075 
0076     /**
0077      * Find the KPluginMetaData structure for the given @p pluginId.
0078      */
0079     virtual KPluginMetaData infoForPluginId(const QString &pluginId) const = 0;
0080 
0081     /**
0082      * Get a list of currently loaded plugins
0083      */
0084     virtual QList<IPlugin*> loadedPlugins() const = 0;
0085 
0086     /**
0087      * @brief Unloads the plugin specified by @p plugin
0088      *
0089      * @param plugin The name of the plugin as specified by the
0090      * X-KDE-PluginInfo-Name key of the .desktop file for the plugin
0091      */
0092     virtual bool unloadPlugin( const QString & plugin ) = 0;
0093 
0094     /**
0095      * @brief Loads the plugin specified by @p pluginName
0096      *
0097      * @param pluginName the name of the plugin, as given in the X-KDE-PluginInfo-Name property
0098      * @returns a pointer to the plugin instance or 0
0099      */
0100     virtual IPlugin* loadPlugin( const QString & pluginName ) = 0;
0101 
0102      /**
0103      * Retrieve a plugin which supports the given extension interface.
0104      *
0105      * All already loaded plugins will be queried and the first one to support the extension interface
0106      * will be returned. Any plugin can be an extension, only the "ServiceTypes=..." entry is
0107      * required in .desktop file for that plugin.
0108      *
0109      * If no already-loaded plugin was found, we try to load a plugin for the given extension.
0110      *
0111      * If no plugin was found, a nullptr will be returned.
0112      *
0113      * @param extension The extension interface. Can be empty if you want to find a plugin by name or other constraint.
0114      * @param pluginName The name of the plugin to load if multiple plugins for the extension exist, corresponds to the X-KDE-PluginInfo-Name
0115      * @param constraints A map of constraints on other plugin info properties.
0116      * @return A KDevelop extension plugin for given service type or 0 if no plugin supports it
0117      */
0118     virtual IPlugin *pluginForExtension(const QString &extension, const QString& pluginName = {}, const QVariantMap& constraints = QVariantMap()) = 0;
0119 
0120      /**
0121      * Retrieve a list of plugins which supports the given extension interface.
0122      * All already loaded plugins will be queried and the first one to support the extension interface
0123      * will be returned. Any plugin can be an extension, only the "ServiceTypes=..." entry is
0124      * required in .desktop file for that plugin.
0125      * @param extension The extension interface
0126      * @param constraints A map of constraints on other plugin info properties.
0127      * @return A KDevelop extension plugin for given service type or 0 if no plugin supports it
0128      */
0129     virtual QList<IPlugin*> allPluginsForExtension(const QString &extension, const QVariantMap& constraints = QVariantMap()) = 0;
0130 
0131      /**
0132      * Retrieve the plugin which supports given extension interface and
0133      * returns a pointer to the extension interface.
0134      *
0135      * All already loaded plugins will be queried and the first one to support the extension interface
0136      * will be returned. Any plugin can be an extension, only "ServiceTypes=..." entry is
0137      * required in .desktop file for that plugin.
0138      * @param extension The extension interface
0139      * @param pluginName The name of the plugin to load if multiple plugins for the extension exist, corresponds to the X-KDE-PluginInfo-Name
0140      * @return Pointer to the extension interface or 0 if no plugin supports it
0141       */
0142     template<class Extension> Extension* extensionForPlugin( const QString &extension = {}, const QString &pluginName = {})
0143     {
0144         QString ext;
0145         if( extension.isEmpty() ) {
0146             ext = QString::fromUtf8(qobject_interface_iid<Extension*>());
0147         } else {
0148             ext = extension;
0149         }
0150         IPlugin *plugin = pluginForExtension(ext, pluginName);
0151         if (plugin) {
0152             return plugin->extension<Extension>();
0153         }
0154         return nullptr;
0155     }
0156 
0157     /**
0158      * Query for plugin information on KDevelop plugins implementing the given extension.
0159      *
0160      * The service version is checked for automatically and the only serviceType
0161      * searched for is "KDevelop/Plugin"
0162      *
0163      * @param extension The extension that should be implemented by the plugin, i.e. listed in X-KDevelop-Interfaces.
0164      * @param constraints A map of constraints on other plugin info properties.
0165      * @return The list of plugin offers.
0166      */
0167     virtual QVector<KPluginMetaData> queryExtensionPlugins(const QString &extension, const QVariantMap& constraints = QVariantMap()) const = 0;
0168 
0169     virtual QList<ContextMenuExtension> queryPluginsForContextMenuExtensions(KDevelop::Context* context, QWidget* parent) const = 0;
0170 
0171 Q_SIGNALS:
0172     void loadingPlugin( const QString& );
0173     void pluginLoaded( KDevelop::IPlugin* );
0174     void unloadingPlugin( KDevelop::IPlugin* );
0175     /**
0176      * This signal is emitted whenever a plugin is unloaded.
0177      * @note: that you shouldn't use the pointer anymore
0178      * except for comparing it against against other pointers. The plugin instance can already have been completely
0179      * deleted when this signal is emitted.
0180      */
0181     void pluginUnloaded( KDevelop::IPlugin* );
0182 
0183 private:
0184     friend class IPlugin;
0185 };
0186 
0187 }
0188 #endif
0189