1 /*
2     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
3     SPDX-FileCopyrightText: 2004, 2007 Alexander Dymo <adymo@kdevelop.org>
4     SPDX-FileCopyrightText: 2006 Matt Rogers <mattr@kde.org
5 
6     Based on code from Kopete
7     SPDX-FileCopyrightText: 2002-2003 Martijn Klingens <klingens@kde.org>
8 
9     SPDX-License-Identifier: LGPL-2.0-or-later
10 */
11 
12 #ifndef KDEVPLATFORM_PLUGINCONTROLLER_H
13 #define KDEVPLATFORM_PLUGINCONTROLLER_H
14 
15 #include <interfaces/iplugincontroller.h>
16 
17 #include "shellexport.h"
18 
19 
20 namespace KDevelop
21 {
22 class Core;
23 class CorePrivate;
24 class IPlugin;
25 class PluginControllerPrivate;
26 /**
27  * The KDevelop plugin controller.
28  * The Plugin controller is responsible for querying, loading and unloading
29  * available plugins.
30  */
31 class KDEVPLATFORMSHELL_EXPORT PluginController: public IPluginController
32 {
33     Q_OBJECT
34 friend class Core;
35 friend class CorePrivate;
36 
37 public:
38 
39     explicit PluginController(Core *core);
40 
41     ~PluginController() override;
42 
43     /**
44      * Get the plugin instance based on the ID. The ID should be whatever is
45      * in X-KDE-PluginInfo-Name
46      */
47     IPlugin* plugin(const QString& pluginId) const;
48 
49     /**
50      * Get the plugin info for a loaded plugin
51      */
52     KPluginMetaData pluginInfo( const IPlugin* ) const override;
53 
54     /**
55      * Find the KPluginMetaData structure for the given @p pluginId.
56      */
57     KPluginMetaData infoForPluginId(const QString &pluginId) const override;
58 
59     /**
60      * Get a list of currently loaded plugins
61      */
62     QList<IPlugin*> loadedPlugins() const override;
63 
64     /**
65      * Returns a uniquely specified plugin. If it isn't already loaded, it will be.
66      * @param pluginName the name of the plugin, as given in the X-KDE-PluginInfo-Name property
67      * @returns a pointer to the plugin instance or 0
68      */
69     IPlugin * loadPlugin( const QString & pluginName ) override;
70 
71     /**
72      * @brief Unloads the plugin specified by @p plugin
73      *
74      * @param plugin The name of the plugin as specified by the
75      * X-KDE-PluginInfo-Name key of the .desktop file for the plugin
76      */
77     bool unloadPlugin( const QString & plugin ) override;
78 
79     enum PluginDeletion {
80         Now,
81         Later
82     };
83 
84     /**
85      * retrieve all plugin infos
86      */
87     QVector<KPluginMetaData> allPluginInfos() const;
88 
89     /**
90      * loads not-yet-loaded plugins and unloads plugins
91      * depending on the configuration in the session\
92      */
93     void updateLoadedPlugins();
94 
95 
96     /**
97      * Queries for the plugin which supports given extension interface.
98      *
99      * All already loaded plugins will be queried and the first one to support the extension interface
100      * will be returned. Any plugin can be an extension, only "ServiceTypes=..." entry is
101      * required in .desktop file for that plugin.
102      *
103      * @param extension The extension interface
104      * @param pluginName The name of the plugin to load if multiple plugins for the extension exist, corresponds to the X-KDE-PluginInfo-Name
105      * @return A KDevelop extension plugin for given service type or 0 if no plugin supports it
106      */
107     IPlugin *pluginForExtension(const QString &extension, const QString &pluginName = {}, const QVariantMap& constraints = QVariantMap()) override;
108 
109     QList<IPlugin*> allPluginsForExtension(const QString &extension, const QVariantMap& constraints = QVariantMap()) override;
110 
111     QStringList allPluginNames() const;
112 
113     QVector<KPluginMetaData> queryExtensionPlugins(const QString& extension, const QVariantMap& constraints = QVariantMap()) const override;
114 
115     QList<ContextMenuExtension> queryPluginsForContextMenuExtensions(KDevelop::Context* context, QWidget* parent) const override;
116 
117     QStringList projectPlugins() const;
118 
119     void loadProjectPlugins();
120     void unloadProjectPlugins();
121 
122     void resetToDefaults();
123 
124 private:
125     /**
126      * Directly unload the given \a plugin, either deleting it now or \a deletion.
127      *
128      * \param plugin plugin to unload
129      * \param deletion if true, delete the plugin later, if false, delete it now.
130      */
131     bool unloadPlugin(IPlugin* plugin, PluginDeletion deletion);
132 
133 
134     /**
135      * @internal
136      *
137      * The internal method for loading plugins.
138      * Called by @ref loadPlugin directly or through the queue for async plugin
139      * loading.
140      */
141     IPlugin* loadPluginInternal( const QString &pluginId );
142 
143     /**
144      * Check whether the plugin identified by @p info has unresolved dependencies.
145      *
146      * Assume a plugin depends on the interfaces Foo and Bar. Then, all available enabled
147      * plugins are queried to check whether any fulfills the interfaces. If any of the
148      * interfaces is not found, then it is inserted into @p missing and this method returns
149      * true. Otherwise, @p missing is empty and this method returns true, indicating that all
150      * dependencies can be fulfilled.
151      *
152      * @return true when there are unresolved dependencies, false otherwise.
153      */
154     bool hasUnresolvedDependencies( const KPluginMetaData& info, QStringList& missing ) const;
155 
156     bool loadDependencies(const KPluginMetaData&, QString& failedPlugin);
157     void loadOptionalDependencies(const KPluginMetaData& info);
158 
159     void cleanup();
160     virtual void initialize();
161 
162 private:
163     const QScopedPointer<class PluginControllerPrivate> d_ptr;
164     Q_DECLARE_PRIVATE(PluginController)
165 };
166 
167 }
168 #endif
169 
170 
171