2 * Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "abstractrunner.h"
23 #include <QMutexLocker>
26 #include <KPluginInfo>
27 #include <KServiceTypeTrader>
30 #include "scripting/runnerscript.h"
31 #include "searchcontext.h"
36 class AbstractRunner::Private
44 KPluginInfo runnerDescription
;
45 AbstractRunner
* runner
;
49 Private(AbstractRunner
* r
, KService::Ptr service
)
50 : priority(NormalPriority
),
53 runnerDescription(service
),
57 if (runnerDescription
.isValid()) {
58 QString language
= runnerDescription
.property("X-Plasma-Language").toString();
60 if (!language
.isEmpty()) {
61 script
= Plasma::loadScriptEngine(language
, runner
);
63 kDebug() << "Could not create a" << language
<< "ScriptEngine for the"
64 << runnerDescription
.name() << "Runner.";
66 QTimer::singleShot(0, runner
, SLOT(init()));
72 static QMutex bigLock
;
75 QMutex
AbstractRunner::Private::bigLock
;
77 AbstractRunner::AbstractRunner(QObject
* parent
, const QString
& serviceId
)
79 d(new Private(this, KService::serviceByStorageId(serviceId
)))
83 AbstractRunner::AbstractRunner(QObject
* parent
, const QVariantList
& args
)
85 d(new Private(this, KService::serviceByStorageId(args
.count() > 0 ? args
[0].toString() : QString())))
89 AbstractRunner::~AbstractRunner()
94 KConfigGroup
AbstractRunner::config() const
96 QString group
= objectName();
97 if (group
.isEmpty()) {
98 group
= "UnnamedRunner";
101 KConfigGroup
runners(KGlobal::config(), "Runners");
102 return KConfigGroup(&runners
, group
);
105 void AbstractRunner::performMatch( Plasma::SearchContext
&globalContext
)
107 static const int reasonableRunTime
= 1500;
108 static const int fastEnoughTime
= 250;
110 d
->runtime
.restart();
111 SearchContext
localContext(0, globalContext
);
113 match(&localContext
);
115 // automatically rate limit runners that become slooow
116 const int runtime
= d
->runtime
.elapsed();
117 bool slowed
= speed() == SlowSpeed
;
119 if (!slowed
&& runtime
> reasonableRunTime
) {
120 // we punish runners that return too slowly, even if they don't bring
122 kDebug() << runnerName() << "runner is too slow, putting it on the back burner.";
127 //If matches were not added, delete items on the heap
128 if (localContext
.addMatchesTo(globalContext
) &&
129 slowed
&& runtime
< fastEnoughTime
) {
132 if (d
->fastRuns
> 2) {
133 // we reward slowed runners who bring back matches fast enough
135 kDebug() << runnerName() << "runner is faster than we thought, kicking it up a notch";
136 setSpeed(NormalSpeed
);
141 bool AbstractRunner::hasMatchOptions()
143 return d
->hasMatchOptions
;
146 void AbstractRunner::setHasMatchOptions(bool hasMatchOptions
)
148 d
->hasMatchOptions
= hasMatchOptions
;
151 void AbstractRunner::createMatchOptions(QWidget
*parent
)
156 bool AbstractRunner::isConfigurable()
161 void AbstractRunner::setIsConfigurable(bool hasConfig
)
163 d
->hasConfig
= hasConfig
;
166 void AbstractRunner::createConfigurationInterface(QWidget
*widget
)
171 AbstractRunner::Speed
AbstractRunner::speed() const
176 void AbstractRunner::setSpeed(Speed speed
)
181 AbstractRunner::Priority
AbstractRunner::priority() const
186 void AbstractRunner::setPriority(Priority priority
)
188 d
->priority
= priority
;
191 KService::List
AbstractRunner::serviceQuery(const QString
&serviceType
, const QString
&constraint
) const
193 QMutexLocker
lock(&Private::bigLock
);
194 return KServiceTypeTrader::self()->query(serviceType
, constraint
);
197 QMutex
* AbstractRunner::bigLock() const
199 return &Private::bigLock
;
202 void AbstractRunner::exec(const Plasma::SearchContext
*search
, const Plasma::SearchMatch
*action
)
205 return d
->script
->exec(search
, action
);
209 void AbstractRunner::match(Plasma::SearchContext
*search
)
212 return d
->script
->match(search
);
216 QString
AbstractRunner::runnerName() const
218 if (!d
->runnerDescription
.isValid()) {
221 return d
->runnerDescription
.property("X-Plasma-RunnerName").toString();
224 void AbstractRunner::init()
231 AbstractRunner::List
AbstractRunner::load(QObject
* parent
, const QStringList
& whitelist
)
237 KService::List offers
= KServiceTypeTrader::self()->query("Plasma/Runner");
239 foreach (KService::Ptr service
, offers
) {
240 if (whitelist
.empty() || whitelist
.contains(service
->name())) {
241 QString language
= service
->property("X-Plasma-Language").toString();
242 AbstractRunner
* runner
= 0;
244 if (language
.isEmpty()) {
246 args
<< service
->storageId();
247 runner
= service
->createInstance
<AbstractRunner
>(parent
, args
, &error
);
249 runner
= new AbstractRunner(parent
, service
->storageId());
253 //kDebug() << "loaded runner : " << service->name();
254 QString phase
= service
->property("X-Plasma-RunnerPhase").toString();
255 if (phase
== "last") {
256 lastRunners
.append(runner
);
257 } else if (phase
== "first") {
258 firstRunners
.append(runner
);
260 runners
.append(runner
);
263 kDebug() << "failed to load runner : " << service
->name() << ". error reported: " << error
;
268 firstRunners
<< runners
<< lastRunners
;
272 } // Plasma namespace
274 #include "abstractrunner.moc"