Akonadi

itemfetchjob.cpp
1 /*
2  Copyright (c) 2006 - 2007 Volker Krause <[email protected]>
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 "itemfetchjob.h"
21 
22 #include "attributefactory.h"
23 #include "collection.h"
24 #include "itemfetchscope.h"
25 #include "job_p.h"
26 #include "protocolhelper_p.h"
27 #include "session_p.h"
28 #include "tagfetchscope.h"
29 #include "private/protocol_p.h"
30 
31 
32 
33 #include <QTimer>
34 
35 using namespace Akonadi;
36 
37 class Akonadi::ItemFetchJobPrivate : public JobPrivate
38 {
39 public:
40  ItemFetchJobPrivate(ItemFetchJob *parent)
41  : JobPrivate(parent)
42  {
43  mCollection = Collection::root();
44  }
45 
46  ~ItemFetchJobPrivate() override
47  {
48  delete mValuePool;
49  }
50 
51  void init()
52  {
53  Q_Q(ItemFetchJob);
54  mEmitTimer = new QTimer(q);
55  mEmitTimer->setSingleShot(true);
56  mEmitTimer->setInterval(100);
57  q->connect(mEmitTimer, SIGNAL(timeout()), q, SLOT(timeout()));
58  }
59 
60  void aboutToFinish() override {
61  timeout();
62  }
63 
64  void timeout()
65  {
66  Q_Q(ItemFetchJob);
67 
68  mEmitTimer->stop(); // in case we are called by result()
69  if (!mPendingItems.isEmpty()) {
70  if (!q->error()) {
71  Q_EMIT q->itemsReceived(mPendingItems);
72  }
73  mPendingItems.clear();
74  }
75  }
76 
77  QString jobDebuggingString() const override
78  {
79  if (mRequestedItems.isEmpty()) {
80  QString str = QStringLiteral("All items from collection %1").arg(mCollection.id());
81  if (mFetchScope.fetchChangedSince().isValid()) {
82  str += QStringLiteral(" changed since %1").arg(mFetchScope.fetchChangedSince().toString());
83  }
84  return str;
85 
86  } else {
87  try {
88  QString itemStr = QStringLiteral("items id: ");
89  bool firstItem = true;
90  for (const Akonadi::Item &item : qAsConst(mRequestedItems)) {
91  if (firstItem) {
92  firstItem = false;
93  } else {
94  itemStr += QStringLiteral(", ");
95  }
96  itemStr += QString::number(item.id());
97  const Akonadi::Collection parentCollection = item.parentCollection();
98  if (parentCollection.isValid()) {
99  itemStr += QStringLiteral(" from collection %1").arg(parentCollection.id());
100  }
101  }
102  return itemStr;
103  //return QString(); //QString::fromLatin1(ProtocolHelper::entitySetToScope(mRequestedItems));
104  } catch (const Exception &e) {
105  return QString::fromUtf8(e.what());
106  }
107  }
108  }
109 
110  Q_DECLARE_PUBLIC(ItemFetchJob)
111 
112  Collection mCollection;
113  Tag mCurrentTag;
114  Item::List mRequestedItems;
115  Item::List mResultItems;
116  ItemFetchScope mFetchScope;
117  Item::List mPendingItems; // items pending for emitting itemsReceived()
118  QTimer *mEmitTimer = nullptr;
119  ProtocolHelperValuePool *mValuePool = nullptr;
120  ItemFetchJob::DeliveryOptions mDeliveryOptions = ItemFetchJob::Default;
121  int mCount = 0;
122 };
123 
124 ItemFetchJob::ItemFetchJob(const Collection &collection, QObject *parent)
125  : Job(new ItemFetchJobPrivate(this), parent)
126 {
127  Q_D(ItemFetchJob);
128 
129  d->init();
130  d->mCollection = collection;
131  d->mValuePool = new ProtocolHelperValuePool; // only worth it for lots of results
132 }
133 
134 ItemFetchJob::ItemFetchJob(const Item &item, QObject *parent)
135  : Job(new ItemFetchJobPrivate(this), parent)
136 {
137  Q_D(ItemFetchJob);
138 
139  d->init();
140  d->mRequestedItems.append(item);
141 }
142 
144  : Job(new ItemFetchJobPrivate(this), parent)
145 {
146  Q_D(ItemFetchJob);
147 
148  d->init();
149  d->mRequestedItems = items;
150 }
151 
153  : Job(new ItemFetchJobPrivate(this), parent)
154 {
155  Q_D(ItemFetchJob);
156 
157  d->init();
158  d->mRequestedItems.reserve(items.size());
159  for (auto id : items) {
160  d->mRequestedItems.append(Item(id));
161  }
162 }
163 
165  : Job(new ItemFetchJobPrivate(this), parent)
166 {
167  Q_D(ItemFetchJob);
168 
169  d->init();
170  d->mRequestedItems.reserve(items.size());
171  for (auto id : items) {
172  d->mRequestedItems.append(Item(id));
173  }
174 }
175 
177  : Job(new ItemFetchJobPrivate(this), parent)
178 {
179  Q_D(ItemFetchJob);
180 
181  d->init();
182  d->mCurrentTag = tag;
183  d->mValuePool = new ProtocolHelperValuePool;
184 }
185 
187 {
188 }
189 
191 {
192  Q_D(ItemFetchJob);
193 
194  try {
195  d->sendCommand(Protocol::FetchItemsCommandPtr::create(
196  d->mRequestedItems.isEmpty() ? Scope() : ProtocolHelper::entitySetToScope(d->mRequestedItems),
197  ProtocolHelper::commandContextToProtocol(d->mCollection, d->mCurrentTag, d->mRequestedItems),
198  ProtocolHelper::itemFetchScopeToProtocol(d->mFetchScope),
199  ProtocolHelper::tagFetchScopeToProtocol(d->mFetchScope.tagFetchScope())));
200  } catch (const Akonadi::Exception &e) {
203  emitResult();
204  return;
205  }
206 }
207 
208 bool ItemFetchJob::doHandleResponse(qint64 tag, const Protocol::CommandPtr &response)
209 {
210  Q_D(ItemFetchJob);
211 
212  if (!response->isResponse() || response->type() != Protocol::Command::FetchItems) {
213  return Job::doHandleResponse(tag, response);
214  }
215 
216  const auto resp = Protocol::cmdCast<Protocol::FetchItemsResponse>(response);
217  // Invalid ID marks the last part of the response
218  if (resp.id() < 0) {
219  return true;
220  }
221 
222  const Item item = ProtocolHelper::parseItemFetchResult(resp, nullptr, d->mValuePool);
223  if (!item.isValid()) {
224  return false;
225  }
226 
227  d->mCount++;
228 
229  if (d->mDeliveryOptions & ItemGetter) {
230  d->mResultItems.append(item);
231  }
232 
233  if (d->mDeliveryOptions & EmitItemsInBatches) {
234  d->mPendingItems.append(item);
235  if (!d->mEmitTimer->isActive()) {
236  d->mEmitTimer->start();
237  }
238  } else if (d->mDeliveryOptions & EmitItemsIndividually) {
239  Q_EMIT itemsReceived(Item::List() << item);
240  }
241 
242  return false;
243 }
244 
245 Item::List ItemFetchJob::items() const
246 {
247  Q_D(const ItemFetchJob);
248 
249  return d->mResultItems;
250 }
251 
253 {
254  Q_D(ItemFetchJob);
255 
256  d->mResultItems.clear();
257 }
258 
260 {
261  Q_D(ItemFetchJob);
262 
263  d->mFetchScope = fetchScope;
264 }
265 
267 {
268  Q_D(ItemFetchJob);
269 
270  return d->mFetchScope;
271 }
272 
274 {
275  Q_D(ItemFetchJob);
276 
277  d->mCollection = collection;
278 }
279 
281 {
282  Q_D(ItemFetchJob);
283 
284  d->mDeliveryOptions = options;
285 }
286 
288 {
289  Q_D(const ItemFetchJob);
290 
291  return d->mDeliveryOptions;
292 }
293 
295 {
296  Q_D(const ItemFetchJob);
297 
298  return d->mCount;
299 }
300 #include "moc_itemfetchjob.cpp"
~ItemFetchJob() override
Destroys the item fetch job.
void itemsReceived(const Akonadi::Item::List &items)
This signal is emitted whenever new items have been fetched completely.
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:385
void emitResult()
items available through items()
Definition: itemfetchjob.h:217
Unknown error.
Definition: job.h:115
Represents a collection of PIM items.
Definition: collection.h:76
void setError(int errorCode)
ItemFetchJob(const Collection &collection, QObject *parent=nullptr)
Creates a new item fetch job that retrieves all items inside the given collection.
void setDeliveryOption(DeliveryOptions options)
Sets the mechanisms by which the items should be fetched.
Base class for all actions in the Akonadi storage.
Definition: job.h:93
void doStart() override
This method must be reimplemented in the concrete jobs.
int size() const const
Item::List items() const
Returns the fetched items.
emitted via signal upon reception
Definition: itemfetchjob.h:218
QUICKADDONS_EXPORT void init()
ItemFetchScope & fetchScope()
Returns the item fetch scope.
void setErrorText(const QString &errorText)
QString number(int n, int base)
QString fromUtf8(const char *str, int size)
DeliveryOptions deliveryOptions() const
Returns the delivery options.
static Collection root()
Returns the root collection.
Definition: collection.cpp:303
Collection parentCollection() const
Returns the parent collection of this object.
Definition: collection.cpp:211
void setFetchScope(const ItemFetchScope &fetchScope)
Sets the item fetch scope.
Specifies which parts of an item should be fetched from the Akonadi storage.
const char * what() const noexcept override
Returns the error message associated with this exception.
Definition: exception.cpp:86
Definition: item.h:44
Helper integration between Akonadi and Qt.
Base class for exceptions used by the Akonadi library.
Definition: exceptionbase.h:43
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
Job that fetches items from the Akonadi storage.
Definition: itemfetchjob.h:84
emitted via signal in bulk (collected and emitted delayed via timer)
Definition: itemfetchjob.h:219
An Akonadi Tag.
Definition: tag.h:39
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...
int count() const
Returns the total number of retrieved items.
QObject * parent() const const
int size() const const
void clearItems()
Save memory by clearing the fetched items.
void setCollection(const Collection &collection)
Specifies the collection the item is in.
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue May 26 2020 22:46:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.