Akonadi

itemsearchjob.cpp
1/*
2 SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "itemsearchjob.h"
8
9#include "itemfetchscope.h"
10#include "job_p.h"
11#include "private/protocol_p.h"
12#include "protocolhelper_p.h"
13#include "searchquery.h"
14#include "tagfetchscope.h"
15
16#include <QCoreApplication>
17#include <QThreadStorage>
18#include <QTimer>
19
20using namespace Akonadi;
21
22class Akonadi::ItemSearchJobPrivate : public JobPrivate
23{
24public:
25 ItemSearchJobPrivate(ItemSearchJob *parent, const SearchQuery &query)
26 : JobPrivate(parent)
27 , mQuery(query)
28 {
29 mEmitTimer.setSingleShot(true);
30 mEmitTimer.setInterval(std::chrono::milliseconds{100});
31 }
32
33 void init()
34 {
35 QObject::connect(&mEmitTimer, &QTimer::timeout, q_ptr, [this]() {
36 timeout();
37 });
38 }
39
40 void aboutToFinish() override
41 {
42 timeout();
43 }
44
45 void timeout()
46 {
48
49 mEmitTimer.stop(); // in case we are called by result()
50 if (!mPendingItems.isEmpty()) {
51 if (!q->error()) {
52 Q_EMIT q->itemsReceived(mPendingItems);
53 }
54 mPendingItems.clear();
55 }
56 }
57 QString jobDebuggingString() const override
58 {
59 QStringList flags;
60 if (mRecursive) {
61 flags.append(QStringLiteral("recursive"));
62 }
63 if (mRemote) {
64 flags.append(QStringLiteral("remote"));
65 }
66 if (mCollections.isEmpty()) {
67 flags.append(QStringLiteral("all collections"));
68 } else {
69 flags.append(QStringLiteral("%1 collections").arg(mCollections.count()));
70 }
71 return QStringLiteral("%1,json=%2").arg(flags.join(QLatin1Char(',')), QString::fromUtf8(mQuery.toJSON()));
72 }
73
74 Q_DECLARE_PUBLIC(ItemSearchJob)
75
76 SearchQuery mQuery;
77 Collection::List mCollections;
78 QStringList mMimeTypes;
79 bool mRecursive = false;
80 bool mRemote = false;
81 ItemFetchScope mItemFetchScope;
82 TagFetchScope mTagFetchScope;
83
84 Item::List mItems;
85 Item::List mPendingItems; // items pending for emitting itemsReceived()
86
87 QTimer mEmitTimer;
88};
89
91
92static void cleanupDefaultSearchSession()
93{
94 instances.setLocalData(nullptr);
95}
96
97static Session *defaultSearchSession()
98{
99 if (!instances.hasLocalData()) {
100 const QByteArray sessionName = Session::defaultSession()->sessionId() + "-SearchSession";
101 instances.setLocalData(new Session(sessionName));
102 qAddPostRoutine(cleanupDefaultSearchSession);
103 }
104 return instances.localData();
105}
106
107static QObject *sessionForJob(QObject *parent)
108{
109 if (qobject_cast<Job *>(parent) || qobject_cast<Session *>(parent)) {
110 return parent;
111 }
112 return defaultSearchSession();
113}
114
116 : Job(new ItemSearchJobPrivate(this, SearchQuery()), sessionForJob(parent))
117{
119 d->init();
120}
121
123 : Job(new ItemSearchJobPrivate(this, query), sessionForJob(parent))
124{
126 d->init();
127}
128
130
132{
134
135 d->mQuery = query;
136}
137
139{
141
142 d->mItemFetchScope = fetchScope;
143}
144
146{
148
149 return d->mItemFetchScope;
150}
151
153{
155
156 d->mTagFetchScope = fetchScope;
157}
158
160{
162
163 return d->mTagFetchScope;
164}
165
167{
169
170 d->mCollections = collections;
171}
172
174{
175 return d_func()->mCollections;
176}
177
179{
181
182 d->mMimeTypes = mimeTypes;
183}
184
186{
187 return d_func()->mMimeTypes;
188}
189
190void ItemSearchJob::setRecursive(bool recursive)
191{
193
194 d->mRecursive = recursive;
195}
196
198{
199 return d_func()->mRecursive;
200}
201
203{
205
206 d->mRemote = enabled;
207}
208
210{
211 return d_func()->mRemote;
212}
213
215{
217
218 auto cmd = Protocol::SearchCommandPtr::create();
219 cmd->setMimeTypes(d->mMimeTypes);
220 if (!d->mCollections.isEmpty()) {
221 QList<qint64> ids;
222 ids.reserve(d->mCollections.size());
223 for (const Collection &col : std::as_const(d->mCollections)) {
224 ids << col.id();
225 }
226 cmd->setCollections(ids);
227 }
228 cmd->setRecursive(d->mRecursive);
229 cmd->setRemote(d->mRemote);
230 cmd->setQuery(QString::fromUtf8(d->mQuery.toJSON()));
231 cmd->setItemFetchScope(ProtocolHelper::itemFetchScopeToProtocol(d->mItemFetchScope));
232 cmd->setTagFetchScope(ProtocolHelper::tagFetchScopeToProtocol(d->mTagFetchScope));
233
234 d->sendCommand(cmd);
235}
236
238{
240
241 if (response->isResponse() && response->type() == Protocol::Command::FetchItems) {
242 const Item item = ProtocolHelper::parseItemFetchResult(Protocol::cmdCast<Protocol::FetchItemsResponse>(response));
243 if (!item.isValid()) {
244 return false;
245 }
246 d->mItems.append(item);
247 d->mPendingItems.append(item);
248 if (!d->mEmitTimer.isActive()) {
249 d->mEmitTimer.start();
250 }
251
252 return false;
253 }
254
255 if (response->isResponse() && response->type() == Protocol::Command::Search) {
256 return true;
257 }
258
259 return Job::doHandleResponse(tag, response);
260}
261
263{
264 Q_D(const ItemSearchJob);
265
266 return d->mItems;
267}
268
269#include "moc_itemsearchjob.cpp"
Represents a collection of PIM items.
Definition collection.h:62
Specifies which parts of an item should be fetched from the Akonadi storage.
Job that searches for items in the Akonadi storage.
~ItemSearchJob() override
Destroys the item search job.
bool isRemoteSearchEnabled() const
Returns whether remote search is enabled.
bool doHandleResponse(qint64 tag, const Protocol::CommandPtr &response) override
This method should be reimplemented in the concrete jobs in case you want to handle incoming data.
QStringList mimeTypes() const
Returns list of mime types to search in.
void setQuery(const SearchQuery &query)
Sets the search query.
ItemFetchScope & fetchScope()
Returns the item fetch scope.
void setMimeTypes(const QStringList &mimeTypes)
Search only for items of given mime types.
void setTagFetchScope(const TagFetchScope &fetchScope)
Sets the tag fetch scope.
void setRecursive(bool recursive)
Sets whether the search should recurse into collections.
bool isRecursive() const
Returns whether the search is recursive.
Collection::List searchCollections() const
Returns list of collections to search.
void setRemoteSearchEnabled(bool enabled)
Sets whether resources should be queried too.
ItemSearchJob(QObject *parent=nullptr)
Creates an invalid search job.
TagFetchScope & tagFetchScope()
Returns the tag fetch scope.
Item::List items() const
Returns the items that matched the search query.
void doStart() override
This method must be reimplemented in the concrete jobs.
void setSearchCollections(const Collection::List &collections)
Search only in given collections.
void setFetchScope(const ItemFetchScope &fetchScope)
Sets the item fetch scope.
Represents a PIM item stored in Akonadi storage.
Definition item.h:101
bool isValid() const
Returns whether the item is valid.
Definition item.cpp:88
Base class for all actions in the Akonadi storage.
Definition job.h:81
virtual bool doHandleResponse(qint64 tag, const Protocol::CommandPtr &response)
This method should be reimplemented in the concrete jobs in case you want to handle incoming data.
Definition job.cpp:381
A query that can be passed to ItemSearchJob or others.
Specifies which parts of a tag should be fetched from the Akonadi storage.
ASAP CLI session.
Helper integration between Akonadi and Qt.
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
void append(QList< T > &&value)
void clear()
qsizetype count() const const
bool isEmpty() const const
void reserve(qsizetype size)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
QString fromUtf8(QByteArrayView str)
QString join(QChar separator) const const
void setInterval(int msec)
void setSingleShot(bool singleShot)
void stop()
void timeout()
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:38 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.