Akonadi

itemfetchjob.cpp
1/*
2 SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "itemfetchjob.h"
8
9#include "attributefactory.h"
10#include "collection.h"
11#include "itemfetchscope.h"
12#include "job_p.h"
13#include "private/protocol_p.h"
14#include "protocolhelper_p.h"
15#include "session_p.h"
16#include "tagfetchscope.h"
17
18#include <QTimer>
19
20using namespace Akonadi;
21
22class Akonadi::ItemFetchJobPrivate : public JobPrivate
23{
24public:
25 explicit ItemFetchJobPrivate(ItemFetchJob *parent)
26 : JobPrivate(parent)
27 , mCollection(Collection::root())
28 {
29 mEmitTimer.setSingleShot(true);
30 mEmitTimer.setInterval(std::chrono::milliseconds{100});
31 }
32
33 ~ItemFetchJobPrivate() override
34 {
35 delete mValuePool;
36 }
37
38 void init()
39 {
40 QObject::connect(&mEmitTimer, &QTimer::timeout, q_ptr, [this]() {
41 timeout();
42 });
43 }
44 void aboutToFinish() override
45 {
46 timeout();
47 }
48
49 void timeout()
50 {
51 Q_Q(ItemFetchJob);
52
53 mEmitTimer.stop(); // in case we are called by result()
54 if (!mPendingItems.isEmpty()) {
55 if (!q->error()) {
56 Q_EMIT q->itemsReceived(mPendingItems);
57 }
58 mPendingItems.clear();
59 }
60 }
61
62 QString jobDebuggingString() const override
63 {
64 if (mRequestedItems.isEmpty()) {
65 QString str = QStringLiteral("All items from collection %1").arg(mCollection.id());
66 if (mFetchScope.fetchChangedSince().isValid()) {
67 str += QStringLiteral(" changed since %1").arg(mFetchScope.fetchChangedSince().toString());
68 }
69 return str;
70
71 } else {
72 try {
73 QString itemStr = QStringLiteral("items id: ");
74 bool firstItem = true;
75 for (const Akonadi::Item &item : std::as_const(mRequestedItems)) {
76 if (firstItem) {
77 firstItem = false;
78 } else {
79 itemStr += QStringLiteral(", ");
80 }
81 itemStr += QString::number(item.id());
82 const Akonadi::Collection parentCollection = item.parentCollection();
83 if (parentCollection.isValid()) {
84 itemStr += QStringLiteral(" from collection %1").arg(parentCollection.id());
85 }
86 }
87 return itemStr;
88 // return QString(); //QString::fromLatin1(ProtocolHelper::entitySetToScope(mRequestedItems));
89 } catch (const Exception &e) {
90 return QString::fromUtf8(e.what());
91 }
92 }
93 }
94
95 Q_DECLARE_PUBLIC(ItemFetchJob)
96
97 Collection mCollection;
98 Tag mCurrentTag;
99 Item::List mRequestedItems;
100 Item::List mResultItems;
101 ItemFetchScope mFetchScope;
102 Item::List mPendingItems; // items pending for emitting itemsReceived()
103 QTimer mEmitTimer;
104 ProtocolHelperValuePool *mValuePool = nullptr;
105 ItemFetchJob::DeliveryOptions mDeliveryOptions = ItemFetchJob::Default;
106 int mCount = 0;
107 Protocol::FetchLimit mItemsLimit;
108};
109
111 : Job(new ItemFetchJobPrivate(this), parent)
112{
114 d->init();
115
116 d->mCollection = collection;
117 d->mValuePool = new ProtocolHelperValuePool; // only worth it for lots of results
118}
119
121 : Job(new ItemFetchJobPrivate(this), parent)
122{
124 d->init();
125
126 d->mRequestedItems.append(item);
127}
128
130 : Job(new ItemFetchJobPrivate(this), parent)
131{
133 d->init();
134
135 d->mRequestedItems = items;
136}
137
139 : Job(new ItemFetchJobPrivate(this), parent)
140{
142 d->init();
143
144 d->mRequestedItems.reserve(items.size());
145 for (auto id : items) {
146 d->mRequestedItems.append(Item(id));
147 }
148}
150 : Job(new ItemFetchJobPrivate(this), parent)
151{
153 d->init();
154
155 d->mCurrentTag = tag;
156 d->mValuePool = new ProtocolHelperValuePool;
157}
158
160
162{
164
165 try {
166 d->sendCommand(Protocol::FetchItemsCommandPtr::create(d->mRequestedItems.isEmpty() ? Scope() : ProtocolHelper::entitySetToScope(d->mRequestedItems),
167 ProtocolHelper::commandContextToProtocol(d->mCollection, d->mCurrentTag, d->mRequestedItems),
168 ProtocolHelper::itemFetchScopeToProtocol(d->mFetchScope),
169 ProtocolHelper::tagFetchScopeToProtocol(d->mFetchScope.tagFetchScope()),
170 d->mItemsLimit));
171 } catch (const Akonadi::Exception &e) {
174 emitResult();
175 return;
176 }
177}
178
180{
182
183 if (!response->isResponse() || response->type() != Protocol::Command::FetchItems) {
184 return Job::doHandleResponse(tag, response);
185 }
186
187 const auto &resp = Protocol::cmdCast<Protocol::FetchItemsResponse>(response);
188 // Invalid ID marks the last part of the response
189 if (resp.id() < 0) {
190 return true;
191 }
192
193 const Item item = ProtocolHelper::parseItemFetchResult(resp, nullptr, d->mValuePool);
194 if (!item.isValid()) {
195 return false;
196 }
197
198 d->mCount++;
199
200 if (d->mDeliveryOptions & ItemGetter) {
201 d->mResultItems.append(item);
202 }
203
204 if (d->mDeliveryOptions & EmitItemsInBatches) {
205 d->mPendingItems.append(item);
206 if (!d->mEmitTimer.isActive()) {
207 d->mEmitTimer.start();
208 }
209 } else if (d->mDeliveryOptions & EmitItemsIndividually) {
211 }
212
213 return false;
214}
215
217{
218 Q_D(const ItemFetchJob);
219
220 return d->mResultItems;
221}
222
224{
226
227 d->mResultItems.clear();
228}
229
231{
233
234 d->mFetchScope = fetchScope;
235}
236
238{
240
241 return d->mFetchScope;
242}
243
245{
247
248 d->mCollection = collection;
249}
250
252{
254
255 d->mDeliveryOptions = options;
256}
257
259{
260 Q_D(const ItemFetchJob);
261
262 return d->mDeliveryOptions;
263}
264
266{
267 Q_D(const ItemFetchJob);
268
269 return d->mCount;
270}
271
272void ItemFetchJob::setLimit(int limit, int start, Qt::SortOrder order)
273{
275 d->mItemsLimit.setLimit(limit);
276 d->mItemsLimit.setLimitOffset(start);
277 d->mItemsLimit.setSortOrder(order);
278}
279#include "moc_itemfetchjob.cpp"
Represents a collection of PIM items.
Definition collection.h:62
Collection parentCollection() const
Returns the parent collection of this object.
Base class for exceptions used by the Akonadi library.
const char * what() const noexcept override
Returns the error message associated with this exception.
Definition exception.cpp:65
Job that fetches items from the Akonadi storage.
int count() const
Returns the total number of retrieved items.
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.
void itemsReceived(const Akonadi::Item::List &items)
This signal is emitted whenever new items have been fetched completely.
void setDeliveryOption(DeliveryOptions options)
Sets the mechanisms by which the items should be fetched.
ItemFetchJob(const Collection &collection, QObject *parent=nullptr)
Creates a new item fetch job that retrieves all items inside the given collection.
void setFetchScope(const ItemFetchScope &fetchScope)
Sets the item fetch scope.
void setLimit(int limit, int start, Qt::SortOrder order=Qt::DescendingOrder)
Sets the limit of fetched items.
DeliveryOptions deliveryOptions() const
Returns the delivery options.
void setCollection(const Collection &collection)
Specifies the collection the item is in.
void doStart() override
This method must be reimplemented in the concrete jobs.
@ EmitItemsInBatches
emitted via signal in bulk (collected and emitted delayed via timer)
@ ItemGetter
items available through items()
@ EmitItemsIndividually
emitted via signal upon reception
ItemFetchScope & fetchScope()
Returns the item fetch scope.
void clearItems()
Save memory by clearing the fetched items.
~ItemFetchJob() override
Destroys the item fetch job.
Item::List items() const
Returns the fetched items.
Specifies which parts of an item should be fetched from the Akonadi storage.
QDateTime fetchChangedSince() const
Returns timestamp of the oldest item to fetch.
Represents a PIM item stored in Akonadi storage.
Definition item.h:100
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
@ Unknown
Unknown error.
Definition job.h:102
void start() override
Jobs are started automatically once entering the event loop again, no need to explicitly call this.
Definition job.cpp:313
An Akonadi Tag.
Definition tag.h:26
void setErrorText(const QString &errorText)
void emitResult()
void setError(int errorCode)
Q_SCRIPTABLE Q_NOREPLY void start()
Helper integration between Akonadi and Qt.
bool isValid() const const
QString toString(QStringView format, QCalendar cal) const const
void clear()
bool isEmpty() const const
qsizetype size() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString arg(Args &&... args) const const
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)
SortOrder
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 Fri Nov 8 2024 11:54:19 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.