1/*
2 Copyright (c) 2009 Volker Krause <vkrause@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
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 the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "agentsearchinterface.h"
21#include "agentsearchinterface_p.h"
22#include "collection.h"
23#include "dbusconnectionpool.h"
24#include "searchresultjob_p.h"
25#include "searchadaptor.h"
26#include "collectionfetchjob.h"
27#include "collectionfetchscope.h"
28#include "servermanager.h"
29#include "agentbase.h"
30
31using namespace Akonadi;
32
33AgentSearchInterfacePrivate::AgentSearchInterfacePrivate(AgentSearchInterface *qq)
34 : q(qq)
35{
36 new Akonadi__SearchAdaptor(this);
37 DBusConnectionPool::threadConnection().registerObject(QLatin1String("/Search"),
38 this, QDBusConnection::ExportAdaptors);
39
40 QTimer::singleShot(0, this, SLOT(delayedInit()));
41}
42
43void AgentSearchInterfacePrivate::delayedInit()
44{
45 QDBusInterface iface(ServerManager::serviceName(ServerManager::Server),
46 QLatin1String("/SearchManager"),
47 QLatin1String("org.freedesktop.Akonadi.SearchManager"),
48 QDBusConnection::sessionBus(), this);
49 QDBusMessage msg = iface.call(QLatin1String("registerInstance"), dynamic_cast<AgentBase *>(q)->identifier());
50}
51
52void AgentSearchInterfacePrivate::addSearch(const QString &query, const QString &queryLanguage, quint64 resultCollectionId)
53{
54 q->addSearch(query, queryLanguage, Collection(resultCollectionId));
55}
56
57void AgentSearchInterfacePrivate::removeSearch(quint64 resultCollectionId)
58{
59 q->removeSearch(Collection(resultCollectionId));
60}
61
62void AgentSearchInterfacePrivate::search(const QByteArray &searchId,
63 const QString &query,
64 quint64 collectionId)
65{
66 mSearchId = searchId;
67 mCollectionId = collectionId;
68
69 CollectionFetchJob *fetchJob = new CollectionFetchJob(Collection(mCollectionId), CollectionFetchJob::Base, this);
70 fetchJob->fetchScope().setAncestorRetrieval(CollectionFetchScope::All);
71 fetchJob->setProperty("query", query);
72 connect(fetchJob, SIGNAL(finished(KJob*)), this, SLOT(collectionReceived(KJob*)));
73}
74
75void AgentSearchInterfacePrivate::collectionReceived(KJob *job)
76{
77 CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob *>(job);
78 if (fetchJob->error()) {
79 kError() << fetchJob->errorString();
80 new SearchResultJob(fetchJob->property("searchId").toByteArray(), Collection(mCollectionId), this);
81 return;
82 }
83
84 if (fetchJob->collections().count() != 1) {
85 kDebug() << "Server requested search in invalid collection, or collection was removed in the meanwhile";
86 // Tell server we are done
87 new SearchResultJob(fetchJob->property("searchId").toByteArray(), Collection(mCollectionId), this);
88 return;
89 }
90
91 const Collection collection = fetchJob->collections().first();
92 q->search(fetchJob->property("query").toString(),
93 collection);
94}
95
96AgentSearchInterface::AgentSearchInterface()
97 : d(new AgentSearchInterfacePrivate(this))
98{
99}
100
101AgentSearchInterface::~AgentSearchInterface()
102{
103 delete d;
104}
105
106void AgentSearchInterface::searchFinished(const QVector<qint64> result, ResultScope scope)
107{
108 if (scope == Akonadi::AgentSearchInterface::Rid) {
109 QVector<QByteArray> rids;
110 rids.reserve(result.size());
111 Q_FOREACH (qint64 rid, result) {
112 rids << QByteArray::number(rid);
113 }
114
115 searchFinished(rids);
116 return;
117 }
118
119 SearchResultJob *resultJob = new SearchResultJob(d->mSearchId, Collection(d->mCollectionId), d);
120 resultJob->setResult(result);
121}
122
123void AgentSearchInterface::searchFinished(const ImapSet &result, ResultScope scope)
124{
125 if (scope == Akonadi::AgentSearchInterface::Rid) {
126 QVector<QByteArray> rids;
127 Q_FOREACH (const ImapInterval &interval, result.intervals()) {
128 for (int i = interval.begin(); i <= interval.end(); ++i) {
129 rids << QByteArray::number(i);
130 }
131 }
132
133 searchFinished(rids);
134 return;
135 }
136
137 SearchResultJob *resultJob = new SearchResultJob(d->mSearchId, Collection(d->mCollectionId), d);
138 resultJob->setResult(result);
139}
140
141void AgentSearchInterface::searchFinished(const QVector<QByteArray> &result)
142{
143 SearchResultJob *resultJob = new SearchResultJob(d->mSearchId, Collection(d->mCollectionId), d);
144 resultJob->setResult(result);
145}
146
147#include "moc_agentsearchinterface_p.cpp"
148