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

Plasma

  • plasma
runnermanager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
3  * Copyright (C) 2007, 2009 Ryan P. Bitanga <ryan.bitanga@gmail.com>
4  * Copyright (C) 2008 Jordi Polo <mumismo@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #include "runnermanager.h"
23 
24 #include "config-plasma.h"
25 
26 #include <QMutex>
27 #include <QTimer>
28 #include <QCoreApplication>
29 
30 #include <kdebug.h>
31 #include <kplugininfo.h>
32 #include <kservicetypetrader.h>
33 #include <kstandarddirs.h>
34 
35 #ifndef PLASMA_NO_SOLID
36 #include <solid/device.h>
37 #include <solid/deviceinterface.h>
38 #endif
39 
40 #include <Weaver/DebuggingAids.h>
41 #include <Weaver/State.h>
42 #include <Weaver/Thread.h>
43 #include <Weaver/ThreadWeaver.h>
44 
45 #include "private/runnerjobs_p.h"
46 #include "pluginloader.h"
47 #include "querymatch.h"
48 
49 using ThreadWeaver::Weaver;
50 using ThreadWeaver::Job;
51 
52 //#define MEASURE_PREPTIME
53 
54 namespace Plasma
55 {
56 
57 /*****************************************************
58 * RunnerManager::Private class
59 *
60 *****************************************************/
61 class RunnerManagerPrivate
62 {
63 public:
64 
65  RunnerManagerPrivate(RunnerManager *parent)
66  : q(parent),
67  deferredRun(0),
68  currentSingleRunner(0),
69  prepped(false),
70  allRunnersPrepped(false),
71  singleRunnerPrepped(false),
72  teardownRequested(false),
73  singleMode(false),
74  singleRunnerWasLoaded(false)
75  {
76  matchChangeTimer.setSingleShot(true);
77  delayTimer.setSingleShot(true);
78 
79  QObject::connect(&matchChangeTimer, SIGNAL(timeout()), q, SLOT(matchesChanged()));
80  QObject::connect(&context, SIGNAL(matchesChanged()), q, SLOT(scheduleMatchesChanged()));
81  QObject::connect(&delayTimer, SIGNAL(timeout()), q, SLOT(unblockJobs()));
82  }
83 
84  ~RunnerManagerPrivate()
85  {
86  KConfigGroup config = configGroup();
87  context.save(config);
88  }
89 
90  void scheduleMatchesChanged()
91  {
92  matchChangeTimer.start(100);
93  }
94 
95  void matchesChanged()
96  {
97  emit q->matchesChanged(context.matches());
98  }
99 
100  void loadConfiguration()
101  {
102  KConfigGroup config = configGroup();
103 
104  //The number of threads used scales with the number of processors.
105 #ifndef PLASMA_NO_SOLID
106  const int numProcs =
107  qMax(Solid::Device::listFromType(Solid::DeviceInterface::Processor).count(), 1);
108 #else
109  const int numProcs = 1;
110 #endif
111  //This entry allows to define a hard upper limit independent of the number of processors.
112  const int maxThreads = config.readEntry("maxThreads", 16);
113  const int numThreads = qMin(maxThreads, 2 + ((numProcs - 1) * 2));
114  //kDebug() << "setting up" << numThreads << "threads for" << numProcs << "processors";
115  if (numThreads > Weaver::instance()->maximumNumberOfThreads()) {
116  Weaver::instance()->setMaximumNumberOfThreads(numThreads);
117  }
118  // Limit the number of instances of a single normal speed runner and all of the slow runners
119  // to half the number of threads
120  const int cap = qMax(2, numThreads/2);
121  DefaultRunnerPolicy::instance().setCap(cap);
122 
123  context.restore(config);
124  }
125 
126  KConfigGroup configGroup()
127  {
128  return conf.isValid() ? conf : KConfigGroup(KGlobal::config(), "PlasmaRunnerManager");
129  }
130 
131  void clearSingleRunner()
132  {
133  if (singleRunnerWasLoaded) {
134  delete currentSingleRunner;
135  }
136 
137  currentSingleRunner = 0;
138  }
139 
140  void loadSingleRunner()
141  {
142  if (!singleMode || singleModeRunnerId.isEmpty()) {
143  clearSingleRunner();
144  return;
145  }
146 
147  if (currentSingleRunner) {
148  if (currentSingleRunner->id() == singleModeRunnerId) {
149  return;
150  }
151 
152  clearSingleRunner();
153  }
154 
155  AbstractRunner *loadedRunner = q->runner(singleModeRunnerId);
156  if (loadedRunner) {
157  singleRunnerWasLoaded = false;
158  currentSingleRunner = loadedRunner;
159  return;
160  }
161 
162  KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner", QString("[X-KDE-PluginInfo-Name] == '%1'").arg(singleModeRunnerId));
163  if (!offers.isEmpty()) {
164  const KService::Ptr &service = offers[0];
165  currentSingleRunner = loadInstalledRunner(service);
166 
167  if (currentSingleRunner) {
168  emit currentSingleRunner->prepare();
169  singleRunnerWasLoaded = true;
170  }
171  }
172  }
173 
174  void loadRunners()
175  {
176  KConfigGroup config = configGroup();
177  KPluginInfo::List offers = RunnerManager::listRunnerInfo();
178 
179  const bool loadAll = config.readEntry("loadAll", false);
180  const QStringList whiteList = config.readEntry("pluginWhiteList", QStringList());
181  const bool noWhiteList = whiteList.isEmpty();
182  KConfigGroup pluginConf;
183  if (conf.isValid()) {
184  pluginConf = KConfigGroup(&conf, "Plugins");
185  } else {
186  pluginConf = KConfigGroup(KGlobal::config(), "Plugins");
187  }
188 
189  advertiseSingleRunnerIds.clear();
190 
191  QSet<AbstractRunner *> deadRunners;
192  QMutableListIterator<KPluginInfo> it(offers);
193  while (it.hasNext()) {
194  KPluginInfo &description = it.next();
195  //kDebug() << "Loading runner: " << service->name() << service->storageId();
196  QString tryExec = description.property("TryExec").toString();
197  //kDebug() << "TryExec is" << tryExec;
198  if (!tryExec.isEmpty() && KStandardDirs::findExe(tryExec).isEmpty()) {
199  // we don't actually have this application!
200  continue;
201  }
202 
203  const QString runnerName = description.pluginName();
204  description.load(pluginConf);
205 
206  const bool loaded = runners.contains(runnerName);
207  const bool selected = loadAll || (description.isPluginEnabled() && (noWhiteList || whiteList.contains(runnerName)));
208 
209  const bool singleQueryModeEnabled = description.property("X-Plasma-AdvertiseSingleRunnerQueryMode").toBool();
210 
211  if (singleQueryModeEnabled) {
212  advertiseSingleRunnerIds.insert(runnerName, description.name());
213  }
214 
215  //kDebug() << loadAll << description.isPluginEnabled() << noWhiteList << whiteList.contains(runnerName);
216  if (selected) {
217  if (!loaded) {
218  AbstractRunner *runner = loadInstalledRunner(description.service());
219 
220  if (runner) {
221  runners.insert(runnerName, runner);
222  }
223  }
224  } else if (loaded) {
225  //Remove runner
226  deadRunners.insert(runners.take(runnerName));
227  kDebug() << "Removing runner: " << runnerName;
228  }
229  }
230 
231  if (!deadRunners.isEmpty()) {
232  QSet<FindMatchesJob *> deadJobs;
233  foreach (FindMatchesJob *job, searchJobs) {
234  if (deadRunners.contains(job->runner())) {
235  QObject::disconnect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*)));
236  searchJobs.remove(job);
237  deadJobs.insert(job);
238  }
239  }
240 
241  foreach (FindMatchesJob *job, oldSearchJobs) {
242  if (deadRunners.contains(job->runner())) {
243  oldSearchJobs.remove(job);
244  deadJobs.insert(job);
245  }
246  }
247 
248  if (deadJobs.isEmpty()) {
249  qDeleteAll(deadRunners);
250  } else {
251  new DelayedJobCleaner(deadJobs, deadRunners);
252  }
253  }
254 
255  if (!singleRunnerWasLoaded) {
256  // in case we deleted it up above
257  clearSingleRunner();
258  }
259 
260  kDebug() << "All runners loaded, total:" << runners.count();
261  }
262 
263  AbstractRunner *loadInstalledRunner(const KService::Ptr service)
264  {
265  if (!service) {
266  return 0;
267  }
268 
269  AbstractRunner *runner = PluginLoader::pluginLoader()->loadRunner(service->property("X-KDE-PluginInfo-Name", QVariant::String).toString());
270 
271  if (runner) {
272  runner->setParent(q);
273  } else {
274  const QString api = service->property("X-Plasma-API").toString();
275 
276  if (api.isEmpty()) {
277  QVariantList args;
278  args << service->storageId();
279  if (Plasma::isPluginVersionCompatible(KPluginLoader(*service).pluginVersion())) {
280  QString error;
281  runner = service->createInstance<AbstractRunner>(q, args, &error);
282  if (!runner) {
283  kDebug() << "Failed to load runner:" << service->name() << ". error reported:" << error;
284  }
285  }
286  } else {
287  //kDebug() << "got a script runner known as" << api;
288  runner = new AbstractRunner(service, q);
289  }
290  }
291 
292  if (runner) {
293  kDebug() << "================= loading runner:" << service->name() << "=================";
294  QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool)));
295  QMetaObject::invokeMethod(runner, "init");
296  }
297 
298  return runner;
299  }
300 
301  void jobDone(ThreadWeaver::Job *job)
302  {
303  FindMatchesJob *runJob = dynamic_cast<FindMatchesJob *>(job);
304 
305  if (!runJob) {
306  return;
307  }
308 
309  if (deferredRun.isEnabled() && runJob->runner() == deferredRun.runner()) {
310  //kDebug() << "job actually done, running now **************";
311  QueryMatch tmpRun = deferredRun;
312  deferredRun = QueryMatch(0);
313  tmpRun.run(context);
314  }
315 
316  searchJobs.remove(runJob);
317  oldSearchJobs.remove(runJob);
318  runJob->deleteLater();
319 
320  if (searchJobs.isEmpty() && context.matches().isEmpty()) {
321  // we finished our run, and there are no valid matches, and so no
322  // signal will have been sent out. so we need to emit the signal
323  // ourselves here
324  emit q->matchesChanged(context.matches());
325  }
326 
327  checkTearDown();
328  }
329 
330  void checkTearDown()
331  {
332  //kDebug() << prepped << teardownRequested << searchJobs.count() << oldSearchJobs.count();
333 
334  if (!prepped || !teardownRequested) {
335  return;
336  }
337 
338  if (Weaver::instance()->isIdle()) {
339  qDeleteAll(searchJobs);
340  searchJobs.clear();
341  qDeleteAll(oldSearchJobs);
342  oldSearchJobs.clear();
343  }
344 
345  if (searchJobs.isEmpty() && oldSearchJobs.isEmpty()) {
346  if (allRunnersPrepped) {
347  foreach (AbstractRunner *runner, runners) {
348  emit runner->teardown();
349  }
350 
351  allRunnersPrepped = false;
352  }
353 
354  if (singleRunnerPrepped) {
355  if (currentSingleRunner) {
356  emit currentSingleRunner->teardown();
357  }
358 
359  singleRunnerPrepped = false;
360  }
361 
362  emit q->queryFinished();
363 
364  prepped = false;
365  teardownRequested = false;
366  }
367  }
368 
369  void unblockJobs()
370  {
371  // WORKAROUND: Queue an empty job to force ThreadWeaver to awaken threads
372  if (searchJobs.isEmpty() && Weaver::instance()->isIdle()) {
373  qDeleteAll(oldSearchJobs);
374  oldSearchJobs.clear();
375  checkTearDown();
376  return;
377  }
378 
379  DummyJob *dummy = new DummyJob(q);
380  Weaver::instance()->enqueue(dummy);
381  QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater()));
382  }
383 
384  void runnerMatchingSuspended(bool suspended)
385  {
386  if (suspended || !prepped || teardownRequested) {
387  return;
388  }
389 
390  AbstractRunner *runner = qobject_cast<AbstractRunner *>(q->sender());
391 
392  if (runner) {
393  startJob(runner);
394  }
395  }
396 
397  void startJob(AbstractRunner *runner)
398  {
399  if ((runner->ignoredTypes() & context.type()) == 0) {
400  FindMatchesJob *job = new FindMatchesJob(runner, &context, Weaver::instance());
401  QObject::connect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*)));
402  if (runner->speed() == AbstractRunner::SlowSpeed) {
403  job->setDelayTimer(&delayTimer);
404  }
405  Weaver::instance()->enqueue(job);
406  searchJobs.insert(job);
407  }
408  }
409 
410  // Delay in ms before slow runners are allowed to run
411  static const int slowRunDelay = 400;
412 
413  RunnerManager *q;
414  QueryMatch deferredRun;
415  RunnerContext context;
416  QTimer matchChangeTimer;
417  QTimer delayTimer; // Timer to control when to run slow runners
418  QHash<QString, AbstractRunner*> runners;
419  QHash<QString, QString> advertiseSingleRunnerIds;
420  AbstractRunner* currentSingleRunner;
421  QSet<FindMatchesJob*> searchJobs;
422  QSet<FindMatchesJob*> oldSearchJobs;
423  KConfigGroup conf;
424  QString singleModeRunnerId;
425  bool loadAll : 1;
426  bool prepped : 1;
427  bool allRunnersPrepped : 1;
428  bool singleRunnerPrepped : 1;
429  bool teardownRequested : 1;
430  bool singleMode : 1;
431  bool singleRunnerWasLoaded : 1;
432 };
433 
434 /*****************************************************
435 * RunnerManager::Public class
436 *
437 *****************************************************/
438 RunnerManager::RunnerManager(QObject *parent)
439  : QObject(parent),
440  d(new RunnerManagerPrivate(this))
441 {
442  d->loadConfiguration();
443  //ThreadWeaver::setDebugLevel(true, 4);
444 }
445 
446 RunnerManager::RunnerManager(KConfigGroup &c, QObject *parent)
447  : QObject(parent),
448  d(new RunnerManagerPrivate(this))
449 {
450  // Should this be really needed? Maybe d->loadConfiguration(c) would make
451  // more sense.
452  d->conf = KConfigGroup(&c, "PlasmaRunnerManager");
453  d->loadConfiguration();
454  //ThreadWeaver::setDebugLevel(true, 4);
455 }
456 
457 RunnerManager::~RunnerManager()
458 {
459  if (!qApp->closingDown() && (!d->searchJobs.isEmpty() || !d->oldSearchJobs.isEmpty())) {
460  new DelayedJobCleaner(d->searchJobs + d->oldSearchJobs);
461  }
462 
463  delete d;
464 }
465 
466 void RunnerManager::reloadConfiguration()
467 {
468  d->loadConfiguration();
469  d->loadRunners();
470 }
471 
472 void RunnerManager::setAllowedRunners(const QStringList &runners)
473 {
474  KConfigGroup config = d->configGroup();
475  config.writeEntry("pluginWhiteList", runners);
476 
477  if (!d->runners.isEmpty()) {
478  // this has been called with runners already created. so let's do an instant reload
479  d->loadRunners();
480  }
481 }
482 
483 QStringList RunnerManager::allowedRunners() const
484 {
485  KConfigGroup config = d->configGroup();
486  return config.readEntry("pluginWhiteList", QStringList());
487 }
488 
489 void RunnerManager::loadRunner(const KService::Ptr service)
490 {
491  KPluginInfo description(service);
492  const QString runnerName = description.pluginName();
493  if (!runnerName.isEmpty() && !d->runners.contains(runnerName)) {
494  AbstractRunner *runner = d->loadInstalledRunner(service);
495  if (runner) {
496  d->runners.insert(runnerName, runner);
497  }
498  }
499 }
500 
501 void RunnerManager::loadRunner(const QString &path)
502 {
503  if (!d->runners.contains(path)) {
504  AbstractRunner *runner = new AbstractRunner(this, path);
505  connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool)));
506  d->runners.insert(path, runner);
507  }
508 }
509 
510 AbstractRunner* RunnerManager::runner(const QString &name) const
511 {
512  if (d->runners.isEmpty()) {
513  d->loadRunners();
514  }
515 
516  return d->runners.value(name, 0);
517 }
518 
519 AbstractRunner *RunnerManager::singleModeRunner() const
520 {
521  return d->currentSingleRunner;
522 }
523 
524 void RunnerManager::setSingleModeRunnerId(const QString &id)
525 {
526  d->singleModeRunnerId = id;
527  d->loadSingleRunner();
528 }
529 
530 QString RunnerManager::singleModeRunnerId() const
531 {
532  return d->singleModeRunnerId;
533 }
534 
535 bool RunnerManager::singleMode() const
536 {
537  return d->singleMode;
538 }
539 
540 void RunnerManager::setSingleMode(bool singleMode)
541 {
542  if (d->singleMode == singleMode) {
543  return;
544  }
545 
546 
547  Plasma::AbstractRunner *prevSingleRunner = d->currentSingleRunner;
548  d->singleMode = singleMode;
549  d->loadSingleRunner();
550  d->singleMode = d->currentSingleRunner;
551 
552  if (prevSingleRunner != d->currentSingleRunner) {
553  if (d->prepped) {
554  matchSessionComplete();
555 
556  if (d->singleMode) {
557  setupMatchSession();
558  }
559  }
560  }
561 }
562 
563 QList<AbstractRunner *> RunnerManager::runners() const
564 {
565  return d->runners.values();
566 }
567 
568 QStringList RunnerManager::singleModeAdvertisedRunnerIds() const
569 {
570  return d->advertiseSingleRunnerIds.keys();
571 }
572 
573 QString RunnerManager::runnerName(const QString &id) const
574 {
575  if (runner(id)) {
576  return runner(id)->name();
577  } else {
578  return d->advertiseSingleRunnerIds.value(id, QString());
579  }
580 }
581 
582 RunnerContext* RunnerManager::searchContext() const
583 {
584  return &d->context;
585 }
586 
587 //Reordering is here so data is not reordered till strictly needed
588 QList<QueryMatch> RunnerManager::matches() const
589 {
590  return d->context.matches();
591 }
592 
593 void RunnerManager::run(const QString &id)
594 {
595  run(d->context.match(id));
596 }
597 
598 void RunnerManager::run(const QueryMatch &match)
599 {
600  if (!match.isEnabled()) {
601  return;
602  }
603 
604  //TODO: this function is not const as it may be used for learning
605  AbstractRunner *runner = match.runner();
606 
607  foreach (FindMatchesJob *job, d->searchJobs) {
608  if (job->runner() == runner && !job->isFinished()) {
609  kDebug() << "deferred run";
610  d->deferredRun = match;
611  return;
612  }
613  }
614 
615  if (d->deferredRun.isValid()) {
616  d->deferredRun = QueryMatch(0);
617  }
618 
619  d->context.run(match);
620 }
621 
622 QList<QAction*> RunnerManager::actionsForMatch(const QueryMatch &match)
623 {
624  AbstractRunner *runner = match.runner();
625  if (runner) {
626  return runner->actionsForMatch(match);
627  }
628 
629  return QList<QAction*>();
630 }
631 
632 QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const
633 {
634  return mimeDataForMatch(d->context.match(id));
635 }
636 
637 
638 QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const
639 {
640  AbstractRunner *runner = match.runner();
641  QMimeData *mimeData;
642  if (runner && QMetaObject::invokeMethod(
643  runner,
644  "mimeDataForMatch", Qt::DirectConnection,
645  Q_RETURN_ARG(QMimeData*, mimeData),
646  Q_ARG(const Plasma::QueryMatch *, &match)
647  )) {
648  return mimeData;
649  }
650 
651  return 0;
652 }
653 
654 KPluginInfo::List RunnerManager::listRunnerInfo(const QString &parentApp)
655 {
656  return PluginLoader::pluginLoader()->listRunnerInfo(parentApp);
657 }
658 
659 void RunnerManager::setupMatchSession()
660 {
661  d->teardownRequested = false;
662 
663  if (d->prepped) {
664  return;
665  }
666 
667  d->prepped = true;
668  if (d->singleMode) {
669  if (d->currentSingleRunner) {
670  emit d->currentSingleRunner->prepare();
671  d->singleRunnerPrepped = true;
672  }
673  } else {
674  foreach (AbstractRunner *runner, d->runners) {
675 #ifdef MEASURE_PREPTIME
676  QTime t;
677  t.start();
678 #endif
679  emit runner->prepare();
680 #ifdef MEASURE_PREPTIME
681  kDebug() << t.elapsed() << runner->name();
682 #endif
683  }
684 
685  d->allRunnersPrepped = true;
686  }
687 }
688 
689 void RunnerManager::matchSessionComplete()
690 {
691  if (!d->prepped) {
692  return;
693  }
694 
695  d->teardownRequested = true;
696  d->checkTearDown();
697 }
698 
699 void RunnerManager::launchQuery(const QString &term)
700 {
701  launchQuery(term, QString());
702 }
703 
704 void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &runnerName)
705 {
706  setupMatchSession();
707  QString term = untrimmedTerm.trimmed();
708 
709  setSingleModeRunnerId(runnerName);
710  setSingleMode(!runnerName.isEmpty());
711 
712  if (term.isEmpty()) {
713  if (d->singleMode && d->currentSingleRunner && d->currentSingleRunner->defaultSyntax()) {
714  term = d->currentSingleRunner->defaultSyntax()->exampleQueries().first().remove(QRegExp(":q:"));
715  } else {
716  reset();
717  return;
718  }
719  }
720 
721  if (d->context.query() == term) {
722  // we already are searching for this!
723  return;
724  }
725 
726  if (d->singleMode && !d->currentSingleRunner) {
727  reset();
728  return;
729  }
730 
731  if (d->runners.isEmpty()) {
732  d->loadRunners();
733  }
734 
735  reset();
736 // kDebug() << "runners searching for" << term << "on" << runnerName;
737  d->context.setQuery(term);
738 
739  QHash<QString, AbstractRunner*> runable;
740 
741  //if the name is not empty we will launch only the specified runner
742  if (d->singleMode && d->currentSingleRunner) {
743  runable.insert(QString(), d->currentSingleRunner);
744  d->context.setSingleRunnerQueryMode(true);
745  } else {
746  runable = d->runners;
747  }
748 
749  foreach (Plasma::AbstractRunner *r, runable) {
750  if (r->isMatchingSuspended()) {
751  continue;
752  }
753 
754  d->startJob(r);
755  }
756 
757  // Start timer to unblock slow runners
758  d->delayTimer.start(RunnerManagerPrivate::slowRunDelay);
759 }
760 
761 bool RunnerManager::execQuery(const QString &term)
762 {
763  return execQuery(term, QString());
764 }
765 
766 bool RunnerManager::execQuery(const QString &untrimmedTerm, const QString &runnerName)
767 {
768  QString term = untrimmedTerm.trimmed();
769 
770  if (term.isEmpty()) {
771  reset();
772  return false;
773  }
774 
775  if (d->runners.isEmpty()) {
776  d->loadRunners();
777  }
778 
779  if (d->context.query() == term) {
780  // we already are searching for this!
781  emit matchesChanged(d->context.matches());
782  return false;
783  }
784 
785  reset();
786  //kDebug() << "executing query about " << term << "on" << runnerName;
787  d->context.setQuery(term);
788  AbstractRunner *r = runner(runnerName);
789 
790  if (!r) {
791  //kDebug() << "failed to find the runner";
792  return false;
793  }
794 
795  if ((r->ignoredTypes() & d->context.type()) != 0) {
796  //kDebug() << "ignored!";
797  return false;
798  }
799 
800  r->performMatch(d->context);
801  //kDebug() << "succeeded with" << d->context.matches().count() << "results";
802  emit matchesChanged(d->context.matches());
803  return true;
804 }
805 
806 QString RunnerManager::query() const
807 {
808  return d->context.query();
809 }
810 
811 void RunnerManager::reset()
812 {
813  // If ThreadWeaver is idle, it is safe to clear previous jobs
814  if (Weaver::instance()->isIdle()) {
815  qDeleteAll(d->searchJobs);
816  qDeleteAll(d->oldSearchJobs);
817  d->oldSearchJobs.clear();
818  } else {
819  Q_FOREACH(FindMatchesJob *job, d->searchJobs) {
820  Weaver::instance()->dequeue(job);
821  }
822  d->oldSearchJobs += d->searchJobs;
823  }
824 
825  d->searchJobs.clear();
826 
827  if (d->deferredRun.isEnabled()) {
828  //kDebug() << "job actually done, running now **************";
829  QueryMatch tmpRun = d->deferredRun;
830  d->deferredRun = QueryMatch(0);
831  tmpRun.run(d->context);
832  }
833 
834  d->context.reset();
835 }
836 
837 } // Plasma namespace
838 
839 #include "runnermanager.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:02:04 by doxygen 1.8.1 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.5 API Reference

Skip menu "kdelibs-4.8.5 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