summaryrefslogtreecommitdiffstats
path: root/examples/imapresource
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-04-21 17:31:22 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-04-21 17:44:30 +0200
commitfcc89a201a06ede057dae86d4591199bf69fab50 (patch)
treeb1aa85322f325fcf2055c0ddf8f7ffcafdf5002b /examples/imapresource
parent0d9d054be6a1716abff20a49e44d94b9b79ab107 (diff)
downloadsink-fcc89a201a06ede057dae86d4591199bf69fab50.tar.gz
sink-fcc89a201a06ede057dae86d4591199bf69fab50.zip
Make sure we always have a complete hierarchy from the IMAP server
Diffstat (limited to 'examples/imapresource')
-rw-r--r--examples/imapresource/imapresource.cpp10
-rw-r--r--examples/imapresource/imapserverproxy.cpp26
-rw-r--r--examples/imapresource/imapserverproxy.h9
3 files changed, 37 insertions, 8 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index 0b3dcf5..8577b8c 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -119,6 +119,8 @@ public:
119 QByteArray createFolder(const Imap::Folder &f) 119 QByteArray createFolder(const Imap::Folder &f)
120 { 120 {
121 const auto parentFolderRid = parentRid(f); 121 const auto parentFolderRid = parentRid(f);
122 bool isToplevel = parentFolderRid.isEmpty();
123
122 SinkTraceCtx(mLogCtx) << "Creating folder: " << f.name() << parentFolderRid << f.flags; 124 SinkTraceCtx(mLogCtx) << "Creating folder: " << f.name() << parentFolderRid << f.flags;
123 125
124 const auto remoteId = folderRid(f); 126 const auto remoteId = folderRid(f);
@@ -126,22 +128,20 @@ public:
126 folder.setName(f.name()); 128 folder.setName(f.name());
127 folder.setIcon("folder"); 129 folder.setIcon("folder");
128 folder.setEnabled(f.subscribed); 130 folder.setEnabled(f.subscribed);
129 QHash<QByteArray, Query::Comparator> mergeCriteria;
130 auto specialPurpose = [&] { 131 auto specialPurpose = [&] {
131 if (hasSpecialPurposeFlag(f.flags)) { 132 if (hasSpecialPurposeFlag(f.flags)) {
132 return getSpecialPurposeType(f.flags); 133 return getSpecialPurposeType(f.flags);
133 } else if (SpecialPurpose::isSpecialPurposeFolderName(f.name()) && parentFolderRid.isEmpty()) { 134 } else if (SpecialPurpose::isSpecialPurposeFolderName(f.name()) && isToplevel) {
134 return SpecialPurpose::getSpecialPurposeType(f.name()); 135 return SpecialPurpose::getSpecialPurposeType(f.name());
135 } 136 }
136 return QByteArray{}; 137 return QByteArray{};
137 }(); 138 }();
138 if (!specialPurpose.isEmpty()) { 139 if (!specialPurpose.isEmpty()) {
139 folder.setSpecialPurpose(QByteArrayList() << specialPurpose); 140 folder.setSpecialPurpose(QByteArrayList() << specialPurpose);
140 mergeCriteria.insert(ApplicationDomain::Folder::SpecialPurpose::name, Query::Comparator(specialPurpose, Query::Comparator::Contains));
141 } 141 }
142 142
143 if (!parentFolderRid.isEmpty()) { 143 if (!isToplevel) {
144 folder.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, parentFolderRid)); 144 folder.setParent(syncStore().resolveRemoteId(ApplicationDomain::Folder::name, parentFolderRid));
145 } 145 }
146 createOrModify(ApplicationDomain::getTypeName<ApplicationDomain::Folder>(), remoteId, folder); 146 createOrModify(ApplicationDomain::getTypeName<ApplicationDomain::Folder>(), remoteId, folder);
147 return remoteId; 147 return remoteId;
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp
index 08a0081..d3ad2d4 100644
--- a/examples/imapresource/imapserverproxy.cpp
+++ b/examples/imapresource/imapserverproxy.cpp
@@ -457,10 +457,23 @@ bool Imap::flagsContain(const QByteArray &f, const QByteArrayList &flags)
457 return caseInsensitiveContains(f, flags); 457 return caseInsensitiveContains(f, flags);
458} 458}
459 459
460static void reportFolder(const Folder &f, QSharedPointer<QSet<QString>> reportedList, std::function<void(const Folder &)> callback) {
461 if (!reportedList->contains(f.path())) {
462 reportedList->insert(f.path());
463 auto c = f;
464 c.noselect = true;
465 callback(c);
466 if (!f.parentPath().isEmpty()){
467 reportFolder(f.parentFolder(), reportedList, callback);
468 }
469 }
470}
471
460KAsync::Job<void> ImapServerProxy::fetchFolders(std::function<void(const Folder &)> callback) 472KAsync::Job<void> ImapServerProxy::fetchFolders(std::function<void(const Folder &)> callback)
461{ 473{
462 SinkTrace() << "Fetching folders"; 474 SinkTrace() << "Fetching folders";
463 auto subscribedList = QSharedPointer<QSet<QString>>::create() ; 475 auto subscribedList = QSharedPointer<QSet<QString>>::create() ;
476 auto reportedList = QSharedPointer<QSet<QString>>::create() ;
464 return list(KIMAP2::ListJob::NoOption, [=](const KIMAP2::MailBoxDescriptor &mailbox, const QList<QByteArray> &){ 477 return list(KIMAP2::ListJob::NoOption, [=](const KIMAP2::MailBoxDescriptor &mailbox, const QList<QByteArray> &){
465 *subscribedList << mailbox.name; 478 *subscribedList << mailbox.name;
466 }).then(list(KIMAP2::ListJob::IncludeUnsubscribed, [=](const KIMAP2::MailBoxDescriptor &mailbox, const QList<QByteArray> &flags) { 479 }).then(list(KIMAP2::ListJob::IncludeUnsubscribed, [=](const KIMAP2::MailBoxDescriptor &mailbox, const QList<QByteArray> &flags) {
@@ -471,17 +484,24 @@ KAsync::Job<void> ImapServerProxy::fetchFolders(std::function<void(const Folder
471 bool sent = caseInsensitiveContains(FolderFlags::Sent, flags); 484 bool sent = caseInsensitiveContains(FolderFlags::Sent, flags);
472 bool drafts = caseInsensitiveContains(FolderFlags::Drafts, flags); 485 bool drafts = caseInsensitiveContains(FolderFlags::Drafts, flags);
473 bool trash = caseInsensitiveContains(FolderFlags::Trash, flags); 486 bool trash = caseInsensitiveContains(FolderFlags::Trash, flags);
474 bool isgmailParent = mailbox.name.toLower() == "[gmail]" || mailbox.name.toLower() == "[Google Mail]";
475 /** 487 /**
476 * Because gmail duplicates messages all over the place we only support a few selected folders for now that should be mostly exclusive. 488 * Because gmail duplicates messages all over the place we only support a few selected folders for now that should be mostly exclusive.
477 */ 489 */
478 if (!(inbox || sent || drafts || trash || isgmailParent)) { 490 if (!(inbox || sent || drafts || trash)) {
479 return; 491 return;
480 } 492 }
481 } 493 }
482 SinkLog() << "Found mailbox: " << mailbox.name << flags << FolderFlags::Noselect << noselect << " sub: " << subscribed; 494 SinkLog() << "Found mailbox: " << mailbox.name << flags << FolderFlags::Noselect << noselect << " sub: " << subscribed;
483 auto ns = getNamespace(mailbox.name); 495 auto ns = getNamespace(mailbox.name);
484 callback(Folder{mailbox.name, ns, mailbox.separator, noselect, subscribed, flags}); 496 auto folder = Folder{mailbox.name, ns, mailbox.separator, noselect, subscribed, flags};
497
498 //call callback for parents if that didn't already happen.
499 //This is necessary because we can have missing bits in the hierarchy in IMAP, but this will not work in sink because we'd end up with an incomplete tree.
500 if (!folder.parentPath().isEmpty() && !reportedList->contains(folder.parentPath())) {
501 reportFolder(folder.parentFolder(), reportedList, callback);
502 }
503 reportedList->insert(folder.path());
504 callback(folder);
485 })); 505 }));
486} 506}
487 507
diff --git a/examples/imapresource/imapserverproxy.h b/examples/imapresource/imapserverproxy.h
index 0d70ba5..2d90f39 100644
--- a/examples/imapresource/imapserverproxy.h
+++ b/examples/imapresource/imapserverproxy.h
@@ -118,6 +118,15 @@ struct Folder {
118 return parentPath; 118 return parentPath;
119 } 119 }
120 120
121 Folder parentFolder() const
122 {
123 Folder parent;
124 parent.mPath = parentPath();
125 parent.mNamespace = mNamespace;
126 parent.mSeparator = mSeparator;
127 return parent;
128 }
129
121 QString name() const 130 QString name() const
122 { 131 {
123 auto pathParts = mPath.split(mSeparator); 132 auto pathParts = mPath.split(mSeparator);