From a6155e56593122ea96a352c98bf39bb8a0b8a0d1 Mon Sep 17 00:00:00 2001 From: "Aaron J. Seigo" Date: Thu, 15 Jul 2010 21:38:56 +0000 Subject: [PATCH] move all plugin loading to the PluginLoader class. svn path=/trunk/KDE/kdelibs/; revision=1150409 --- applet.cpp | 84 +---------------- applet.h | 1 + dataenginemanager.cpp | 39 +------- pluginloader.cpp | 205 +++++++++++++++++++++++++++++++++++++++--- pluginloader.h | 50 ++++++++++- service.cpp | 41 +-------- service.h | 1 + 7 files changed, 249 insertions(+), 172 deletions(-) diff --git a/applet.cpp b/applet.cpp index 66e059d89..f3e3f7090 100644 --- a/applet.cpp +++ b/applet.cpp @@ -2293,89 +2293,7 @@ Applet *Applet::loadPlasmoid(const QString &path, uint appletId, const QVariantL Applet *Applet::load(const QString &appletName, uint appletId, const QVariantList &args) { - Applet* applet = 0; - - // Get the plugin loader - if (PluginLoader::pluginLoader()) { - applet = PluginLoader::pluginLoader()->loadApplet(appletName, appletId, args); - if (applet) { - return applet; - } - } - - // the application-specific appletLoader failed to create an applet, here we try with our own logic. - - if (appletName.isEmpty()) { - return 0; - } - - const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); - - bool isContainment = false; - if (offers.isEmpty()) { - //TODO: what would be -really- cool is offer to try and download the applet - // from the network at this point - offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); - if (offers.count() > 0) { - isContainment = true; - } - } - - /* if (offers.count() > 1) { - kDebug() << "hey! we got more than one! let's blindly take the first one"; - } */ - - AppletPrivate::filterOffers(offers); - if (offers.isEmpty()) { - kDebug() << "offers is empty for " << appletName; - return 0; - } - - KService::Ptr offer = offers.first(); - - if (appletId == 0) { - appletId = ++AppletPrivate::s_maxAppletId; - } - - QVariantList allArgs; - allArgs << offer->storageId() << appletId << args; - - if (!offer->property("X-Plasma-API").toString().isEmpty()) { - kDebug() << "we have a script using the" - << offer->property("X-Plasma-API").toString() << "API"; - if (isContainment) { - return new Containment(0, allArgs); - } else { - if (offer->serviceTypes().contains("Plasma/PopupApplet")) { - return new PopupApplet(0, allArgs); - } else { - return new Applet(0, allArgs); - } - } - } - - KPluginLoader plugin(*offer); - - if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion()) && - (appletName != "internal:extender")) { - return 0; - } - - - QString error; - - if (appletName == "internal:extender") { - applet = new ExtenderApplet(0, allArgs); - } else { - applet = offer->createInstance(0, allArgs, &error); - } - - if (!applet) { - kDebug() << "Couldn't load applet \"" << appletName << "\"! reason given: " << error; - } - - return applet; + return PluginLoader::pluginLoader()->loadApplet(appletName, appletId, args); } Applet *Applet::load(const KPluginInfo &info, uint appletId, const QVariantList &args) diff --git a/applet.h b/applet.h index d57b08e1d..1dbde86e1 100644 --- a/applet.h +++ b/applet.h @@ -1128,6 +1128,7 @@ class PLASMA_EXPORT Applet : public QGraphicsWidget friend class AppletHandle; friend class AppletPrivate; friend class AccessAppletJobPrivate; + friend class PluginLoader; friend class PopupApplet; friend class PopupAppletPrivate; friend class AssociatedApplicationManager; diff --git a/dataenginemanager.cpp b/dataenginemanager.cpp index 6b82934b4..1056e9cb6 100644 --- a/dataenginemanager.cpp +++ b/dataenginemanager.cpp @@ -112,49 +112,16 @@ Plasma::DataEngine *DataEngineManager::engine(const QString &name) const Plasma::DataEngine *DataEngineManager::loadEngine(const QString &name) { - Plasma::DataEngine *engine = 0; Plasma::DataEngine::Dict::const_iterator it = d->engines.constFind(name); - - // Ask the application's plugin loader, if present - if (PluginLoader::pluginLoader()) { - engine = PluginLoader::pluginLoader()->loadDataEngine(name); - if (engine) { - return engine; - } - } - + if (it != d->engines.constEnd()) { - engine = *it; + DataEngine *engine = *it; engine->d->ref(); return engine; } - // load the engine, add it to the engines - QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", - constraint); - QString error; - - if (offers.isEmpty()) { - kDebug() << "offers are empty for " << name << " with constraint " << constraint; - } else { - QVariantList allArgs; - allArgs << offers.first()->storageId(); - QString api = offers.first()->property("X-Plasma-API").toString(); - if (api.isEmpty()) { - if (offers.first()) { - KPluginLoader plugin(*offers.first()); - if (Plasma::isPluginVersionCompatible(plugin.pluginVersion())) { - engine = offers.first()->createInstance(0, allArgs, &error); - } - } - } else { - engine = new DataEngine(0, offers.first()); - } - } - + DataEngine *engine = PluginLoader::pluginLoader()->loadDataEngine(name); if (!engine) { - kDebug() << "Couldn't load engine \"" << name << "\". Error given: " << error; return d->nullEngine(); } diff --git a/pluginloader.cpp b/pluginloader.cpp index a050bf18c..83acf2f7c 100644 --- a/pluginloader.cpp +++ b/pluginloader.cpp @@ -18,8 +18,19 @@ */ #include "pluginloader.h" -#include + #include +#include +#include +#include + +#include "applet.h" +#include "containment.h" +#include "packagestructure.h" +#include "popupapplet.h" +#include "private/applet_p.h" +#include "private/extenderapplet_p.h" +#include "private/service_p.h" // for NullService namespace Plasma { @@ -37,28 +48,202 @@ PluginLoader::~PluginLoader() void PluginLoader::setPluginLoader(PluginLoader* loader) { - if(!s_pluginLoader) { + if (!s_pluginLoader) { s_pluginLoader = loader; } else { - kDebug() << "Cannot set pluginLoader, already set!"; + kDebug() << "Cannot set pluginLoader, already set!" << s_pluginLoader; } } -PluginLoader* PluginLoader::pluginLoader() +PluginLoader *PluginLoader::pluginLoader() { + if (!s_pluginLoader) { + // we have been called before any PluginLoader was set, so just use the default + // implementation. this prevents plugins from nefariously injecting their own + // plugin loader if the app doesn't + s_pluginLoader = new PluginLoader; + } + return s_pluginLoader; } -Applet* PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args) -{ Q_UNUSED(name) Q_UNUSED(appletId) Q_UNUSED(args) return 0; +Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args) +{ + // the application-specific appletLoader failed to create an applet, here we try with our own logic. + if (name.isEmpty()) { + return 0; + } + + Applet *applet = internalLoadApplet(name, appletId, args); + if (applet) { + return applet; + } + + const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); + KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); + + bool isContainment = false; + if (offers.isEmpty()) { + //TODO: what would be -really- cool is offer to try and download the applet + // from the network at this point + offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); + if (offers.count() > 0) { + isContainment = true; + } + } + + /* if (offers.count() > 1) { + kDebug() << "hey! we got more than one! let's blindly take the first one"; + } */ + + AppletPrivate::filterOffers(offers); + if (offers.isEmpty()) { + kDebug() << "offers is empty for " << name; + return 0; + } + + KService::Ptr offer = offers.first(); + + if (appletId == 0) { + appletId = ++AppletPrivate::s_maxAppletId; + } + + QVariantList allArgs; + allArgs << offer->storageId() << appletId << args; + + if (!offer->property("X-Plasma-API").toString().isEmpty()) { + kDebug() << "we have a script using the" + << offer->property("X-Plasma-API").toString() << "API"; + if (isContainment) { + return new Containment(0, allArgs); + } else { + if (offer->serviceTypes().contains("Plasma/PopupApplet")) { + return new PopupApplet(0, allArgs); + } else { + return new Applet(0, allArgs); + } + } + } + + KPluginLoader plugin(*offer); + + if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion()) && + (name != "internal:extender")) { + return 0; + } + + + QString error; + if (name == "internal:extender") { + applet = new ExtenderApplet(0, allArgs); + } else { + applet = offer->createInstance(0, allArgs, &error); + } + + if (!applet) { + kDebug() << "Couldn't load applet \"" << name << "\"! reason given: " << error; + } + + return applet; } -DataEngine* PluginLoader::loadDataEngine(const QString &name) -{ Q_UNUSED(name) return 0; +DataEngine *PluginLoader::loadDataEngine(const QString &name) +{ + DataEngine *engine = internalLoadDataEngine(name); + if (engine) { + return engine; + } + + // load the engine, add it to the engines + QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); + KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", + constraint); + QString error; + + if (offers.isEmpty()) { + kDebug() << "offers are empty for " << name << " with constraint " << constraint; + } else { + QVariantList allArgs; + allArgs << offers.first()->storageId(); + QString api = offers.first()->property("X-Plasma-API").toString(); + if (api.isEmpty()) { + if (offers.first()) { + KPluginLoader plugin(*offers.first()); + if (Plasma::isPluginVersionCompatible(plugin.pluginVersion())) { + engine = offers.first()->createInstance(0, allArgs, &error); + } + } + } else { + engine = new DataEngine(0, offers.first()); + } + } + + if (!engine) { + kDebug() << "Couldn't load engine \"" << name << "\". Error given: " << error; + } + + return engine; } -Service* PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent) -{ Q_UNUSED(name) Q_UNUSED(args) Q_UNUSED(parent) return 0; +Service *PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent) +{ + Service *service = internalLoadService(name, args, parent); + if (service) { + return service; + } + + //TODO: scripting API support + if (name.isEmpty()) { + return new NullService(QString(), parent); + } + + QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); + KService::List offers = KServiceTypeTrader::self()->query("Plasma/Service", constraint); + + if (offers.isEmpty()) { + kDebug() << "offers is empty for " << name; + return new NullService(name, parent); + } + + KService::Ptr offer = offers.first(); + QString error; + + if (Plasma::isPluginVersionCompatible(KPluginLoader(*offer).pluginVersion())) { + service = offer->createInstance(parent, args, &error); + } + + if (!service) { + kDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error; + return new NullService(name, parent); + } + + if (service->name().isEmpty()) { + service->setName(name); + } + + return service; +} + +Applet* PluginLoader::internalLoadApplet(const QString &name, uint appletId, const QVariantList &args) +{ + Q_UNUSED(name) + Q_UNUSED(appletId) + Q_UNUSED(args) + return 0; +} + +DataEngine* PluginLoader::internalLoadDataEngine(const QString &name) +{ + Q_UNUSED(name) + return 0; +} + +Service* PluginLoader::internalLoadService(const QString &name, const QVariantList &args, QObject *parent) +{ + Q_UNUSED(name) + Q_UNUSED(args) + Q_UNUSED(parent) + return 0; } } // Plasma Namespace diff --git a/pluginloader.h b/pluginloader.h index f23b7c691..eb42335c3 100644 --- a/pluginloader.h +++ b/pluginloader.h @@ -55,7 +55,7 @@ public: * @param args to send the applet extra arguments * @return a pointer to the loaded applet, or 0 on load failure **/ - virtual Applet* loadApplet(const QString &name, uint appletId = 0, + virtual Applet *loadApplet(const QString &name, uint appletId = 0, const QVariantList &args = QVariantList()); /** @@ -64,7 +64,7 @@ public: * @param name the name of the engine * @return the data engine that was loaded, or the NullEngine on failure. **/ - virtual DataEngine* loadDataEngine(const QString &name); + virtual DataEngine *loadDataEngine(const QString &name); /** * Load an external Service and supply it to Plasma. @@ -75,7 +75,7 @@ public: * * @return a Service object, unlike Plasma::Service::loadService, this can return null. **/ - virtual Service* loadService(const QString &name, const QVariantList &args, QObject *parent = 0); + virtual Service *loadService(const QString &name, const QVariantList &args, QObject *parent = 0); /** * Set the plugin loader which will be queried for all loads. @@ -90,6 +90,50 @@ public: **/ static PluginLoader* pluginLoader(); +protected: + /** + * A re-implementable method that allows subclasses to override + * the default behaviour of loadApplet. If the applet requested is not recognized, + * then the implementation should return a NULL pointer. This method is called + * by loadApplet prior to attempting to load an applet using the standard Plasma + * plugin mechanisms. + * + * @param name the plugin name, as returned by KPluginInfo::pluginName() + * @param appletId unique ID to assign the applet, or zero to have one + * assigned automatically. + * @param args to send the applet extra arguments + * @return a pointer to the loaded applet, or 0 on load failure + **/ + virtual Applet *internalLoadApplet(const QString &name, uint appletId = 0, + const QVariantList &args = QVariantList()); + + /** + * A re-implementable method that allows subclasses to override + * the default behaviour of loadDataEngine. If the engine requested is not recognized, + * then the implementation should return a NULL pointer. This method is called + * by loadDataEngine prior to attempting to load a DataEgine using the standard Plasma + * plugin mechanisms. + * + * @param name the name of the engine + * @return the data engine that was loaded, or the NullEngine on failure. + **/ + virtual DataEngine *internalLoadDataEngine(const QString &name); + + /** + * A re-implementable method that allows subclasses to override + * the default behaviour of loadService. If the service requested is not recognized, + * then the implementation should return a NULL pointer. This method is called + * by loadService prior to attempting to load a Service using the standard Plasma + * plugin mechanisms. + * + * @param name the plugin name of the service to load + * @param args a list of arguments to supply to the service plugin when loading it + * @param parent the parent object, if any, for the service + * + * @return a Service object, unlike Plasma::Service::loadService, this can return null. + **/ + virtual Service *internalLoadService(const QString &name, const QVariantList &args, QObject *parent = 0); + private: PluginLoaderPrivate * const d; }; diff --git a/service.cpp b/service.cpp index 863824bf0..a201ed39c 100644 --- a/service.cpp +++ b/service.cpp @@ -72,46 +72,7 @@ Service *Service::load(const QString &name, QObject *parent) Service *Service::load(const QString &name, const QVariantList &args, QObject *parent) { - //TODO: scripting API support - if (name.isEmpty()) { - return new NullService(QString(), parent); - } - - QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Service", constraint); - - if (offers.isEmpty()) { - kDebug() << "offers is empty for " << name; - return new NullService(name, parent); - } - - KService::Ptr offer = offers.first(); - QString error; - //args << name; - Service *service = 0; - - // Ask the application's plugin loader, if present - if (PluginLoader::pluginLoader()) { - service = PluginLoader::pluginLoader()->loadService(name, args, parent); - if (service) { - return service; - } - } - - if (Plasma::isPluginVersionCompatible(KPluginLoader(*offer).pluginVersion())) { - service = offer->createInstance(parent, args, &error); - } - - if (!service) { - kDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error; - return new NullService(name, parent); - } - - if (service->name().isEmpty()) { - service->setName(name); - } - - return service; + return PluginLoader::pluginLoader()->loadService(name, args, parent); } Service *Service::access(const KUrl &url, QObject *parent) diff --git a/service.h b/service.h index 87c8220e3..5ac7e7b3a 100644 --- a/service.h +++ b/service.h @@ -309,6 +309,7 @@ private: friend class PackagePrivate; friend class ServiceProvider; friend class RemoveService; + friend class PluginLoader; }; } // namespace Plasma