Akonadi

itemsearchjob.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Tobias Koenig <[email protected]>
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 
20 using namespace Akonadi;
21 
22 class Akonadi::ItemSearchJobPrivate : public JobPrivate
23 {
24 public:
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 
92 static void cleanupDefaultSearchSession()
93 {
94  instances.setLocalData(nullptr);
95 }
96 
97 static 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 
107 static 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 
190 void 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  QVector<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 
237 bool ItemSearchJob::doHandleResponse(qint64 tag, const Protocol::CommandPtr &response)
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"
bool isValid() const
Returns whether the item is valid.
Definition: item.cpp:88
void append(const T &value)
void setRecursive(bool recursive)
Sets whether the search should recurse into collections.
Job that searches for items in the Akonadi storage.
Definition: itemsearchjob.h:53
Specifies which parts of a tag should be fetched from the Akonadi storage.
Definition: tagfetchscope.h:22
Item::List items() const
Returns the items that matched the search query.
QString fromUtf8(const char *str, int size)
ItemSearchJob(QObject *parent=nullptr)
Creates an invalid search job.
void setSearchCollections(const Collection::List &collections)
Search only in given collections.
QCA_EXPORT void init()
Represents a collection of PIM items.
Definition: collection.h:61
void setFetchScope(const ItemFetchScope &fetchScope)
Sets the item fetch scope.
A query that can be passed to ItemSearchJob or others.
Definition: searchquery.h:116
void setTagFetchScope(const TagFetchScope &fetchScope)
Sets the tag fetch scope.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QVector< Item > List
Describes a list of items.
Definition: item.h:115
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
QStringList mimeTypes() const
Returns list of mime types to search in.
Collection::List searchCollections() const
Returns list of collections to search.
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.
bool isRecursive() const
Returns whether the search is recursive.
static Session * defaultSession()
Returns the default session for this thread.
QByteArray sessionId() const
Returns the session identifier.
A communication session with the Akonadi storage.
Definition: core/session.h:55
void timeout()
~ItemSearchJob() override
Destroys the item search job.
void setQuery(const SearchQuery &query)
Sets the search query.
QString join(const QString &separator) const const
Base class for all actions in the Akonadi storage.
Definition: job.h:80
void reserve(int size)
TagFetchScope & tagFetchScope()
Returns the tag fetch scope.
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
void doStart() override
This method must be reimplemented in the concrete jobs.
ItemFetchScope & fetchScope()
Returns the item fetch scope.
bool isRemoteSearchEnabled() const
Returns whether remote search is enabled.
void setRemoteSearchEnabled(bool enabled)
Sets whether resources should be queried too.
void setMimeTypes(const QStringList &mimeTypes)
Search only for items of given mime types.
Represents a PIM item stored in Akonadi storage.
Definition: item.h:104
Q_D(Todo)
Specifies which parts of an item should be fetched from the Akonadi storage.
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jul 2 2022 06:41:48 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.