diff options
-rw-r--r-- | examples/imapresource/imapresource.cpp | 129 | ||||
-rw-r--r-- | examples/imapresource/imapserverproxy.cpp | 94 | ||||
-rw-r--r-- | examples/imapresource/imapserverproxy.h | 14 |
3 files changed, 139 insertions, 98 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp index 63ae07b..aa0fb94 100644 --- a/examples/imapresource/imapresource.cpp +++ b/examples/imapresource/imapresource.cpp | |||
@@ -40,10 +40,14 @@ | |||
40 | #include "entitystore.h" | 40 | #include "entitystore.h" |
41 | #include "remoteidmap.h" | 41 | #include "remoteidmap.h" |
42 | #include "query.h" | 42 | #include "query.h" |
43 | |||
44 | #include <QtGlobal> | ||
43 | #include <QDate> | 45 | #include <QDate> |
44 | #include <QUuid> | 46 | #include <QUuid> |
45 | #include <QDir> | 47 | #include <QDir> |
46 | #include <QDirIterator> | 48 | #include <QDirIterator> |
49 | #include <QDateTime> | ||
50 | #include <QtAlgorithms> | ||
47 | 51 | ||
48 | #include "imapserverproxy.h" | 52 | #include "imapserverproxy.h" |
49 | #include "entityreader.h" | 53 | #include "entityreader.h" |
@@ -149,7 +153,7 @@ public: | |||
149 | } | 153 | } |
150 | } | 154 | } |
151 | 155 | ||
152 | void synchronizeMails(const QString &path, const QVector<Message> &messages) | 156 | void synchronizeMails(const QString &path, const Message &message) |
153 | { | 157 | { |
154 | auto time = QSharedPointer<QTime>::create(); | 158 | auto time = QSharedPointer<QTime>::create(); |
155 | time->start(); | 159 | time->start(); |
@@ -159,23 +163,20 @@ public: | |||
159 | 163 | ||
160 | const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); | 164 | const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); |
161 | 165 | ||
162 | int count = 0; | 166 | const auto remoteId = assembleMailRid(folderLocalId, message.uid); |
163 | for (const auto &message : messages) { | ||
164 | count++; | ||
165 | const auto remoteId = assembleMailRid(folderLocalId, message.uid); | ||
166 | 167 | ||
167 | SinkTrace() << "Found a mail " << remoteId << message.msg->subject(true)->asUnicodeString() << message.flags; | 168 | Q_ASSERT(message.msg); |
169 | SinkTrace() << "Found a mail " << remoteId << message.msg->subject(true)->asUnicodeString() << message.flags; | ||
168 | 170 | ||
169 | auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier); | 171 | auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier); |
170 | mail.setFolder(folderLocalId); | 172 | mail.setFolder(folderLocalId); |
171 | mail.setMimeMessage(message.msg->encodedContent()); | 173 | mail.setMimeMessage(message.msg->encodedContent()); |
172 | mail.setUnread(!message.flags.contains(Imap::Flags::Seen)); | 174 | mail.setUnread(!message.flags.contains(Imap::Flags::Seen)); |
173 | mail.setImportant(message.flags.contains(Imap::Flags::Flagged)); | 175 | mail.setImportant(message.flags.contains(Imap::Flags::Flagged)); |
174 | 176 | ||
175 | createOrModify(bufferType, remoteId, mail); | 177 | createOrModify(bufferType, remoteId, mail); |
176 | } | 178 | // const auto elapsed = time->elapsed(); |
177 | const auto elapsed = time->elapsed(); | 179 | // SinkTrace() << "Synchronized " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; |
178 | SinkTrace() << "Synchronized " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; | ||
179 | } | 180 | } |
180 | 181 | ||
181 | void synchronizeRemovals(const QString &path, const QSet<qint64> &messages) | 182 | void synchronizeRemovals(const QString &path, const QSet<qint64> &messages) |
@@ -220,29 +221,71 @@ public: | |||
220 | auto capabilities = imap->getCapabilities(); | 221 | auto capabilities = imap->getCapabilities(); |
221 | bool canDoIncrementalRemovals = false; | 222 | bool canDoIncrementalRemovals = false; |
222 | return KAsync::start<void>([=]() { | 223 | return KAsync::start<void>([=]() { |
224 | //First we fetch flag changes for all messages. Since we don't know which messages are locally available we just get everything and only apply to what we have. | ||
225 | SinkLog() << "About to update flags" << folder.normalizedPath(); | ||
223 | auto uidNext = syncStore().readValue(folder.normalizedPath().toUtf8() + "uidnext").toLongLong(); | 226 | auto uidNext = syncStore().readValue(folder.normalizedPath().toUtf8() + "uidnext").toLongLong(); |
224 | const auto changedsince = syncStore().readValue(folder.normalizedPath().toUtf8() + "changedsince").toLongLong(); | 227 | const auto changedsince = syncStore().readValue(folder.normalizedPath().toUtf8() + "changedsince").toLongLong(); |
225 | return imap->fetchFlags(folder, KIMAP2::ImapSet(1, qMax(uidNext, qint64(1))), changedsince, [this, folder](const QVector<Message> &messages) { | 228 | return imap->fetchFlags(folder, KIMAP2::ImapSet(1, qMax(uidNext, qint64(1))), changedsince, [this, folder](const Message &message) { |
226 | // synchronizeMails(folder.normalizedPath(), messages); | ||
227 | const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folder.normalizedPath().toUtf8()); | 229 | const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folder.normalizedPath().toUtf8()); |
228 | for (const auto &message : messages) { | 230 | const auto remoteId = assembleMailRid(folderLocalId, message.uid); |
229 | const auto remoteId = assembleMailRid(folderLocalId, message.uid); | ||
230 | 231 | ||
232 | SinkLog() << "Updating mail flags " << remoteId << message.flags; | ||
231 | 233 | ||
232 | auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier); | 234 | auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier); |
233 | mail.setUnread(!message.flags.contains(Imap::Flags::Seen)); | 235 | mail.setUnread(!message.flags.contains(Imap::Flags::Seen)); |
234 | mail.setImportant(message.flags.contains(Imap::Flags::Flagged)); | 236 | mail.setImportant(message.flags.contains(Imap::Flags::Flagged)); |
235 | 237 | ||
236 | modify(ENTITY_TYPE_MAIL, remoteId, mail); | 238 | modify(ENTITY_TYPE_MAIL, remoteId, mail); |
237 | } | ||
238 | }) | 239 | }) |
239 | .syncThen<void, SelectResult>([this, folder](const SelectResult &selectResult) { | 240 | .syncThen<void, SelectResult>([this, folder](const SelectResult &selectResult) { |
240 | syncStore().writeValue(folder.normalizedPath().toUtf8() + "changedsince", QByteArray::number(selectResult.highestModSequence)); | 241 | syncStore().writeValue(folder.normalizedPath().toUtf8() + "changedsince", QByteArray::number(selectResult.highestModSequence)); |
241 | }); | 242 | }); |
242 | }) | 243 | }) |
243 | .then<void>([=]() { | 244 | .then<void>([=]() { |
245 | //Get the range we're interested in. This is what we're going to download. | ||
246 | return imap->fetchUidsSince(imap->mailboxFromFolder(folder), QDate::currentDate().addDays(-14)) | ||
247 | .then<void, QVector<qint64>>([this, folder, imap](const QVector<qint64> &uidsToFetch) { | ||
248 | SinkTrace() << "Received result set " << uidsToFetch; | ||
249 | SinkTrace() << "About to fetch mail" << folder.normalizedPath(); | ||
250 | const auto uidNext = syncStore().readValue(folder.normalizedPath().toUtf8() + "uidnext").toLongLong(); | ||
251 | QVector<qint64> filteredAndSorted = uidsToFetch; | ||
252 | qSort(filteredAndSorted.begin(), filteredAndSorted.end(), qGreater<qint64>()); | ||
253 | auto lowerBound = qLowerBound(filteredAndSorted.begin(), filteredAndSorted.end(), uidNext, qGreater<qint64>()); | ||
254 | if (lowerBound != filteredAndSorted.end()) { | ||
255 | filteredAndSorted.erase(lowerBound, filteredAndSorted.end()); | ||
256 | } | ||
257 | |||
258 | auto maxUid = QSharedPointer<qint64>::create(0); | ||
259 | if (!filteredAndSorted.isEmpty()) { | ||
260 | *maxUid = filteredAndSorted.first(); | ||
261 | } | ||
262 | SinkTrace() << "Uids to fetch: " << filteredAndSorted; | ||
263 | return imap->fetchMessages(folder, filteredAndSorted, [this, folder, maxUid](const Message &m) { | ||
264 | if (*maxUid < m.uid) { | ||
265 | *maxUid = m.uid; | ||
266 | } | ||
267 | synchronizeMails(folder.normalizedPath(), m); | ||
268 | }, | ||
269 | [this, maxUid, folder](int progress, int total) { | ||
270 | SinkLog() << "Progress: " << progress << " out of " << total; | ||
271 | //commit every 10 messages | ||
272 | if ((progress % 10) == 0) { | ||
273 | commit(); | ||
274 | } | ||
275 | }) | ||
276 | .syncThen<void>([this, maxUid, folder]() { | ||
277 | SinkLog() << "UIDMAX: " << *maxUid << folder.normalizedPath(); | ||
278 | if (*maxUid > 0) { | ||
279 | syncStore().writeValue(folder.normalizedPath().toUtf8() + "uidnext", QByteArray::number(*maxUid)); | ||
280 | } | ||
281 | commit(); | ||
282 | }); | ||
283 | }); | ||
284 | }) | ||
285 | .then<void>([=]() { | ||
244 | //TODO Remove what's no longer existing | 286 | //TODO Remove what's no longer existing |
245 | if (canDoIncrementalRemovals) { | 287 | if (canDoIncrementalRemovals) { |
288 | //TODO do an examine with QRESYNC and remove VANISHED messages | ||
246 | } else { | 289 | } else { |
247 | return imap->fetchUids(folder).syncThen<void, QVector<qint64>>([this, folder](const QVector<qint64> &uids) { | 290 | return imap->fetchUids(folder).syncThen<void, QVector<qint64>>([this, folder](const QVector<qint64> &uids) { |
248 | SinkTrace() << "Syncing removals"; | 291 | SinkTrace() << "Syncing removals"; |
@@ -251,32 +294,6 @@ public: | |||
251 | }); | 294 | }); |
252 | } | 295 | } |
253 | return KAsync::null<void>(); | 296 | return KAsync::null<void>(); |
254 | }) | ||
255 | .then<void>([this, folder, imap]() { | ||
256 | SinkTrace() << "About to fetch mail"; | ||
257 | const auto uidNext = syncStore().readValue(folder.normalizedPath().toUtf8() + "uidnext").toLongLong(); | ||
258 | auto maxUid = QSharedPointer<qint64>::create(0); | ||
259 | return imap->fetchMessages(folder, uidNext, [this, folder, maxUid](const QVector<Message> &messages) { | ||
260 | SinkTrace() << "Got mail"; | ||
261 | for (const auto &m : messages) { | ||
262 | if (*maxUid < m.uid) { | ||
263 | *maxUid = m.uid; | ||
264 | } | ||
265 | } | ||
266 | synchronizeMails(folder.normalizedPath(), messages); | ||
267 | }, | ||
268 | [this, maxUid, folder](int progress, int total) { | ||
269 | SinkLog() << "Progress: " << progress << " out of " << total; | ||
270 | //commit every 10 messages | ||
271 | if ((progress % 10) == 0) { | ||
272 | commit(); | ||
273 | } | ||
274 | }) | ||
275 | .syncThen<void>([this, maxUid, folder]() { | ||
276 | syncStore().writeValue(folder.normalizedPath().toUtf8() + "uidnext", QByteArray::number(*maxUid)); | ||
277 | SinkLog() << "UIDMAX: " << *maxUid << folder.normalizedPath(); | ||
278 | commit(); | ||
279 | }); | ||
280 | }); | 297 | }); |
281 | 298 | ||
282 | 299 | ||
@@ -578,10 +595,8 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in | |||
578 | auto inspectionJob = imap->login(mUser, mPassword) | 595 | auto inspectionJob = imap->login(mUser, mPassword) |
579 | .then<Imap::SelectResult>(imap->select(folderRemoteId)) | 596 | .then<Imap::SelectResult>(imap->select(folderRemoteId)) |
580 | .syncThen<void, Imap::SelectResult>([](Imap::SelectResult){}) | 597 | .syncThen<void, Imap::SelectResult>([](Imap::SelectResult){}) |
581 | .then<void>(imap->fetch(set, scope, [imap, messageByUid](const QVector<Imap::Message> &messages) { | 598 | .then<void>(imap->fetch(set, scope, [imap, messageByUid](const Imap::Message &message) { |
582 | for (const auto &m : messages) { | 599 | messageByUid->insert(message.uid, message); |
583 | messageByUid->insert(m.uid, m); | ||
584 | } | ||
585 | })); | 600 | })); |
586 | 601 | ||
587 | if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { | 602 | if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { |
@@ -641,10 +656,8 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in | |||
641 | auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create(); | 656 | auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create(); |
642 | return imap->login(mUser, mPassword) | 657 | return imap->login(mUser, mPassword) |
643 | .then<void>(imap->select(remoteId).syncThen<void>([](){})) | 658 | .then<void>(imap->select(remoteId).syncThen<void>([](){})) |
644 | .then<void>(imap->fetch(set, scope, [=](const QVector<Imap::Message> &messages) { | 659 | .then<void>(imap->fetch(set, scope, [=](const Imap::Message message) { |
645 | for (const auto &m : messages) { | 660 | messageByUid->insert(message.uid, message); |
646 | messageByUid->insert(m.uid, m); | ||
647 | } | ||
648 | })) | 661 | })) |
649 | .then<void>([imap, messageByUid, expectedCount]() { | 662 | .then<void>([imap, messageByUid, expectedCount]() { |
650 | if (messageByUid->size() != expectedCount) { | 663 | if (messageByUid->size() != expectedCount) { |
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp index a75825e..58164d3 100644 --- a/examples/imapresource/imapserverproxy.cpp +++ b/examples/imapresource/imapserverproxy.cpp | |||
@@ -263,21 +263,24 @@ KAsync::Job<void> ImapServerProxy::fetch(const KIMAP2::ImapSet &set, KIMAP2::Fet | |||
263 | 263 | ||
264 | KAsync::Job<QVector<qint64>> ImapServerProxy::search(const KIMAP2::ImapSet &set) | 264 | KAsync::Job<QVector<qint64>> ImapServerProxy::search(const KIMAP2::ImapSet &set) |
265 | { | 265 | { |
266 | return search(KIMAP2::Term(KIMAP2::Term::Uid, set)); | ||
267 | } | ||
268 | |||
269 | KAsync::Job<QVector<qint64>> ImapServerProxy::search(const KIMAP2::Term &term) | ||
270 | { | ||
266 | auto search = new KIMAP2::SearchJob(mSession); | 271 | auto search = new KIMAP2::SearchJob(mSession); |
267 | search->setTerm(KIMAP2::Term(KIMAP2::Term::Uid, set)); | 272 | search->setTerm(term); |
268 | search->setUidBased(true); | 273 | search->setUidBased(true); |
269 | return runJob<QVector<qint64>>(search, [](KJob *job) -> QVector<qint64> { | 274 | return runJob<QVector<qint64>>(search, [](KJob *job) -> QVector<qint64> { |
270 | return static_cast<KIMAP2::SearchJob*>(job)->results(); | 275 | return static_cast<KIMAP2::SearchJob*>(job)->results(); |
271 | }); | 276 | }); |
272 | } | 277 | } |
273 | 278 | ||
274 | KAsync::Job<void> ImapServerProxy::fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback) | 279 | KAsync::Job<void> ImapServerProxy::fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, const std::function<void(const Message &)> &callback) |
275 | { | 280 | { |
276 | return fetch(set, scope, | 281 | return fetch(set, scope, |
277 | [callback](const KIMAP2::FetchJob::Result &result) { | 282 | [callback](const KIMAP2::FetchJob::Result &result) { |
278 | QVector<Message> list; | 283 | callback(Message{result.uid, result.size, result.attributes, result.flags, result.message}); |
279 | list << Message{result.uid, result.size, result.attributes, result.flags, result.message}; | ||
280 | callback(list); | ||
281 | }); | 284 | }); |
282 | } | 285 | } |
283 | 286 | ||
@@ -286,9 +289,9 @@ QStringList ImapServerProxy::getCapabilities() const | |||
286 | return mCapabilities; | 289 | return mCapabilities; |
287 | } | 290 | } |
288 | 291 | ||
289 | KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox, const qint64 minUid) | 292 | KAsync::Job<QVector<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox, const qint64 minUid) |
290 | { | 293 | { |
291 | auto list = QSharedPointer<QList<qint64>>::create(); | 294 | auto list = QSharedPointer<QVector<qint64>>::create(); |
292 | KIMAP2::FetchJob::FetchScope scope; | 295 | KIMAP2::FetchJob::FetchScope scope; |
293 | scope.mode = KIMAP2::FetchJob::FetchScope::Flags; | 296 | scope.mode = KIMAP2::FetchJob::FetchScope::Flags; |
294 | 297 | ||
@@ -304,14 +307,19 @@ KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox, | |||
304 | 307 | ||
305 | list->append(result.uid); | 308 | list->append(result.uid); |
306 | }) | 309 | }) |
307 | .syncThen<QList<qint64>>([list](){ | 310 | .syncThen<QVector<qint64>>([list](){ |
308 | return *list; | 311 | return *list; |
309 | }); | 312 | }); |
310 | } | 313 | } |
311 | 314 | ||
312 | KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUids(const QString &mailbox) | 315 | KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUids(const QString &mailbox) |
313 | { | 316 | { |
314 | return select(mailbox).then<QVector<qint64>>(search(KIMAP2::ImapSet(1, 0))); | 317 | return select(mailbox).then<QVector<qint64>>(search(KIMAP2::Term(KIMAP2::Term::Uid, KIMAP2::ImapSet(1, 0)))); |
318 | } | ||
319 | |||
320 | KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUidsSince(const QString &mailbox, const QDate &since) | ||
321 | { | ||
322 | return select(mailbox).then<QVector<qint64>>(search(KIMAP2::Term(KIMAP2::Term::Since, since))); | ||
315 | } | 323 | } |
316 | 324 | ||
317 | KAsync::Job<void> ImapServerProxy::list(KIMAP2::ListJob::Option option, const std::function<void(const KIMAP2::MailBoxDescriptor &mailboxes, const QList<QByteArray> &flags)> &callback) | 325 | KAsync::Job<void> ImapServerProxy::list(KIMAP2::ListJob::Option option, const std::function<void(const KIMAP2::MailBoxDescriptor &mailboxes, const QList<QByteArray> &flags)> &callback) |
@@ -390,7 +398,7 @@ QString ImapServerProxy::mailboxFromFolder(const Folder &folder) const | |||
390 | return folder.pathParts.join(mPersonalNamespaceSeparator); | 398 | return folder.pathParts.join(mPersonalNamespaceSeparator); |
391 | } | 399 | } |
392 | 400 | ||
393 | KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const QVector<Message> &)> callback) | 401 | KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const Message &)> callback) |
394 | { | 402 | { |
395 | SinkTrace() << "Fetching flags " << folder.normalizedPath(); | 403 | SinkTrace() << "Fetching flags " << folder.normalizedPath(); |
396 | return select(mailboxFromFolder(folder)).then<SelectResult, SelectResult>([=](const SelectResult &selectResult) -> KAsync::Job<SelectResult> { | 404 | return select(mailboxFromFolder(folder)).then<SelectResult, SelectResult>([=](const SelectResult &selectResult) -> KAsync::Job<SelectResult> { |
@@ -413,7 +421,7 @@ KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, cons | |||
413 | }); | 421 | }); |
414 | } | 422 | } |
415 | 423 | ||
416 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) | 424 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const Message &)> callback, std::function<void(int, int)> progress) |
417 | { | 425 | { |
418 | auto time = QSharedPointer<QTime>::create(); | 426 | auto time = QSharedPointer<QTime>::create(); |
419 | time->start(); | 427 | time->start(); |
@@ -426,40 +434,56 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 ui | |||
426 | } | 434 | } |
427 | 435 | ||
428 | SinkTrace() << "Fetching messages from " << folder.normalizedPath() << selectResult.uidNext << uidNext; | 436 | SinkTrace() << "Fetching messages from " << folder.normalizedPath() << selectResult.uidNext << uidNext; |
429 | return fetchHeaders(mailboxFromFolder(folder), (uidNext + 1)).then<void, QList<qint64>>([this, callback, time, progress, folder](const QList<qint64> &uidsToFetch){ | 437 | return fetchHeaders(mailboxFromFolder(folder), (uidNext + 1)).then<void, QVector<qint64>>([this, callback, time, progress, folder](const QVector<qint64> &uidsToFetch){ |
430 | SinkTrace() << "Fetched headers" << folder.normalizedPath(); | 438 | SinkTrace() << "Fetched headers" << folder.normalizedPath(); |
431 | SinkTrace() << " Total: " << uidsToFetch.size(); | 439 | SinkTrace() << " Total: " << uidsToFetch.size(); |
432 | SinkTrace() << " Uids to fetch: " << uidsToFetch; | 440 | SinkTrace() << " Uids to fetch: " << uidsToFetch; |
433 | SinkTrace() << " Took: " << Sink::Log::TraceTime(time->elapsed()); | 441 | SinkTrace() << " Took: " << Sink::Log::TraceTime(time->elapsed()); |
434 | auto totalCount = uidsToFetch.size(); | 442 | return fetchMessages(folder, uidsToFetch, callback, progress); |
443 | }); | ||
444 | |||
445 | }); | ||
446 | } | ||
447 | |||
448 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, const QVector<qint64> &uidsToFetch, std::function<void(const Message &)> callback, std::function<void(int, int)> progress) | ||
449 | { | ||
450 | auto time = QSharedPointer<QTime>::create(); | ||
451 | time->start(); | ||
452 | Q_ASSERT(!mPersonalNamespaceSeparator.isNull()); | ||
453 | return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidsToFetch](const SelectResult &selectResult) -> KAsync::Job<void> { | ||
454 | |||
455 | SinkTrace() << "Fetching messages" << folder.normalizedPath(); | ||
456 | SinkTrace() << " Total: " << uidsToFetch.size(); | ||
457 | SinkTrace() << " Uids to fetch: " << uidsToFetch; | ||
458 | auto totalCount = uidsToFetch.size(); | ||
459 | if (progress) { | ||
460 | progress(0, totalCount); | ||
461 | } | ||
462 | if (uidsToFetch.isEmpty()) { | ||
463 | SinkTrace() << "Nothing to fetch"; | ||
464 | return KAsync::null<void>(); | ||
465 | } | ||
466 | KIMAP2::FetchJob::FetchScope scope; | ||
467 | scope.parts.clear(); | ||
468 | scope.mode = KIMAP2::FetchJob::FetchScope::Full; | ||
469 | |||
470 | KIMAP2::ImapSet set; | ||
471 | set.add(uidsToFetch); | ||
472 | auto count = QSharedPointer<int>::create(); | ||
473 | return fetch(set, scope, [=](const Message &message) { | ||
474 | *count += 1; | ||
435 | if (progress) { | 475 | if (progress) { |
436 | progress(0, totalCount); | 476 | progress(*count, totalCount); |
437 | } | ||
438 | if (uidsToFetch.isEmpty()) { | ||
439 | SinkTrace() << "Nothing to fetch"; | ||
440 | callback(QVector<Message>()); | ||
441 | return KAsync::null<void>(); | ||
442 | } | 477 | } |
443 | KIMAP2::FetchJob::FetchScope scope; | 478 | callback(message); |
444 | scope.parts.clear(); | ||
445 | scope.mode = KIMAP2::FetchJob::FetchScope::Full; | ||
446 | |||
447 | KIMAP2::ImapSet set; | ||
448 | set.add(uidsToFetch.toVector()); | ||
449 | auto count = QSharedPointer<int>::create(); | ||
450 | return fetch(set, scope, [=](const QVector<Message> &messages) { | ||
451 | *count += messages.size(); | ||
452 | if (progress) { | ||
453 | progress(*count, totalCount); | ||
454 | } | ||
455 | callback(messages); | ||
456 | }); | ||
457 | }); | 479 | }); |
458 | 480 | }) | |
481 | .syncThen<void>([time]() { | ||
482 | SinkTrace() << "The fetch took: " << Sink::Log::TraceTime(time->elapsed()); | ||
459 | }); | 483 | }); |
460 | } | 484 | } |
461 | 485 | ||
462 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) | 486 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::function<void(const Message &)> callback, std::function<void(int, int)> progress) |
463 | { | 487 | { |
464 | return fetchMessages(folder, 0, callback, progress); | 488 | return fetchMessages(folder, 0, callback, progress); |
465 | } | 489 | } |
diff --git a/examples/imapresource/imapserverproxy.h b/examples/imapresource/imapserverproxy.h index 452b479..8b39f23 100644 --- a/examples/imapresource/imapserverproxy.h +++ b/examples/imapresource/imapserverproxy.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <KIMAP2/ListJob> | 25 | #include <KIMAP2/ListJob> |
26 | #include <KIMAP2/Session> | 26 | #include <KIMAP2/Session> |
27 | #include <KIMAP2/FetchJob> | 27 | #include <KIMAP2/FetchJob> |
28 | #include <KIMAP2/SearchJob> | ||
28 | 29 | ||
29 | namespace Imap { | 30 | namespace Imap { |
30 | 31 | ||
@@ -110,30 +111,33 @@ public: | |||
110 | KAsync::Job<void> expunge(const KIMAP2::ImapSet &set); | 111 | KAsync::Job<void> expunge(const KIMAP2::ImapSet &set); |
111 | KAsync::Job<void> copy(const KIMAP2::ImapSet &set, const QString &newMailbox); | 112 | KAsync::Job<void> copy(const KIMAP2::ImapSet &set, const QString &newMailbox); |
112 | KAsync::Job<QVector<qint64>> search(const KIMAP2::ImapSet &set); | 113 | KAsync::Job<QVector<qint64>> search(const KIMAP2::ImapSet &set); |
114 | KAsync::Job<QVector<qint64>> search(const KIMAP2::Term &term); | ||
113 | 115 | ||
114 | typedef std::function<void(const KIMAP2::FetchJob::Result &)> FetchCallback; | 116 | typedef std::function<void(const KIMAP2::FetchJob::Result &)> FetchCallback; |
115 | 117 | ||
116 | KAsync::Job<void> fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, FetchCallback callback); | 118 | KAsync::Job<void> fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, FetchCallback callback); |
117 | KAsync::Job<void> fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback); | 119 | KAsync::Job<void> fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, const std::function<void(const Message &)> &callback); |
118 | KAsync::Job<void> list(KIMAP2::ListJob::Option option, const std::function<void(const KIMAP2::MailBoxDescriptor &mailboxes,const QList<QByteArray> &flags)> &callback); | 120 | KAsync::Job<void> list(KIMAP2::ListJob::Option option, const std::function<void(const KIMAP2::MailBoxDescriptor &mailboxes,const QList<QByteArray> &flags)> &callback); |
119 | 121 | ||
120 | QStringList getCapabilities() const; | 122 | QStringList getCapabilities() const; |
121 | 123 | ||
122 | //Composed calls that do login etc. | 124 | //Composed calls that do login etc. |
123 | KAsync::Job<QList<qint64>> fetchHeaders(const QString &mailbox, qint64 minUid = 1); | 125 | KAsync::Job<QVector<qint64>> fetchHeaders(const QString &mailbox, qint64 minUid = 1); |
124 | KAsync::Job<void> remove(const QString &mailbox, const KIMAP2::ImapSet &set); | 126 | KAsync::Job<void> remove(const QString &mailbox, const KIMAP2::ImapSet &set); |
125 | KAsync::Job<void> remove(const QString &mailbox, const QByteArray &imapSet); | 127 | KAsync::Job<void> remove(const QString &mailbox, const QByteArray &imapSet); |
126 | KAsync::Job<void> move(const QString &mailbox, const KIMAP2::ImapSet &set, const QString &newMailbox); | 128 | KAsync::Job<void> move(const QString &mailbox, const KIMAP2::ImapSet &set, const QString &newMailbox); |
127 | KAsync::Job<QString> createSubfolder(const QString &parentMailbox, const QString &folderName); | 129 | KAsync::Job<QString> createSubfolder(const QString &parentMailbox, const QString &folderName); |
128 | KAsync::Job<QString> renameSubfolder(const QString &mailbox, const QString &newName); | 130 | KAsync::Job<QString> renameSubfolder(const QString &mailbox, const QString &newName); |
129 | KAsync::Job<QVector<qint64>> fetchUids(const QString &mailbox); | 131 | KAsync::Job<QVector<qint64>> fetchUids(const QString &mailbox); |
132 | KAsync::Job<QVector<qint64>> fetchUidsSince(const QString &mailbox, const QDate &since); | ||
130 | 133 | ||
131 | QString mailboxFromFolder(const Folder &) const; | 134 | QString mailboxFromFolder(const Folder &) const; |
132 | 135 | ||
133 | KAsync::Job<void> fetchFolders(std::function<void(const Folder &)> callback); | 136 | KAsync::Job<void> fetchFolders(std::function<void(const Folder &)> callback); |
134 | KAsync::Job<void> fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); | 137 | KAsync::Job<void> fetchMessages(const Folder &folder, std::function<void(const Message &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); |
135 | KAsync::Job<void> fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); | 138 | KAsync::Job<void> fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const Message &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); |
136 | KAsync::Job<SelectResult> fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const QVector<Message> &)> callback); | 139 | KAsync::Job<void> fetchMessages(const Folder &folder, const QVector<qint64> &uidsToFetch, std::function<void(const Message &)> callback, std::function<void(int, int)> progress); |
140 | KAsync::Job<SelectResult> fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const Message &)> callback); | ||
137 | KAsync::Job<QVector<qint64>> fetchUids(const Folder &folder); | 141 | KAsync::Job<QVector<qint64>> fetchUids(const Folder &folder); |
138 | 142 | ||
139 | private: | 143 | private: |