diff --git a/resources/kolab/kolabresource.cpp b/resources/kolab/kolabresource.cpp index 509bacb1a..2e8abf21b 100644 --- a/resources/kolab/kolabresource.cpp +++ b/resources/kolab/kolabresource.cpp @@ -1,228 +1,227 @@ /* Copyright (c) 2014 Christian Mollekopf This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kolabresource.h" #include #include #include #include #include #include #include #include #include #include #include "kolabretrievecollectionstask.h" #include "kolabresourcestate.h" #include "kolabhelpers.h" #include "settings.h" #include "kolabaddtagtask.h" #include "kolabchangeitemstagstask.h" #include "kolabchangetagtask.h" #include "kolabremovetagtask.h" #include "kolabretrievetagstask.h" KolabResource::KolabResource(const QString& id) :ImapResource(id) { //Load translations from imap resource KGlobal::locale()->insertCatalog(QLatin1String("akonadi_imap_resource")); } KolabResource::~KolabResource() { } void KolabResource::delayedInit() { ImapResource::delayedInit(); settings()->setRetrieveMetadataOnFolderListing(false); Q_ASSERT(!settings()->retrieveMetadataOnFolderListing()); } QString KolabResource::defaultName() { return i18n("Kolab Resource"); } ResourceStateInterface::Ptr KolabResource::createResourceState(const TaskArguments &args) { return ResourceStateInterface::Ptr(new KolabResourceState(this, args)); } void KolabResource::retrieveCollections() { emit status(AgentBase::Running, i18nc("@info:status", "Retrieving folders")); - setKeepLocalCollectionChanges(QSet() << "CONTENTMIMETYPES" << "AccessRights"); startTask(new KolabRetrieveCollectionsTask(createResourceState(TaskArguments()), this)); synchronizeTags(); } void KolabResource::retrieveItems(const Akonadi::Collection &col) { //The collection that we receive was fetched when the task was scheduled, it is therefore possible that it is outdated. //We refetch the collection since we rely on up-to-date annotations. //FIXME: because this is async and not part of the resourcetask, it can't be killed. ResourceBase should just provide an up-to date copy of the collection. Akonadi::CollectionFetchJob *fetchJob = new Akonadi::CollectionFetchJob(col, Akonadi::CollectionFetchJob::Base, this); fetchJob->fetchScope().setAncestorRetrieval(Akonadi::CollectionFetchScope::All); fetchJob->fetchScope().setIncludeStatistics(true); fetchJob->fetchScope().setIncludeUnsubscribed(true); connect(fetchJob, SIGNAL(result(KJob*)), this, SLOT(onItemRetrievalCollectionFetchDone(KJob*))); } void KolabResource::onItemRetrievalCollectionFetchDone(KJob *job) { if (job->error()) { kWarning() << "Failed to retrieve collection before RetrieveItemsTask: " << job->errorString(); cancelTask(i18n("Failed to retrieve items.")); return; } Akonadi::CollectionFetchJob *fetchJob = static_cast(job); Q_ASSERT(fetchJob->collections().size() == 1); const Akonadi::Collection col = fetchJob->collections().first(); //This is the only part that differs form the imap resource: We make sure the annotations are up-to date before synchronizing //HACK avoid infinite recursions, the metadatatask should be scheduled at most once per retrieveItemsJob static QSet updatedCollections; if (!updatedCollections.contains(col.id()) && (!col.attribute() || col.attribute()->timestamp() < QDateTime::currentDateTime().addSecs(-60).toTime_t())) { updatedCollections.insert(col.id()); scheduleCustomTask(this, "triggerCollectionExtraInfoJobs", QVariant::fromValue(col), Akonadi::ResourceBase::Prepend); deferTask(); return; } updatedCollections.remove(col.id()); setItemStreamingEnabled(true); RetrieveItemsTask *task = new RetrieveItemsTask( createResourceState(TaskArguments(col)), this); connect(task, SIGNAL(status(int,QString)), SIGNAL(status(int,QString))); connect(this, SIGNAL(retrieveNextItemSyncBatch(int)), task, SLOT(onReadyForNextBatch(int))); startTask(task); } void KolabResource::itemAdded(const Akonadi::Item& item, const Akonadi::Collection& collection) { bool ok = true; const Akonadi::Item imapItem = KolabHelpers::translateToImap(item, ok); if (!ok) { kWarning() << "Failed to convert item"; cancelTask(); return; } ImapResource::itemAdded(imapItem, collection); } void KolabResource::itemChanged(const Akonadi::Item& item, const QSet< QByteArray >& parts) { bool ok = true; const Akonadi::Item imapItem = KolabHelpers::translateToImap(item, ok); if (!ok) { kWarning() << "Failed to convert item"; cancelTask(); return; } ImapResource::itemChanged(imapItem, parts); } void KolabResource::itemsMoved(const Akonadi::Item::List& items, const Akonadi::Collection& source, const Akonadi::Collection& destination) { bool ok = true; const Akonadi::Item::List imapItems = KolabHelpers::translateToImap(items, ok); if (!ok) { kWarning() << "Failed to convert item"; cancelTask(); return; } ImapResource::itemsMoved(imapItems, source, destination); } static Akonadi::Collection updateAnnotations(const Akonadi::Collection &collection) { //Set the annotations on new folders const QByteArray kolabType = KolabHelpers::kolabTypeForMimeType(collection.contentMimeTypes()); if (!kolabType.isEmpty()) { Akonadi::Collection col = collection; Akonadi::CollectionAnnotationsAttribute *attr = col.attribute(Akonadi::Collection::AddIfMissing); QMap annotations = attr->annotations(); KolabHelpers::setFolderTypeAnnotation(annotations, kolabType); attr->setAnnotations(annotations); return col; } return collection; } void KolabResource::collectionAdded(const Akonadi::Collection& collection, const Akonadi::Collection& parent) { //Set the annotations on new folders const Akonadi::Collection col = updateAnnotations(collection); //TODO we need to save the collections as well if the annotations have changed //or we simply don't have the annotations locally, which perhaps is also not required? ImapResource::collectionAdded(col, parent); } void KolabResource::collectionChanged(const Akonadi::Collection& collection, const QSet< QByteArray >& parts) { //Update annotations if necessary const Akonadi::Collection col = updateAnnotations(collection); //TODO we need to save the collections as well if the annotations have changed emit status( AgentBase::Running, i18nc( "@info:status", "Updating folder '%1'", collection.name() ) ); ChangeCollectionTask *task = new ChangeCollectionTask( createResourceState(TaskArguments(collection, parts)), this ); task->syncEnabledState(true); startTask(task); } void KolabResource::tagAdded(const Akonadi::Tag &tag) { KolabAddTagTask *task = new KolabAddTagTask(createResourceState(TaskArguments(tag)), this); startTask(task); } void KolabResource::tagChanged(const Akonadi::Tag &tag) { KolabChangeTagTask *task = new KolabChangeTagTask(createResourceState(TaskArguments(tag)), QSharedPointer(new TagConverter), this); startTask(task); } void KolabResource::tagRemoved(const Akonadi::Tag &tag) { KolabRemoveTagTask *task = new KolabRemoveTagTask(createResourceState(TaskArguments(tag)), this); startTask(task); } void KolabResource::itemsTagsChanged(const Akonadi::Item::List &items, const QSet &addedTags, const QSet &removedTags) { KolabChangeItemsTagsTask *task = new KolabChangeItemsTagsTask(createResourceState(TaskArguments(items, addedTags, removedTags)), QSharedPointer(new TagConverter), this); startTask(task); } void KolabResource::retrieveTags() { KolabRetrieveTagTask *task = new KolabRetrieveTagTask(createResourceState(TaskArguments()), this); startTask(task); } AKONADI_RESOURCE_MAIN( KolabResource ) diff --git a/resources/kolab/kolabretrievecollectionstask.cpp b/resources/kolab/kolabretrievecollectionstask.cpp index f7415c1fa..44b417fc9 100644 --- a/resources/kolab/kolabretrievecollectionstask.cpp +++ b/resources/kolab/kolabretrievecollectionstask.cpp @@ -1,478 +1,492 @@ /* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens Copyright (c) 2014 Christian Mollekopf This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kolabretrievecollectionstask.h" #include "kolabhelpers.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include RetrieveMetadataJob::RetrieveMetadataJob(KIMAP::Session *session, const QStringList &mailboxes, const QStringList &serverCapabilities, const QSet &requestedMetadata, const QString &separator, QObject *parent) : KJob(parent) , mJobs(0) , mRequestedMetadata(requestedMetadata) , mServerCapabilities(serverCapabilities) , mMailboxes(mailboxes) , mSession(session) , mSeparator(separator) { } void RetrieveMetadataJob::start() { QSet toplevelMailboxes; Q_FOREACH (const QString &mailbox, mMailboxes) { const QStringList parts = mailbox.split(mSeparator); if (!parts.isEmpty()) { toplevelMailboxes << parts.first(); } } if ( mServerCapabilities.contains( QLatin1String("METADATA") ) || mServerCapabilities.contains( QLatin1String("ANNOTATEMORE") ) ) { //TODO perhaps exclude the shared and other users namespaces by listing only toplevel (with %), and then only getting metadata of the toplevel folders. Q_FOREACH (const QString &mailbox, toplevelMailboxes) { { KIMAP::GetMetaDataJob *meta = new KIMAP::GetMetaDataJob(mSession); meta->setMailBox(mailbox + QLatin1String("*")); if ( mServerCapabilities.contains( QLatin1String("METADATA") ) ) { meta->setServerCapability( KIMAP::MetaDataJobBase::Metadata ); } else { meta->setServerCapability( KIMAP::MetaDataJobBase::Annotatemore ); } meta->setDepth( KIMAP::GetMetaDataJob::AllLevels ); Q_FOREACH (const QByteArray &requestedEntry, mRequestedMetadata) { meta->addRequestedEntry(requestedEntry); } connect( meta, SIGNAL(result(KJob*)), SLOT(onGetMetaDataDone(KJob*)) ); mJobs++; meta->start(); } } } // Get the ACLs from the mailbox if it's supported if ( mServerCapabilities.contains( QLatin1String("ACL") ) ) { Q_FOREACH (const QString &mailbox, mMailboxes) { KIMAP::MyRightsJob *rights = new KIMAP::MyRightsJob( mSession ); rights->setMailBox(mailbox); connect( rights, SIGNAL(result(KJob*)), SLOT(onRightsReceived(KJob*)) ); mJobs++; rights->start(); } } checkDone(); } void RetrieveMetadataJob::onGetMetaDataDone( KJob *job ) { mJobs--; if ( job->error() ) { kWarning() << "Get metadata failed: " << job->errorString(); setError(KJob::UserDefinedError); checkDone(); return; } KIMAP::GetMetaDataJob *meta = qobject_cast( job ); const QHash > metadata = meta->allMetaDataForMailboxes(); Q_FOREACH (const QString &folder, metadata.keys()) { mMetadata.insert(folder, metadata.value(folder)); } checkDone(); } void RetrieveMetadataJob::onRightsReceived( KJob *job ) { mJobs--; if ( job->error() ) { kWarning() << "MyRights failed: " << job->errorString(); setError(KJob::UserDefinedError); checkDone(); return; // Well, no metadata for us then... } KIMAP::MyRightsJob *rightsJob = qobject_cast( job ); const KIMAP::Acl::Rights imapRights = rightsJob->rights(); mRights.insert(rightsJob->mailBox(), imapRights); checkDone(); } void RetrieveMetadataJob::checkDone() { if (!mJobs) { kDebug() << "done"; emitResult(); } } KolabRetrieveCollectionsTask::KolabRetrieveCollectionsTask(ResourceStateInterface::Ptr resource, QObject* parent) - : ResourceTask(CancelIfNoSession, resource, parent), - mJobs(0) + : ResourceTask(CancelIfNoSession, resource, parent) + , mJobs(0) + , cContentMimeTypes("CONTENTMIMETYPES") + , cAccessRights("AccessRights") + , cImapAcl("imapacl") + , cCollectionAnnotations("collectionannotations") + , cDefaultKeepLocalChanges(QSet() << cContentMimeTypes << cAccessRights << cImapAcl << cCollectionAnnotations) + , cDefaultMimeTypes(QStringList() << Akonadi::Collection::mimeType() << QLatin1String("application/x-kolab-objects")) + , cCollectionOnlyContentMimeTypes(QStringList() << Akonadi::Collection::mimeType()) { mRequestedMetadata << "/shared/vendor/kolab/folder-type"; mRequestedMetadata << "/private/vendor/kolab/folder-type"; } KolabRetrieveCollectionsTask::~KolabRetrieveCollectionsTask() { } void KolabRetrieveCollectionsTask::doStart(KIMAP::Session *session) { kDebug() << "Starting collection retrieval"; mTime.start(); mSession = session; Akonadi::Collection root; root.setName(resourceName()); root.setRemoteId(rootRemoteId()); root.setContentMimeTypes(QStringList(Akonadi::Collection::mimeType())); root.setParentCollection(Akonadi::Collection::root()); root.addAttribute(new NoSelectAttribute(true)); root.attribute(Akonadi::Collection::AddIfMissing)->setIconName(QLatin1String("kolab")); Akonadi::CachePolicy policy; policy.setInheritFromParent(false); policy.setSyncOnDemand(true); QStringList localParts; localParts << QLatin1String(Akonadi::MessagePart::Envelope) << QLatin1String(Akonadi::MessagePart::Header); int cacheTimeout = 60; if (isDisconnectedModeEnabled()) { // For disconnected mode we also cache the body // and we keep all data indifinitely localParts << QLatin1String(Akonadi::MessagePart::Body); cacheTimeout = -1; } policy.setLocalParts(localParts); policy.setCacheTimeout(cacheTimeout); policy.setIntervalCheckTime(intervalCheckTime()); root.setCachePolicy(policy); mMailCollections.insert(QString(), root); //jobs are serialized by the session if (isSubscriptionEnabled()) { KIMAP::ListJob *fullListJob = new KIMAP::ListJob(session); fullListJob->setOption(KIMAP::ListJob::NoOption); fullListJob->setQueriedNamespaces(serverNamespaces()); connect( fullListJob, SIGNAL(mailBoxesReceived(QList,QList >)), this, SLOT(onFullMailBoxesReceived(QList,QList >)) ); connect( fullListJob, SIGNAL(result(KJob*)), SLOT(onFullMailBoxesReceiveDone(KJob*))); mJobs++; fullListJob->start(); } KIMAP::ListJob *listJob = new KIMAP::ListJob(session); listJob->setOption(KIMAP::ListJob::IncludeUnsubscribed); listJob->setQueriedNamespaces(serverNamespaces()); connect(listJob, SIGNAL(mailBoxesReceived(QList,QList >)), this, SLOT(onMailBoxesReceived(QList,QList >))); connect(listJob, SIGNAL(result(KJob*)), SLOT(onMailBoxesReceiveDone(KJob*))); mJobs++; listJob->start(); } void KolabRetrieveCollectionsTask::onMailBoxesReceived(const QList< KIMAP::MailBoxDescriptor > &descriptors, const QList< QList > &flags) { for (int i=0; i &namespaces) const { Q_FOREACH (const KIMAP::MailBoxDescriptor &desc, namespaces) { if (path.startsWith(desc.name.left(desc.name.size() - 1))) { //Namespace ends with path separator and pathPart doesn't return true; } } return false; } void KolabRetrieveCollectionsTask::setAttributes(Akonadi::Collection &c, const QStringList &pathParts, const QString &path) { CollectionIdentificationAttribute *attr = c.attribute(Akonadi::Collection::AddIfMissing); attr->setIdentifier(path.toLatin1()); // If the folder is a other users top-level folder mark it accordingly if (pathParts.size() == 1 && isNamespaceFolder(path, resourceState()->userNamespaces())) { Akonadi::EntityDisplayAttribute *attr = c.attribute(Akonadi::Collection::AddIfMissing); attr->setDisplayName(i18n("Other Users")); attr->setIconName(QLatin1String("x-mail-distribution-list")); } //Mark user folders for searching if (pathParts.size() >= 2 && isNamespaceFolder(path, resourceState()->userNamespaces())) { CollectionIdentificationAttribute *attr = c.attribute(Akonadi::Collection::AddIfMissing); if (pathParts.size() == 2) { attr->setCollectionNamespace("usertoplevel"); } else { attr->setCollectionNamespace("user"); } } // If the folder is a shared folders top-level folder mark it accordingly if (pathParts.size() == 1 && isNamespaceFolder(path, resourceState()->sharedNamespaces())) { Akonadi::EntityDisplayAttribute *attr = c.attribute(Akonadi::Collection::AddIfMissing); attr->setDisplayName(i18n("Shared Folders")); attr->setIconName(QLatin1String("x-mail-distribution-list")); } //Mark shared folders for searching if (pathParts.size() >= 2 && isNamespaceFolder(path, resourceState()->sharedNamespaces())) { CollectionIdentificationAttribute *attr = c.attribute(Akonadi::Collection::AddIfMissing); attr->setCollectionNamespace("shared"); } } void KolabRetrieveCollectionsTask::createCollection(const QString &mailbox, const QList ¤tFlags, bool isSubscribed) { const QString separator = separatorCharacter(); Q_ASSERT(separator.size() == 1); const QString boxName = mailbox.endsWith( separator ) ? mailbox.left( mailbox.size()-1 ) : mailbox; const QStringList pathParts = boxName.split( separator ); const QString pathPart = pathParts.last(); Akonadi::Collection c; //If we had a dummy collection we need to replace it if (mMailCollections.contains(mailbox)) { c = mMailCollections.value(mailbox); } c.setName( pathPart ); c.setRemoteId( separator + pathPart ); const QStringList parentPath = pathParts.mid(0, pathParts.size() - 1); const Akonadi::Collection parentCollection = getOrCreateParent(parentPath.join(separator)); c.setParentCollection(parentCollection); - c.setContentMimeTypes(QStringList() << Akonadi::Collection::mimeType() << KMime::Message::mimeType()); + //TODO get from ResourceState, and add KMime::Message::mimeType() for the normal imap resource by default + //We add a dummy mimetype, otherwise the itemsync doesn't even work (action is disabled and resourcebase aborts the operation) + c.setContentMimeTypes(cDefaultMimeTypes); + c.setKeepLocalChanges(cDefaultKeepLocalChanges); //assume LRS, until myrights is executed if (serverCapabilities().contains(QLatin1String("ACL"))) { c.setRights(Akonadi::Collection::ReadOnly); } else { c.setRights(Akonadi::Collection::AllRights); } setAttributes(c, pathParts, mailbox); // If the folder is the Inbox, make some special settings. if (pathParts.size() == 1 && pathPart.compare(QLatin1String("inbox") , Qt::CaseInsensitive) == 0) { Akonadi::EntityDisplayAttribute *attr = c.attribute(Akonadi::Collection::AddIfMissing); attr->setDisplayName(i18n("Inbox")); attr->setIconName(QLatin1String("mail-folder-inbox")); setIdleCollection(c); } // If this folder is a noselect folder, make some special settings. if (currentFlags.contains("\\noselect")) { c.addAttribute(new NoSelectAttribute(true)); - c.setContentMimeTypes(QStringList() << Akonadi::Collection::mimeType()); + c.setContentMimeTypes(cCollectionOnlyContentMimeTypes); c.setRights( Akonadi::Collection::ReadOnly ); } else { // remove the noselect attribute explicitly, in case we had set it before (eg. for non-subscribed non-leaf folders) c.removeAttribute(); } // If this folder is a noinferiors folder, it is not allowed to create subfolders inside. if (currentFlags.contains("\\noinferiors")) { //kDebug() << "Noinferiors: " << currentPath; c.addAttribute(new NoInferiorsAttribute(true)); c.setRights(c.rights() & ~Akonadi::Collection::CanCreateCollection); } c.setEnabled(isSubscribed); // kDebug() << "creating collection " << mailbox << " with parent " << parentPath; mMailCollections.insert(mailbox, c); //This is no longer required mSubscribedMailboxes.remove(mailbox); } void KolabRetrieveCollectionsTask::onMailBoxesReceiveDone(KJob* job) { kDebug() << "All mailboxes received: " << mTime.elapsed(); kDebug() << "in total: " << mMailCollections.size(); mJobs--; if (job->error()) { cancelTask(job->errorString()); } else { - QStringList personalMailboxes; + QSet personalMailboxes; Q_FOREACH(const QString &mailbox, mMailCollections.keys()) { if (!isNamespaceFolder(mailbox, resourceState()->userNamespaces() + resourceState()->sharedNamespaces())) { if (mailbox.isEmpty()) { continue; } personalMailboxes << mailbox; } } + const QStringList metadataMailboxes = personalMailboxes.unite( mSubscribedMailboxes.toList().toSet()).toList(); - RetrieveMetadataJob *metadata = new RetrieveMetadataJob(mSession, personalMailboxes, serverCapabilities(), mRequestedMetadata, separatorCharacter(), this); + RetrieveMetadataJob *metadata = new RetrieveMetadataJob(mSession, metadataMailboxes, serverCapabilities(), mRequestedMetadata, separatorCharacter(), this); connect(metadata, SIGNAL(result(KJob*)), this, SLOT(onMetadataRetrieved(KJob*))); mJobs++; metadata->start(); } } void KolabRetrieveCollectionsTask::applyRights(QHash rights) { // kDebug() << rights; Q_FOREACH(const QString &mailbox, rights.keys()) { if (mMailCollections.contains(mailbox)) { const KIMAP::Acl::Rights imapRights = rights.value(mailbox); QStringList parts = mailbox.split(separatorCharacter()); parts.removeLast(); QString parentMailbox = parts.join(separatorCharacter()); if (!parentMailbox.isEmpty() &&!rights.contains(parentMailbox)) { kWarning() << "Couldn't find parent mailbox rights"; } const KIMAP::Acl::Rights parentImapRights = rights.value(parentMailbox); // kDebug() << mailbox << parentMailbox << imapRights << parentImapRights; Akonadi::Collection &collection = mMailCollections[mailbox]; CollectionMetadataHelper::applyRights(collection, imapRights, parentImapRights); // Store the mailbox ACLs Akonadi::ImapAclAttribute *aclAttribute = collection.attribute( Akonadi::Collection::AddIfMissing ); const KIMAP::Acl::Rights oldRights = aclAttribute->myRights(); if ( oldRights != imapRights ) { aclAttribute->setMyRights( imapRights ); } } else { kWarning() << "Can't find mailbox " << mailbox; } } } void KolabRetrieveCollectionsTask::applyMetadata(QHash > metadataMap) { // kDebug() << metadataMap; Q_FOREACH(const QString &mailbox, metadataMap.keys()) { const QMap metadata = metadataMap.value(mailbox); if (mMailCollections.contains(mailbox)) { Akonadi::Collection &collection = mMailCollections[mailbox]; // kDebug() << "setting metadata: " << mailbox << metadata; collection.attribute(Akonadi::Collection::AddIfMissing)->setAnnotations(metadata); const QByteArray type = KolabHelpers::getFolderTypeAnnotation(metadata); const Kolab::FolderType folderType = KolabHelpers::folderTypeFromString(type); collection.setContentMimeTypes(KolabHelpers::getContentMimeTypes(folderType)); + QSet keepLocalChanges = collection.keepLocalChanges(); + keepLocalChanges.remove(cContentMimeTypes); + collection.setKeepLocalChanges(keepLocalChanges); } } } void KolabRetrieveCollectionsTask::onMetadataRetrieved(KJob *job) { kDebug() << mTime.elapsed(); mJobs--; if (job->error()) { kWarning() << job->errorString(); cancelTask(job->errorString()); } else { RetrieveMetadataJob *metadata = static_cast(job); applyRights(metadata->mRights); applyMetadata(metadata->mMetadata); checkDone(); } } void KolabRetrieveCollectionsTask::checkDone() { if (!mJobs) { collectionsRetrieved(mMailCollections.values()); kDebug() << "done " << mTime.elapsed(); } } void KolabRetrieveCollectionsTask::onFullMailBoxesReceived(const QList< KIMAP::MailBoxDescriptor >& descriptors, const QList< QList< QByteArray > >& flags) { Q_UNUSED(flags); foreach (const KIMAP::MailBoxDescriptor &descriptor, descriptors) { mSubscribedMailboxes.insert(descriptor.name); } } void KolabRetrieveCollectionsTask::onFullMailBoxesReceiveDone(KJob* job) { kDebug() << "received subscribed collections " << mTime.elapsed(); mJobs--; if (job->error()) { cancelTask(job->errorString()); } else { checkDone(); } } diff --git a/resources/kolab/kolabretrievecollectionstask.h b/resources/kolab/kolabretrievecollectionstask.h index 53f11db35..b3d9c0e01 100644 --- a/resources/kolab/kolabretrievecollectionstask.h +++ b/resources/kolab/kolabretrievecollectionstask.h @@ -1,92 +1,100 @@ /* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens Copyright (c) 2014 Christian Mollekopf This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KOLABRETRIEVECOLLECTIONSTASK_H #define KOLABRETRIEVECOLLECTIONSTASK_H #include #include #include class KolabRetrieveCollectionsTask : public ResourceTask { Q_OBJECT public: explicit KolabRetrieveCollectionsTask(ResourceStateInterface::Ptr resource, QObject *parent = 0); virtual ~KolabRetrieveCollectionsTask(); private slots: void onMailBoxesReceived(const QList &descriptors, const QList< QList > &flags); void onMailBoxesReceiveDone(KJob *job); void onFullMailBoxesReceived(const QList &descriptors, const QList > &flags); void onFullMailBoxesReceiveDone(KJob *job); void onMetadataRetrieved(KJob *job); protected: virtual void doStart(KIMAP::Session *session); private: void checkDone(); Akonadi::Collection getOrCreateParent(const QString &parentPath); void createCollection(const QString &mailbox, const QList &flags, bool isSubscribed); bool isNamespaceFolder(const QString &path, const QList &namespaces) const; void setAttributes(Akonadi::Collection &c, const QStringList &pathParts, const QString &path); void applyRights(QHash rights); void applyMetadata(QHash > metadata); int mJobs; QHash mMailCollections; QSet mSubscribedMailboxes; QSet mRequestedMetadata; KIMAP::Session *mSession; QTime mTime; + //For implicit sharing + const QByteArray cContentMimeTypes; + const QByteArray cAccessRights; + const QByteArray cImapAcl; + const QByteArray cCollectionAnnotations; + const QSet cDefaultKeepLocalChanges; + const QStringList cDefaultMimeTypes; + const QStringList cCollectionOnlyContentMimeTypes; }; class RetrieveMetadataJob : public KJob { Q_OBJECT public: RetrieveMetadataJob(KIMAP::Session *session, const QStringList &mailboxes, const QStringList &serverCapabilities, const QSet &requestedMetadata, const QString &separator, QObject *parent = 0); void start(); QHash > mMetadata; QHash mRights; private: void checkDone(); int mJobs; QSet mRequestedMetadata; QStringList mServerCapabilities; QStringList mMailboxes; KIMAP::Session *mSession; QString mSeparator; private Q_SLOTS: void onGetMetaDataDone(KJob *job); void onRightsReceived(KJob *job); }; #endif