summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/imapresource/imapresource.cpp75
-rw-r--r--examples/imapresource/imapserverproxy.cpp25
-rw-r--r--examples/imapresource/imapserverproxy.h16
3 files changed, 57 insertions, 59 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index f3f2c26..4482a54 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -77,6 +77,16 @@ static QByteArray assembleMailRid(const ApplicationDomain::Mail &mail, qint64 im
77 return assembleMailRid(mail.getFolder(), imapUid); 77 return assembleMailRid(mail.getFolder(), imapUid);
78} 78}
79 79
80static QByteArray folderRid(const Imap::Folder &folder)
81{
82 return folder.path().toUtf8();
83}
84
85static QByteArray parentRid(const Imap::Folder &folder)
86{
87 return folder.parentPath().toUtf8();
88}
89
80 90
81class ImapSynchronizer : public Sink::Synchronizer { 91class ImapSynchronizer : public Sink::Synchronizer {
82public: 92public:
@@ -86,10 +96,10 @@ public:
86 96
87 } 97 }
88 98
89 QByteArray createFolder(const QString &folderName, const QString &folderPath, const QString &parentFolderRid, const QByteArray &icon) 99 QByteArray createFolder(const QString &folderName, const QByteArray &folderRemoteId, const QByteArray &parentFolderRid, const QByteArray &icon)
90 { 100 {
91 SinkTrace() << "Creating folder: " << folderName << parentFolderRid; 101 SinkTrace() << "Creating folder: " << folderName << parentFolderRid;
92 const auto remoteId = folderPath.toUtf8(); 102 const auto remoteId = folderRemoteId;
93 const auto bufferType = ENTITY_TYPE_FOLDER; 103 const auto bufferType = ENTITY_TYPE_FOLDER;
94 Sink::ApplicationDomain::Folder folder; 104 Sink::ApplicationDomain::Folder folder;
95 folder.setName(folderName); 105 folder.setName(folderName);
@@ -102,7 +112,7 @@ public:
102 } 112 }
103 113
104 if (!parentFolderRid.isEmpty()) { 114 if (!parentFolderRid.isEmpty()) {
105 folder.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, parentFolderRid.toUtf8())); 115 folder.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, parentFolderRid));
106 } 116 }
107 createOrModify(bufferType, remoteId, folder, mergeCriteria); 117 createOrModify(bufferType, remoteId, folder, mergeCriteria);
108 return remoteId; 118 return remoteId;
@@ -116,8 +126,8 @@ public:
116 scanForRemovals(bufferType, 126 scanForRemovals(bufferType,
117 [&folderList](const QByteArray &remoteId) -> bool { 127 [&folderList](const QByteArray &remoteId) -> bool {
118 // folderList.contains(remoteId) 128 // folderList.contains(remoteId)
119 for (const auto &folderPath : folderList) { 129 for (const auto &folder : folderList) {
120 if (folderPath.path() == remoteId) { 130 if (folderRid(folder) == remoteId) {
121 return true; 131 return true;
122 } 132 }
123 } 133 }
@@ -126,19 +136,19 @@ public:
126 ); 136 );
127 137
128 for (const auto &f : folderList) { 138 for (const auto &f : folderList) {
129 createFolder(f.name(), f.path(), f.parentPath(), "folder"); 139 createFolder(f.name(), folderRid(f), parentRid(f), "folder");
130 } 140 }
131 } 141 }
132 142
133 void synchronizeMails(const QString &path, const Message &message) 143 void synchronizeMails(const QByteArray &folderRid, const Message &message)
134 { 144 {
135 auto time = QSharedPointer<QTime>::create(); 145 auto time = QSharedPointer<QTime>::create();
136 time->start(); 146 time->start();
137 const QByteArray bufferType = ENTITY_TYPE_MAIL; 147 const QByteArray bufferType = ENTITY_TYPE_MAIL;
138 148
139 SinkTrace() << "Importing new mail." << path; 149 SinkTrace() << "Importing new mail." << folderRid;
140 150
141 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8()); 151 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folderRid);
142 152
143 const auto remoteId = assembleMailRid(folderLocalId, message.uid); 153 const auto remoteId = assembleMailRid(folderLocalId, message.uid);
144 154
@@ -153,18 +163,21 @@ public:
153 163
154 createOrModify(bufferType, remoteId, mail); 164 createOrModify(bufferType, remoteId, mail);
155 // const auto elapsed = time->elapsed(); 165 // const auto elapsed = time->elapsed();
156 // SinkTrace() << "Synchronized " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; 166 // SinkTrace() << "Synchronized " << count << " mails in " << folderRid << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]";
157 } 167 }
158 168
159 void synchronizeRemovals(const QString &path, const QSet<qint64> &messages) 169 void synchronizeRemovals(const QByteArray &folderRid, const QSet<qint64> &messages)
160 { 170 {
161 auto time = QSharedPointer<QTime>::create(); 171 auto time = QSharedPointer<QTime>::create();
162 time->start(); 172 time->start();
163 const QByteArray bufferType = ENTITY_TYPE_MAIL; 173 const QByteArray bufferType = ENTITY_TYPE_MAIL;
174 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folderRid);
175 if (folderLocalId.isEmpty()) {
176 SinkWarning() << "Failed to lookup local id of: " << folderRid;
177 return;
178 }
164 179
165 SinkTrace() << "Finding removed mail."; 180 SinkTrace() << "Finding removed mail: " << folderLocalId << " remoteId: " << folderRid;
166
167 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, path.toUtf8());
168 181
169 int count = 0; 182 int count = 0;
170 183
@@ -182,24 +195,27 @@ public:
182 ); 195 );
183 196
184 const auto elapsed = time->elapsed(); 197 const auto elapsed = time->elapsed();
185 SinkLog() << "Removed " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; 198 SinkLog() << "Removed " << count << " mails in " << folderRid << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]";
186 } 199 }
187 200
188 KAsync::Job<void> synchronizeFolder(QSharedPointer<ImapServerProxy> imap, const Imap::Folder &folder, const QDate &dateFilter) 201 KAsync::Job<void> synchronizeFolder(QSharedPointer<ImapServerProxy> imap, const Imap::Folder &folder, const QDate &dateFilter)
189 { 202 {
190 QSet<qint64> uids; 203 QSet<qint64> uids;
191 SinkLog() << "Synchronizing mails" << folder.path(); 204 SinkLogCtx(mLogCtx) << "Synchronizing mails: " << folderRid(folder);
205 if (folder.path().isEmpty()) {
206 return KAsync::error<void>("Invalid folder");
207 }
192 auto capabilities = imap->getCapabilities(); 208 auto capabilities = imap->getCapabilities();
193 bool canDoIncrementalRemovals = false; 209 bool canDoIncrementalRemovals = false;
194 return KAsync::start<void>([=]() { 210 return KAsync::start<void>([=]() {
195 //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. 211 //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.
196 auto uidNext = syncStore().readValue(folder.normalizedPath().toUtf8() + "uidnext").toLongLong(); 212 auto uidNext = syncStore().readValue(folderRid(folder), "uidnext").toLongLong();
197 bool ok = false; 213 bool ok = false;
198 const auto changedsince = syncStore().readValue(folder.normalizedPath().toUtf8() + "changedsince").toLongLong(&ok); 214 const auto changedsince = syncStore().readValue(folderRid(folder), "changedsince").toLongLong(&ok);
199 SinkLog() << "About to update flags" << folder.path() << "changedsince: " << changedsince; 215 SinkLog() << "About to update flags" << folder.path() << "changedsince: " << changedsince;
200 if (ok) { 216 if (ok) {
201 return imap->fetchFlags(folder, KIMAP2::ImapSet(1, qMax(uidNext, qint64(1))), changedsince, [this, folder](const Message &message) { 217 return imap->fetchFlags(folder, KIMAP2::ImapSet(1, qMax(uidNext, qint64(1))), changedsince, [this, folder](const Message &message) {
202 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folder.normalizedPath().toUtf8()); 218 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folderRid(folder));
203 const auto remoteId = assembleMailRid(folderLocalId, message.uid); 219 const auto remoteId = assembleMailRid(folderLocalId, message.uid);
204 220
205 SinkLog() << "Updating mail flags " << remoteId << message.flags; 221 SinkLog() << "Updating mail flags " << remoteId << message.flags;
@@ -212,13 +228,14 @@ public:
212 }) 228 })
213 .syncThen<void, SelectResult>([this, folder](const SelectResult &selectResult) { 229 .syncThen<void, SelectResult>([this, folder](const SelectResult &selectResult) {
214 SinkLog() << "Flags updated. New changedsince value: " << selectResult.highestModSequence; 230 SinkLog() << "Flags updated. New changedsince value: " << selectResult.highestModSequence;
215 syncStore().writeValue(folder.normalizedPath().toUtf8() + "changedsince", QByteArray::number(selectResult.highestModSequence)); 231 syncStore().writeValue(folderRid(folder), "changedsince", QByteArray::number(selectResult.highestModSequence));
216 }); 232 });
217 } else { 233 } else {
234 //We hit this path on initial sync
218 return imap->select(imap->mailboxFromFolder(folder)) 235 return imap->select(imap->mailboxFromFolder(folder))
219 .syncThen<void, SelectResult>([this, folder](const SelectResult &selectResult) { 236 .syncThen<void, SelectResult>([this, folder](const SelectResult &selectResult) {
220 SinkLog() << "No flags to update. New changedsince value: " << selectResult.highestModSequence; 237 SinkLog() << "No flags to update. New changedsince value: " << selectResult.highestModSequence;
221 syncStore().writeValue(folder.normalizedPath().toUtf8() + "changedsince", QByteArray::number(selectResult.highestModSequence)); 238 syncStore().writeValue(folderRid(folder), "changedsince", QByteArray::number(selectResult.highestModSequence));
222 }); 239 });
223 } 240 }
224 }) 241 })
@@ -232,8 +249,8 @@ public:
232 }(); 249 }();
233 return job.then<void, QVector<qint64>>([this, folder, imap](const QVector<qint64> &uidsToFetch) { 250 return job.then<void, QVector<qint64>>([this, folder, imap](const QVector<qint64> &uidsToFetch) {
234 SinkTrace() << "Received result set " << uidsToFetch; 251 SinkTrace() << "Received result set " << uidsToFetch;
235 SinkTrace() << "About to fetch mail" << folder.normalizedPath(); 252 SinkTrace() << "About to fetch mail" << folder.path();
236 const auto uidNext = syncStore().readValue(folder.normalizedPath().toUtf8() + "uidnext").toLongLong(); 253 const auto uidNext = syncStore().readValue(folderRid(folder), "uidnext").toLongLong();
237 QVector<qint64> filteredAndSorted = uidsToFetch; 254 QVector<qint64> filteredAndSorted = uidsToFetch;
238 qSort(filteredAndSorted.begin(), filteredAndSorted.end(), qGreater<qint64>()); 255 qSort(filteredAndSorted.begin(), filteredAndSorted.end(), qGreater<qint64>());
239 auto lowerBound = qLowerBound(filteredAndSorted.begin(), filteredAndSorted.end(), uidNext, qGreater<qint64>()); 256 auto lowerBound = qLowerBound(filteredAndSorted.begin(), filteredAndSorted.end(), uidNext, qGreater<qint64>());
@@ -250,7 +267,7 @@ public:
250 if (*maxUid < m.uid) { 267 if (*maxUid < m.uid) {
251 *maxUid = m.uid; 268 *maxUid = m.uid;
252 } 269 }
253 synchronizeMails(folder.normalizedPath(), m); 270 synchronizeMails(folderRid(folder), m);
254 }, 271 },
255 [this, maxUid, folder](int progress, int total) { 272 [this, maxUid, folder](int progress, int total) {
256 SinkLog() << "Progress: " << progress << " out of " << total; 273 SinkLog() << "Progress: " << progress << " out of " << total;
@@ -260,9 +277,9 @@ public:
260 } 277 }
261 }) 278 })
262 .syncThen<void>([this, maxUid, folder]() { 279 .syncThen<void>([this, maxUid, folder]() {
263 SinkLog() << "UIDMAX: " << *maxUid << folder.normalizedPath(); 280 SinkLog() << "UIDMAX: " << *maxUid << folder.path();
264 if (*maxUid > 0) { 281 if (*maxUid > 0) {
265 syncStore().writeValue(folder.normalizedPath().toUtf8() + "uidnext", QByteArray::number(*maxUid)); 282 syncStore().writeValue(folderRid(folder) + "uidnext", QByteArray::number(*maxUid));
266 } 283 }
267 commit(); 284 commit();
268 }); 285 });
@@ -274,8 +291,8 @@ public:
274 //TODO do an examine with QRESYNC and remove VANISHED messages 291 //TODO do an examine with QRESYNC and remove VANISHED messages
275 } else { 292 } else {
276 return imap->fetchUids(folder).syncThen<void, QVector<qint64>>([this, folder](const QVector<qint64> &uids) { 293 return imap->fetchUids(folder).syncThen<void, QVector<qint64>>([this, folder](const QVector<qint64> &uids) {
277 SinkTrace() << "Syncing removals"; 294 SinkTrace() << "Syncing removals: " << folder.path();
278 synchronizeRemovals(folder.normalizedPath(), uids.toList().toSet()); 295 synchronizeRemovals(folderRid(folder), uids.toList().toSet());
279 commit(); 296 commit();
280 }); 297 });
281 } 298 }
@@ -688,7 +705,7 @@ protected:
688 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort); 705 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
689 auto inspectionJob = imap->login(mUser, mPassword) 706 auto inspectionJob = imap->login(mUser, mPassword)
690 .then<void>(imap->fetchFolders([=](const Imap::Folder &f) { 707 .then<void>(imap->fetchFolders([=](const Imap::Folder &f) {
691 *folderByPath << f.normalizedPath(); 708 *folderByPath << f.path();
692 *folderByName << f.name(); 709 *folderByName << f.name();
693 })) 710 }))
694 .then<void>([this, folderByName, folderByPath, folder, remoteId, imap]() { 711 .then<void>([this, folderByName, folderByPath, folder, remoteId, imap]() {
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp
index d6f0c7f..af1f4d1 100644
--- a/examples/imapresource/imapserverproxy.cpp
+++ b/examples/imapresource/imapserverproxy.cpp
@@ -396,25 +396,22 @@ KAsync::Job<void> ImapServerProxy::fetchFolders(std::function<void(const Folder
396 396
397QString ImapServerProxy::mailboxFromFolder(const Folder &folder) const 397QString ImapServerProxy::mailboxFromFolder(const Folder &folder) const
398{ 398{
399 if (folder.path().isEmpty()) { 399 Q_ASSERT(!folder.path().isEmpty());
400 return folder.path(mPersonalNamespaceSeparator); 400 return folder.path();
401 } else {
402 return folder.path();
403 }
404} 401}
405 402
406KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const Message &)> callback) 403KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const Message &)> callback)
407{ 404{
408 SinkTrace() << "Fetching flags " << folder.normalizedPath(); 405 SinkTrace() << "Fetching flags " << folder.path();
409 return select(mailboxFromFolder(folder)).then<SelectResult, SelectResult>([=](const SelectResult &selectResult) -> KAsync::Job<SelectResult> { 406 return select(mailboxFromFolder(folder)).then<SelectResult, SelectResult>([=](const SelectResult &selectResult) -> KAsync::Job<SelectResult> {
410 SinkTrace() << "Modeseq " << folder.normalizedPath() << selectResult.highestModSequence << changedsince; 407 SinkTrace() << "Modeseq " << folder.path() << selectResult.highestModSequence << changedsince;
411 408
412 if (selectResult.highestModSequence == static_cast<quint64>(changedsince)) { 409 if (selectResult.highestModSequence == static_cast<quint64>(changedsince)) {
413 SinkTrace()<< folder.normalizedPath() << "Changedsince didn't change, nothing to do."; 410 SinkTrace()<< folder.path() << "Changedsince didn't change, nothing to do.";
414 return KAsync::value<SelectResult>(selectResult); 411 return KAsync::value<SelectResult>(selectResult);
415 } 412 }
416 413
417 SinkTrace() << "Fetching flags " << folder.normalizedPath() << set << selectResult.highestModSequence << changedsince; 414 SinkTrace() << "Fetching flags " << folder.path() << set << selectResult.highestModSequence << changedsince;
418 415
419 KIMAP2::FetchJob::FetchScope scope; 416 KIMAP2::FetchJob::FetchScope scope;
420 scope.mode = KIMAP2::FetchJob::FetchScope::Flags; 417 scope.mode = KIMAP2::FetchJob::FetchScope::Flags;
@@ -432,15 +429,15 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 ui
432 time->start(); 429 time->start();
433 Q_ASSERT(!mPersonalNamespaceSeparator.isNull()); 430 Q_ASSERT(!mPersonalNamespaceSeparator.isNull());
434 return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidNext](const SelectResult &selectResult) -> KAsync::Job<void> { 431 return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidNext](const SelectResult &selectResult) -> KAsync::Job<void> {
435 SinkTrace() << "UIDNEXT " << folder.normalizedPath() << selectResult.uidNext << uidNext; 432 SinkTrace() << "UIDNEXT " << folder.path() << selectResult.uidNext << uidNext;
436 if (selectResult.uidNext == (uidNext + 1)) { 433 if (selectResult.uidNext == (uidNext + 1)) {
437 SinkTrace()<< folder.normalizedPath() << "Uidnext didn't change, nothing to do."; 434 SinkTrace()<< folder.path() << "Uidnext didn't change, nothing to do.";
438 return KAsync::null<void>(); 435 return KAsync::null<void>();
439 } 436 }
440 437
441 SinkTrace() << "Fetching messages from " << folder.normalizedPath() << selectResult.uidNext << uidNext; 438 SinkTrace() << "Fetching messages from " << folder.path() << selectResult.uidNext << uidNext;
442 return fetchHeaders(mailboxFromFolder(folder), (uidNext + 1)).then<void, QVector<qint64>>([this, callback, time, progress, folder](const QVector<qint64> &uidsToFetch){ 439 return fetchHeaders(mailboxFromFolder(folder), (uidNext + 1)).then<void, QVector<qint64>>([this, callback, time, progress, folder](const QVector<qint64> &uidsToFetch){
443 SinkTrace() << "Fetched headers" << folder.normalizedPath(); 440 SinkTrace() << "Fetched headers" << folder.path();
444 SinkTrace() << " Total: " << uidsToFetch.size(); 441 SinkTrace() << " Total: " << uidsToFetch.size();
445 SinkTrace() << " Uids to fetch: " << uidsToFetch; 442 SinkTrace() << " Uids to fetch: " << uidsToFetch;
446 SinkTrace() << " Took: " << Sink::Log::TraceTime(time->elapsed()); 443 SinkTrace() << " Took: " << Sink::Log::TraceTime(time->elapsed());
@@ -457,7 +454,7 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, const QVe
457 Q_ASSERT(!mPersonalNamespaceSeparator.isNull()); 454 Q_ASSERT(!mPersonalNamespaceSeparator.isNull());
458 return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidsToFetch](const SelectResult &selectResult) -> KAsync::Job<void> { 455 return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidsToFetch](const SelectResult &selectResult) -> KAsync::Job<void> {
459 456
460 SinkTrace() << "Fetching messages" << folder.normalizedPath(); 457 SinkTrace() << "Fetching messages" << folder.path();
461 SinkTrace() << " Total: " << uidsToFetch.size(); 458 SinkTrace() << " Total: " << uidsToFetch.size();
462 SinkTrace() << " Uids to fetch: " << uidsToFetch; 459 SinkTrace() << " Uids to fetch: " << uidsToFetch;
463 auto totalCount = uidsToFetch.size(); 460 auto totalCount = uidsToFetch.size();
diff --git a/examples/imapresource/imapserverproxy.h b/examples/imapresource/imapserverproxy.h
index 22527c0..fa2d022 100644
--- a/examples/imapresource/imapserverproxy.h
+++ b/examples/imapresource/imapserverproxy.h
@@ -72,16 +72,7 @@ struct Folder {
72 { 72 {
73 } 73 }
74 74
75 QString normalizedPath() const
76 {
77 return path('/');
78 }
79 75
80 QString path(const QChar &s) const
81 {
82 Q_ASSERT(!s.isNull());
83 return pathParts.join(s);
84 }
85 76
86 QString path() const 77 QString path() const
87 { 78 {
@@ -97,13 +88,6 @@ struct Folder {
97 return parts.join(mSeparator); 88 return parts.join(mSeparator);
98 } 89 }
99 90
100 QString normalizedParentPath() const
101 {
102 Q_ASSERT(!pathParts.isEmpty());
103 auto parts = pathParts;
104 parts.removeLast();
105 return parts.join('/');
106 }
107 91
108 QString name() const 92 QString name() const
109 { 93 {