Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / plasma / applets / kickoff / core / searchmodel.cpp
blobb54c97562a053e493877f1d3485ef0431b8e6622
1 /*
2 Copyright 2007 Robert Knight <robertknight@gmail.com>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library 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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 // Own
21 #include "core/searchmodel.h"
23 #include "config-kickoff-applets.h"
24 // Qt
26 // KDE
27 #include <KDebug>
28 #include <KMimeType>
29 #include <KServiceTypeTrader>
30 #ifdef HAVE_STRIGIDBUS
31 #include <strigi/qtdbus/strigiclient.h>
32 #endif
33 #include <solid/networking.h>
35 // Local
36 #include "core/models.h"
38 using namespace Kickoff;
40 class SearchModel::Private
42 public:
43 Private(SearchModel *parent) : q(parent) {}
45 void addItemForIface(SearchInterface *iface,QStandardItem *item)
47 int index = searchIfaces.indexOf(iface);
48 Q_ASSERT(index >= 0);
49 q->item(index)->appendRow(item);
51 void clear()
53 for (int i=0;i<q->rowCount();i++) {
54 q->item(i)->removeRows(0,q->item(i)->rowCount());
58 SearchModel * const q;
59 QList<SearchInterface*> searchIfaces;
62 SearchModel::SearchModel(QObject *parent)
63 : KickoffModel(parent)
64 , d(new Private(this))
66 d->searchIfaces << new ApplicationSearch(this);
67 //d->searchIfaces << new IndexerSearch(this);
68 d->searchIfaces << new WebSearch(this);
70 foreach(SearchInterface *iface,d->searchIfaces) {
71 QStandardItem *ifaceItem = new QStandardItem(iface->name());
72 appendRow(ifaceItem);
73 connect(iface,SIGNAL(resultsAvailable(QStringList)),
74 this,SLOT(resultsAvailable(QStringList)));
75 connect(iface,SIGNAL(resultsAvailable(ResultList)),
76 this,SLOT(resultsAvailable(ResultList)));
79 SearchModel::~SearchModel()
81 delete d;
83 void SearchModel::resultsAvailable(const QStringList& results)
85 SearchInterface *iface = qobject_cast<SearchInterface*>(sender());
87 Q_ASSERT(iface);
89 foreach(const QString& result,results) {
90 //kDebug() << "Search hit from" << iface->name() << result;
91 QStandardItem *resultItem = StandardItemFactory::createItemForUrl(result);
92 d->addItemForIface(iface,resultItem);
95 void SearchModel::resultsAvailable(const ResultList& results)
97 SearchInterface *iface = qobject_cast<SearchInterface*>(sender());
99 Q_ASSERT(iface);
101 foreach(const SearchResult& result,results) {
102 QStandardItem *item = StandardItemFactory::createItemForUrl(result.url);
103 item->setData(result.title,Qt::DisplayRole);
104 item->setData(result.subTitle,SubTitleRole);
105 d->addItemForIface(iface,item);
108 void SearchModel::setQuery(const QString& query)
110 d->clear();
112 if (query.isEmpty()) {
113 return;
116 foreach(SearchInterface *iface, d->searchIfaces) {
117 iface->setQuery(query);
121 SearchInterface::SearchInterface(QObject *parent)
122 : QObject(parent)
126 ApplicationSearch::ApplicationSearch(QObject *parent)
127 : SearchInterface(parent)
131 QString ApplicationSearch::name() const
133 return i18n("Applications");
136 void ApplicationSearch::setQuery(const QString& query)
138 //QString mimeName = mimeNameForQuery(query);
139 QString traderQuery = QString("((exist GenericName) and ('%1' ~~ GenericName)) or ('%1' ~~ Name) or ((exist Keywords) and ('%1' ~in Keywords))"
140 //" or ('%2' in MimeType)"
142 .arg(query); //.arg(mimeName);
143 KServiceTypeTrader *trader = KServiceTypeTrader::self();
144 KService::List results = trader->query("Application",traderQuery);
146 // If we have KDE 3 and KDE 4 versions of a service, return only the
147 // KDE 4 version
148 QHash<QString,int> desktopNames;
149 QSet<QString> execFields;
150 for (int i=0;i<results.count();i++) {
151 KService::Ptr service = results[i];
153 int existingPos = desktopNames.value(service->name(),-1);
154 KService::Ptr existing = existingPos < 0 ? KService::Ptr(0) : results[existingPos];
156 if (!existing.isNull()) {
157 if (isLaterVersion(existing,service)) {
158 results[i] = 0;
159 } else if (isLaterVersion(service,existing)) {
160 results[existingPos] = 0;
161 } else {
162 // do not show more than one entry which does the same thing when run
163 // (ie. ignore entries that have an identical 'Exec' field to an existing
164 // entry)
165 if (execFields.contains(service->exec())) {
166 results[i] = 0;
169 } else {
170 desktopNames.insert(service->name(),i);
171 execFields.insert(service->exec());
175 QStringList pathResults;
176 foreach(KService::Ptr service,results) {
177 if (!service.isNull() && !service->noDisplay()) {
178 pathResults << service->entryPath();
181 emit resultsAvailable(pathResults);
184 QString ApplicationSearch::mimeNameForQuery(const QString& query) const
186 KMimeType::Ptr type = KMimeType::findByPath('.'+query,0,true);
187 if (type) {
188 kDebug() << "Mime type name" << type->name();
189 return type->name();
191 return QString();
193 WebSearch::WebSearch(QObject *parent)
194 : SearchInterface(parent)
197 QString WebSearch::name() const
199 return i18n("Web Searches");
201 void WebSearch::setQuery(const QString& query)
203 ResultList results;
204 SearchResult googleResult;
205 googleResult.url = QString("http://www.google.com/search?q=%1").arg(query);
206 googleResult.title = i18n("Search web for '%1'",query);
207 results << googleResult;
208 emit resultsAvailable(results);
210 IndexerSearch::IndexerSearch(QObject *parent)
211 : SearchInterface(parent)
214 QString IndexerSearch::name() const
216 return i18n("Documents");
218 void IndexerSearch::setQuery(const QString& query)
220 #ifdef HAVE_STRIGIDBUS
221 static const StrigiClient searchClient;
223 QList<QString> urls;
224 QList<StrigiHit> hits = searchClient.getHits(query,10,0);
225 foreach(const StrigiHit& hit,hits) {
226 if (!hit.uri.isEmpty()) {
227 urls << hit.uri;
230 emit resultsAvailable(urls);
231 #endif
234 #include "searchmodel.moc"