not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / plasma / runners / services / servicerunner.cpp
blob95eb73d319a3c593d6fc2c9faef2149a1c71db0d
1 /*
2 * Copyright (C) 2006 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 version 2 as
6 * published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details
13 * You should have received a copy of the GNU Library General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "servicerunner.h"
21 #include <QWidget>
22 #include <KIcon>
24 #include <KDebug>
25 #include <KLocale>
26 #include <KRun>
27 #include <KService>
28 #include <KServiceTypeTrader>
30 ServiceRunner::ServiceRunner(QObject *parent, const QVariantList &args)
31 : Plasma::AbstractRunner( parent )
33 Q_UNUSED(args)
35 setObjectName("Application");
36 setPriority(AbstractRunner::HighestPriority);
39 ServiceRunner::~ServiceRunner()
43 void ServiceRunner::match(Plasma::RunnerContext &context)
45 const QString term = context.query();
46 if (term.length() < 3) {
47 return;
50 QMutexLocker lock(bigLock());
51 // Search for applications which are executable and case-insensitively match the search term
52 // See http://techbase.kde.org/Development/Tutorials/Services/Traders#The_KTrader_Query_Language
53 // if the following is unclear to you.
54 QString query = QString("exist Exec and ('%1' =~ Name)").arg(term);
55 KService::List services = KServiceTypeTrader::self()->query("Application", query);
57 QList<Plasma::QueryMatch> matches;
59 QHash<QString, bool> seen;
60 if (!services.isEmpty()) {
61 //kDebug() << service->name() << "is an exact match!" << service->storageId() << service->exec();
62 KService::Ptr service = services.at(0);
63 if (!service->noDisplay()) {
64 Plasma::QueryMatch match(this);
65 match.setType(Plasma::QueryMatch::ExactMatch);
66 setupAction(service, match);
67 match.setRelevance(1);
68 matches << match;
69 seen[service->storageId()] = true;
70 seen[service->exec()] = true;
74 // Search for applications which are executable and the term case-insensitive matches any of
75 // * a substring of one of the keywords
76 // * a substring of the GenericName field
77 // * a substring of the Name field
78 // Note that before asking for the content of e.g. Keywords and GenericName we need to ask if
79 // they exist to prevent a tree evaluation error if they are not defined.
80 query = QString("exist Exec and ( (exist Keywords and '%1' ~subin Keywords) or (exist GenericName and '%1' ~~ GenericName) or (exist Name and '%1' ~~ Name) )").arg(term);
81 services = KServiceTypeTrader::self()->query("Application", query);
82 services += KServiceTypeTrader::self()->query("KCModule", query);
84 //kDebug() << "got " << services.count() << " services from " << query;
85 foreach (const KService::Ptr &service, services) {
86 if (service->noDisplay()) {
87 continue;
90 QString id = service->storageId();
91 QString exec = service->exec();
92 if (seen.contains(id) || seen.contains(exec)) {
93 //kDebug() << "already seen" << id << exec;
94 continue;
97 //kDebug() << "haven't seen" << id << "so processing now";
98 seen[id] = true;
99 seen[exec] = true;
101 Plasma::QueryMatch match(this);
102 match.setType(Plasma::QueryMatch::PossibleMatch);
103 setupAction(service, match);
104 qreal relevance(0.6);
106 if (service->name().contains(term, Qt::CaseInsensitive)) {
107 relevance = 0.8;
109 if (service->name().startsWith(term, Qt::CaseInsensitive)) {
110 relevance += 0.5;
112 } else if (service->genericName().contains(term, Qt::CaseInsensitive)) {
113 relevance = 0.7;
115 if (service->genericName().startsWith(term, Qt::CaseInsensitive)) {
116 relevance += 0.5;
120 if (service->categories().contains("KDE") || service->serviceTypes().contains("KCModule")) {
121 //kDebug() << "found a kde thing" << id << match.subtext() << relevance;
122 if (id.startsWith("kde-")) {
123 // This is an older version, let's disambiguate it
124 QString subtext("KDE3");
126 //kDebug() << "old" << service->type();
127 if (service->type() == "KCModule") {
128 // avoid showing old kcms
129 continue;
132 if (!match.subtext().isEmpty()) {
133 subtext.append(", " + match.subtext());
136 match.setSubtext(subtext);
137 } else {
138 relevance += .1;
142 //kDebug() << service->name() << "is this relevant:" << relevance;
143 match.setRelevance(relevance);
144 matches << match;
147 context.addMatches(term, matches);
150 void ServiceRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
152 Q_UNUSED(context);
153 QMutexLocker lock(bigLock());
154 KService::Ptr service = KService::serviceByStorageId(match.data().toString());
155 if (service) {
156 KRun::run(*service, KUrl::List(), 0);
160 void ServiceRunner::setupAction(const KService::Ptr &service, Plasma::QueryMatch &match)
162 const QString name = service->name();
164 match.setText(name);
165 match.setData(service->storageId());
167 if (!service->genericName().isEmpty() && service->genericName() != name) {
168 match.setSubtext(service->genericName());
169 } else if (!service->comment().isEmpty()) {
170 match.setSubtext(service->comment());
173 if (!service->icon().isEmpty()) {
174 match.setIcon(KIcon(service->icon()));
178 #include "servicerunner.moc"