SVN commit 653771 by zander: Make loading of plugins configurable. The effect is that loading of plugins (which takes time and memory) can be explicity enabled / disabled per context. The usecase here is that when the sysadmin installs a bibliographic plugin and I never use it, I can disable it from taking resoures when I start KOffice apps. M +5 -1 KoDockRegistry.cpp M +51 -10 KoPluginLoader.cpp M +32 -2 KoPluginLoader.h --- trunk/koffice/libs/kofficecore/KoDockRegistry.cpp #653770:653771 @@ -26,7 +26,11 @@ } void KoDockRegistry::init() { - KoPluginLoader::instance()->load( QString::fromLatin1("KOffice/Dock")); + KoPluginLoader::PluginsConfig config; + config.whiteList = "docker-plugins"; + config.blacklist = "disabled-docker-plugins"; + config.group = "koffice"; + KoPluginLoader::instance()->load( QString::fromLatin1("KOffice/Dock"), QString(), config); } KoDockRegistry::~KoDockRegistry() --- trunk/koffice/libs/kofficecore/KoPluginLoader.cpp #653770:653771 @@ -17,6 +17,8 @@ * Boston, MA 02110-1301, USA. */ +#include "KoPluginLoader.h" + #include #include @@ -24,12 +26,13 @@ #include #include #include +#include -#include - class KoPluginLoader::Private { public: QStringList loadedServiceTypes; + + static KoPluginLoader *singleton; }; KoPluginLoader::KoPluginLoader() @@ -42,35 +45,66 @@ delete d; } -KoPluginLoader *KoPluginLoader::m_singleton = 0; -static KStaticDeleter staticShapeRegistryDeleter; +KoPluginLoader *KoPluginLoader::Private::singleton = 0; +static KStaticDeleter pluginLoaderStatic; KoPluginLoader* KoPluginLoader::instance() { - if(KoPluginLoader::m_singleton == 0) + if(KoPluginLoader::Private::singleton == 0) { - staticShapeRegistryDeleter.setObject(m_singleton, new KoPluginLoader()); + pluginLoaderStatic.setObject(Private::singleton, new KoPluginLoader()); } - return KoPluginLoader::m_singleton; + return KoPluginLoader::Private::singleton; } -void KoPluginLoader::load(const QString & serviceType, const QString & versionString) -{ +void KoPluginLoader::load(const QString & serviceType, const QString & versionString, const PluginsConfig &config) { // Don't load the same plugins again if (d->loadedServiceTypes.contains(serviceType)) { return; } + // kDebug() << "KoPluginLoader::load " << serviceType << kBacktrace() << endl; d->loadedServiceTypes << serviceType; QString query = QString::fromLatin1("(Type == 'Service')"); if(! versionString.isEmpty()) query += QString::fromLatin1(" and (%1)").arg(versionString); const KService::List offers = KServiceTypeTrader::self()->query(serviceType, query); + KService::List plugins; + bool configChanged = false; + QList blacklist; // what we will save out afterwards + if(config.whiteList && config.blacklist && config.group) { + kDebug(30003) << "loading " << serviceType << " with checking the config\n"; + KConfigGroup configGroup = KGlobal::config()->group(config.group); + QList whiteList = configGroup.readEntry(config.whiteList, config.defaults); + QList knownList; - foreach(KService::Ptr service, offers) { + // if there was no list of defaults; all plugins are loaded. + const bool firstStart = !config.defaults.isEmpty() && !configGroup.hasKey(config.whiteList); + knownList = configGroup.readEntry(config.blacklist, knownList); + if(firstStart) + configChanged = true; + + foreach(KSharedPtr service, offers) { + QString lib = service->library(); + if(whiteList.contains(lib)) + plugins.append(service); + else if(!firstStart && !blacklist.contains(lib)) { // also load newly installed plugins. + plugins.append(service); + configChanged = true; + } + else + blacklist << service->library(); + } + } + else + plugins = offers; + + QList whiteList; + foreach(KSharedPtr service, plugins) { int errCode = 0; QObject * plugin = KService::createInstance(service, this, QStringList(), &errCode ); if ( plugin ) { + whiteList << service->library(); kDebug(30003) << "Loaded plugin " << service->name() << endl; delete plugin; } @@ -78,5 +112,12 @@ kWarning(30003) <<"loading plugin '" << service->name() << "' failed, "<< KLibLoader::errorString( errCode ) << " ("<< errCode << ")\n"; } } + + if(configChanged && config.whiteList && config.blacklist && config.group) { + KConfigGroup configGroup = KGlobal::config()->group(config.group); + configGroup.writeEntry(config.whiteList, whiteList); + configGroup.writeEntry(config.blacklist, blacklist); + } } + #include "KoPluginLoader.moc" --- trunk/koffice/libs/kofficecore/KoPluginLoader.h #653770:653771 @@ -68,6 +68,29 @@ Q_OBJECT public: + /** + * Config object for load() + * It is possible to limit which plugins will be loaded in the KConfig configuration file by + * stating explicitly which plugins are wanted. + */ + struct PluginsConfig { + PluginsConfig() : group(0), whiteList(0), blacklist(0) {} + /** + * The properties are retrieved from the config using the following construct; + * /code + * KConfigGroup configGroup = KGlobal::config()->group(config.group); + * /endcode + * For most cases you can pass the string "koffice" into this variable. + */ + const char * group; + /// This contains the variable name for the list of plugins (by library name) the user wants to load + const char * whiteList; + /// This contains the variable name for the list of plugins (by library name) that will not be loaded + const char * blacklist; + /// A registry can state it wants to load a default set of plugins instead of all plugins + /// when the application starts the first time. Append all such plugin (library) names to this list. + QStringList defaults; + }; ~KoPluginLoader(); @@ -81,8 +104,16 @@ * Load all plugins that conform to the versiontype and versionstring, * for instance: * KoPluginLoader::instance()->load("KOffice/Flake", "([X-Flake-Version] == 3)"); + * This method allows you to optionally limit the plugins that are loaded by version, but also + * using a user configurable set of config options. + * If you pass a PluginsConfig struct only those plugins are loaded that are specified in the + * application config file. New plugins found since last start will be automatically loaded. + * @param serviceType The string used to identify the plugins. + * @param versionString A string match that allows you to check for a specific version + * @param config when passing a valid config only the wanted plugins are actually loaded + * @return a list of services (by library name) that were not know in the config */ - void load(const QString & serviceType, const QString & versionString = QString()); + void load(const QString & serviceType, const QString & versionString = QString(), const PluginsConfig &config = PluginsConfig() ); private: KoPluginLoader(); @@ -90,7 +121,6 @@ KoPluginLoader operator=(const KoPluginLoader&); private: - static KoPluginLoader *m_singleton; class Private; Private * const d; };