1 /* 2 kopetepluginmanager.h - Kopete Plugin Loader 3 4 Copyright (c) 2002-2003 by Duncan Mac-Vicar Prett <duncan@kde.org> 5 Copyright (c) 2002-2003 by Martijn Klingens <klingens@kde.org> 6 7 Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org> 8 9 ************************************************************************* 10 * * 11 * This library is free software; you can redistribute it and/or * 12 * modify it under the terms of the GNU Lesser General Public * 13 * License as published by the Free Software Foundation; either * 14 * version 2 of the License, or (at your option) any later version. * 15 * * 16 ************************************************************************* 17 */ 18 19 #ifndef KOPETEPLUGINMANAGER_H 20 #define KOPETEPLUGINMANAGER_H 21 22 #include <QObject> 23 #include <QList> 24 #include "libkopete_export.h" 25 26 class KPluginInfo; 27 28 namespace Kopete { 29 class Plugin; 30 class Protocol; 31 typedef QList<Plugin *> PluginList; 32 class PluginManagerPrivate; 33 34 /** 35 * @author Duncan Mac-Vicar Prett <duncan@kde.org> 36 * @author Martijn Klingens <klingens@kde.org> 37 */ 38 class LIBKOPETE_EXPORT PluginManager : public QObject 39 { 40 friend class PluginManagerPrivate; 41 Q_OBJECT 42 Q_ENUMS(PluginLoadMode) 43 44 public: 45 /** 46 * Retrieve the plugin loader instance. 47 */ 48 static PluginManager *self(); 49 50 /** 51 * Returns a list of all available plugins for the given category. 52 * Currently there are two categories, "Plugins" and "Protocols", but 53 * you can add your own categories if you want. 54 * 55 * If you pass an empty string you get the complete list of ALL plugins. 56 * 57 * You can query all information on the plugins through the KPluginInfo 58 * interface. 59 */ 60 QList<KPluginInfo> availablePlugins(const QString &category = QString()) const; 61 62 /** 63 * Returns a list of all plugins that are actually loaded. 64 * If you omit the category you get all, otherwise it's a filtered list. 65 * See also @ref availablePlugins(). 66 */ 67 PluginList loadedPlugins(const QString &category = QString()) const; 68 69 /** 70 * @brief Search by plugin name. This is the key used as X-KDE-PluginInfo-Name in 71 * the .desktop file, e.g. "kopete_jabber" 72 * 73 * @return The @ref Kopete::Plugin object found by the search, or a null 74 * pointer if the plugin is not loaded. 75 * 76 * If you want to also load the plugin you can better use @ref loadPlugin, which returns 77 * the pointer to the plugin if it's already loaded. 78 */ 79 Plugin *plugin(const QString &pluginName) const; 80 81 /** 82 * @return the KPluginInfo for the specified plugin 83 */ 84 KPluginInfo pluginInfo(const Kopete::Plugin *plugin) const; 85 86 /** 87 * Shuts down the plugin manager on Kopete shutdown, but first 88 * unloads all plugins asynchronously. 89 * 90 * After 3 seconds all plugins should be removed; what's still left 91 * by then is unloaded through a hard delete instead. 92 * 93 * Note that this call also derefs the plugin manager from the event 94 * loop, so do NOT call this method when not terminating Kopete! 95 */ 96 void shutdown(); 97 98 /** 99 * Enable a plugin. 100 * 101 * This marks a plugin as enabled in the config file, so loadAll() 102 * can pick it up later. 103 * 104 * This method does not actually load a plugin, it only edits the 105 * config file. 106 * 107 * @param name is the name of the plugin as it is listed in the .desktop 108 * file in the X-KDE-Library field. 109 * @param enabled sets whether or not the plugin is enabled 110 * 111 * Returns false when no appropriate plugin can be found. 112 */ 113 bool setPluginEnabled(const QString &name, bool enabled = true); 114 115 /** 116 * This method check if all the plugins are loaded. 117 * @return true if all the plugins are loaded. 118 */ 119 bool isAllPluginsLoaded() const; 120 121 /** 122 * Plugin loading mode. Used by @ref loadPlugin(). Code that doesn't want to block 123 * the GUI and/or lot a lot of plugins at once should use asynchronous loading (@c LoadAsync). 124 * The default is synchronous loading (@c LoadSync). 125 */ 126 enum PluginLoadMode { 127 LoadSync, LoadAsync 128 }; 129 130 public Q_SLOTS: 131 /** 132 * @brief Load a single plugin by plugin name. Returns an existing plugin 133 * if one is already loaded in memory. 134 * 135 * If mode is set to Async, the plugin will be queued and loaded in 136 * the background. This method will return a null pointer. To get 137 * the loaded plugin you can track the @ref pluginLoaded() signal. 138 * 139 * See also @ref plugin(). 140 */ 141 Plugin *loadPlugin(const QString &pluginId, PluginLoadMode mode = LoadSync); 142 143 /** 144 * @brief Unload the plugin specified by @p pluginName 145 */ 146 bool unloadPlugin(const QString &pluginName); 147 148 /** 149 * @brief Loads all the enabled plugins. Also used to reread the 150 * config file when the configuration has changed. 151 */ 152 void loadAllPlugins(); 153 154 Q_SIGNALS: 155 /** 156 * @brief Signals a new plugin has just been loaded. 157 */ 158 void pluginLoaded(Kopete::Plugin *plugin); 159 160 /** 161 * @brief Signals a plugin has just been unloaded. 162 */ 163 void pluginUnloaded(const QString &pluginName); 164 165 /** 166 * @brief Signals a new protocol has just been loaded. 167 * @note pluginLoaded is also emitted before this signal 168 */ 169 void protocolLoaded(Kopete::Protocol *protocol); 170 171 /** 172 * @brief All plugins have been loaded by the plugin manager. 173 * 174 * This signal is emitted exactly ONCE, when the plugin manager has emptied 175 * its plugin queue for the first time. This means that if you call an async 176 * loadPlugin() before loadAllPlugins() this signal is probably emitted after 177 * the initial call completes, unless you are quick enough to fill the queue 178 * before it completes, which is a dangerous race you shouldn't count upon :) 179 * 180 * The signal is delayed one event loop iteration through a singleShot timer, 181 * but that is not guaranteed to be enough for account instantiation. You may 182 * need an additional timer for it in the code if you want to programmatically 183 * act on it. 184 * 185 * If you use the signal for enabling/disabling GUI objects there is little 186 * chance a user is able to activate them in the short while that's remaining, 187 * the slow part of the code is over now and the remaining processing time 188 * is neglectable for the user. 189 */ 190 void allPluginsLoaded(); 191 192 private Q_SLOTS: 193 /** 194 * @brief Cleans up some references if the plugin is destroyed 195 */ 196 void slotPluginDestroyed(QObject *plugin); 197 198 /** 199 * shutdown() starts a timer, when it fires we force all plugins 200 * to be unloaded here by deref()-ing the event loop to trigger the plugin 201 * manager's destruction 202 */ 203 void slotShutdownTimeout(); 204 205 /** 206 * Common entry point to deref() the KApplication. Used both by the clean 207 * shutdown and the timeout condition of slotShutdownTimeout() 208 */ 209 void slotShutdownDone(); 210 211 /** 212 * Emitted by a Kopete::Plugin when it's ready for unload 213 */ 214 void slotPluginReadyForUnload(); 215 216 /** 217 * Load a plugin from our queue. Does nothing if the queue is empty. 218 * Schedules itself again if more plugins are pending. 219 */ 220 void slotLoadNextPlugin(); 221 222 private: 223 /** 224 * @internal 225 * 226 * The internal method for loading plugins. 227 * Called by @ref loadPlugin directly or through the queue for async plugin 228 * loading. 229 */ 230 Plugin *loadPluginInternal(const QString &pluginId); 231 232 /** 233 * @internal 234 * 235 * Find the KPluginInfo structure by key. Reduces some code duplication. 236 * 237 * Returns a null pointer when no plugin info is found. 238 */ 239 KPluginInfo infoForPluginId(const QString &pluginId) const; 240 241 PluginManager(); 242 ~PluginManager(); 243 }; 244 } 245 246 #endif // KOPETEPLUGINMANAGER_H 247 248 // vim: set noet ts=4 sts=4 sw=4: 249