7#include "itemfetchjob.h"
9#include "akonadicore_debug.h"
10#include "attributefactory.h"
11#include "collection.h"
12#include "itemfetchscope.h"
14#include "private/protocol_p.h"
15#include "protocolhelper_p.h"
17#include "tagfetchscope.h"
25class Akonadi::ItemFetchJobPrivate :
public JobPrivate
27 static constexpr std::size_t MaxBatchSize = 10'000UL;
30 explicit ItemFetchJobPrivate(ItemFetchJob *parent)
32 , mCollection(Collection::root())
34 mEmitTimer.setSingleShot(
true);
35 mEmitTimer.setInterval(std::chrono::milliseconds{100});
38 ~ItemFetchJobPrivate()
override
50 void aboutToFinish()
override
60 if (!mPendingItems.isEmpty()) {
62 Q_EMIT q->itemsReceived(mPendingItems);
64 mPendingItems.clear();
70 if (!mRequestedItems.empty()) {
73 if (mItemsLimit.limit() > -1 && mCount >= mItemsLimit.limit()) {
77 const auto batchSize = qMin(MaxBatchSize, mRemainingItems.size());
83 const auto batch = mRemainingItems.subspan(0, batchSize);
84 mRemainingItems = mRemainingItems.subspan(batch.size());
85 const auto batchItems = QList(batch.begin(), batch.end());
86 sendCommand(Protocol::FetchItemsCommandPtr::create(ProtocolHelper::entitySetToScope(batchItems),
87 ProtocolHelper::commandContextToProtocol(mCollection, mCurrentTag, batchItems),
88 ProtocolHelper::itemFetchScopeToProtocol(mFetchScope),
89 ProtocolHelper::tagFetchScopeToProtocol(mFetchScope.tagFetchScope()),
93 Q_ASSERT(mCount == 0);
95 ProtocolHelper::commandContextToProtocol(mCollection, mCurrentTag, mRequestedItems),
96 ProtocolHelper::itemFetchScopeToProtocol(mFetchScope),
97 ProtocolHelper::tagFetchScopeToProtocol(mFetchScope.tagFetchScope()),
104 QString jobDebuggingString()
const override
106 if (mRequestedItems.isEmpty()) {
107 QString str = QStringLiteral(
"All items from collection %1").arg(mCollection.id());
108 if (mFetchScope.fetchChangedSince().isValid()) {
109 str += QStringLiteral(
" changed since %1").
arg(mFetchScope.fetchChangedSince().toString());
115 QString itemStr = QStringLiteral(
"items id: ");
116 bool firstItem =
true;
117 for (
const Akonadi::Item &item : std::as_const(mRequestedItems)) {
121 itemStr += QStringLiteral(
", ");
124 const Akonadi::Collection parentCollection = item.parentCollection();
125 if (parentCollection.isValid()) {
126 itemStr += QStringLiteral(
" from collection %1").
arg(parentCollection.id());
130 }
catch (
const Exception &e) {
136 Q_DECLARE_PUBLIC(ItemFetchJob)
138 Collection mCollection;
142 ItemFetchScope mFetchScope;
145 ProtocolHelperValuePool *mValuePool =
nullptr;
146 ItemFetchJob::DeliveryOptions mDeliveryOptions = ItemFetchJob::Default;
148 Protocol::FetchLimit mItemsLimit;
149 std::span<Item> mRemainingItems;
153 :
Job(new ItemFetchJobPrivate(this),
parent)
158 d->mCollection = collection;
159 d->mValuePool =
new ProtocolHelperValuePool;
163 :
Job(new ItemFetchJobPrivate(this),
parent)
168 d->mRequestedItems.append(item);
172 :
Job(new ItemFetchJobPrivate(this),
parent)
177 d->mRequestedItems =
items;
181 :
Job(new ItemFetchJobPrivate(this),
parent)
186 d->mRequestedItems.reserve(
items.size());
187 for (
auto id :
items) {
188 d->mRequestedItems.append(
Item(
id));
192 :
Job(new ItemFetchJobPrivate(this),
parent)
197 d->mCurrentTag = tag;
198 d->mValuePool =
new ProtocolHelperValuePool;
208 d->mRemainingItems = std::span(d->mRequestedItems.begin(), d->mRequestedItems.size());
222 if (!response->isResponse() || response->type() != Protocol::Command::FetchItems) {
226 const auto &resp = Protocol::cmdCast<Protocol::FetchItemsResponse>(response);
229 if (d->mRemainingItems.empty()) {
232 return d->requestBatch();
235 const Item item = ProtocolHelper::parseItemFetchResult(resp,
nullptr, d->mValuePool);
243 d->mResultItems.append(item);
247 d->mPendingItems.append(item);
248 if (!d->mEmitTimer.isActive()) {
249 d->mEmitTimer.start();
262 return d->mResultItems;
269 d->mResultItems.clear();
283 return d->mFetchScope;
290 d->mCollection = collection;
297 d->mDeliveryOptions = options;
304 return d->mDeliveryOptions;
317 d->mItemsLimit.setLimit(limit);
318 d->mItemsLimit.setLimitOffset(
start);
319 d->mItemsLimit.setSortOrder(order);
321#include "moc_itemfetchjob.cpp"
Represents a collection of PIM items.
Base class for exceptions used by the Akonadi library.
const char * what() const noexcept override
Returns the error message associated with this exception.
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.
Represents a PIM item stored in Akonadi storage.
bool isValid() const
Returns whether the item is valid.
QList< Item > List
Describes a list of items.
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.
Job(QObject *parent=nullptr)
Creates a new job.
void start() override
Jobs are started automatically once entering the event loop again, no need to explicitly call this.
void setErrorText(const QString &errorText)
void setError(int errorCode)
Helper integration between Akonadi and Qt.
KLEO_EXPORT std::unique_ptr< GpgME::DefaultAssuanTransaction > sendCommand(std::shared_ptr< GpgME::Context > &assuanContext, const std::string &command, GpgME::Error &err)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QString arg(Args &&... args) const const
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)