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

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • 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  if (prepped) {
297  emit runner->prepare();
298  }
299  }
300 
301  return runner;
302  }
303 
304  void jobDone(ThreadWeaver::Job *job)
305  {
306  FindMatchesJob *runJob = dynamic_cast<FindMatchesJob *>(job);
307 
308  if (!runJob) {
309  return;
310  }
311 
312  if (deferredRun.isEnabled() && runJob->runner() == deferredRun.runner()) {
313  //kDebug() << "job actually done, running now **************";
314  QueryMatch tmpRun = deferredRun;
315  deferredRun = QueryMatch(0);
316  tmpRun.run(context);
317  }
318 
319  searchJobs.remove(runJob);
320  oldSearchJobs.remove(runJob);
321  runJob->deleteLater();
322 
323  if (searchJobs.isEmpty() && context.matches().isEmpty()) {
324  // we finished our run, and there are no valid matches, and so no
325  // signal will have been sent out. so we need to emit the signal
326  // ourselves here
327  emit q->matchesChanged(context.matches());
328  }
329 
330  checkTearDown();
331  }
332 
333  void checkTearDown()
334  {
335  //kDebug() << prepped << teardownRequested << searchJobs.count() << oldSearchJobs.count();
336 
337  if (!prepped || !teardownRequested) {
338  return;
339  }
340 
341  if (Weaver::instance()->isIdle()) {
342  qDeleteAll(searchJobs);
343  searchJobs.clear();
344  qDeleteAll(oldSearchJobs);
345  oldSearchJobs.clear();
346  }
347 
348  if (searchJobs.isEmpty() && oldSearchJobs.isEmpty()) {
349  if (allRunnersPrepped) {
350  foreach (AbstractRunner *runner, runners) {
351  emit runner->teardown();
352  }
353 
354  allRunnersPrepped = false;
355  }
356 
357  if (singleRunnerPrepped) {
358  if (currentSingleRunner) {
359  emit currentSingleRunner->teardown();
360  }
361 
362  singleRunnerPrepped = false;
363  }
364 
365  emit q->queryFinished();
366 
367  prepped = false;
368  teardownRequested = false;
369  }
370  }
371 
372  void unblockJobs()
373  {
374  // WORKAROUND: Queue an empty job to force ThreadWeaver to awaken threads
375  if (searchJobs.isEmpty() && Weaver::instance()->isIdle()) {
376  qDeleteAll(oldSearchJobs);
377  oldSearchJobs.clear();
378  checkTearDown();
379  return;
380  }
381 
382  DummyJob *dummy = new DummyJob(q);
383  Weaver::instance()->enqueue(dummy);
384  QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater()));
385  }
386 
387  void runnerMatchingSuspended(bool suspended)
388  {
389  if (suspended || !prepped || teardownRequested) {
390  return;
391  }
392 
393  AbstractRunner *runner = qobject_cast<AbstractRunner *>(q->sender());
394 
395  if (runner) {
396  startJob(runner);
397  }
398  }
399 
400  void startJob(AbstractRunner *runner)
401  {
402  if ((runner->ignoredTypes() & context.type()) == 0) {
403  FindMatchesJob *job = new FindMatchesJob(runner, &context, Weaver::instance());
404  QObject::connect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*)));
405  if (runner->speed() == AbstractRunner::SlowSpeed) {
406  job->setDelayTimer(&delayTimer);
407  }
408  Weaver::instance()->enqueue(job);
409  searchJobs.insert(job);
410  }
411  }
412 
413  // Delay in ms before slow runners are allowed to run
414  static const int slowRunDelay = 400;
415 
416  RunnerManager *q;
417  QueryMatch deferredRun;
418  RunnerContext context;
419  QTimer matchChangeTimer;
420  QTimer delayTimer; // Timer to control when to run slow runners
421  QHash<QString, AbstractRunner*> runners;
422  QHash<QString, QString> advertiseSingleRunnerIds;
423  AbstractRunner* currentSingleRunner;
424  QSet<FindMatchesJob*> searchJobs;
425  QSet<FindMatchesJob*> oldSearchJobs;
426  KConfigGroup conf;
427  QString singleModeRunnerId;
428  bool loadAll : 1;
429  bool prepped : 1;
430  bool allRunnersPrepped : 1;
431  bool singleRunnerPrepped : 1;
432  bool teardownRequested : 1;
433  bool singleMode : 1;
434  bool singleRunnerWasLoaded : 1;
435 };
436 
437 /*****************************************************
438 * RunnerManager::Public class
439 *
440 *****************************************************/
441 RunnerManager::RunnerManager(QObject *parent)
442  : QObject(parent),
443  d(new RunnerManagerPrivate(this))
444 {
445  d->loadConfiguration();
446  //ThreadWeaver::setDebugLevel(true, 4);
447 }
448 
449 RunnerManager::RunnerManager(KConfigGroup &c, QObject *parent)
450  : QObject(parent),
451  d(new RunnerManagerPrivate(this))
452 {
453  // Should this be really needed? Maybe d->loadConfiguration(c) would make
454  // more sense.
455  d->conf = KConfigGroup(&c, "PlasmaRunnerManager");
456  d->loadConfiguration();
457  //ThreadWeaver::setDebugLevel(true, 4);
458 }
459 
460 RunnerManager::~RunnerManager()
461 {
462  if (!qApp->closingDown() && (!d->searchJobs.isEmpty() || !d->oldSearchJobs.isEmpty())) {
463  new DelayedJobCleaner(d->searchJobs + d->oldSearchJobs);
464  }
465 
466  delete d;
467 }
468 
469 void RunnerManager::reloadConfiguration()
470 {
471  d->loadConfiguration();
472  d->loadRunners();
473 }
474 
475 void RunnerManager::setAllowedRunners(const QStringList &runners)
476 {
477  KConfigGroup config = d->configGroup();
478  config.writeEntry("pluginWhiteList", runners);
479 
480  if (!d->runners.isEmpty()) {
481  // this has been called with runners already created. so let's do an instant reload
482  d->loadRunners();
483  }
484 }
485 
486 QStringList RunnerManager::allowedRunners() const
487 {
488  KConfigGroup config = d->configGroup();
489  return config.readEntry("pluginWhiteList", QStringList());
490 }
491 
492 void RunnerManager::loadRunner(const KService::Ptr service)
493 {
494  KPluginInfo description(service);
495  const QString runnerName = description.pluginName();
496  if (!runnerName.isEmpty() && !d->runners.contains(runnerName)) {
497  AbstractRunner *runner = d->loadInstalledRunner(service);
498  if (runner) {
499  d->runners.insert(runnerName, runner);
500  }
501  }
502 }
503 
504 void RunnerManager::loadRunner(const QString &path)
505 {
506  if (!d->runners.contains(path)) {
507  AbstractRunner *runner = new AbstractRunner(this, path);
508  connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool)));
509  d->runners.insert(path, runner);
510  }
511 }
512 
513 AbstractRunner* RunnerManager::runner(const QString &name) const
514 {
515  if (d->runners.isEmpty()) {
516  d->loadRunners();
517  }
518 
519  return d->runners.value(name, 0);
520 }
521 
522 AbstractRunner *RunnerManager::singleModeRunner() const
523 {
524  return d->currentSingleRunner;
525 }
526 
527 void RunnerManager::setSingleModeRunnerId(const QString &id)
528 {
529  d->singleModeRunnerId = id;
530  d->loadSingleRunner();
531 }
532 
533 QString RunnerManager::singleModeRunnerId() const
534 {
535  return d->singleModeRunnerId;
536 }
537 
538 bool RunnerManager::singleMode() const
539 {
540  return d->singleMode;
541 }
542 
543 void RunnerManager::setSingleMode(bool singleMode)
544 {
545  if (d->singleMode == singleMode) {
546  return;
547  }
548 
549 
550  Plasma::AbstractRunner *prevSingleRunner = d->currentSingleRunner;
551  d->singleMode = singleMode;
552  d->loadSingleRunner();
553  d->singleMode = d->currentSingleRunner;
554 
555  if (prevSingleRunner != d->currentSingleRunner) {
556  if (d->prepped) {
557  matchSessionComplete();
558 
559  if (d->singleMode) {
560  setupMatchSession();
561  }
562  }
563  }
564 }
565 
566 QList<AbstractRunner *> RunnerManager::runners() const
567 {
568  return d->runners.values();
569 }
570 
571 QStringList RunnerManager::singleModeAdvertisedRunnerIds() const
572 {
573  return d->advertiseSingleRunnerIds.keys();
574 }
575 
576 QString RunnerManager::runnerName(const QString &id) const
577 {
578  if (runner(id)) {
579  return runner(id)->name();
580  } else {
581  return d->advertiseSingleRunnerIds.value(id, QString());
582  }
583 }
584 
585 RunnerContext* RunnerManager::searchContext() const
586 {
587  return &d->context;
588 }
589 
590 //Reordering is here so data is not reordered till strictly needed
591 QList<QueryMatch> RunnerManager::matches() const
592 {
593  return d->context.matches();
594 }
595 
596 void RunnerManager::run(const QString &id)
597 {
598  run(d->context.match(id));
599 }
600 
601 void RunnerManager::run(const QueryMatch &match)
602 {
603  if (!match.isEnabled()) {
604  return;
605  }
606 
607  //TODO: this function is not const as it may be used for learning
608  AbstractRunner *runner = match.runner();
609 
610  foreach (FindMatchesJob *job, d->searchJobs) {
611  if (job->runner() == runner && !job->isFinished()) {
612  kDebug() << "deferred run";
613  d->deferredRun = match;
614  return;
615  }
616  }
617 
618  if (d->deferredRun.isValid()) {
619  d->deferredRun = QueryMatch(0);
620  }
621 
622  d->context.run(match);
623 }
624 
625 QList<QAction*> RunnerManager::actionsForMatch(const QueryMatch &match)
626 {
627  AbstractRunner *runner = match.runner();
628  if (runner) {
629  return runner->actionsForMatch(match);
630  }
631 
632  return QList<QAction*>();
633 }
634 
635 QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const
636 {
637  return mimeDataForMatch(d->context.match(id));
638 }
639 
640 
641 QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const
642 {
643  AbstractRunner *runner = match.runner();
644  QMimeData *mimeData;
645  if (runner && QMetaObject::invokeMethod(
646  runner,
647  "mimeDataForMatch", Qt::DirectConnection,
648  Q_RETURN_ARG(QMimeData*, mimeData),
649  Q_ARG(const Plasma::QueryMatch *, &match)
650  )) {
651  return mimeData;
652  }
653 
654  return 0;
655 }
656 
657 KPluginInfo::List RunnerManager::listRunnerInfo(const QString &parentApp)
658 {
659  return PluginLoader::pluginLoader()->listRunnerInfo(parentApp);
660 }
661 
662 void RunnerManager::setupMatchSession()
663 {
664  d->teardownRequested = false;
665 
666  if (d->prepped) {
667  return;
668  }
669 
670  d->prepped = true;
671  if (d->singleMode) {
672  if (d->currentSingleRunner) {
673  emit d->currentSingleRunner->prepare();
674  d->singleRunnerPrepped = true;
675  }
676  } else {
677  foreach (AbstractRunner *runner, d->runners) {
678 #ifdef MEASURE_PREPTIME
679  QTime t;
680  t.start();
681 #endif
682  emit runner->prepare();
683 #ifdef MEASURE_PREPTIME
684  kDebug() << t.elapsed() << runner->name();
685 #endif
686  }
687 
688  d->allRunnersPrepped = true;
689  }
690 }
691 
692 void RunnerManager::matchSessionComplete()
693 {
694  if (!d->prepped) {
695  return;
696  }
697 
698  d->teardownRequested = true;
699  d->checkTearDown();
700 }
701 
702 void RunnerManager::launchQuery(const QString &term)
703 {
704  launchQuery(term, QString());
705 }
706 
707 void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &runnerName)
708 {
709  setupMatchSession();
710  QString term = untrimmedTerm.trimmed();
711 
712  setSingleModeRunnerId(runnerName);
713  setSingleMode(!runnerName.isEmpty());
714 
715  if (term.isEmpty()) {
716  if (d->singleMode && d->currentSingleRunner && d->currentSingleRunner->defaultSyntax()) {
717  term = d->currentSingleRunner->defaultSyntax()->exampleQueries().first().remove(QRegExp(":q:"));
718  } else {
719  reset();
720  return;
721  }
722  }
723 
724  if (d->context.query() == term) {
725  // we already are searching for this!
726  return;
727  }
728 
729  if (d->singleMode && !d->currentSingleRunner) {
730  reset();
731  return;
732  }
733 
734  if (d->runners.isEmpty()) {
735  d->loadRunners();
736  }
737 
738  reset();
739 // kDebug() << "runners searching for" << term << "on" << runnerName;
740  d->context.setQuery(term);
741 
742  QHash<QString, AbstractRunner*> runable;
743 
744  //if the name is not empty we will launch only the specified runner
745  if (d->singleMode && d->currentSingleRunner) {
746  runable.insert(QString(), d->currentSingleRunner);
747  d->context.setSingleRunnerQueryMode(true);
748  } else {
749  runable = d->runners;
750  }
751 
752  foreach (Plasma::AbstractRunner *r, runable) {
753  if (r->isMatchingSuspended()) {
754  continue;
755  }
756 
757  d->startJob(r);
758  }
759 
760  // Start timer to unblock slow runners
761  d->delayTimer.start(RunnerManagerPrivate::slowRunDelay);
762 }
763 
764 bool RunnerManager::execQuery(const QString &term)
765 {
766  return execQuery(term, QString());
767 }
768 
769 bool RunnerManager::execQuery(const QString &untrimmedTerm, const QString &runnerName)
770 {
771  QString term = untrimmedTerm.trimmed();
772 
773  if (term.isEmpty()) {
774  reset();
775  return false;
776  }
777 
778  if (d->runners.isEmpty()) {
779  d->loadRunners();
780  }
781 
782  if (d->context.query() == term) {
783  // we already are searching for this!
784  emit matchesChanged(d->context.matches());
785  return false;
786  }
787 
788  reset();
789  //kDebug() << "executing query about " << term << "on" << runnerName;
790  d->context.setQuery(term);
791  AbstractRunner *r = runner(runnerName);
792 
793  if (!r) {
794  //kDebug() << "failed to find the runner";
795  return false;
796  }
797 
798  if ((r->ignoredTypes() & d->context.type()) != 0) {
799  //kDebug() << "ignored!";
800  return false;
801  }
802 
803  r->performMatch(d->context);
804  //kDebug() << "succeeded with" << d->context.matches().count() << "results";
805  emit matchesChanged(d->context.matches());
806  return true;
807 }
808 
809 QString RunnerManager::query() const
810 {
811  return d->context.query();
812 }
813 
814 void RunnerManager::reset()
815 {
816  // If ThreadWeaver is idle, it is safe to clear previous jobs
817  if (Weaver::instance()->isIdle()) {
818  qDeleteAll(d->searchJobs);
819  qDeleteAll(d->oldSearchJobs);
820  d->oldSearchJobs.clear();
821  } else {
822  Q_FOREACH(FindMatchesJob *job, d->searchJobs) {
823  Weaver::instance()->dequeue(job);
824  }
825  d->oldSearchJobs += d->searchJobs;
826  }
827 
828  d->searchJobs.clear();
829 
830  if (d->deferredRun.isEnabled()) {
831  //kDebug() << "job actually done, running now **************";
832  QueryMatch tmpRun = d->deferredRun;
833  d->deferredRun = QueryMatch(0);
834  tmpRun.run(d->context);
835  }
836 
837  d->context.reset();
838 }
839 
840 } // Plasma namespace
841 
842 #include "runnermanager.moc"
Plasma::PluginLoader::pluginLoader
static PluginLoader * pluginLoader()
Return the active plugin loader.
Definition: pluginloader.cpp:67
runnermanager.h
Plasma::AbstractRunner::name
QString name
Definition: abstractrunner.h:69
pluginloader.h
Plasma::RunnerManager::allowedRunners
QStringList allowedRunners() const
Definition: runnermanager.cpp:486
Plasma::RunnerManager::singleModeRunner
AbstractRunner * singleModeRunner() const
Definition: runnermanager.cpp:522
Plasma::RunnerManager::singleModeAdvertisedRunnerIds
QStringList singleModeAdvertisedRunnerIds() const
Definition: runnermanager.cpp:571
Plasma::AbstractRunner
An abstract base class for Plasma Runner plugins.
Definition: abstractrunner.h:63
Plasma::RunnerManager::setSingleMode
void setSingleMode(bool singleMode)
Sets whether or not the manager is in single mode.
Definition: runnermanager.cpp:543
Plasma::RunnerManager::setupMatchSession
void setupMatchSession()
Call this method when the runners should be prepared for a query session.
Definition: runnermanager.cpp:662
Plasma::PluginLoader::loadRunner
AbstractRunner * loadRunner(const QString &name)
Load a Runner plugin.
Definition: pluginloader.cpp:199
Plasma::RunnerManager::RunnerManager
RunnerManager(QObject *parent=0)
Definition: runnermanager.cpp:441
QObject
Plasma::RunnerManager::query
QString query() const
Definition: runnermanager.cpp:809
Plasma::QueryMatch::run
void run(const RunnerContext &context) const
Requests this match to activae using the given context.
Definition: querymatch.cpp:273
Plasma::RunnerManager::setAllowedRunners
void setAllowedRunners(const QStringList &runners)
Sets a whitelist for the plugins that can be loaded.
Definition: runnermanager.cpp:475
Plasma::RunnerManager::reloadConfiguration
void reloadConfiguration()
Causes a reload of the current configuration.
Definition: runnermanager.cpp:469
Plasma::QueryMatch::isEnabled
bool isEnabled() const
Definition: querymatch.cpp:218
Plasma::RunnerManager::setSingleModeRunnerId
void setSingleModeRunnerId(const QString &id)
Puts the manager into "single runner" mode using the given runner; if the runner does not exist or ca...
Definition: runnermanager.cpp:527
Plasma::AbstractRunner::actionsForMatch
virtual QList< QAction * > actionsForMatch(const Plasma::QueryMatch &match)
A given match can have more than action that can be performed on it.
Definition: abstractrunner.cpp:162
Plasma::RunnerManager::loadRunner
void loadRunner(const KService::Ptr service)
Attempts to add the AbstractRunner plugin represented by the KService passed in.
Definition: runnermanager.cpp:492
Plasma::RunnerManager::runners
QList< AbstractRunner * > runners() const
Definition: runnermanager.cpp:566
Plasma::isPluginVersionCompatible
bool isPluginVersionCompatible(unsigned int version)
Verifies that a plugin is compatible with plasma.
Definition: version.cpp:51
Plasma::RunnerManager::matchesChanged
void matchesChanged(const QList< Plasma::QueryMatch > &matches)
Emitted each time a new match is added to the list.
Plasma::RunnerManager::mimeDataForMatch
QMimeData * mimeDataForMatch(const QueryMatch &match) const
Definition: runnermanager.cpp:641
Plasma::RunnerManager::matches
QList< QueryMatch > matches() const
Retrieves all available matches found so far for the previously launched query.
Definition: runnermanager.cpp:591
Plasma::AbstractRunner::prepare
void prepare()
This signal is emitted when matching is about to commence, giving runners an opportunity to prepare t...
Plasma::RunnerManager::searchContext
RunnerContext * searchContext() const
Retrieves the current context.
Definition: runnermanager.cpp:585
Plasma::AbstractRunner::isMatchingSuspended
bool isMatchingSuspended() const
Definition: abstractrunner.cpp:367
Plasma::RunnerContext
The RunnerContext class provides information related to a search, including the search term...
Definition: runnercontext.h:46
Plasma::AbstractRunner::SlowSpeed
Definition: abstractrunner.h:74
Plasma::RunnerManager::run
void run(const QueryMatch &match)
Runs a given match.
Definition: runnermanager.cpp:601
Plasma::QueryMatch
A match returned by an AbstractRunner in response to a given RunnerContext.
Definition: querymatch.h:47
Plasma::RunnerManager::singleModeRunnerId
QString singleModeRunnerId() const
Definition: runnermanager.cpp:533
Plasma::PluginLoader::listRunnerInfo
KPluginInfo::List listRunnerInfo(const QString &parentApp=QString())
Returns a list of all known Runner implementations.
Definition: pluginloader.cpp:300
Plasma::RunnerManager::launchQuery
void launchQuery(const QString &term, const QString &runnerId)
Launch a query, this will create threads and return inmediately.
Definition: runnermanager.cpp:707
Plasma::AbstractRunner::ignoredTypes
RunnerContext::Types ignoredTypes() const
Returns the OR'ed value of all the Information types (as defined in RunnerContext::Type) this runner ...
Definition: abstractrunner.cpp:260
Plasma::QueryMatch::runner
AbstractRunner * runner() const
Definition: querymatch.cpp:138
querymatch.h
Plasma::RunnerManager::singleMode
bool singleMode() const
Definition: runnermanager.cpp:538
Plasma::AbstractRunner::performMatch
void performMatch(Plasma::RunnerContext &context)
Triggers a call to match.
Definition: abstractrunner.cpp:123
Plasma::RunnerManager::runner
AbstractRunner * runner(const QString &name) const
Finds and returns a loaded runner or NULL.
Definition: runnermanager.cpp:513
Plasma::RunnerManager::runnerName
QString runnerName(const QString &id) const
Returns the translated name of a runner.
Definition: runnermanager.cpp:576
Plasma::RunnerManager::~RunnerManager
~RunnerManager()
Definition: runnermanager.cpp:460
Plasma::RunnerManager::actionsForMatch
QList< QAction * > actionsForMatch(const QueryMatch &match)
Retrieves the list of actions, if any, for a match.
Definition: runnermanager.cpp:625
Plasma::RunnerManager::reset
void reset()
Reset the current data and stops the query.
Definition: runnermanager.cpp:814
Plasma::RunnerManager::matchSessionComplete
void matchSessionComplete()
Call this method when the query session is finished for the time being.
Definition: runnermanager.cpp:692
Plasma::RunnerManager::listRunnerInfo
static KPluginInfo::List listRunnerInfo(const QString &parentApp=QString())
Returns a list of all known Runner implementations.
Definition: runnermanager.cpp:657
Plasma::RunnerManager::execQuery
bool execQuery(const QString &term, const QString &runnerName)
Execute a query, this method will only return when the query is executed This means that the method m...
Definition: runnermanager.cpp:769
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:34 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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