• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 API Reference
  • 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         const 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         QSet<AbstractRunner *> deadRunners;
00192         QMutableListIterator<KPluginInfo> it(offers);
00193         while (it.hasNext()) {
00194             KPluginInfo &description = it.next();
00195             //kDebug() << "Loading runner: " << service->name() << service->storageId();
00196             QString tryExec = description.property("TryExec").toString();
00197             //kDebug() << "TryExec is" << tryExec;
00198             if (!tryExec.isEmpty() && KStandardDirs::findExe(tryExec).isEmpty()) {
00199                 // we don't actually have this application!
00200                 continue;
00201             }
00202 
00203             const QString runnerName = description.pluginName();
00204             description.load(pluginConf);
00205 
00206             const bool loaded = runners.contains(runnerName);
00207             const bool selected = loadAll || (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                 deadRunners.insert(runners.take(runnerName));
00227                 kDebug() << "Removing runner: " << runnerName;
00228             }
00229         }
00230 
00231         if (!deadRunners.isEmpty()) {
00232                 QSet<FindMatchesJob *> deadJobs;
00233                 foreach (FindMatchesJob *job, searchJobs) {
00234                     if (deadRunners.contains(job->runner())) {
00235                         QObject::disconnect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*)));
00236                         searchJobs.remove(job);
00237                         deadJobs.insert(job);
00238                     }
00239                 }
00240 
00241                 foreach (FindMatchesJob *job, oldSearchJobs) {
00242                     if (deadRunners.contains(job->runner())) {
00243                         oldSearchJobs.remove(job);
00244                         deadJobs.insert(job);
00245                     }
00246                 }
00247 
00248             if (deadJobs.isEmpty()) {
00249                 qDeleteAll(deadRunners);
00250             } else {
00251                 new DelayedJobCleaner(deadJobs, deadRunners);
00252             }
00253         }
00254 
00255         kDebug() << "All runners loaded, total:" << runners.count();
00256     }
00257 
00258     AbstractRunner *loadInstalledRunner(const KService::Ptr service)
00259     {
00260         if (!service) {
00261             return 0;
00262         }
00263 
00264         AbstractRunner *runner = PluginLoader::pluginLoader()->loadRunner(service->property("X-KDE-PluginInfo-Name", QVariant::String).toString());
00265 
00266         if (runner) {
00267             runner->setParent(q);
00268         } else {
00269             const QString api = service->property("X-Plasma-API").toString();
00270 
00271             if (api.isEmpty()) {
00272                 QVariantList args;
00273                 args << service->storageId();
00274                 if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
00275                     QString error;
00276                     runner = service->createInstance<AbstractRunner>(q, args, &error);
00277                     if (!runner) {
00278                         kDebug() << "Failed to load runner:" << service->name() << ". error reported:" << error;
00279                     }
00280                 }
00281             } else {
00282                 //kDebug() << "got a script runner known as" << api;
00283                 runner = new AbstractRunner(service, q);
00284             }
00285         }
00286 
00287         if (runner) {
00288             kDebug() << "================= loading runner:" << service->name() << "=================";
00289             QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool)));
00290             QMetaObject::invokeMethod(runner, "init");
00291         }
00292 
00293         return runner;
00294     }
00295 
00296     void jobDone(ThreadWeaver::Job *job)
00297     {
00298         FindMatchesJob *runJob = dynamic_cast<FindMatchesJob *>(job);
00299 
00300         if (!runJob) {
00301             return;
00302         }
00303 
00304         if (deferredRun.isEnabled() && runJob->runner() == deferredRun.runner()) {
00305             //kDebug() << "job actually done, running now **************";
00306             QueryMatch tmpRun = deferredRun;
00307             deferredRun = QueryMatch(0);
00308             tmpRun.run(context);
00309         }
00310 
00311         searchJobs.remove(runJob);
00312         oldSearchJobs.remove(runJob);
00313         runJob->deleteLater();
00314 
00315         if (searchJobs.isEmpty() && context.matches().isEmpty()) {
00316             // we finished our run, and there are no valid matches, and so no
00317             // signal will have been sent out. so we need to emit the signal
00318             // ourselves here
00319             emit q->matchesChanged(context.matches());
00320         }
00321 
00322         checkTearDown();
00323     }
00324 
00325     void checkTearDown()
00326     {
00327         //kDebug() << prepped << teardownRequested << searchJobs.count() << oldSearchJobs.count();
00328 
00329         if (!prepped || !teardownRequested) {
00330             return;
00331         }
00332 
00333         if (Weaver::instance()->isIdle()) {
00334             qDeleteAll(searchJobs);
00335             searchJobs.clear();
00336             qDeleteAll(oldSearchJobs);
00337             oldSearchJobs.clear();
00338         }
00339 
00340         if (searchJobs.isEmpty() && oldSearchJobs.isEmpty()) {
00341             if (allRunnersPrepped) {
00342                 foreach (AbstractRunner *runner, runners) {
00343                     emit runner->teardown();
00344                 }
00345 
00346                 allRunnersPrepped = false;
00347             }
00348 
00349             if (singleRunnerPrepped) {
00350                 if (currentSingleRunner) {
00351                     emit currentSingleRunner->teardown();
00352                 }
00353 
00354                 singleRunnerPrepped = false;
00355             }
00356 
00357             emit q->queryFinished();
00358 
00359             prepped = false;
00360             teardownRequested = false;
00361         }
00362     }
00363 
00364     void unblockJobs()
00365     {
00366         // WORKAROUND: Queue an empty job to force ThreadWeaver to awaken threads
00367         if (searchJobs.isEmpty() && Weaver::instance()->isIdle()) {
00368             qDeleteAll(oldSearchJobs);
00369             oldSearchJobs.clear();
00370             checkTearDown();
00371             return;
00372         }
00373 
00374         DummyJob *dummy = new DummyJob(q);
00375         Weaver::instance()->enqueue(dummy);
00376         QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater()));
00377     }
00378 
00379     void runnerMatchingSuspended(bool suspended)
00380     {
00381         if (suspended || !prepped || teardownRequested) {
00382             return;
00383         }
00384 
00385         AbstractRunner *runner = qobject_cast<AbstractRunner *>(q->sender());
00386 
00387         if (runner) {
00388             startJob(runner);
00389         }
00390     }
00391 
00392     void startJob(AbstractRunner *runner)
00393     {
00394         if ((runner->ignoredTypes() & context.type()) == 0) {
00395             FindMatchesJob *job = new FindMatchesJob(runner, &context, Weaver::instance());
00396             QObject::connect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*)));
00397             if (runner->speed() == AbstractRunner::SlowSpeed) {
00398                 job->setDelayTimer(&delayTimer);
00399             }
00400             Weaver::instance()->enqueue(job);
00401             searchJobs.insert(job);
00402         }
00403     }
00404 
00405     // Delay in ms before slow runners are allowed to run
00406     static const int slowRunDelay = 400;
00407 
00408     RunnerManager *q;
00409     QueryMatch deferredRun;
00410     RunnerContext context;
00411     QTimer matchChangeTimer;
00412     QTimer delayTimer; // Timer to control when to run slow runners
00413     QHash<QString, AbstractRunner*> runners;
00414     QHash<QString, QString> advertiseSingleRunnerIds;
00415     AbstractRunner* currentSingleRunner;
00416     QSet<FindMatchesJob*> searchJobs;
00417     QSet<FindMatchesJob*> oldSearchJobs;
00418     KConfigGroup conf;
00419     QString singleModeRunnerId;
00420     bool loadAll : 1;
00421     bool prepped : 1;
00422     bool allRunnersPrepped : 1;
00423     bool singleRunnerPrepped : 1;
00424     bool teardownRequested : 1;
00425     bool singleMode : 1;
00426     bool singleRunnerWasLoaded : 1;
00427 };
00428 
00429 /*****************************************************
00430 *  RunnerManager::Public class
00431 *
00432 *****************************************************/
00433 RunnerManager::RunnerManager(QObject *parent)
00434     : QObject(parent),
00435       d(new RunnerManagerPrivate(this))
00436 {
00437     d->loadConfiguration();
00438     //ThreadWeaver::setDebugLevel(true, 4);
00439 }
00440 
00441 RunnerManager::RunnerManager(KConfigGroup &c, QObject *parent)
00442     : QObject(parent),
00443       d(new RunnerManagerPrivate(this))
00444 {
00445     // Should this be really needed? Maybe d->loadConfiguration(c) would make
00446     // more sense.
00447     d->conf = KConfigGroup(&c, "PlasmaRunnerManager");
00448     d->loadConfiguration();
00449     //ThreadWeaver::setDebugLevel(true, 4);
00450 }
00451 
00452 RunnerManager::~RunnerManager()
00453 {
00454     if (!qApp->closingDown() && (!d->searchJobs.isEmpty() || !d->oldSearchJobs.isEmpty())) {
00455         new DelayedJobCleaner(d->searchJobs + d->oldSearchJobs);
00456     }
00457 
00458     delete d;
00459 }
00460 
00461 void RunnerManager::reloadConfiguration()
00462 {
00463     d->loadConfiguration();
00464     d->loadRunners();
00465 }
00466 
00467 void RunnerManager::setAllowedRunners(const QStringList &runners)
00468 {
00469     KConfigGroup config = d->configGroup();
00470     config.writeEntry("pluginWhiteList", runners);
00471 
00472     if (!d->runners.isEmpty()) {
00473         // this has been called with runners already created. so let's do an instant reload
00474         d->loadRunners();
00475     }
00476 }
00477 
00478 QStringList RunnerManager::allowedRunners() const
00479 {
00480     KConfigGroup config = d->configGroup();
00481     return config.readEntry("pluginWhiteList", QStringList());
00482 }
00483 
00484 void RunnerManager::loadRunner(const KService::Ptr service)
00485 {
00486     KPluginInfo description(service);
00487     const QString runnerName = description.pluginName();
00488     if (!runnerName.isEmpty() && !d->runners.contains(runnerName)) {
00489         AbstractRunner *runner = d->loadInstalledRunner(service);
00490         if (runner) {
00491             d->runners.insert(runnerName, runner);
00492         }
00493     }
00494 }
00495 
00496 void RunnerManager::loadRunner(const QString &path)
00497 {
00498     if (!d->runners.contains(path)) {
00499         AbstractRunner *runner = new AbstractRunner(this, path);
00500         connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool)));
00501         d->runners.insert(path, runner);
00502     }
00503 }
00504 
00505 AbstractRunner* RunnerManager::runner(const QString &name) const
00506 {
00507     if (d->runners.isEmpty()) {
00508         d->loadRunners();
00509     }
00510 
00511     return d->runners.value(name, 0);
00512 }
00513 
00514 AbstractRunner *RunnerManager::singleModeRunner() const
00515 {
00516     return d->currentSingleRunner;
00517 }
00518 
00519 void RunnerManager::setSingleModeRunnerId(const QString &id)
00520 {
00521     d->singleModeRunnerId = id;
00522     d->loadSingleRunner();
00523 }
00524 
00525 QString RunnerManager::singleModeRunnerId() const
00526 {
00527     return d->singleModeRunnerId;
00528 }
00529 
00530 bool RunnerManager::singleMode() const
00531 {
00532     return d->singleMode;
00533 }
00534 
00535 void RunnerManager::setSingleMode(bool singleMode)
00536 {
00537     if (d->singleMode == singleMode) {
00538         return;
00539     }
00540 
00541 
00542     Plasma::AbstractRunner *prevSingleRunner = d->currentSingleRunner;
00543     d->singleMode = singleMode;
00544     d->loadSingleRunner();
00545     d->singleMode = d->currentSingleRunner;
00546 
00547     if (prevSingleRunner != d->currentSingleRunner) {
00548         if (d->prepped) {
00549             matchSessionComplete();
00550 
00551             if (d->singleMode) {
00552                 setupMatchSession();
00553             }
00554         }
00555     }
00556 }
00557 
00558 QList<AbstractRunner *> RunnerManager::runners() const
00559 {
00560     return d->runners.values();
00561 }
00562 
00563 QStringList RunnerManager::singleModeAdvertisedRunnerIds() const
00564 {
00565     return d->advertiseSingleRunnerIds.keys();
00566 }
00567 
00568 QString RunnerManager::runnerName(const QString &id) const
00569 {
00570     if (runner(id)) {
00571         return runner(id)->name();
00572     } else {
00573         return d->advertiseSingleRunnerIds.value(id, QString());
00574     }
00575 }
00576 
00577 RunnerContext* RunnerManager::searchContext() const
00578 {
00579     return &d->context;
00580 }
00581 
00582 //Reordering is here so data is not reordered till strictly needed
00583 QList<QueryMatch> RunnerManager::matches() const
00584 {
00585     return d->context.matches();
00586 }
00587 
00588 void RunnerManager::run(const QString &id)
00589 {
00590     run(d->context.match(id));
00591 }
00592 
00593 void RunnerManager::run(const QueryMatch &match)
00594 {
00595     if (!match.isEnabled()) {
00596         return;
00597     }
00598 
00599     //TODO: this function is not const as it may be used for learning
00600     AbstractRunner *runner = match.runner();
00601 
00602     foreach (FindMatchesJob *job, d->searchJobs) {
00603         if (job->runner() == runner && !job->isFinished()) {
00604             kDebug() << "deferred run";
00605             d->deferredRun = match;
00606             return;
00607         }
00608     }
00609 
00610     if (d->deferredRun.isValid()) {
00611         d->deferredRun = QueryMatch(0);
00612     }
00613 
00614     d->context.run(match);
00615 }
00616 
00617 QList<QAction*> RunnerManager::actionsForMatch(const QueryMatch &match)
00618 {
00619     AbstractRunner *runner = match.runner();
00620     if (runner) {
00621         return runner->actionsForMatch(match);
00622     }
00623 
00624     return QList<QAction*>();
00625 }
00626 
00627 QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const
00628 {
00629     return mimeDataForMatch(d->context.match(id));
00630 }
00631 
00632 
00633 QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const
00634 {
00635     AbstractRunner *runner = match.runner();
00636     QMimeData *mimeData;
00637     if (runner && QMetaObject::invokeMethod(
00638             runner,
00639             "mimeDataForMatch", Qt::DirectConnection,
00640             Q_RETURN_ARG(QMimeData*, mimeData),
00641             Q_ARG(const Plasma::QueryMatch *, &match)
00642     )) {
00643         return mimeData;
00644     }
00645 
00646     return 0;
00647 }
00648 
00649 KPluginInfo::List RunnerManager::listRunnerInfo(const QString &parentApp)
00650 {
00651     return PluginLoader::pluginLoader()->listRunnerInfo(parentApp);
00652 }
00653 
00654 void RunnerManager::setupMatchSession()
00655 {
00656     d->teardownRequested = false;
00657 
00658     if (d->prepped) {
00659         return;
00660     }
00661 
00662     d->prepped = true;
00663     if (d->singleMode) {
00664         if (d->currentSingleRunner) {
00665             emit d->currentSingleRunner->prepare();
00666             d->singleRunnerPrepped = true;
00667         }
00668     } else {
00669         foreach (AbstractRunner *runner, d->runners) {
00670 #ifdef MEASURE_PREPTIME
00671             QTime t;
00672             t.start();
00673 #endif
00674             emit runner->prepare();
00675 #ifdef MEASURE_PREPTIME
00676             kDebug() << t.elapsed() << runner->name();
00677 #endif
00678         }
00679 
00680         d->allRunnersPrepped = true;
00681     }
00682 }
00683 
00684 void RunnerManager::matchSessionComplete()
00685 {
00686     if (!d->prepped) {
00687         return;
00688     }
00689 
00690     d->teardownRequested = true;
00691     d->checkTearDown();
00692 }
00693 
00694 void RunnerManager::launchQuery(const QString &term)
00695 {
00696     launchQuery(term, QString());
00697 }
00698 
00699 void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &runnerName)
00700 {
00701     setupMatchSession();
00702     QString term = untrimmedTerm.trimmed();
00703 
00704     setSingleModeRunnerId(runnerName);
00705     setSingleMode(!runnerName.isEmpty());
00706 
00707     if (term.isEmpty()) {
00708         if (d->singleMode && d->currentSingleRunner && d->currentSingleRunner->defaultSyntax()) {
00709             term = d->currentSingleRunner->defaultSyntax()->exampleQueries().first().remove(QRegExp(":q:"));
00710         } else {
00711             reset();
00712             return;
00713         }
00714     }
00715 
00716     if (d->context.query() == term) {
00717         // we already are searching for this!
00718         return;
00719     }
00720 
00721     if (d->singleMode && !d->currentSingleRunner) {
00722         reset();
00723         return;
00724     }
00725 
00726     if (d->runners.isEmpty()) {
00727         d->loadRunners();
00728     }
00729 
00730     reset();
00731 //    kDebug() << "runners searching for" << term << "on" << runnerName;
00732     d->context.setQuery(term);
00733 
00734     QHash<QString, AbstractRunner*> runable;
00735 
00736     //if the name is not empty we will launch only the specified runner
00737     if (d->singleMode && d->currentSingleRunner) {
00738         runable.insert(QString(), d->currentSingleRunner);
00739         d->context.setSingleRunnerQueryMode(true);
00740     } else {
00741         runable = d->runners;
00742     }
00743 
00744     foreach (Plasma::AbstractRunner *r, runable) {
00745         if (r->isMatchingSuspended()) {
00746             continue;
00747         }
00748 
00749         d->startJob(r);
00750     }
00751 
00752     // Start timer to unblock slow runners
00753     d->delayTimer.start(RunnerManagerPrivate::slowRunDelay);
00754 }
00755 
00756 bool RunnerManager::execQuery(const QString &term)
00757 {
00758     return execQuery(term, QString());
00759 }
00760 
00761 bool RunnerManager::execQuery(const QString &untrimmedTerm, const QString &runnerName)
00762 {
00763     QString term = untrimmedTerm.trimmed();
00764 
00765     if (term.isEmpty()) {
00766         reset();
00767         return false;
00768     }
00769 
00770     if (d->runners.isEmpty()) {
00771         d->loadRunners();
00772     }
00773 
00774     if (d->context.query() == term) {
00775         // we already are searching for this!
00776         emit matchesChanged(d->context.matches());
00777         return false;
00778     }
00779 
00780     reset();
00781     //kDebug() << "executing query about " << term << "on" << runnerName;
00782     d->context.setQuery(term);
00783     AbstractRunner *r = runner(runnerName);
00784 
00785     if (!r) {
00786         //kDebug() << "failed to find the runner";
00787         return false;
00788     }
00789 
00790     if ((r->ignoredTypes() & d->context.type()) != 0) {
00791         //kDebug() << "ignored!";
00792         return false;
00793     }
00794 
00795     r->performMatch(d->context);
00796     //kDebug() << "succeeded with" << d->context.matches().count() << "results";
00797     emit matchesChanged(d->context.matches());
00798     return true;
00799 }
00800 
00801 QString RunnerManager::query() const
00802 {
00803     return d->context.query();
00804 }
00805 
00806 void RunnerManager::reset()
00807 {
00808     // If ThreadWeaver is idle, it is safe to clear previous jobs
00809     if (Weaver::instance()->isIdle()) {
00810         qDeleteAll(d->searchJobs);
00811         qDeleteAll(d->oldSearchJobs);
00812         d->oldSearchJobs.clear();
00813     } else {
00814         Weaver::instance()->dequeue();
00815         d->oldSearchJobs += d->searchJobs;
00816     }
00817 
00818     d->searchJobs.clear();
00819 
00820     if (d->deferredRun.isEnabled()) {
00821         //kDebug() << "job actually done, running now **************";
00822         QueryMatch tmpRun = d->deferredRun;
00823         d->deferredRun = QueryMatch(0);
00824         tmpRun.run(d->context);
00825     }
00826 
00827     d->context.reset();
00828 }
00829 
00830 } // Plasma namespace
00831 
00832 #include "runnermanager.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:36:16 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

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

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal