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

Plasma

runnermanager.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
00003  *   Copyright (C) 2007, 2009 Ryan P. Bitanga <ryan.bitanga@gmail.com>
00004  *   Copyright (C) 2008 Jordi Polo <mumismo@gmail.com>
00005  *
00006  *   This program is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU Library General Public License as
00008  *   published by the Free Software Foundation; either version 2, or
00009  *   (at your option) any later version.
00010  *
00011  *   This program is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details
00015  *
00016  *   You should have received a copy of the GNU Library General Public
00017  *   License along with this program; if not, write to the
00018  *   Free Software Foundation, Inc.,
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  */
00021 
00022 #include "runnermanager.h"
00023 
00024 #include "config-plasma.h"
00025 
00026 #include <QMutex>
00027 #include <QTimer>
00028 #include <QCoreApplication>
00029 
00030 #include <kdebug.h>
00031 #include <kplugininfo.h>
00032 #include <kservicetypetrader.h>
00033 #include <kstandarddirs.h>
00034 
00035 #ifndef PLASMA_NO_SOLID
00036 #include <solid/device.h>
00037 #include <solid/deviceinterface.h>
00038 #endif
00039 
00040 #include <Weaver/DebuggingAids.h>
00041 #include <Weaver/State.h>
00042 #include <Weaver/Thread.h>
00043 #include <Weaver/ThreadWeaver.h>
00044 
00045 #include "private/runnerjobs_p.h"
00046 #include "pluginloader.h"
00047 #include "querymatch.h"
00048 
00049 using ThreadWeaver::Weaver;
00050 using ThreadWeaver::Job;
00051 
00052 //#define MEASURE_PREPTIME
00053 
00054 namespace Plasma
00055 {
00056 
00057 /*****************************************************
00058 *  RunnerManager::Private class
00059 *
00060 *****************************************************/
00061 class RunnerManagerPrivate
00062 {
00063 public:
00064 
00065     RunnerManagerPrivate(RunnerManager *parent)
00066       : q(parent),
00067         deferredRun(0),
00068         currentSingleRunner(0),
00069         prepped(false),
00070         allRunnersPrepped(false),
00071         singleRunnerPrepped(false),
00072         teardownRequested(false),
00073         singleMode(false),
00074         singleRunnerWasLoaded(false)
00075     {
00076         matchChangeTimer.setSingleShot(true);
00077         delayTimer.setSingleShot(true);
00078 
00079         QObject::connect(&matchChangeTimer, SIGNAL(timeout()), q, SLOT(matchesChanged()));
00080         QObject::connect(&context, SIGNAL(matchesChanged()), q, SLOT(scheduleMatchesChanged()));
00081         QObject::connect(&delayTimer, SIGNAL(timeout()), q, SLOT(unblockJobs()));
00082     }
00083 
00084     ~RunnerManagerPrivate()
00085     {
00086         KConfigGroup config = configGroup();
00087         context.save(config);
00088     }
00089 
00090     void scheduleMatchesChanged()
00091     {
00092         matchChangeTimer.start(100);
00093     }
00094 
00095     void matchesChanged()
00096     {
00097         emit q->matchesChanged(context.matches());
00098     }
00099 
00100     void loadConfiguration()
00101     {
00102         KConfigGroup config = configGroup();
00103 
00104         //The number of threads used scales with the number of processors.
00105 #ifndef PLASMA_NO_SOLID
00106         const int numProcs =
00107             qMax(Solid::Device::listFromType(Solid::DeviceInterface::Processor).count(), 1);
00108 #else
00109         const int numProcs = 1;
00110 #endif
00111         //This entry allows to define a hard upper limit independent of the number of processors.
00112         const int maxThreads = config.readEntry("maxThreads", 16);
00113         const int numThreads = qMin(maxThreads, 2 + ((numProcs - 1) * 2));
00114         //kDebug() << "setting up" << numThreads << "threads for" << numProcs << "processors";
00115         if (numThreads > Weaver::instance()->maximumNumberOfThreads()) {
00116             Weaver::instance()->setMaximumNumberOfThreads(numThreads);
00117         }
00118         // Limit the number of instances of a single normal speed runner and all of the slow runners
00119         // to half the number of threads
00120         const int cap = qMax(2, numThreads/2);
00121         DefaultRunnerPolicy::instance().setCap(cap);
00122 
00123         context.restore(config);
00124     }
00125 
00126     KConfigGroup configGroup()
00127     {
00128         return conf.isValid() ? conf : KConfigGroup(KGlobal::config(), "PlasmaRunnerManager");
00129     }
00130 
00131     void clearSingleRunner()
00132     {
00133         if (singleRunnerWasLoaded) {
00134             delete currentSingleRunner;
00135         }
00136 
00137         currentSingleRunner = 0;
00138     }
00139 
00140     void loadSingleRunner()
00141     {
00142         if (!singleMode || singleModeRunnerId.isEmpty()) {
00143             clearSingleRunner();
00144             return;
00145         }
00146 
00147         if (currentSingleRunner) {
00148             if (currentSingleRunner->id() == singleModeRunnerId) {
00149                 return;
00150             }
00151 
00152             clearSingleRunner();
00153         }
00154 
00155         AbstractRunner *loadedRunner = q->runner(singleModeRunnerId);
00156         if (loadedRunner) {
00157             singleRunnerWasLoaded = false;
00158             currentSingleRunner = loadedRunner;
00159             return;
00160         }
00161 
00162         KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner", QString("[X-KDE-PluginInfo-Name] == '%1'").arg(singleModeRunnerId));
00163         if (!offers.isEmpty()) {
00164             const KService::Ptr &service = offers[0];
00165             currentSingleRunner = loadInstalledRunner(service);
00166 
00167             if (currentSingleRunner) {
00168                 emit currentSingleRunner->prepare();
00169                 singleRunnerWasLoaded = true;
00170             }
00171         }
00172     }
00173 
00174     void loadRunners()
00175     {
00176         KConfigGroup config = configGroup();
00177         KPluginInfo::List offers = RunnerManager::listRunnerInfo();
00178 
00179         const bool loadAll = config.readEntry("loadAll", false);
00180         QStringList whiteList = config.readEntry("pluginWhiteList", QStringList());
00181         const bool noWhiteList = whiteList.isEmpty();
00182         KConfigGroup pluginConf;
00183         if (conf.isValid()) {
00184             pluginConf = KConfigGroup(&conf, "Plugins");
00185         } else {
00186             pluginConf = KConfigGroup(KGlobal::config(), "Plugins");
00187         }
00188 
00189         advertiseSingleRunnerIds.clear();
00190 
00191         QMutableListIterator<KPluginInfo> it(offers);
00192         while (it.hasNext()) {
00193             KPluginInfo &description = it.next();
00194             //kDebug() << "Loading runner: " << service->name() << service->storageId();
00195             QString tryExec = description.property("TryExec").toString();
00196             //kDebug() << "TryExec is" << tryExec;
00197             if (!tryExec.isEmpty() && KStandardDirs::findExe(tryExec).isEmpty()) {
00198                 // we don't actually have this application!
00199                 continue;
00200             }
00201 
00202             const QString runnerName = description.pluginName();
00203             description.load(pluginConf);
00204 
00205             const bool loaded = runners.contains(runnerName);
00206             const bool selected = loadAll ||
00207                             (description.isPluginEnabled() && (noWhiteList || whiteList.contains(runnerName)));
00208 
00209             const bool singleQueryModeEnabled = description.property("X-Plasma-AdvertiseSingleRunnerQueryMode").toBool();
00210 
00211             if (singleQueryModeEnabled) {
00212                 advertiseSingleRunnerIds.insert(runnerName, description.name());
00213             }
00214 
00215             //kDebug() << loadAll << description.isPluginEnabled() << noWhiteList << whiteList.contains(runnerName);
00216             if (selected) {
00217                 if (!loaded) {
00218                     AbstractRunner *runner = loadInstalledRunner(description.service());
00219 
00220                     if (runner) {
00221                         runners.insert(runnerName, runner);
00222                     }
00223                 }
00224             } else if (loaded) {
00225                 //Remove runner
00226                 AbstractRunner *runner = runners.take(runnerName);
00227                 kDebug() << "Removing runner: " << runnerName;
00228                 delete runner;
00229             }
00230         }
00231 
00232         kDebug() << "All runners loaded, total:" << runners.count();
00233     }
00234 
00235     AbstractRunner *loadInstalledRunner(const KService::Ptr service)
00236     {
00237         if (!service) {
00238             return 0;
00239         }
00240 
00241         AbstractRunner *runner = PluginLoader::pluginLoader()->loadRunner(service->property("X-KDE-PluginInfo-Name", QVariant::String).toString());
00242 
00243         if (runner) {
00244             runner->setParent(q);
00245         } else {
00246             const QString api = service->property("X-Plasma-API").toString();
00247 
00248             if (api.isEmpty()) {
00249                 QVariantList args;
00250                 args << service->storageId();
00251                 if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
00252                     QString error;
00253                     runner = service->createInstance<AbstractRunner>(q, args, &error);
00254                     if (!runner) {
00255                         kDebug() << "Failed to load runner:" << service->name() << ". error reported:" << error;
00256                     }
00257                 }
00258             } else {
00259                 //kDebug() << "got a script runner known as" << api;
00260                 runner = new AbstractRunner(service, q);
00261             }
00262         }
00263 
00264         if (runner) {
00265             kDebug() << "================= loading runner:" << service->name() << "=================";
00266             QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool)));
00267             QMetaObject::invokeMethod(runner, "init");
00268         }
00269 
00270         return runner;
00271     }
00272 
00273     void jobDone(ThreadWeaver::Job *job)
00274     {
00275         FindMatchesJob *runJob = dynamic_cast<FindMatchesJob *>(job);
00276 
00277         if (!runJob) {
00278             return;
00279         }
00280 
00281         if (deferredRun.isEnabled() && runJob->runner() == deferredRun.runner()) {
00282             //kDebug() << "job actually done, running now **************";
00283             QueryMatch tmpRun = deferredRun;
00284             deferredRun = QueryMatch(0);
00285             tmpRun.run(context);
00286         }
00287 
00288         searchJobs.remove(runJob);
00289         oldSearchJobs.remove(runJob);
00290         runJob->deleteLater();
00291 
00292         if (searchJobs.isEmpty() && context.matches().isEmpty()) {
00293             // we finished our run, and there are no valid matches, and so no
00294             // signal will have been sent out. so we need to emit the signal
00295             // ourselves here
00296             emit q->matchesChanged(context.matches());
00297         }
00298 
00299         checkTearDown();
00300     }
00301 
00302     void checkTearDown()
00303     {
00304         //kDebug() << prepped << teardownRequested << searchJobs.count() << oldSearchJobs.count();
00305 
00306         if (!prepped || !teardownRequested) {
00307             return;
00308         }
00309 
00310         if (Weaver::instance()->isIdle()) {
00311             qDeleteAll(searchJobs);
00312             searchJobs.clear();
00313             qDeleteAll(oldSearchJobs);
00314             oldSearchJobs.clear();
00315         }
00316 
00317         if (searchJobs.isEmpty() && oldSearchJobs.isEmpty()) {
00318             if (allRunnersPrepped) {
00319                 foreach (AbstractRunner *runner, runners) {
00320                     emit runner->teardown();
00321                 }
00322 
00323                 allRunnersPrepped = false;
00324             }
00325 
00326             if (singleRunnerPrepped) {
00327                 if (currentSingleRunner) {
00328                     emit currentSingleRunner->teardown();
00329                 }
00330 
00331                 singleRunnerPrepped = false;
00332             }
00333 
00334             emit q->queryFinished();
00335 
00336             prepped = false;
00337             teardownRequested = false;
00338         }
00339     }
00340 
00341     void unblockJobs()
00342     {
00343         // WORKAROUND: Queue an empty job to force ThreadWeaver to awaken threads
00344         if (searchJobs.isEmpty() && Weaver::instance()->isIdle()) {
00345             qDeleteAll(oldSearchJobs);
00346             oldSearchJobs.clear();
00347             checkTearDown();
00348             return;
00349         }
00350 
00351         DummyJob *dummy = new DummyJob(q);
00352         Weaver::instance()->enqueue(dummy);
00353         QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater()));
00354     }
00355 
00356     void runnerMatchingSuspended(bool suspended)
00357     {
00358         if (suspended || !prepped || teardownRequested) {
00359             return;
00360         }
00361 
00362         AbstractRunner *runner = qobject_cast<AbstractRunner *>(q->sender());
00363 
00364         if (runner) {
00365             startJob(runner);
00366         }
00367     }
00368 
00369     void startJob(AbstractRunner *runner)
00370     {
00371         if ((runner->ignoredTypes() & context.type()) == 0) {
00372             FindMatchesJob *job = new FindMatchesJob(runner, &context, Weaver::instance());
00373             QObject::connect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*)));
00374             if (runner->speed() == AbstractRunner::SlowSpeed) {
00375                 job->setDelayTimer(&delayTimer);
00376             }
00377             Weaver::instance()->enqueue(job);
00378             searchJobs.insert(job);
00379         }
00380     }
00381 
00382     // Delay in ms before slow runners are allowed to run
00383     static const int slowRunDelay = 400;
00384 
00385     RunnerManager *q;
00386     QueryMatch deferredRun;
00387     RunnerContext context;
00388     QTimer matchChangeTimer;
00389     QTimer delayTimer; // Timer to control when to run slow runners
00390     QHash<QString, AbstractRunner*> runners;
00391     QHash<QString, QString> advertiseSingleRunnerIds;
00392     AbstractRunner* currentSingleRunner;
00393     QSet<FindMatchesJob*> searchJobs;
00394     QSet<FindMatchesJob*> oldSearchJobs;
00395     KConfigGroup conf;
00396     QString singleModeRunnerId;
00397     bool loadAll : 1;
00398     bool prepped : 1;
00399     bool allRunnersPrepped : 1;
00400     bool singleRunnerPrepped : 1;
00401     bool teardownRequested : 1;
00402     bool singleMode : 1;
00403     bool singleRunnerWasLoaded : 1;
00404 };
00405 
00406 /*****************************************************
00407 *  RunnerManager::Public class
00408 *
00409 *****************************************************/
00410 RunnerManager::RunnerManager(QObject *parent)
00411     : QObject(parent),
00412       d(new RunnerManagerPrivate(this))
00413 {
00414     d->loadConfiguration();
00415     //ThreadWeaver::setDebugLevel(true, 4);
00416 }
00417 
00418 RunnerManager::RunnerManager(KConfigGroup &c, QObject *parent)
00419     : QObject(parent),
00420       d(new RunnerManagerPrivate(this))
00421 {
00422     // Should this be really needed? Maybe d->loadConfiguration(c) would make
00423     // more sense.
00424     d->conf = KConfigGroup(&c, "PlasmaRunnerManager");
00425     d->loadConfiguration();
00426     //ThreadWeaver::setDebugLevel(true, 4);
00427 }
00428 
00429 RunnerManager::~RunnerManager()
00430 {
00431     if (!qApp->closingDown() && (!d->searchJobs.isEmpty() || !d->oldSearchJobs.isEmpty())) {
00432         new DelayedJobCleaner(d->searchJobs + d->oldSearchJobs, Weaver::instance());
00433     }
00434 
00435     delete d;
00436 }
00437 
00438 void RunnerManager::reloadConfiguration()
00439 {
00440     d->loadConfiguration();
00441     d->loadRunners();
00442 }
00443 
00444 void RunnerManager::setAllowedRunners(const QStringList &runners)
00445 {
00446     qDeleteAll(d->runners);
00447     d->runners.clear();
00448 
00449     KConfigGroup config = d->configGroup();
00450     config.writeEntry("pluginWhiteList", runners);
00451 }
00452 
00453 QStringList RunnerManager::allowedRunners() const
00454 {
00455     KConfigGroup config = d->configGroup();
00456     return config.readEntry("pluginWhiteList", QStringList());
00457 }
00458 
00459 void RunnerManager::loadRunner(const KService::Ptr service)
00460 {
00461     KPluginInfo description(service);
00462     const QString runnerName = description.pluginName();
00463     if (!runnerName.isEmpty() && !d->runners.contains(runnerName)) {
00464         AbstractRunner *runner = d->loadInstalledRunner(service);
00465         if (runner) {
00466             d->runners.insert(runnerName, runner);
00467         }
00468     }
00469 }
00470 
00471 void RunnerManager::loadRunner(const QString &path)
00472 {
00473     if (!d->runners.contains(path)) {
00474         AbstractRunner *runner = new AbstractRunner(this, path);
00475         connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool)));
00476         d->runners.insert(path, runner);
00477     }
00478 }
00479 
00480 AbstractRunner* RunnerManager::runner(const QString &name) const
00481 {
00482     if (d->runners.isEmpty()) {
00483         d->loadRunners();
00484     }
00485 
00486     return d->runners.value(name, 0);
00487 }
00488 
00489 AbstractRunner *RunnerManager::singleModeRunner() const
00490 {
00491     return d->currentSingleRunner;
00492 }
00493 
00494 void RunnerManager::setSingleModeRunnerId(const QString &id)
00495 {
00496     d->singleModeRunnerId = id;
00497     d->loadSingleRunner();
00498 }
00499 
00500 QString RunnerManager::singleModeRunnerId() const
00501 {
00502     return d->singleModeRunnerId;
00503 }
00504 
00505 bool RunnerManager::singleMode() const
00506 {
00507     return d->singleMode;
00508 }
00509 
00510 void RunnerManager::setSingleMode(bool singleMode)
00511 {
00512     if (d->singleMode == singleMode) {
00513         return;
00514     }
00515 
00516 
00517     Plasma::AbstractRunner *prevSingleRunner = d->currentSingleRunner;
00518     d->singleMode = singleMode;
00519     d->loadSingleRunner();
00520     d->singleMode = d->currentSingleRunner;
00521 
00522     if (prevSingleRunner != d->currentSingleRunner) {
00523         if (d->prepped) {
00524             matchSessionComplete();
00525 
00526             if (d->singleMode) {
00527                 setupMatchSession();
00528             }
00529         }
00530     }
00531 }
00532 
00533 QList<AbstractRunner *> RunnerManager::runners() const
00534 {
00535     return d->runners.values();
00536 }
00537 
00538 QStringList RunnerManager::singleModeAdvertisedRunnerIds() const
00539 {
00540     return d->advertiseSingleRunnerIds.keys();
00541 }
00542 
00543 QString RunnerManager::runnerName(const QString &id) const
00544 {
00545     if (runner(id)) {
00546         return runner(id)->name();
00547     } else {
00548         return d->advertiseSingleRunnerIds.value(id, QString());
00549     }
00550 }
00551 
00552 RunnerContext* RunnerManager::searchContext() const
00553 {
00554     return &d->context;
00555 }
00556 
00557 //Reordering is here so data is not reordered till strictly needed
00558 QList<QueryMatch> RunnerManager::matches() const
00559 {
00560     return d->context.matches();
00561 }
00562 
00563 void RunnerManager::run(const QString &id)
00564 {
00565     run(d->context.match(id));
00566 }
00567 
00568 void RunnerManager::run(const QueryMatch &match)
00569 {
00570     if (!match.isEnabled()) {
00571         return;
00572     }
00573 
00574     //TODO: this function is not const as it may be used for learning
00575     AbstractRunner *runner = match.runner();
00576 
00577     foreach (FindMatchesJob *job, d->searchJobs) {
00578         if (job->runner() == runner && !job->isFinished()) {
00579             kDebug() << "deferred run";
00580             d->deferredRun = match;
00581             return;
00582         }
00583     }
00584 
00585     if (d->deferredRun.isValid()) {
00586         d->deferredRun = QueryMatch(0);
00587     }
00588 
00589     d->context.run(match);
00590 }
00591 
00592 QList<QAction*> RunnerManager::actionsForMatch(const QueryMatch &match)
00593 {
00594     AbstractRunner *runner = match.runner();
00595     if (runner) {
00596         return runner->actionsForMatch(match);
00597     }
00598 
00599     return QList<QAction*>();
00600 }
00601 
00602 QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const
00603 {
00604     return mimeDataForMatch(d->context.match(id));
00605 }
00606 
00607 
00608 QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const
00609 {
00610     AbstractRunner *runner = match.runner();
00611     QMimeData *mimeData;
00612     if (runner && QMetaObject::invokeMethod(
00613             runner,
00614             "mimeDataForMatch", Qt::DirectConnection,
00615             Q_RETURN_ARG(QMimeData*, mimeData),
00616             Q_ARG(const Plasma::QueryMatch *, &match)
00617     )) {
00618         return mimeData;
00619     }
00620 
00621     return 0;
00622 }
00623 
00624 KPluginInfo::List RunnerManager::listRunnerInfo(const QString &parentApp)
00625 {
00626     return PluginLoader::pluginLoader()->listRunnerInfo(parentApp);
00627 }
00628 
00629 void RunnerManager::setupMatchSession()
00630 {
00631     d->teardownRequested = false;
00632 
00633     if (d->prepped) {
00634         return;
00635     }
00636 
00637     d->prepped = true;
00638     if (d->singleMode) {
00639         if (d->currentSingleRunner) {
00640             emit d->currentSingleRunner->prepare();
00641             d->singleRunnerPrepped = true;
00642         }
00643     } else {
00644         foreach (AbstractRunner *runner, d->runners) {
00645 #ifdef MEASURE_PREPTIME
00646             QTime t;
00647             t.start();
00648 #endif
00649             emit runner->prepare();
00650 #ifdef MEASURE_PREPTIME
00651             kDebug() << t.elapsed() << runner->name();
00652 #endif
00653         }
00654 
00655         d->allRunnersPrepped = true;
00656     }
00657 }
00658 
00659 void RunnerManager::matchSessionComplete()
00660 {
00661     if (!d->prepped) {
00662         return;
00663     }
00664 
00665     d->teardownRequested = true;
00666     d->checkTearDown();
00667 }
00668 
00669 void RunnerManager::launchQuery(const QString &term)
00670 {
00671     launchQuery(term, QString());
00672 }
00673 
00674 void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &runnerName)
00675 {
00676     setupMatchSession();
00677     QString term = untrimmedTerm.trimmed();
00678 
00679     setSingleModeRunnerId(runnerName);
00680     setSingleMode(!runnerName.isEmpty());
00681 
00682     if (term.isEmpty()) {
00683         if (d->singleMode && d->currentSingleRunner && d->currentSingleRunner->defaultSyntax()) {
00684             term = d->currentSingleRunner->defaultSyntax()->exampleQueries().first().remove(QRegExp(":q:"));
00685         } else {
00686             reset();
00687             return;
00688         }
00689     }
00690 
00691     if (d->context.query() == term) {
00692         // we already are searching for this!
00693         return;
00694     }
00695 
00696     if (d->singleMode && !d->currentSingleRunner) {
00697         reset();
00698         return;
00699     }
00700 
00701     if (d->runners.isEmpty()) {
00702         d->loadRunners();
00703     }
00704 
00705     reset();
00706 //    kDebug() << "runners searching for" << term << "on" << runnerName;
00707     d->context.setQuery(term);
00708 
00709     QHash<QString, AbstractRunner*> runable;
00710 
00711     //if the name is not empty we will launch only the specified runner
00712     if (d->singleMode && d->currentSingleRunner) {
00713         runable.insert(QString(), d->currentSingleRunner);
00714         d->context.setSingleRunnerQueryMode(true);
00715     } else {
00716         runable = d->runners;
00717     }
00718 
00719     foreach (Plasma::AbstractRunner *r, runable) {
00720         if (r->isMatchingSuspended()) {
00721             continue;
00722         }
00723 
00724         d->startJob(r);
00725     }
00726 
00727     // Start timer to unblock slow runners
00728     d->delayTimer.start(RunnerManagerPrivate::slowRunDelay);
00729 }
00730 
00731 bool RunnerManager::execQuery(const QString &term)
00732 {
00733     return execQuery(term, QString());
00734 }
00735 
00736 bool RunnerManager::execQuery(const QString &untrimmedTerm, const QString &runnerName)
00737 {
00738     QString term = untrimmedTerm.trimmed();
00739 
00740     if (term.isEmpty()) {
00741         reset();
00742         return false;
00743     }
00744 
00745     if (d->runners.isEmpty()) {
00746         d->loadRunners();
00747     }
00748 
00749     if (d->context.query() == term) {
00750         // we already are searching for this!
00751         emit matchesChanged(d->context.matches());
00752         return false;
00753     }
00754 
00755     reset();
00756     //kDebug() << "executing query about " << term << "on" << runnerName;
00757     d->context.setQuery(term);
00758     AbstractRunner *r = runner(runnerName);
00759 
00760     if (!r) {
00761         //kDebug() << "failed to find the runner";
00762         return false;
00763     }
00764 
00765     if ((r->ignoredTypes() & d->context.type()) != 0) {
00766         //kDebug() << "ignored!";
00767         return false;
00768     }
00769 
00770     r->performMatch(d->context);
00771     //kDebug() << "succeeded with" << d->context.matches().count() << "results";
00772     emit matchesChanged(d->context.matches());
00773     return true;
00774 }
00775 
00776 QString RunnerManager::query() const
00777 {
00778     return d->context.query();
00779 }
00780 
00781 void RunnerManager::reset()
00782 {
00783     // If ThreadWeaver is idle, it is safe to clear previous jobs
00784     if (Weaver::instance()->isIdle()) {
00785         qDeleteAll(d->searchJobs);
00786         qDeleteAll(d->oldSearchJobs);
00787         d->oldSearchJobs.clear();
00788     } else {
00789         Weaver::instance()->dequeue();
00790         d->oldSearchJobs += d->searchJobs;
00791     }
00792 
00793     d->searchJobs.clear();
00794 
00795     if (d->deferredRun.isEnabled()) {
00796         //kDebug() << "job actually done, running now **************";
00797         QueryMatch tmpRun = d->deferredRun;
00798         d->deferredRun = QueryMatch(0);
00799         tmpRun.run(d->context);
00800     }
00801 
00802     d->context.reset();
00803 }
00804 
00805 } // Plasma namespace
00806 
00807 #include "runnermanager.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