move all plugin loading to the PluginLoader class.

svn path=/trunk/KDE/kdelibs/; revision=1150409
This commit is contained in:
Aaron J. Seigo 2010-07-15 21:38:56 +00:00
parent fd71ff404b
commit a6155e5659
7 changed files with 249 additions and 172 deletions

View File

@ -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::load(const QString &appletName, uint appletId, const QVariantList &args)
{ {
Applet* applet = 0; return PluginLoader::pluginLoader()->loadApplet(appletName, appletId, args);
// 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<Plasma::Applet>(0, allArgs, &error);
}
if (!applet) {
kDebug() << "Couldn't load applet \"" << appletName << "\"! reason given: " << error;
}
return applet;
} }
Applet *Applet::load(const KPluginInfo &info, uint appletId, const QVariantList &args) Applet *Applet::load(const KPluginInfo &info, uint appletId, const QVariantList &args)

View File

@ -1128,6 +1128,7 @@ class PLASMA_EXPORT Applet : public QGraphicsWidget
friend class AppletHandle; friend class AppletHandle;
friend class AppletPrivate; friend class AppletPrivate;
friend class AccessAppletJobPrivate; friend class AccessAppletJobPrivate;
friend class PluginLoader;
friend class PopupApplet; friend class PopupApplet;
friend class PopupAppletPrivate; friend class PopupAppletPrivate;
friend class AssociatedApplicationManager; friend class AssociatedApplicationManager;

View File

@ -112,49 +112,16 @@ Plasma::DataEngine *DataEngineManager::engine(const QString &name) const
Plasma::DataEngine *DataEngineManager::loadEngine(const QString &name) Plasma::DataEngine *DataEngineManager::loadEngine(const QString &name)
{ {
Plasma::DataEngine *engine = 0;
Plasma::DataEngine::Dict::const_iterator it = d->engines.constFind(name); 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()) { if (it != d->engines.constEnd()) {
engine = *it; DataEngine *engine = *it;
engine->d->ref(); engine->d->ref();
return engine; return engine;
} }
// load the engine, add it to the engines DataEngine *engine = PluginLoader::pluginLoader()->loadDataEngine(name);
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<Plasma::DataEngine>(0, allArgs, &error);
}
}
} else {
engine = new DataEngine(0, offers.first());
}
}
if (!engine) { if (!engine) {
kDebug() << "Couldn't load engine \"" << name << "\". Error given: " << error;
return d->nullEngine(); return d->nullEngine();
} }

View File

@ -18,8 +18,19 @@
*/ */
#include "pluginloader.h" #include "pluginloader.h"
#include <kglobal.h>
#include <kdebug.h> #include <kdebug.h>
#include <kglobal.h>
#include <kservice.h>
#include <kservicetypetrader.h>
#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 { namespace Plasma {
@ -37,28 +48,202 @@ PluginLoader::~PluginLoader()
void PluginLoader::setPluginLoader(PluginLoader* loader) void PluginLoader::setPluginLoader(PluginLoader* loader)
{ {
if(!s_pluginLoader) { if (!s_pluginLoader) {
s_pluginLoader = loader; s_pluginLoader = loader;
} else { } 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; return s_pluginLoader;
} }
Applet* PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args) Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args)
{ Q_UNUSED(name) Q_UNUSED(appletId) Q_UNUSED(args) return 0; {
// 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<Plasma::Applet>(0, allArgs, &error);
}
if (!applet) {
kDebug() << "Couldn't load applet \"" << name << "\"! reason given: " << error;
}
return applet;
} }
DataEngine* PluginLoader::loadDataEngine(const QString &name) DataEngine *PluginLoader::loadDataEngine(const QString &name)
{ Q_UNUSED(name) return 0; {
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<Plasma::DataEngine>(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) Service *PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent)
{ Q_UNUSED(name) Q_UNUSED(args) Q_UNUSED(parent) return 0; {
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<Plasma::Service>(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 } // Plasma Namespace

View File

@ -55,7 +55,7 @@ public:
* @param args to send the applet extra arguments * @param args to send the applet extra arguments
* @return a pointer to the loaded applet, or 0 on load failure * @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()); const QVariantList &args = QVariantList());
/** /**
@ -64,7 +64,7 @@ public:
* @param name the name of the engine * @param name the name of the engine
* @return the data engine that was loaded, or the NullEngine on failure. * @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. * 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. * @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. * Set the plugin loader which will be queried for all loads.
@ -90,6 +90,50 @@ public:
**/ **/
static PluginLoader* pluginLoader(); 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: private:
PluginLoaderPrivate * const d; PluginLoaderPrivate * const d;
}; };

View File

@ -72,46 +72,7 @@ Service *Service::load(const QString &name, QObject *parent)
Service *Service::load(const QString &name, const QVariantList &args, QObject *parent) Service *Service::load(const QString &name, const QVariantList &args, QObject *parent)
{ {
//TODO: scripting API support return PluginLoader::pluginLoader()->loadService(name, args, parent);
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<Plasma::Service>(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;
} }
Service *Service::access(const KUrl &url, QObject *parent) Service *Service::access(const KUrl &url, QObject *parent)

View File

@ -309,6 +309,7 @@ private:
friend class PackagePrivate; friend class PackagePrivate;
friend class ServiceProvider; friend class ServiceProvider;
friend class RemoveService; friend class RemoveService;
friend class PluginLoader;
}; };
} // namespace Plasma } // namespace Plasma