• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kmail

kmacctcachedimap.cpp

Go to the documentation of this file.
00001 
00032 #include "kmacctcachedimap.h"
00033 using KMail::SieveConfig;
00034 
00035 #include "kmfoldertree.h"
00036 #include "kmfoldermgr.h"
00037 #include "kmfiltermgr.h"
00038 #include "kmfoldercachedimap.h"
00039 #include "kmmainwin.h"
00040 #include "accountmanager.h"
00041 using KMail::AccountManager;
00042 #include "progressmanager.h"
00043 
00044 #include <kio/passworddialog.h>
00045 #include <kio/scheduler.h>
00046 #include <kio/slave.h>
00047 #include <kdebug.h>
00048 #include <kstandarddirs.h>
00049 #include <kconfiggroup.h>
00050 
00051 #include <QList>
00052 
00053 KMAcctCachedImap::KMAcctCachedImap( AccountManager* aOwner,
00054                     const QString& aAccountName, uint id )
00055   : KMail::ImapAccountBase( aOwner, aAccountName, id ), mFolder( 0 ),
00056     mAnnotationCheckPassed(false),
00057     mGroupwareType( GroupwareKolab ),
00058     mSentCustomLoginCommand(false)
00059 {
00060   // Never EVER set this for the cached IMAP account
00061   mAutoExpunge = false;
00062 }
00063 
00064 
00065 //-----------------------------------------------------------------------------
00066 KMAcctCachedImap::~KMAcctCachedImap()
00067 {
00068   killAllJobsInternal( true );
00069 }
00070 
00071 
00072 //-----------------------------------------------------------------------------
00073 void KMAcctCachedImap::init() {
00074   ImapAccountBase::init();
00075 }
00076 
00077 //-----------------------------------------------------------------------------
00078 void KMAcctCachedImap::pseudoAssign( const KMAccount * a ) {
00079   killAllJobs( true );
00080   if (mFolder)
00081   {
00082     mFolder->setContentState(KMFolderCachedImap::imapNoInformation);
00083     mFolder->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00084   }
00085   ImapAccountBase::pseudoAssign( a );
00086 }
00087 
00088 //-----------------------------------------------------------------------------
00089 void KMAcctCachedImap::setImapFolder(KMFolderCachedImap *aFolder)
00090 {
00091   mFolder = aFolder;
00092   mFolder->setImapPath( "/" );
00093   mFolder->setAccount( this );
00094 }
00095 
00096 
00097 //-----------------------------------------------------------------------------
00098 void KMAcctCachedImap::setAutoExpunge( bool /*aAutoExpunge*/ )
00099 {
00100   // Never EVER set this for the cached IMAP account
00101   mAutoExpunge = false;
00102 }
00103 
00104 //-----------------------------------------------------------------------------
00105 void KMAcctCachedImap::killAllJobs( bool disconnectSlave )
00106 {
00107   //kDebug(5006) <<"killAllJobs: disconnectSlave=" << disconnectSlave << mapJobData.count() <<" jobs in map.";
00108   QList<KMFolderCachedImap*> folderList = killAllJobsInternal( disconnectSlave );
00109   for( QList<KMFolderCachedImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00110     KMFolderCachedImap *fld = *it;
00111     fld->resetSyncState();
00112     fld->setContentState(KMFolderCachedImap::imapNoInformation);
00113     fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00114     fld->sendFolderComplete(false);
00115   }
00116 }
00117 
00118 //-----------------------------------------------------------------------------
00119 // Common between killAllJobs and the destructor - which shouldn't call sendFolderComplete
00120 QList<KMFolderCachedImap*> KMAcctCachedImap::killAllJobsInternal( bool disconnectSlave )
00121 {
00122   // Make list of folders to reset. This must be done last, since folderComplete
00123   // can trigger the next queued mail check already.
00124   QList<KMFolderCachedImap*> folderList;
00125   QMap<KJob*, jobData>::Iterator it = mapJobData.begin();
00126   for (; it != mapJobData.end(); ++it) {
00127     if ((*it).parent)
00128       folderList << static_cast<KMFolderCachedImap*>((*it).parent->storage());
00129     // Kill the job - except if it's the one that already died and is calling us
00130     if ( mSlave && !it.key()->error() ) {
00131       it.key()->kill();
00132       mSlave = 0; // killing a job, kills the slave
00133     }
00134   }
00135   mapJobData.clear();
00136 
00137   // Clear the joblist. Make SURE to stop the job emitting "finished"
00138   QList<CachedImapJob*>::const_iterator jt;
00139   for( jt = mJobList.constBegin(); jt != mJobList.constEnd(); ++jt )
00140     (*jt)->setPassiveDestructor( true );
00141   KMAccount::deleteFolderJobs();
00142 
00143   if ( disconnectSlave && mSlave ) {
00144     KIO::Scheduler::disconnectSlave( mSlave );
00145     mSlave = 0;
00146   }
00147   return folderList;
00148 }
00149 
00150 //-----------------------------------------------------------------------------
00151 void KMAcctCachedImap::cancelMailCheck()
00152 {
00153   // Make list of folders to reset, like in killAllJobs
00154   QList<KMFolderCachedImap*> folderList;
00155   QMap<KJob*, jobData>::Iterator it = mapJobData.begin();
00156   for (; it != mapJobData.end(); ++it) {
00157     if ( (*it).cancellable && (*it).parent )
00158       folderList << static_cast<KMFolderCachedImap*>((*it).parent->storage());
00159   }
00160   // Kill jobs
00161   ImapAccountBase::cancelMailCheck();
00162   // Reset sync states and emit folderComplete, this is important for
00163   // KMAccount::checkingMail() to be reset, in case we restart checking mail later.
00164   for( QList<KMFolderCachedImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00165     KMFolderCachedImap *fld = *it;
00166     fld->resetSyncState();
00167     fld->setContentState(KMFolderCachedImap::imapNoInformation);
00168     fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00169     fld->sendFolderComplete(false);
00170   }
00171 }
00172 
00173 //-----------------------------------------------------------------------------
00174 void KMAcctCachedImap::killJobsForItem(KMFolderTreeItem * fti)
00175 {
00176   QMap<KJob *, jobData>::Iterator it = mapJobData.begin();
00177   while (it != mapJobData.end())
00178   {
00179     if (it.value().parent == fti->folder())
00180     {
00181       killAllJobs();
00182       break;
00183     }
00184     else ++it;
00185   }
00186 }
00187 
00188 // Reimplemented from ImapAccountBase because we only check one folder at a time
00189 void KMAcctCachedImap::slotCheckQueuedFolders()
00190 {
00191     mMailCheckFolders.clear();
00192     mMailCheckFolders.append( mFoldersQueuedForChecking.front() );
00193     mFoldersQueuedForChecking.pop_front();
00194     if ( mFoldersQueuedForChecking.isEmpty() )
00195       disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00196                   this, SLOT( slotCheckQueuedFolders() ) );
00197 
00198     kmkernel->acctMgr()->singleCheckMail(this, true);
00199     mMailCheckFolders.clear();
00200 }
00201 
00202 void KMAcctCachedImap::processNewMail( bool /*interactive*/ )
00203 {
00204   assert( mFolder );
00205 
00206   if ( mMailCheckFolders.isEmpty() )
00207     processNewMail( mFolder, true );
00208   else {
00209     KMFolder* f = mMailCheckFolders.front();
00210     mMailCheckFolders.pop_front();
00211     processNewMail( static_cast<KMFolderCachedImap *>( f->storage() ), false );
00212   }
00213 }
00214 
00215 void KMAcctCachedImap::processNewMail( KMFolderCachedImap* folder,
00216                                        bool recurse )
00217 {
00218   assert( folder );
00219   // This should never be set for a cached IMAP account
00220   mAutoExpunge = false;
00221   mCountLastUnread = 0;
00222   mUnreadBeforeCheck.clear();
00223   // stop sending noops during sync, that will keep the connection open
00224   mNoopTimer.stop();
00225 
00226   // reset namespace todo
00227   if ( folder == mFolder ) {
00228     QStringList nsToList = namespaces()[PersonalNS];
00229     QStringList otherNSToCheck = namespaces()[OtherUsersNS];
00230     otherNSToCheck += namespaces()[SharedNS];
00231     for ( QStringList::Iterator it = otherNSToCheck.begin();
00232           it != otherNSToCheck.end(); ++it ) {
00233       if ( (*it).isEmpty() ) {
00234         // empty namespaces are included in the "normal" listing
00235         // as the folders are created under the root folder
00236         nsToList += *it;
00237       }
00238     }
00239     folder->setNamespacesToList( nsToList );
00240   }
00241 
00242   Q_ASSERT( !mMailCheckProgressItem );
00243   mMailCheckProgressItem = KPIM::ProgressManager::createProgressItem(
00244     "MailCheck" + QString::number( id() ),
00245     folder->label(), // will be changed immediately in serverSync anyway
00246     QString(),
00247     true, // can be canceled
00248     useSSL() || useTLS() );
00249   connect( mMailCheckProgressItem, SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
00250            this, SLOT( slotProgressItemCanceled( KPIM::ProgressItem* ) ) );
00251 
00252   folder->setAccount(this);
00253   connect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
00254           this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
00255   folder->serverSync( recurse );
00256 }
00257 
00258 void KMAcctCachedImap::postProcessNewMail( KMFolderCachedImap* folder, bool )
00259 {
00260   mNoopTimer.start( 60000 ); // send a noop every minute to avoid "connection broken" errors
00261   disconnect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
00262              this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
00263   mMailCheckProgressItem->setComplete();
00264   mMailCheckProgressItem = 0;
00265 
00266   if ( folder == mFolder ) {
00267     // We remove everything from the deleted folders list after a full sync.
00268     // Even if it fails (no permission), because on the next sync we want the folder to reappear,
00269     //  instead of the user being stuck with "can't delete" every time.
00270     // And we do it for _all_ deleted folders, even those that were deleted on the server in the first place (slotListResult).
00271     //  Otherwise this might have side effects much later (e.g. when regaining permissions to a folder we could see before)
00272 
00273 #if 0 // this opens a race: delete a folder during a sync (after the sync checked that folder), and it'll be forgotten...
00274     mDeletedFolders.clear();
00275 #endif
00276     mPreviouslyDeletedFolders.clear();
00277   }
00278 
00279   KMail::ImapAccountBase::postProcessNewMail();
00280 }
00281 
00282 void KMAcctCachedImap::addUnreadMsgCount( const KMFolderCachedImap *folder,
00283                                           int countUnread )
00284 {
00285   if ( folder->imapPath() != "/INBOX/" ) {
00286     // new mail in INBOX is processed with KMAccount::processNewMsg() and
00287     // therefore doesn't need to be counted here
00288     const QString folderId = folder->folder()->idString();
00289     int newInFolder = countUnread;
00290     if ( mUnreadBeforeCheck.contains( folderId )  )
00291       newInFolder -= mUnreadBeforeCheck[folderId];
00292     if ( newInFolder > 0 )
00293       addToNewInFolder( folderId, newInFolder );
00294   }
00295   mCountUnread += countUnread;
00296 }
00297 
00298 void KMAcctCachedImap::addLastUnreadMsgCount( const KMFolderCachedImap *folder,
00299                                               int countLastUnread )
00300 {
00301   mUnreadBeforeCheck[folder->folder()->idString()] = countLastUnread;
00302   mCountLastUnread += countLastUnread;
00303 }
00304 
00305 //
00306 //
00307 // read/write config
00308 //
00309 //
00310 
00311 void KMAcctCachedImap::readConfig( KConfigGroup & config ) {
00312   ImapAccountBase::readConfig( config );
00313   // Apparently this method is only ever called once (from KMKernel::init) so this is ok
00314   mPreviouslyDeletedFolders = config.readEntry( "deleted-folders", QStringList() );
00315   mDeletedFolders.clear(); // but just in case...
00316   const QStringList oldPaths = config.readEntry( "renamed-folders-paths", QStringList() );
00317   const QStringList newNames = config.readEntry( "renamed-folders-names", QStringList() );
00318   QStringList::const_iterator it = oldPaths.begin();
00319   QStringList::const_iterator nameit = newNames.begin();
00320   for( ; it != oldPaths.end() && nameit != newNames.end(); ++it, ++nameit ) {
00321     addRenamedFolder( *it, QString(), *nameit );
00322   }
00323   mGroupwareType = (GroupwareType)config.readEntry( "groupwareType", (int)GroupwareKolab );
00324 }
00325 
00326 void KMAcctCachedImap::writeConfig( KConfigGroup & config ) {
00327   ImapAccountBase::writeConfig( config );
00328   config.writeEntry( "deleted-folders", mDeletedFolders + mPreviouslyDeletedFolders );
00329   config.writeEntry( "renamed-folders-paths", mRenamedFolders.keys() );
00330   const QList<RenamedFolder> values = mRenamedFolders.values();
00331   QStringList lstNames;
00332   QList<RenamedFolder>::const_iterator it = values.begin();
00333   for ( ; it != values.end() ; ++it )
00334     lstNames.append( (*it).mNewName );
00335   config.writeEntry( "renamed-folders-names", lstNames );
00336   config.writeEntry( "groupwareType", (int)mGroupwareType );
00337 }
00338 
00339 void KMAcctCachedImap::invalidateIMAPFolders()
00340 {
00341   invalidateIMAPFolders( mFolder );
00342 }
00343 
00344 void KMAcctCachedImap::invalidateIMAPFolders( KMFolderCachedImap* folder )
00345 {
00346   if( !folder || !folder->folder() )
00347     return;
00348 
00349   folder->setAccount(this);
00350 
00351   QStringList strList;
00352   QList<QPointer<KMFolder> > folderList;
00353   kmkernel->dimapFolderMgr()->createFolderList( &strList, &folderList,
00354                         folder->folder()->child(), QString(),
00355                         false );
00356   QList<QPointer<KMFolder> >::Iterator it;
00357   mCountLastUnread = 0;
00358   mUnreadBeforeCheck.clear();
00359 
00360   for( it = folderList.begin(); it != folderList.end(); ++it ) {
00361     KMFolder *f = *it;
00362     if( f && f->folderType() == KMFolderTypeCachedImap ) {
00363       KMFolderCachedImap *cfolder = static_cast<KMFolderCachedImap*>(f->storage());
00364       // This invalidates the folder completely
00365       cfolder->setUidValidity("INVALID");
00366       cfolder->writeUidCache();
00367       processNewMailSingleFolder( f );
00368     }
00369   }
00370   folder->setUidValidity("INVALID");
00371   folder->writeUidCache();
00372 
00373   processNewMailSingleFolder( folder->folder() );
00374 }
00375 
00376 //-----------------------------------------------------------------------------
00377 void KMAcctCachedImap::addDeletedFolder( KMFolder* folder )
00378 {
00379   if ( !folder || folder->folderType() != KMFolderTypeCachedImap )
00380     return;
00381   KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>(folder->storage());
00382   addDeletedFolder( storage->imapPath() );
00383   kDebug(5006) << storage->imapPath();
00384 
00385   // Add all child folders too
00386   if( folder->child() ) {
00387     QList<KMFolderNode*>::const_iterator it;
00388     for ( it = folder->child()->constBegin();
00389         it != folder->child()->constEnd();
00390         ++it ) {
00391       KMFolderNode *node = (*it);
00392       if( node && !node->isDir() ) {
00393         addDeletedFolder( static_cast<KMFolder*>( node ) ); // recurse
00394       }
00395     }
00396   }
00397 }
00398 
00399 void KMAcctCachedImap::addDeletedFolder( const QString& imapPath )
00400 {
00401   mDeletedFolders << imapPath;
00402 }
00403 
00404 QStringList KMAcctCachedImap::deletedFolderPaths( const QString& subFolderPath ) const
00405 {
00406   QStringList lst;
00407   for ( QStringList::const_iterator it = mDeletedFolders.begin(); it != mDeletedFolders.end(); ++it ) {
00408     if ( (*it).startsWith( subFolderPath ) )
00409       // We must reverse the order, so that sub sub sub folders are deleted first
00410       lst.prepend( *it );
00411   }
00412   for ( QStringList::const_iterator it = mPreviouslyDeletedFolders.begin(); it != mPreviouslyDeletedFolders.end(); ++it ) {
00413     if ( (*it).startsWith( subFolderPath ) )
00414       lst.prepend( *it );
00415   }
00416   kDebug(5006) << "For" << subFolderPath <<" returning:" << lst;
00417   Q_ASSERT( !lst.isEmpty() );
00418   return lst;
00419 }
00420 
00421 bool KMAcctCachedImap::isDeletedFolder( const QString& subFolderPath ) const
00422 {
00423   return mDeletedFolders.contains( subFolderPath ) ;
00424 }
00425 
00426 bool KMAcctCachedImap::isPreviouslyDeletedFolder( const QString& subFolderPath ) const
00427 {
00428   return mPreviouslyDeletedFolders.contains( subFolderPath ) ;
00429 }
00430 
00431 void KMAcctCachedImap::removeDeletedFolder( const QString& subFolderPath )
00432 {
00433   mDeletedFolders.removeAll( subFolderPath );
00434   mPreviouslyDeletedFolders.removeAll( subFolderPath );
00435 }
00436 
00437 void KMAcctCachedImap::addRenamedFolder( const QString& subFolderPath, const QString& oldLabel, const QString& newName )
00438 {
00439   mRenamedFolders.insert( subFolderPath, RenamedFolder( oldLabel, newName ) );
00440 }
00441 
00442 void KMAcctCachedImap::removeRenamedFolder( const QString& subFolderPath )
00443 {
00444   mRenamedFolders.remove( subFolderPath );
00445 }
00446 
00447 void KMAcctCachedImap::slotProgressItemCanceled( ProgressItem* )
00448 {
00449   bool abortConnection = !mSlaveConnected;
00450   killAllJobs( abortConnection );
00451   if ( abortConnection ) {
00452     // If we were trying to connect, tell kmfoldercachedimap so that it moves on
00453     emit connectionResult( KIO::ERR_USER_CANCELED, QString() );
00454   }
00455 }
00456 
00457 FolderStorage* KMAcctCachedImap::rootFolder() const
00458 {
00459   return mFolder;
00460 }
00461 
00462 
00463 QString KMAcctCachedImap::renamedFolder( const QString& imapPath ) const
00464 {
00465   QMap<QString, RenamedFolder>::ConstIterator renit = mRenamedFolders.find( imapPath );
00466   if ( renit != mRenamedFolders.end() )
00467     return (*renit).mNewName;
00468   return QString();
00469 }
00470 
00471 #include "kmacctcachedimap.moc"

kmail

Skip menu "kmail"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal