allow loading of individual runners, including from packages

svn path=/trunk/KDE/kdelibs/; revision=1106782
This commit is contained in:
Aaron J. Seigo 2010-03-23 22:43:34 +00:00
parent f2e0fc2d93
commit b16960c73b
6 changed files with 183 additions and 84 deletions

View File

@ -45,16 +45,30 @@ namespace Plasma
K_GLOBAL_STATIC(QMutex, s_bigLock)
AbstractRunner::AbstractRunner(QObject *parent, const QString &serviceId)
AbstractRunner::AbstractRunner(QObject *parent, const QString &path)
: QObject(parent),
d(new AbstractRunnerPrivate(this, KService::serviceByStorageId(serviceId)))
d(new AbstractRunnerPrivate(this))
{
d->init(path);
}
AbstractRunner::AbstractRunner(const KService::Ptr service, QObject *parent)
: QObject(parent),
d(new AbstractRunnerPrivate(this))
{
d->init(service);
}
AbstractRunner::AbstractRunner(QObject *parent, const QVariantList &args)
: QObject(parent),
d(new AbstractRunnerPrivate(this, KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString())))
d(new AbstractRunnerPrivate(this))
{
if (args.count() > 0) {
KService::Ptr service = KService::serviceByStorageId(args[0].toString());
if (service) {
d->init(service);
}
}
}
AbstractRunner::~AbstractRunner()
@ -187,6 +201,7 @@ void AbstractRunner::clearActions()
QMimeData * AbstractRunner::mimeDataForMatch(const QueryMatch *match)
{
Q_UNUSED(match)
return 0;
}
@ -274,37 +289,54 @@ void AbstractRunner::match(Plasma::RunnerContext &search)
QString AbstractRunner::name() const
{
if (!d->runnerDescription.isValid()) {
return objectName();
if (d->runnerDescription.isValid()) {
return d->runnerDescription.name();
}
return d->runnerDescription.name();
if (d->package) {
return d->package->metadata().name();
}
return objectName();
}
QIcon AbstractRunner::icon() const
{
if (!d->runnerDescription.isValid()) {
return QIcon();
if (d->runnerDescription.isValid()) {
return KIcon(d->runnerDescription.icon());
}
return KIcon(d->runnerDescription.icon());
if (d->package) {
return KIcon(d->package->metadata().icon());
}
return QIcon();
}
QString AbstractRunner::id() const
{
if (!d->runnerDescription.isValid()) {
return objectName();
}
if (d->runnerDescription.isValid()) {
return d->runnerDescription.pluginName();
}
if (d->package) {
return d->package->metadata().pluginName();
}
return objectName();
}
QString AbstractRunner::description() const
{
if (!d->runnerDescription.isValid()) {
return objectName();
return d->runnerDescription.property("Comment").toString();
}
return d->runnerDescription.property("Comment").toString();
if (d->package) {
return d->package->metadata().description();
}
return objectName();
}
const Package* AbstractRunner::package() const
@ -326,37 +358,17 @@ DataEngine *AbstractRunner::dataEngine(const QString &name) const
return d->dataEngine(name);
}
AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r, KService::Ptr service)
AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r)
: priority(AbstractRunner::NormalPriority),
speed(AbstractRunner::NormalSpeed),
blackListed(0),
script(0),
runnerDescription(service),
runner(r),
fastRuns(0),
package(0),
hasRunOptions(false),
defaultSyntax(0)
{
if (runnerDescription.isValid()) {
const QString api = runnerDescription.property("X-Plasma-API").toString();
if (!api.isEmpty()) {
const QString path = KStandardDirs::locate("data",
"plasma/runners/" + runnerDescription.pluginName() + '/');
PackageStructure::Ptr structure =
Plasma::packageStructure(api, Plasma::RunnerComponent);
structure->setPath(path);
package = new Package(path, structure);
script = Plasma::loadScriptEngine(api, runner);
if (!script) {
kDebug() << "Could not create a(n)" << api << "ScriptEngine for the"
<< runnerDescription.name() << "Runner.";
delete package;
package = 0;
}
}
}
}
AbstractRunnerPrivate::~AbstractRunnerPrivate()
@ -367,6 +379,58 @@ AbstractRunnerPrivate::~AbstractRunnerPrivate()
package = 0;
}
void AbstractRunnerPrivate::init(const KService::Ptr service)
{
runnerDescription = KPluginInfo(service);
if (runnerDescription.isValid()) {
const QString api = runnerDescription.property("X-Plasma-API").toString();
if (!api.isEmpty()) {
const QString path = KStandardDirs::locate("data", "plasma/runners/" + runnerDescription.pluginName() + '/');
prepScripting(path, api);
if (!script) {
kDebug() << "Could not create a(n)" << api << "ScriptEngine for the" << runnerDescription.name() << "Runner.";
}
}
}
}
void AbstractRunnerPrivate::init(const QString &path)
{
prepScripting(path);
}
void AbstractRunnerPrivate::prepScripting(const QString &path, QString api)
{
if (script) {
return;
}
if (package) {
delete package;
}
PackageStructure::Ptr structure = Plasma::packageStructure(api, Plasma::RunnerComponent);
structure->setPath(path);
package = new Package(path, structure);
if (!package->isValid()) {
kDebug() << "Invalid Runner package at" << path;
delete package;
package = 0;
return;
}
if (api.isEmpty()) {
api = package->metadata().implementationApi();
}
script = Plasma::loadScriptEngine(api, runner);
if (!script) {
delete package;
package = 0;
}
}
// put all setup routines for script here. at this point we can assume that
// package exists and that we have a script engine
void AbstractRunnerPrivate::setupScriptSupport()

