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 "accountmanager.h"
00045 using KMail::AccountManager;
00046 #include "progressmanager.h"
00047
00048 #include <kio/passdlg.h>
00049 #include <kio/scheduler.h>
00050 #include <kio/slave.h>
00051 #include <kmessagebox.h>
00052 #include <kdebug.h>
00053 #include <kstandarddirs.h>
00054 #include <kapplication.h>
00055 #include <kconfig.h>
00056
00057 #include <qstylesheet.h>
00058
00059 KMAcctCachedImap::KMAcctCachedImap( AccountManager* aOwner,
00060 const QString& aAccountName, uint id )
00061 : KMail::ImapAccountBase( aOwner, aAccountName, id ), mFolder( 0 ),
00062 mAnnotationCheckPassed(false)
00063 {
00064
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
00086
00087 void KMAcctCachedImap::pseudoAssign( const KMAccount * a ) {
00088 killAllJobs( true );
00089 if (mFolder)
00090 {
00091 mFolder->setContentState(KMFolderCachedImap::imapNoInformation);
00092 mFolder->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00093 }
00094 ImapAccountBase::pseudoAssign( a );
00095 }
00096
00097
00098 void KMAcctCachedImap::setImapFolder(KMFolderCachedImap *aFolder)
00099 {
00100 mFolder = aFolder;
00101 mFolder->setImapPath( "/" );
00102 mFolder->setAccount( this );
00103 }
00104
00105
00106
00107 void KMAcctCachedImap::setAutoExpunge( bool )
00108 {
00109
00110 mAutoExpunge = false;
00111 }
00112
00113
00114 void KMAcctCachedImap::killAllJobs( bool disconnectSlave )
00115 {
00116
00117 QValueList<KMFolderCachedImap*> folderList = killAllJobsInternal( disconnectSlave );
00118 for( QValueList<KMFolderCachedImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00119 KMFolderCachedImap *fld = *it;
00120 fld->resetSyncState();
00121 fld->setContentState(KMFolderCachedImap::imapNoInformation);
00122 fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00123 fld->sendFolderComplete(FALSE);
00124 }
00125 }
00126
00127
00128
00129 QValueList<KMFolderCachedImap*> KMAcctCachedImap::killAllJobsInternal( bool disconnectSlave )
00130 {
00131
00132
00133 QValueList<KMFolderCachedImap*> folderList;
00134 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00135 for (; it != mapJobData.end(); ++it) {
00136 if ((*it).parent)
00137 folderList << static_cast<KMFolderCachedImap*>((*it).parent->storage());
00138
00139 if ( !it.key()->error() && mSlave ) {
00140 it.key()->kill();
00141 mSlave = 0;
00142 }
00143 }
00144 mapJobData.clear();
00145
00146
00147 for( QPtrListIterator<CachedImapJob> it( mJobList ); it.current(); ++it )
00148 it.current()->setPassiveDestructor( true );
00149 KMAccount::deleteFolderJobs();
00150
00151 if ( disconnectSlave && mSlave ) {
00152 KIO::Scheduler::disconnectSlave( mSlave );
00153 mSlave = 0;
00154 }
00155 return folderList;
00156 }
00157
00158
00159 void KMAcctCachedImap::cancelMailCheck()
00160 {
00161
00162 QValueList<KMFolderCachedImap*> folderList;
00163 QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00164 for (; it != mapJobData.end(); ++it) {
00165 if ( (*it).cancellable && (*it).parent )
00166 folderList << static_cast<KMFolderCachedImap*>((*it).parent->storage());
00167 }
00168
00169 ImapAccountBase::cancelMailCheck();
00170
00171
00172 for( QValueList<KMFolderCachedImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00173 KMFolderCachedImap *fld = *it;
00174 fld->resetSyncState();
00175 fld->setContentState(KMFolderCachedImap::imapNoInformation);
00176 fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
00177 fld->sendFolderComplete(FALSE);
00178 }
00179 }
00180
00181
00182 void KMAcctCachedImap::killJobsForItem(KMFolderTreeItem * fti)
00183 {
00184 QMap<KIO::Job *, jobData>::Iterator it = mapJobData.begin();
00185 while (it != mapJobData.end())
00186 {
00187 if (it.data().parent == fti->folder())
00188 {
00189 killAllJobs();
00190 break;
00191 }
00192 else ++it;
00193 }
00194 }
00195
00196
00197 void KMAcctCachedImap::slotCheckQueuedFolders()
00198 {
00199 mMailCheckFolders.clear();
00200 mMailCheckFolders.append( mFoldersQueuedForChecking.front() );
00201 mFoldersQueuedForChecking.pop_front();
00202 if ( mFoldersQueuedForChecking.isEmpty() )
00203 disconnect( this, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00204 this, SLOT( slotCheckQueuedFolders() ) );
00205
00206 kmkernel->acctMgr()->singleCheckMail(this, true);
00207 mMailCheckFolders.clear();
00208 }
00209
00210 void KMAcctCachedImap::processNewMail( bool )
00211 {
00212 assert( mFolder );
00213
00214 if ( mMailCheckFolders.isEmpty() )
00215 processNewMail( mFolder, true );
00216 else {
00217 KMFolder* f = mMailCheckFolders.front();
00218 mMailCheckFolders.pop_front();
00219 processNewMail( static_cast<KMFolderCachedImap *>( f->storage() ), false );
00220 }
00221 }
00222
00223 void KMAcctCachedImap::processNewMail( KMFolderCachedImap* folder,
00224 bool recurse )
00225 {
00226 assert( folder );
00227
00228
00229 mAutoExpunge = false;
00230 mCountLastUnread = 0;
00231 mUnreadBeforeCheck.clear();
00232
00233 mNoopTimer.stop();
00234
00235
00236 if ( folder == mFolder ) {
00237 QStringList nsToList = namespaces()[PersonalNS];
00238 QStringList otherNSToCheck = namespaces()[OtherUsersNS];
00239 otherNSToCheck += namespaces()[SharedNS];
00240 for ( QStringList::Iterator it = otherNSToCheck.begin();
00241 it != otherNSToCheck.end(); ++it ) {
00242 if ( (*it).isEmpty() ) {
00243
00244
00245 nsToList += *it;
00246 }
00247 }
00248 folder->setNamespacesToList( nsToList );
00249 }
00250
00251 Q_ASSERT( !mMailCheckProgressItem );
00252 mMailCheckProgressItem = KPIM::ProgressManager::createProgressItem(
00253 "MailCheck" + QString::number( id() ),
00254 QStyleSheet::escape( folder->label() ),
00255 QString::null,
00256 true,
00257 useSSL() || useTLS() );
00258 connect( mMailCheckProgressItem, SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
00259 this, SLOT( slotProgressItemCanceled( KPIM::ProgressItem* ) ) );
00260
00261 folder->setAccount(this);
00262 connect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
00263 this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
00264 folder->serverSync( recurse );
00265 }
00266
00267 void KMAcctCachedImap::postProcessNewMail( KMFolderCachedImap* folder, bool )
00268 {
00269 mNoopTimer.start( 60000 );
00270 disconnect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
00271 this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
00272 mMailCheckProgressItem->setComplete();
00273 mMailCheckProgressItem = 0;
00274
00275 if ( folder == mFolder ) {
00276
00277
00278
00279
00280
00281
00282 #if 0 // this opens a race: delete a folder during a sync (after the sync checked that folder), and it'll be forgotten...
00283 mDeletedFolders.clear();
00284 #endif
00285 mPreviouslyDeletedFolders.clear();
00286 }
00287
00288 KMail::ImapAccountBase::postProcessNewMail();
00289 }
00290
00291 void KMAcctCachedImap::addUnreadMsgCount( const KMFolderCachedImap *folder,
00292 int countUnread )
00293 {
00294 if ( folder->imapPath() != "/INBOX/" ) {
00295
00296
00297 const QString folderId = folder->folder()->idString();
00298 int newInFolder = countUnread;
00299 if ( mUnreadBeforeCheck.find( folderId ) != mUnreadBeforeCheck.end() )
00300 newInFolder -= mUnreadBeforeCheck[folderId];
00301 if ( newInFolder > 0 )
00302 addToNewInFolder( folderId, newInFolder );
00303 }
00304 mCountUnread += countUnread;
00305 }
00306
00307 void KMAcctCachedImap::addLastUnreadMsgCount( const KMFolderCachedImap *folder,
00308 int countLastUnread )
00309 {
00310 mUnreadBeforeCheck[folder->folder()->idString()] = countLastUnread;
00311 mCountLastUnread += countLastUnread;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 void KMAcctCachedImap::readConfig( KConfig & config ) {
00321 ImapAccountBase::readConfig( config );
00322
00323 mPreviouslyDeletedFolders = config.readListEntry( "deleted-folders" );
00324 mDeletedFolders.clear();
00325 const QStringList oldPaths = config.readListEntry( "renamed-folders-paths" );
00326 const QStringList newNames = config.readListEntry( "renamed-folders-names" );
00327 QStringList::const_iterator it = oldPaths.begin();
00328 QStringList::const_iterator nameit = newNames.begin();
00329 for( ; it != oldPaths.end() && nameit != newNames.end(); ++it, ++nameit ) {
00330 addRenamedFolder( *it, QString::null, *nameit );
00331 }
00332 }
00333
00334 void KMAcctCachedImap::writeConfig( KConfig & config ) {
00335 ImapAccountBase::writeConfig( config );
00336 config.writeEntry( "deleted-folders", mDeletedFolders + mPreviouslyDeletedFolders );
00337 config.writeEntry( "renamed-folders-paths", mRenamedFolders.keys() );
00338 const QValueList<RenamedFolder> values = mRenamedFolders.values();
00339 QStringList lstNames;
00340 QValueList<RenamedFolder>::const_iterator it = values.begin();
00341 for ( ; it != values.end() ; ++it )
00342 lstNames.append( (*it).mNewName );
00343 config.writeEntry( "renamed-folders-names", lstNames );
00344 }
00345
00346 void KMAcctCachedImap::invalidateIMAPFolders()
00347 {
00348 invalidateIMAPFolders( mFolder );
00349 }
00350
00351 void KMAcctCachedImap::invalidateIMAPFolders( KMFolderCachedImap* folder )
00352 {
00353 if( !folder || !folder->folder() )
00354 return;
00355
00356 folder->setAccount(this);
00357
00358 QStringList strList;
00359 QValueList<QGuardedPtr<KMFolder> > folderList;
00360 kmkernel->dimapFolderMgr()->createFolderList( &strList, &folderList,
00361 folder->folder()->child(), QString::null,
00362 false );
00363 QValueList<QGuardedPtr<KMFolder> >::Iterator it;
00364 mCountLastUnread = 0;
00365 mUnreadBeforeCheck.clear();
00366
00367 for( it = folderList.begin(); it != folderList.end(); ++it ) {
00368 KMFolder *f = *it;
00369 if( f && f->folderType() == KMFolderTypeCachedImap ) {
00370 KMFolderCachedImap *cfolder = static_cast<KMFolderCachedImap*>(f->storage());
00371
00372 cfolder->setUidValidity("INVALID");
00373 cfolder->writeUidCache();
00374 processNewMailSingleFolder( f );
00375 }
00376 }
00377 folder->setUidValidity("INVALID");
00378 folder->writeUidCache();
00379
00380 processNewMailSingleFolder( folder->folder() );
00381 }
00382
00383
00384 void KMAcctCachedImap::addDeletedFolder( KMFolder* folder )
00385 {
00386 if ( !folder || folder->folderType() != KMFolderTypeCachedImap )
00387 return;
00388 KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>(folder->storage());
00389 addDeletedFolder( storage->imapPath() );
00390 kdDebug(5006) << k_funcinfo << storage->imapPath() << endl;
00391
00392
00393 if( folder->child() ) {
00394 KMFolderNode *node = folder->child()->first();
00395 while( node ) {
00396 if( !node->isDir() ) {
00397 addDeletedFolder( static_cast<KMFolder*>( node ) );
00398 }
00399 node = folder->child()->next();
00400 }
00401 }
00402 }
00403
00404 void KMAcctCachedImap::addDeletedFolder( const QString& imapPath )
00405 {
00406 mDeletedFolders << imapPath;
00407 }
00408
00409 QStringList KMAcctCachedImap::deletedFolderPaths( const QString& subFolderPath ) const
00410 {
00411 QStringList lst;
00412 for ( QStringList::const_iterator it = mDeletedFolders.begin(); it != mDeletedFolders.end(); ++it ) {
00413 if ( (*it).startsWith( subFolderPath ) )
00414
00415 lst.prepend( *it );
00416 }
00417 for ( QStringList::const_iterator it = mPreviouslyDeletedFolders.begin(); it != mPreviouslyDeletedFolders.end(); ++it ) {
00418 if ( (*it).startsWith( subFolderPath ) )
00419 lst.prepend( *it );
00420 }
00421 kdDebug(5006) << "KMAcctCachedImap::deletedFolderPaths for " << subFolderPath << " returning: " << lst << endl;
00422 Q_ASSERT( !lst.isEmpty() );
00423 return lst;
00424 }
00425
00426 bool KMAcctCachedImap::isDeletedFolder( const QString& subFolderPath ) const
00427 {
00428 return mDeletedFolders.find( subFolderPath ) != mDeletedFolders.end();
00429 }
00430
00431 bool KMAcctCachedImap::isPreviouslyDeletedFolder( const QString& subFolderPath ) const
00432 {
00433 return mPreviouslyDeletedFolders.find( subFolderPath ) != mPreviouslyDeletedFolders.end();
00434 }
00435
00436 void KMAcctCachedImap::removeDeletedFolder( const QString& subFolderPath )
00437 {
00438 mDeletedFolders.remove( subFolderPath );
00439 mPreviouslyDeletedFolders.remove( subFolderPath );
00440 }
00441
00442 void KMAcctCachedImap::addRenamedFolder( const QString& subFolderPath, const QString& oldLabel, const QString& newName )
00443 {
00444 mRenamedFolders.insert( subFolderPath, RenamedFolder( oldLabel, newName ) );
00445 }
00446
00447 void KMAcctCachedImap::removeRenamedFolder( const QString& subFolderPath )
00448 {
00449 mRenamedFolders.remove( subFolderPath );
00450 }
00451
00452 void KMAcctCachedImap::slotProgressItemCanceled( ProgressItem* )
00453 {
00454 bool abortConnection = !mSlaveConnected;
00455 killAllJobs( abortConnection );
00456 if ( abortConnection ) {
00457
00458 emit connectionResult( KIO::ERR_USER_CANCELED, QString::null );
00459 }
00460 }
00461
00462 FolderStorage* const KMAcctCachedImap::rootFolder() const
00463 {
00464 return mFolder;
00465 }
00466
00467
00468 QString KMAcctCachedImap::renamedFolder( const QString& imapPath ) const
00469 {
00470 QMap<QString, RenamedFolder>::ConstIterator renit = mRenamedFolders.find( imapPath );
00471 if ( renit != mRenamedFolders.end() )
00472 return (*renit).mNewName;
00473 return QString::null;
00474 }
00475
00476 #include "kmacctcachedimap.moc"