• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Plasma

abstractrunner.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU Library General Public License as
00006  *   published by the Free Software Foundation; either version 2, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "abstractrunner.h"
00021 
00022 #include <QAction>
00023 #include <QHash>
00024 #include <QMenu>
00025 #include <QMimeData>
00026 #include <QMutex>
00027 #include <QMutexLocker>
00028 #include <QTimer>
00029 
00030 #include <kdebug.h>
00031 #include <kicon.h>
00032 #include <kplugininfo.h>
00033 #include <kservicetypetrader.h>
00034 #include <kstandarddirs.h>
00035 
00036 #include <plasma/package.h>
00037 #include <plasma/querymatch.h>
00038 
00039 #include "private/abstractrunner_p.h"
00040 #include "runnercontext.h"
00041 #include "scripting/runnerscript.h"
00042 
00043 namespace Plasma
00044 {
00045 
00046 K_GLOBAL_STATIC(QMutex, s_bigLock)
00047 
00048 AbstractRunner::AbstractRunner(QObject *parent, const QString &path)
00049     : QObject(parent),
00050       d(new AbstractRunnerPrivate(this))
00051 {
00052     d->init(path);
00053 }
00054 
00055 AbstractRunner::AbstractRunner(const KService::Ptr service, QObject *parent)
00056     : QObject(parent),
00057       d(new AbstractRunnerPrivate(this))
00058 {
00059     d->init(service);
00060 }
00061 
00062 AbstractRunner::AbstractRunner(QObject *parent, const QVariantList &args)
00063     : QObject(parent),
00064       d(new AbstractRunnerPrivate(this))
00065 {
00066     if (args.count() > 0) {
00067         KService::Ptr service = KService::serviceByStorageId(args[0].toString());
00068         if (service) {
00069             d->init(service);
00070         }
00071     }
00072 }
00073 
00074 AbstractRunner::~AbstractRunner()
00075 {
00076     delete d;
00077 }
00078 
00079 KConfigGroup AbstractRunner::config() const
00080 {
00081     QString group = objectName();
00082     if (group.isEmpty()) {
00083         group = "UnnamedRunner";
00084     }
00085 
00086     KConfigGroup runners(KGlobal::config(), "Runners");
00087     return KConfigGroup(&runners, group);
00088 }
00089 
00090 void AbstractRunner::reloadConfiguration()
00091 {
00092     if (d->script) {
00093         emit d->script->reloadConfiguration();
00094     }
00095 }
00096 
00097 void AbstractRunner::addSyntax(const RunnerSyntax &syntax)
00098 {
00099     d->syntaxes.append(syntax);
00100 }
00101 
00102 void AbstractRunner::setDefaultSyntax(const RunnerSyntax &syntax)
00103 {
00104     d->syntaxes.append(syntax);
00105     d->defaultSyntax = &(d->syntaxes.last());
00106 }
00107 
00108 void AbstractRunner::setSyntaxes(const QList<RunnerSyntax> &syntaxes)
00109 {
00110     d->syntaxes = syntaxes;
00111 }
00112 
00113 QList<RunnerSyntax> AbstractRunner::syntaxes() const
00114 {
00115     return d->syntaxes;
00116 }
00117 
00118 RunnerSyntax *AbstractRunner::defaultSyntax() const
00119 {
00120     return d->defaultSyntax;
00121 }
00122 
00123 void AbstractRunner::performMatch(Plasma::RunnerContext &localContext)
00124 {
00125     static const int reasonableRunTime = 1500;
00126     static const int fastEnoughTime = 250;
00127 
00128     if (d->suspendMatching) {
00129         return;
00130     }
00131 
00132     QTime time;
00133     time.restart();
00134 
00135     //The local copy is already obtained in the job
00136     match(localContext);
00137 
00138     // automatically rate limit runners that become slooow
00139     const int runtime = time.elapsed();
00140     bool slowed = speed() == SlowSpeed;
00141 
00142     if (!slowed && runtime > reasonableRunTime) {
00143         // we punish runners that return too slowly, even if they don't bring
00144         // back matches
00145         kDebug() << id() << "runner is too slow, putting it on the back burner.";
00146         d->fastRuns = 0;
00147         setSpeed(SlowSpeed);
00148     }
00149 
00150     if (slowed && runtime < fastEnoughTime && localContext.query().size() > 2) {
00151         ++d->fastRuns;
00152 
00153         if (d->fastRuns > 2) {
00154             // we reward slowed runners who bring back matches fast enough
00155             // 3 times in a row
00156             kDebug() << id() << "runner is faster than we thought, kicking it up a notch";
00157             setSpeed(NormalSpeed);
00158         }
00159     }
00160 }
00161 
00162 QList<QAction*> AbstractRunner::actionsForMatch(const Plasma::QueryMatch &match)
00163 {
00164     Q_UNUSED(match)
00165     QList<QAction*> ret;
00166     if (d->script) {
00167         emit d->script->actionsForMatch(match, &ret);
00168     }
00169     return ret;
00170 }
00171 
00172 QAction* AbstractRunner::addAction(const QString &id, const QIcon &icon, const QString &text)
00173 {
00174     QAction *a = new QAction(icon, text, this);
00175     d->actions.insert(id, a);
00176     return a;
00177 }
00178 
00179 void AbstractRunner::addAction(const QString &id, QAction *action)
00180 {
00181     d->actions.insert(id, action);
00182 }
00183 
00184 void AbstractRunner::removeAction(const QString &id)
00185 {
00186     QAction *a = d->actions.take(id);
00187     delete a;
00188 }
00189 
00190 QAction* AbstractRunner::action(const QString &id) const
00191 {
00192     return d->actions.value(id);
00193 }
00194 
00195 QHash<QString, QAction*> AbstractRunner::actions() const
00196 {
00197     return d->actions;
00198 }
00199 
00200 void AbstractRunner::clearActions()
00201 {
00202     qDeleteAll(d->actions);
00203     d->actions.clear();
00204 }
00205 
00206 QMimeData * AbstractRunner::mimeDataForMatch(const QueryMatch *match)
00207 {
00208     Q_UNUSED(match)
00209     return 0;
00210 }
00211 
00212 bool AbstractRunner::hasRunOptions()
00213 {
00214     return d->hasRunOptions;
00215 }
00216 
00217 void AbstractRunner::setHasRunOptions(bool hasRunOptions)
00218 {
00219     d->hasRunOptions = hasRunOptions;
00220 }
00221 
00222 void AbstractRunner::createRunOptions(QWidget *parent)
00223 {
00224     if (d->script) {
00225         emit d->script->createRunOptions(parent);
00226     }
00227 }
00228 
00229 AbstractRunner::Speed AbstractRunner::speed() const
00230 {
00231     // the only time the read lock will fail is if we were slow are going to speed up
00232     // or if we were fast and are going to slow down; so don't wait in this case, just
00233     // say we're slow. we either will be soon or were just a moment ago and it doesn't
00234     // hurt to do one more run the slow way
00235     if (!d->speedLock.tryLockForRead()) {
00236         return SlowSpeed;
00237     }
00238     Speed s = d->speed;
00239     d->speedLock.unlock();
00240     return s;
00241 }
00242 
00243 void AbstractRunner::setSpeed(Speed speed)
00244 {
00245     d->speedLock.lockForWrite();
00246     d->speed = speed;
00247     d->speedLock.unlock();
00248 }
00249 
00250 AbstractRunner::Priority AbstractRunner::priority() const
00251 {
00252     return d->priority;
00253 }
00254 
00255 void AbstractRunner::setPriority(Priority priority)
00256 {
00257     d->priority = priority;
00258 }
00259 
00260 RunnerContext::Types AbstractRunner::ignoredTypes() const
00261 {
00262     return d->blackListed;
00263 }
00264 
00265 void AbstractRunner::setIgnoredTypes(RunnerContext::Types types)
00266 {
00267     d->blackListed = types;
00268 }
00269 
00270 KService::List AbstractRunner::serviceQuery(const QString &serviceType, const QString &constraint) const
00271 {
00272     return KServiceTypeTrader::self()->query(serviceType, constraint);
00273 }
00274 
00275 QMutex* AbstractRunner::bigLock()
00276 {
00277     return s_bigLock;
00278 }
00279 
00280 void AbstractRunner::run(const Plasma::RunnerContext &search, const Plasma::QueryMatch &action)
00281 {
00282     if (d->script) {
00283         return d->script->run(search, action);
00284     }
00285 }
00286 
00287 void AbstractRunner::match(Plasma::RunnerContext &search)
00288 {
00289     if (d->script) {
00290         return d->script->match(search);
00291     }
00292 }
00293 
00294 QString AbstractRunner::name() const
00295 {
00296     if (d->runnerDescription.isValid()) {
00297         return d->runnerDescription.name();
00298     }
00299 
00300     if (d->package) {
00301         return d->package->metadata().name();
00302     }
00303 
00304     return objectName();
00305 }
00306 
00307 QIcon AbstractRunner::icon() const
00308 {
00309     if (d->runnerDescription.isValid()) {
00310         return KIcon(d->runnerDescription.icon());
00311     }
00312 
00313     if (d->package) {
00314         return KIcon(d->package->metadata().icon());
00315     }
00316 
00317     return QIcon();
00318 }
00319 
00320 QString AbstractRunner::id() const
00321 {
00322     if (d->runnerDescription.isValid()) {
00323         return d->runnerDescription.pluginName();
00324     }
00325 
00326     if (d->package) {
00327         return d->package->metadata().pluginName();
00328     }
00329 
00330     return objectName();
00331 }
00332 
00333 QString AbstractRunner::description() const
00334 {
00335     if (d->runnerDescription.isValid()) {
00336         return d->runnerDescription.property("Comment").toString();
00337     }
00338 
00339     if (d->package) {
00340         return d->package->metadata().description();
00341     }
00342 
00343     return objectName();
00344 }
00345 
00346 const Package* AbstractRunner::package() const
00347 {
00348     return d->package;
00349 }
00350 
00351 
00352 void AbstractRunner::init()
00353 {
00354     if (d->script) {
00355         d->setupScriptSupport();
00356         d->script->init();
00357     }
00358 
00359     reloadConfiguration();
00360 }
00361 
00362 DataEngine *AbstractRunner::dataEngine(const QString &name) const
00363 {
00364     return d->dataEngine(name);
00365 }
00366 
00367 bool AbstractRunner::isMatchingSuspended() const
00368 {
00369     return d->suspendMatching;
00370 }
00371 
00372 void AbstractRunner::suspendMatching(bool suspend)
00373 {
00374     if (d->suspendMatching == suspend) {
00375         return;
00376     }
00377 
00378     d->suspendMatching = suspend;
00379     emit matchingSuspended(suspend);
00380 }
00381 
00382 AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r)
00383     : priority(AbstractRunner::NormalPriority),
00384       speed(AbstractRunner::NormalSpeed),
00385       blackListed(0),
00386       script(0),
00387       runner(r),
00388       fastRuns(0),
00389       package(0),
00390       defaultSyntax(0),
00391       hasRunOptions(false),
00392       suspendMatching(false)
00393 {
00394 }
00395 
00396 AbstractRunnerPrivate::~AbstractRunnerPrivate()
00397 {
00398     delete script;
00399     script = 0;
00400     delete package;
00401     package = 0;
00402 }
00403 
00404 void AbstractRunnerPrivate::init(const KService::Ptr service)
00405 {
00406     runnerDescription = KPluginInfo(service);
00407     if (runnerDescription.isValid()) {
00408         const QString api = runnerDescription.property("X-Plasma-API").toString();
00409         if (!api.isEmpty()) {
00410             const QString path = KStandardDirs::locate("data", "plasma/runners/" + runnerDescription.pluginName() + '/');
00411             prepScripting(path, api);
00412             if (!script) {
00413                 kDebug() << "Could not create a(n)" << api << "ScriptEngine for the" << runnerDescription.name() << "Runner.";
00414             }
00415         }
00416     }
00417 }
00418 
00419 void AbstractRunnerPrivate::init(const QString &path)
00420 {
00421     prepScripting(path);
00422 }
00423 
00424 void AbstractRunnerPrivate::prepScripting(const QString &path, QString api)
00425 {
00426     if (script) {
00427         return;
00428     }
00429 
00430     delete package;
00431 
00432     PackageStructure::Ptr structure = Plasma::packageStructure(api, Plasma::RunnerComponent);
00433     structure->setPath(path);
00434     package = new Package(path, structure);
00435 
00436     if (!package->isValid()) {
00437         kDebug() << "Invalid Runner package at" << path;
00438         delete package;
00439         package = 0;
00440         return;
00441     }
00442 
00443     if (api.isEmpty()) {
00444         api = package->metadata().implementationApi();
00445     }
00446 
00447     script = Plasma::loadScriptEngine(api, runner);
00448     if (!script) {
00449         delete package;
00450         package = 0;
00451     }
00452 }
00453 
00454 // put all setup routines for script here. at this point we can assume that
00455 // package exists and that we have a script engine
00456 void AbstractRunnerPrivate::setupScriptSupport()
00457 {
00458     if (!package) {
00459         return;
00460     }
00461 
00462     kDebug() << "setting up script support, package is in" << package->path()
00463              << "which is a" << package->structure()->type() << "package"
00464              << ", main script is" << package->filePath("mainscript");
00465 
00466     QString translationsPath = package->filePath("translations");
00467     if (!translationsPath.isEmpty()) {
00468         //FIXME: we should _probably_ use a KComponentData to segregate the applets
00469         //       from each other; but I want to get the basics working first :)
00470         KGlobal::dirs()->addResourceDir("locale", translationsPath);
00471         KGlobal::locale()->insertCatalog(package->metadata().pluginName());
00472     }
00473 }
00474 
00475 } // Plasma namespace
00476 
00477 #include "abstractrunner.moc"

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal