kmail Library API Documentation

kmacctcachedimap.cpp

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