View File

@ -281,12 +281,9 @@ class PLASMA_EXPORT AbstractRunner : public QObject
friend class RunnerManager;
friend class RunnerManagerPrivate;
/**
* Constructs a Runner object. Since AbstractRunner has pure virtuals,
* this constructor can not be called directly. Rather a subclass must
* be created
*/
explicit AbstractRunner(QObject *parent = 0, const QString &serviceId = QString());
explicit AbstractRunner(QObject *parent = 0, const QString &path = QString());
explicit AbstractRunner(const KService::Ptr service, QObject *parent = 0);
AbstractRunner(QObject *parent, const QVariantList &args);
/**

View File

@ -111,7 +111,7 @@ class PLASMA_EXPORT Applet : public QGraphicsWidget
~Applet();
/**
* @return a package structure representing a Theme
* @return a package structure representing an Applet
*/
static PackageStructure::Ptr packageStructure();

View File

@ -32,8 +32,11 @@ class AbstractRunner;
class AbstractRunnerPrivate : public DataEngineConsumer
{
public:
AbstractRunnerPrivate(AbstractRunner *r, KService::Ptr service);
AbstractRunnerPrivate(AbstractRunner *r);
~AbstractRunnerPrivate();
void init(const KService::Ptr service);
void init(const QString &path);
void prepScripting(const QString &path, QString api = QString());
void setupScriptSupport();
AbstractRunner::Priority priority;

View File

@ -153,21 +153,9 @@ public:
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner", QString("[X-KDE-PluginInfo-Name] == '%1'").arg(singleModeRunnerId));
if (!offers.isEmpty()) {
const KService::Ptr &service = offers[0];
QString api = service->property("X-Plasma-API").toString();
QString error;
if (api.isEmpty()) {
QVariantList args;
args << service->storageId();
if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
currentSingleRunner = service->createInstance<AbstractRunner>(q, args, &error);
}
} else {
currentSingleRunner = new AbstractRunner(q, service->storageId());
}
currentSingleRunner = loadInstalledRunner(service);
if (currentSingleRunner) {
QMetaObject::invokeMethod(currentSingleRunner, "init");
emit currentSingleRunner->prepare();
singleRunnerWasLoaded = true;
}
@ -201,7 +189,7 @@ public:
}
KPluginInfo description(service);
QString runnerName = description.pluginName();
const QString runnerName = description.pluginName();
description.load(pluginConf);
const bool loaded = runners.contains(runnerName);
@ -217,36 +205,10 @@ public:
//kDebug() << loadAll << description.isPluginEnabled() << noWhiteList << whiteList.contains(runnerName);
if (selected) {
if (!loaded) {
QString api = service->property("X-Plasma-API").toString();
QString error;
AbstractRunner *runner = 0;
if (api.isEmpty()) {
QVariantList args;
args << service->storageId();
if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
runner = service->createInstance<AbstractRunner>(q, args, &error);
}
} else {
//kDebug() << "got a script runner known as" << api;
runner = new AbstractRunner(q, service->storageId());
}
AbstractRunner *runner = loadInstalledRunner(service);
if (runner) {
kDebug() << "================= loading runner:" << service->name() << "=================";
/*
foreach (const RunnerSyntax &syntax, runner->syntaxes()) {
kDebug() << syntax.exampleQueriesWithTermDescription().join(", ") << " ==> " << syntax.description();
}
*/
QMetaObject::invokeMethod(runner, "init");
runners.insert(runnerName, runner);
} else {
kDebug() << "failed to load runner:" << service->name()
<< ". error reported:" << error;
continue;
}
}
} else if (loaded) {
@ -260,6 +222,34 @@ public:
kDebug() << "All runners loaded, total:" << runners.count();
}
AbstractRunner *loadInstalledRunner(const KService::Ptr service)
{
AbstractRunner *runner = 0;
const QString api = service->property("X-Plasma-API").toString();
if (api.isEmpty()) {
QVariantList args;
args << service->storageId();
if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
QString error;
runner = service->createInstance<AbstractRunner>(q, args, &error);
if (!runner) {
kDebug() << "Failed to load runner:" << service->name() << ". error reported:" << error;
}
}
} else {
//kDebug() << "got a script runner known as" << api;
runner = new AbstractRunner(service, q);
}
if (runner) {
kDebug() << "================= loading runner:" << service->name() << "=================";
QMetaObject::invokeMethod(runner, "init");
}
return runner;
}
void jobDone(ThreadWeaver::Job *job)
{
FindMatchesJob *runJob = dynamic_cast<FindMatchesJob *>(job);
@ -420,6 +410,28 @@ QStringList RunnerManager::allowedRunners() const
return config.readEntry("pluginWhiteList", QStringList());
}
void RunnerManager::loadRunner(const KService::Ptr service)
{
KPluginInfo description(service);
const QString runnerName = description.pluginName();
if (!runnerName.isEmpty() && !d->runners.contains(runnerName)) {
AbstractRunner *runner = d->loadInstalledRunner(service);
if (runner) {
d->runners.insert(runnerName, runner);
}
}
}
void RunnerManager::loadRunner(const QString &path)
{
if (!d->runners.contains(path)) {
AbstractRunner *runner = new AbstractRunner(this, path);
if (runner) {
d->runners.insert(path, runner);
}
}
}
AbstractRunner* RunnerManager::runner(const QString &name) const
{
if (d->runners.isEmpty()) {

View File

@ -162,6 +162,29 @@ class PLASMA_EXPORT RunnerManager : public QObject
*/
void setAllowedRunners(const QStringList &runners);
/**
* Attempts to add the AbstractRunner plugin represented
* by the KService passed in. Usually one can simply let
* the configuration of plugins handle loading Runner plugins,
* but in cases where specific runners should be loaded this
* allows for that to take place
*
* @arg service the service to use to load the plugin
* @since 4.5
*/
void loadRunner(const KService::Ptr service);
/**
* Attempts to add the AbstractRunner from a Plasma::Package on disk.
* Usually one can simply let the configuration of plugins
* handle loading Runner plugins, but in cases where specific
* runners should be loaded this allows for that to take place
*
* @arg path the path to a Runner package to load
* @since 4.5
*/
void loadRunner(const QString &path);
/**
* @return the list of allowed plugins
* @since 4.4