summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-09-14 16:16:42 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-09-15 16:14:19 +0200
commit6d5be4fb7b8cbc450e2780905eaac9a18b486c5c (patch)
tree3e0f42e15889c271a41f4d6225a44b21c066b16a
parentca9c54670cc2d26386c80a2aeed2c999313ec362 (diff)
downloadsink-6d5be4fb7b8cbc450e2780905eaac9a18b486c5c.tar.gz
sink-6d5be4fb7b8cbc450e2780905eaac9a18b486c5c.zip
New synchronization algorithm that only fetches the last 14 days.
-rw-r--r--examples/imapresource/imapresource.cpp129
-rw-r--r--examples/imapresource/imapserverproxy.cpp94
-rw-r--r--examples/imapresource/imapserverproxy.h14
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
264KAsync::Job<QVector<qint64>> ImapServerProxy::search(const KIMAP2::ImapSet &set) 264KAsync::Job<QVector<qint64>> ImapServerProxy::search(const KIMAP2::ImapSet &set)
265{ 265{
266 return search(KIMAP2::Term(KIMAP2::Term::Uid, set));
267}
268
269KAsync::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
274KAsync::Job<void> ImapServerProxy::fetch(const KIMAP2::ImapSet &set, KIMAP2::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback) 279KAsync::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
289KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox, const qint64 minUid) 292KAsync::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
312KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUids(const QString &mailbox) 315KAsync::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
320KAsync::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
317KAsync::Job<void> ImapServerProxy::list(KIMAP2::ListJob::Option option, const std::function<void(const KIMAP2::MailBoxDescriptor &mailboxes, const QList<QByteArray> &flags)> &callback) 325KAsync::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
393KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const QVector<Message> &)> callback) 401KAsync::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
416KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) 424KAsync::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
448KAsync::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
462KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) 486KAsync::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
29namespace Imap { 30namespace 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
139private: 143private: