Scripting update.

svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=770587
This commit is contained in:
Petri Damstén 2008-02-04 04:41:40 +00:00
parent dfb3854a10
commit 8a15088888
11 changed files with 318 additions and 34 deletions

View File

@ -23,8 +23,11 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <KDebug> #include <KDebug>
#include <KPluginInfo>
#include <KServiceTypeTrader> #include <KServiceTypeTrader>
#include <QTimer>
#include "scripting/runnerscript.h"
#include "searchcontext.h" #include "searchcontext.h"
namespace Plasma namespace Plasma
@ -38,21 +41,47 @@ class AbstractRunner::Private
Priority priority; Priority priority;
Speed speed; Speed speed;
int tier; int tier;
RunnerScript* script;
KPluginInfo runnerDescription;
AbstractRunner* runner;
Private() Private(AbstractRunner* r, KService::Ptr service)
: priority(NormalPriority), : priority(NormalPriority),
speed(NormalSpeed), speed(NormalSpeed),
tier(0) tier(0),
{} script(0),
runnerDescription(service),
runner(r)
{
if (runnerDescription.isValid()) {
QString language = runnerDescription.property("X-Plasma-Language").toString();
if (!language.isEmpty()) {
script = Plasma::loadScriptEngine(language, runner);
if (!script) {
kDebug() << "Could not create a" << language << "ScriptEngine for the"
<< runnerDescription.name() << "Runner.";
} else {
QTimer::singleShot(0, runner, SLOT(init()));
}
}
}
}
static QMutex serviceTypeTraderLock; static QMutex serviceTypeTraderLock;
}; };
QMutex AbstractRunner::Private::serviceTypeTraderLock; QMutex AbstractRunner::Private::serviceTypeTraderLock;
AbstractRunner::AbstractRunner(QObject* parent) AbstractRunner::AbstractRunner(QObject* parent, const QString& serviceId)
: QObject(parent), : QObject(parent),
d(new Private()) d(new Private(this, KService::serviceByStorageId(serviceId)))
{
}
AbstractRunner::AbstractRunner(QObject* parent, const QVariantList& args)
: QObject(parent),
d(new Private(this, KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString())))
{ {
} }
@ -163,7 +192,31 @@ KService::List AbstractRunner::serviceQuery(const QString &serviceType, const QS
void AbstractRunner::exec(Plasma::SearchMatch *action) void AbstractRunner::exec(Plasma::SearchMatch *action)
{ {
Q_UNUSED(action) if (d->script) {
return d->script->exec(action);
}
}
void AbstractRunner::match(Plasma::SearchContext *search)
{
if (d->script) {
return d->script->match(search);
}
}
QString AbstractRunner::runnerName() const
{
if (!d->runnerDescription.isValid()) {
return QString();
}
return d->runnerDescription.property("X-Plasma-RunnerName").toString();
}
void AbstractRunner::init()
{
if (d->script) {
d->script->init();
}
} }
AbstractRunner::List AbstractRunner::loadRunners(QObject* parent, const QStringList& whitelist) AbstractRunner::List AbstractRunner::loadRunners(QObject* parent, const QStringList& whitelist)
@ -174,9 +227,17 @@ AbstractRunner::List AbstractRunner::loadRunners(QObject* parent, const QStringL
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner"); KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner");
QString error; QString error;
QVariantList allArgs;
foreach (KService::Ptr service, offers) { foreach (KService::Ptr service, offers) {
if( whitelist.empty() || whitelist.contains( service->name() ) ) { if( whitelist.empty() || whitelist.contains( service->name() ) ) {
AbstractRunner* runner = service->createInstance<AbstractRunner>(parent, QVariantList(), &error); allArgs << service->storageId();
QString language = service->property("X-Plasma-Language").toString();
AbstractRunner* runner;
if (language.isEmpty()) {
runner = service->createInstance<AbstractRunner>(parent, allArgs, &error);
} else {
runner = new AbstractRunner(parent, service->storageId());
}
if (runner) { if (runner) {
//kDebug() << "loaded runner : " << service->name(); //kDebug() << "loaded runner : " << service->name();
QString phase = service->property("X-Plasma-RunnerPhase").toString(); QString phase = service->property("X-Plasma-RunnerPhase").toString();

View File

@ -35,6 +35,8 @@ class KCompletion;
namespace Plasma namespace Plasma
{ {
class RunnerScript;
/** /**
* An abstract base class for Plasma Runner plugins * An abstract base class for Plasma Runner plugins
* *
@ -73,7 +75,8 @@ class PLASMA_EXPORT AbstractRunner : public QObject
* this constructor can not be called directly. Rather a subclass must * this constructor can not be called directly. Rather a subclass must
* be created * be created
*/ */
explicit AbstractRunner(QObject* parent = 0); explicit AbstractRunner(QObject* parent = 0, const QString& serviceId = QString());
AbstractRunner(QObject* parent, const QVariantList& args);
virtual ~AbstractRunner(); virtual ~AbstractRunner();
/** /**
@ -102,7 +105,7 @@ class PLASMA_EXPORT AbstractRunner : public QObject
* to return from this method right away, nor to create all matches * to return from this method right away, nor to create all matches
* here. * here.
*/ */
virtual void match(Plasma::SearchContext *search) = 0; virtual void match(Plasma::SearchContext *search);
/** /**
* Triggers a call to match. * Triggers a call to match.
@ -166,6 +169,11 @@ class PLASMA_EXPORT AbstractRunner : public QObject
*/ */
Priority priority() const; Priority priority() const;
/**
* Returns the engine name for the Runner
*/
QString runnerName() const;
protected: protected:
/** /**
* Sets whether or not the the runner has options for matches * Sets whether or not the the runner has options for matches
@ -213,6 +221,9 @@ class PLASMA_EXPORT AbstractRunner : public QObject
KService::List serviceQuery(const QString &serviceType, KService::List serviceQuery(const QString &serviceType,
const QString &constraint = QString()) const; const QString &constraint = QString()) const;
protected slots:
void init();
private: private:
class Private; class Private;
Private* const d; Private* const d;

View File

@ -26,8 +26,11 @@
#include <QVariant> #include <QVariant>
#include <KDebug> #include <KDebug>
#include <KPluginInfo>
#include <KService>
#include "datacontainer.h" #include "datacontainer.h"
#include "scripting/dataenginescript.h"
namespace Plasma namespace Plasma
{ {
@ -35,17 +38,31 @@ namespace Plasma
class DataEngine::Private class DataEngine::Private
{ {
public: public:
Private(DataEngine* e) Private(DataEngine* e, KService::Ptr service)
: engine(e), : engine(e),
ref(0), ref(0),
updateTimerId(0), updateTimerId(0),
minUpdateInterval(-1), minUpdateInterval(-1),
limit(0), limit(0),
valid(true) valid(true),
script(0),
dataEngineDescription(service)
{ {
updateTimer = new QTimer(engine); updateTimer = new QTimer(engine);
updateTimer->setSingleShot(true); updateTimer->setSingleShot(true);
updateTimestamp.start(); updateTimestamp.start();
if (dataEngineDescription.isValid()) {
QString language = dataEngineDescription.property("X-Plasma-Language").toString();
if (!language.isEmpty()) {
script = Plasma::loadScriptEngine(language, engine);
if (!script) {
kDebug() << "Could not create a" << language << "ScriptEngine for the"
<< dataEngineDescription.name() << "DataEngine.";
}
}
}
} }
DataContainer* source(const QString& sourceName, bool createWhenMissing = true) DataContainer* source(const QString& sourceName, bool createWhenMissing = true)
@ -167,12 +184,24 @@ class DataEngine::Private
QString icon; QString icon;
uint limit; uint limit;
bool valid; bool valid;
DataEngineScript* script;
KPluginInfo dataEngineDescription;
}; };
DataEngine::DataEngine(QObject* parent) DataEngine::DataEngine(QObject* parent, const QString& serviceId)
: QObject(parent), : QObject(parent),
d(new Private(this)) d(new Private(this, KService::serviceByStorageId(serviceId)))
{
connect(d->updateTimer, SIGNAL(timeout()), this, SLOT(checkForUpdates()));
//FIXME: we should delay this call; to when is the question.
//Update DataEngine::init() api docu when fixed
QTimer::singleShot(0, this, SLOT(startInit()));
}
DataEngine::DataEngine(QObject* parent, const QVariantList& args)
: QObject(parent),
d(new Private(this, KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString())))
{ {
connect(d->updateTimer, SIGNAL(timeout()), this, SLOT(checkForUpdates())); connect(d->updateTimer, SIGNAL(timeout()), this, SLOT(checkForUpdates()));
//FIXME: we should delay this call; to when is the question. //FIXME: we should delay this call; to when is the question.
@ -267,23 +296,33 @@ void DataEngine::internalUpdateSource(DataContainer* source)
void DataEngine::init() void DataEngine::init()
{ {
if (d->script) {
d->script->init();
} else {
// kDebug() << "DataEngine::init() called "; // kDebug() << "DataEngine::init() called ";
// default implementation does nothing. this is for engines that have to // default implementation does nothing. this is for engines that have to
// start things in motion external to themselves before they can work // start things in motion external to themselves before they can work
} }
}
bool DataEngine::sourceRequested(const QString &name) bool DataEngine::sourceRequested(const QString &name)
{ {
Q_UNUSED(name) if (d->script) {
return d->script->sourceRequested(name);
} else {
return false; return false;
} }
}
bool DataEngine::updateSource(const QString& source) bool DataEngine::updateSource(const QString& source)
{ {
Q_UNUSED(source); if (d->script) {
return d->script->updateSource(source);
} else {
//kDebug() << "updateSource source" << endl; //kDebug() << "updateSource source" << endl;
return false; //TODO: should this be true to trigger, even needless, updates on every tick? return false; //TODO: should this be true to trigger, even needless, updates on every tick?
} }
}
void DataEngine::setData(const QString& source, const QVariant& value) void DataEngine::setData(const QString& source, const QVariant& value)
{ {
@ -488,6 +527,15 @@ void DataEngine::checkForUpdates()
} }
} }
QString DataEngine::engineName() const
{
if (!d->dataEngineDescription.isValid()) {
return QString();
}
return d->dataEngineDescription.property("X-Plasma-EngineName").toString();
}
} }
#include "dataengine.moc" #include "dataengine.moc"

View File

@ -33,6 +33,7 @@ namespace Plasma
{ {
class DataContainer; class DataContainer;
class DataEngineScript;
/** /**
* @class DataEngine * @class DataEngine
@ -50,6 +51,7 @@ class DataContainer;
**/ **/
class PLASMA_EXPORT DataEngine : public QObject class PLASMA_EXPORT DataEngine : public QObject
{ {
friend class DataEngineScript;
Q_OBJECT Q_OBJECT
Q_PROPERTY( QStringList sources READ sources ) Q_PROPERTY( QStringList sources READ sources )
Q_PROPERTY( bool valid READ isValid ) Q_PROPERTY( bool valid READ isValid )
@ -66,7 +68,8 @@ class PLASMA_EXPORT DataEngine : public QObject
* *
* @param parent The parent object. * @param parent The parent object.
**/ **/
explicit DataEngine(QObject* parent = 0); explicit DataEngine(QObject* parent = 0, const QString& serviceId = QString());
DataEngine(QObject* parent, const QVariantList& args);
virtual ~DataEngine(); virtual ~DataEngine();
/** /**
@ -77,6 +80,11 @@ class PLASMA_EXPORT DataEngine : public QObject
**/ **/
virtual QStringList sources() const; virtual QStringList sources() const;
/**
* Returns the engine name for the DataEngine
*/
QString engineName() const;
/** /**
* Connects a source to an object for data updates. The object must * Connects a source to an object for data updates. The object must
* have a slot with the following signature: * have a slot with the following signature:

View File

@ -18,6 +18,7 @@
*/ */
#include "dataenginemanager.h" #include "dataenginemanager.h"
#include "scripting/scriptengine.h"
#include <KDebug> #include <KDebug>
#include <KServiceTypeTrader> #include <KServiceTypeTrader>
@ -119,11 +120,18 @@ Plasma::DataEngine* DataEngineManager::loadDataEngine(const QString& name)
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine",
constraint); constraint);
QString error; QString error;
QVariantList allArgs;
allArgs << offers.first()->storageId();
if (offers.isEmpty()) { if (offers.isEmpty()) {
kDebug() << "offers are empty for " << name << " with constraint " << constraint; kDebug() << "offers are empty for " << name << " with constraint " << constraint;
} else { } else {
engine = offers.first()->createInstance<Plasma::DataEngine>(0, QVariantList(), &error); QString language = offers.first()->property("X-Plasma-Language").toString();
if (language.isEmpty()) {
engine = offers.first()->createInstance<Plasma::DataEngine>(0, allArgs, &error);
} else {
engine = new DataEngine(0, offers.first()->storageId());
}
} }
if (!engine) { if (!engine) {

View File

@ -32,7 +32,7 @@ public:
DataEngineScript::DataEngineScript(QObject *parent) DataEngineScript::DataEngineScript(QObject *parent)
: ScriptEngine(parent), : ScriptEngine(parent),
d(0) d(new Private)
{ {
} }
@ -51,6 +51,83 @@ DataEngine* DataEngineScript::dataEngine() const
return d->dataEngine; return d->dataEngine;
} }
bool DataEngineScript::sourceRequested(const QString &name)
{
Q_UNUSED(name)
return false;
}
bool DataEngineScript::updateSource(const QString& source)
{
Q_UNUSED(source)
return false;
}
void DataEngineScript::setData(const QString& source, const QString& key,
const QVariant& value)
{
if (d->dataEngine) {
d->dataEngine->setData(source, key, value);
}
}
void DataEngineScript::setData(const QString &source, const QVariant &value)
{
if (d->dataEngine) {
d->dataEngine->setData(source, value);
}
}
void DataEngineScript::clearData(const QString& source)
{
if (d->dataEngine) {
d->dataEngine->clearData(source);
}
}
void DataEngineScript::removeData(const QString& source, const QString& key)
{
if (d->dataEngine) {
d->dataEngine->removeData(source, key);
}
}
void DataEngineScript::setSourceLimit(uint limit)
{
if (d->dataEngine) {
d->dataEngine->setSourceLimit(limit);
}
}
void DataEngineScript::setMinimumUpdateInterval(int minimumMs)
{
if (d->dataEngine) {
d->dataEngine->setMinimumUpdateInterval(minimumMs);
}
}
int DataEngineScript::minimumUpdateInterval() const
{
if (d->dataEngine) {
return d->dataEngine->minimumUpdateInterval();
}
return 0;
}
void DataEngineScript::setUpdateInterval(uint frequency)
{
if (d->dataEngine) {
d->dataEngine->setUpdateInterval(frequency);
}
}
void DataEngineScript::clearSources()
{
if (d->dataEngine) {
d->dataEngine->clearSources();
}
}
} // Plasma namespace } // Plasma namespace
#include "dataenginescript.moc" #include "dataenginescript.moc"

View File

@ -53,6 +53,37 @@ public:
*/ */
DataEngine* dataEngine() const; DataEngine* dataEngine() const;
/**
* Called when the script should create a source that does not currently
* exist.
*
* @param name the name of the source that should be created
* @return true if a DataContainer was set up, false otherwise
*/
virtual bool sourceRequested(const QString &name);
/**
* Called when the script should refresh the data contained in a given
* source.
*
* @param source the name of the source that should be updated
* @return true if the data was changed, or false if there was no
* change or if the change will occur later
**/
virtual bool updateSource(const QString& source);
protected:
void setData(const QString& source, const QString& key,
const QVariant& value);
void setData(const QString &source, const QVariant &value);
void clearData(const QString& source);
void removeData(const QString& source, const QString& key);
void setSourceLimit(uint limit);
void setMinimumUpdateInterval(int minimumMs);
int minimumUpdateInterval() const;
void setUpdateInterval(uint frequency);
void clearSources();
private: private:
class Private; class Private;
Private * const d; Private * const d;

View File

@ -32,7 +32,7 @@ public:
RunnerScript::RunnerScript(QObject *parent) RunnerScript::RunnerScript(QObject *parent)
: ScriptEngine(parent), : ScriptEngine(parent),
d(0) d(new Private)
{ {
} }
@ -51,6 +51,16 @@ AbstractRunner* RunnerScript::runner() const
return d->runner; return d->runner;
} }
void RunnerScript::match(Plasma::SearchContext *search)
{
Q_UNUSED(search)
}
void RunnerScript::exec(Plasma::SearchMatch *action)
{
Q_UNUSED(action)
}
} // Plasma namespace } // Plasma namespace
#include "runnerscript.moc" #include "runnerscript.moc"

View File

@ -27,6 +27,8 @@ namespace Plasma
{ {
class AbstractRunner; class AbstractRunner;
class SearchContext;
class SearchMatch;
class PLASMA_EXPORT RunnerScript : public ScriptEngine class PLASMA_EXPORT RunnerScript : public ScriptEngine
{ {
@ -53,6 +55,19 @@ public:
*/ */
AbstractRunner* runner() const; AbstractRunner* runner() const;
/**
* Called when the script should create SearchMatch instances through
* SearchContext::addInformationalMatch, SearchContext::addExactMatch, and
* SearchContext::addPossibleMatch.
*/
virtual void match(Plasma::SearchContext *search);
/**
* Called whenever an exact or possible match associated with this
* runner is triggered.
*/
virtual void exec(Plasma::SearchMatch *action);
private: private:
class Private; class Private;
Private * const d; Private * const d;

View File

@ -177,12 +177,24 @@ AppletScript* loadScriptEngine(const QString &language, Applet *applet)
DataEngineScript* loadScriptEngine(const QString &language, DataEngine *dataEngine) DataEngineScript* loadScriptEngine(const QString &language, DataEngine *dataEngine)
{ {
return static_cast<DataEngineScript*>(loadEngine(language, DataEngineComponent, dataEngine)); DataEngineScript *engine = static_cast<DataEngineScript*>(loadEngine(language, DataEngineComponent, dataEngine));
if (engine) {
engine->setDataEngine(dataEngine);
}
return engine;
} }
RunnerScript* loadScriptEngine(const QString &language, AbstractRunner *runner) RunnerScript* loadScriptEngine(const QString &language, AbstractRunner *runner)
{ {
return static_cast<RunnerScript*>(loadEngine(language, RunnerComponent, runner)); RunnerScript* engine = static_cast<RunnerScript*>(loadEngine(language, RunnerComponent, runner));
if (engine) {
engine->setRunner(runner);
}
return engine;
} }
} // namespace Plasma } // namespace Plasma

View File

@ -54,6 +54,9 @@ Comment[x-test]=xxKRunner pluginxx
Comment[zh_CN]=KRunner Comment[zh_CN]=KRunner
Comment[zh_TW]=KRunner Comment[zh_TW]=KRunner
[PropertyDef::X-Plasma-RunnerName]
Type=QString
[PropertyDef::X-Plasma-RunnerPhase] [PropertyDef::X-Plasma-RunnerPhase]
Type=QString Type=QString