/* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens 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 "retrievecollectionstask.h" #include "noselectattribute.h" #include "noinferiorsattribute.h" #include #include #include #include #include #include RetrieveCollectionsTask::RetrieveCollectionsTask( ResourceStateInterface::Ptr resource, QObject *parent ) : ResourceTask( CancelIfNoSession, resource, parent ) { } RetrieveCollectionsTask::~RetrieveCollectionsTask() { } void RetrieveCollectionsTask::doStart( KIMAP::Session *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 ) ); 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 ); m_reportedCollections.insert( QString(), root ); // this is ugly, but the result of LSUB is unfortunately not a sub-set of LIST // it also contains subscribed but currently not available (eg. deleted) mailboxes // so we need to use both and exclude mailboxes in LSUB but not in LIST if ( isSubscriptionEnabled() ) { KIMAP::ListJob *fullListJob = new KIMAP::ListJob( session ); fullListJob->setIncludeUnsubscribed( true ); fullListJob->setQueriedNamespaces( serverNamespaces() ); connect( fullListJob, SIGNAL(mailBoxesReceived(QList,QList >)), this, SLOT(onFullMailBoxesReceived(QList,QList >)) ); connect( fullListJob, SIGNAL(result(KJob*)), SLOT(onFullMailBoxesReceiveDone(KJob*)) ); fullListJob->start(); } KIMAP::ListJob *listJob = new KIMAP::ListJob( session ); listJob->setIncludeUnsubscribed( !isSubscriptionEnabled() ); listJob->setQueriedNamespaces( serverNamespaces() ); connect( listJob, SIGNAL(mailBoxesReceived(QList,QList >)), this, SLOT(onMailBoxesReceived(QList,QList >)) ); connect( listJob, SIGNAL(result(KJob*)), SLOT(onMailBoxesReceiveDone(KJob*)) ); listJob->start(); } void RetrieveCollectionsTask::onMailBoxesReceived( const QList< KIMAP::MailBoxDescriptor > &descriptors, const QList< QList > &flags ) { QStringList contentTypes; contentTypes << KMime::Message::mimeType() << Akonadi::Collection::mimeType(); if ( !descriptors.isEmpty() ) { // This is still not optimal way of getting the separator, but it's better // than guessing every time from RID of parent collection setSeparatorCharacter( descriptors.first().separator ); } for ( int i=0; i(); m_dummyCollections.remove( currentPath ); m_reportedCollections.remove( currentPath ); m_reportedCollections.insert( currentPath, c ); } parentPath = currentPath; continue; } const QList currentFlags = isDummy ? ( QList() << "\\noselect" ) : flags[i]; Akonadi::Collection c; c.setName( pathPart ); c.setRemoteId( separator + pathPart ); const Akonadi::Collection parentCollection = m_reportedCollections.value( parentPath ); c.setParentCollection( parentCollection ); c.setContentMimeTypes( contentTypes ); // If the folder is the Inbox, make some special settings. if ( currentPath.compare( separator + 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 the folder is the user top-level folder, mark it as well, even although it is not officially noted in the RFC if ( currentPath == ( separator + QLatin1String( "user" ) ) && currentFlags.contains( "\\noselect" ) ) { Akonadi::EntityDisplayAttribute *attr = c.attribute( Akonadi::Collection::AddIfMissing ); attr->setDisplayName( i18n( "Shared Folders" ) ); attr->setIconName( QLatin1String("x-mail-distribution-list") ); } // If this folder is a noselect folder, make some special settings. if ( currentFlags.contains( "\\noselect" ) ) { kDebug() << "Dummy collection created: " << currentPath; c.addAttribute( new NoSelectAttribute( true ) ); c.setContentMimeTypes( QStringList() << Akonadi::Collection::mimeType() ); 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 ); } m_reportedCollections.insert( currentPath, c ); if ( isDummy ) { m_dummyCollections.insert( currentPath, c ); } parentPath = currentPath; } } } void RetrieveCollectionsTask::onMailBoxesReceiveDone( KJob* job ) { if ( job->error() ) { cancelTask( job->errorString() ); } else { collectionsRetrieved( m_reportedCollections.values() ); } } void RetrieveCollectionsTask::onFullMailBoxesReceived( const QList< KIMAP::MailBoxDescriptor >& descriptors, const QList< QList< QByteArray > >& flags ) { Q_UNUSED( flags ); foreach ( const KIMAP::MailBoxDescriptor &descriptor, descriptors ) { m_fullReportedCollections.insert( descriptor.name ); } } void RetrieveCollectionsTask::onFullMailBoxesReceiveDone(KJob* job) { if ( job->error() ) { cancelTask( job->errorString() ); } }