kmail Library API Documentation

kmacctimap.cpp

00001 
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025 
00026 #include "kmacctimap.h"
00027 using KMail::SieveConfig;
00028 
00029 #include "broadcaststatus.h"
00030 using KPIM::BroadcastStatus;
00031 #include "kmfoldertree.h"
00032 #include "kmfoldermgr.h"
00033 #include "kmfolderimap.h"
00034 #include "kmmainwin.h"
00035 #include "folderstorage.h"
00036 #include "imapjob.h"
00037 using KMail::ImapJob;
00038 #include "progressmanager.h"
00039 using KPIM::ProgressItem;
00040 using KPIM::ProgressManager;
00041 #include <kio/scheduler.h>
00042 #include <kio/slave.h>
00043 #include <kmessagebox.h>
00044 #include <kdebug.h>
00045 
00046 
00047 //-----------------------------------------------------------------------------
00048 KMAcctImap::KMAcctImap(KMAcctMgr* aOwner, const QString& aAccountName, uint id):
00049   KMail::ImapAccountBase(aOwner, aAccountName, id),
00050   mCountRemainChecks( 0 ), mInteractive( true )
00051 {
00052   mFolder = 0;
00053   mNoopTimer.start( 60000 ); // // send a noop every minute
00054   mOpenFolders.setAutoDelete(true);
00055   connect(kmkernel->imapFolderMgr(), SIGNAL(changed()),
00056       this, SLOT(slotUpdateFolderList()));
00057   connect(&mErrorTimer, SIGNAL(timeout()), SLOT(slotResetConnectionError()));
00058 }
00059 
00060 
00061 //-----------------------------------------------------------------------------
00062 KMAcctImap::~KMAcctImap()
00063 {
00064   killAllJobs( true );
00065 }
00066 
00067 
00068 //-----------------------------------------------------------------------------
00069 QString KMAcctImap::type() const
00070 {
00071   return "imap";
00072 }
00073 
00074 //-----------------------------------------------------------------------------
00075 void KMAcctImap::pseudoAssign( const KMAccount * a ) {
00076   killAllJobs( true );
00077   if (mFolder)
00078   {
00079     mFolder->setContentState(KMFolderImap::imapNoInformation);
00080     mFolder->setSubfolderState(KMFolderImap::imapNoInformation);
00081   }
00082   ImapAccountBase::pseudoAssign( a );
00083 }
00084 
00085 //-----------------------------------------------------------------------------
00086 void KMAcctImap::setImapFolder(KMFolderImap *aFolder)
00087 {
00088   mFolder = aFolder;
00089   mFolder->setImapPath(mPrefix);
00090 }
00091 
00092 
00093 //-----------------------------------------------------------------------------
00094 
00095 bool KMAcctImap::handleError( int errorCode, const QString &errorMsg, KIO::Job* job, const QString& context, bool abortSync )
00096 {
00097   /* TODO check where to handle this one better. */
00098   if ( errorCode == KIO::ERR_DOES_NOT_EXIST ) {
00099     // folder is gone, so reload the folderlist
00100     if ( mFolder )
00101       mFolder->listDirectory();
00102     return true;
00103   }
00104   return ImapAccountBase::handleError( errorCode, errorMsg, job, context, abortSync );
00105 }
00106 
00107 
00108 //-----------------------------------------------------------------------------
00109 void KMAcctImap::killAllJobs( bool disconnectSlave )
00110 {
00111   QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00112   for ( ; it != mapJobData.end(); ++it)
00113   {
00114     QPtrList<KMMessage> msgList = (*it).msgList;
00115     QPtrList<KMMessage>::Iterator it2 = msgList.begin();
00116     for ( ; it2 != msgList.end(); ++it2 ) {
00117        KMMessage *msg = *it2;
00118        if ( msg->transferInProgress() ) {
00119           kdDebug(5006) << "KMAcctImap::killAllJobs - resetting mail" << endl;
00120           msg->setTransferInProgress( false );
00121        }
00122     }
00123     if ((*it).parent)
00124     {
00125       // clear folder state
00126       KMFolderImap *fld = static_cast<KMFolderImap*>((*it).parent->storage());
00127       fld->setCheckingValidity(false);
00128       fld->setContentState(KMFolderImap::imapNoInformation);
00129       fld->setSubfolderState(KMFolderImap::imapNoInformation);
00130       fld->sendFolderComplete(FALSE);
00131       fld->removeJobs();
00132     }
00133     if ( (*it).progressItem )
00134     {
00135       (*it).progressItem->setComplete();
00136     }
00137   }
00138   if (mSlave && mapJobData.begin() != mapJobData.end())
00139   {
00140     mSlave->kill();
00141     mSlave = 0;
00142   }
00143   // remove the jobs
00144   mapJobData.clear();
00145   KMAccount::deleteFolderJobs();
00146   // make sure that no new-mail-check is blocked
00147   if (mCountRemainChecks > 0)
00148   {
00149     checkDone( false, CheckOK ); // returned 0 new messages
00150     mCountRemainChecks = 0;
00151   }
00152   if ( disconnectSlave && slave() ) {
00153     KIO::Scheduler::disconnectSlave( slave() );
00154     mSlave = 0;
00155   }
00156 }
00157 
00158 //-----------------------------------------------------------------------------
00159 void KMAcctImap::ignoreJobsForMessage( KMMessage* msg )
00160 {
00161   if (!msg) return;
00162   QPtrListIterator<ImapJob> it( mJobList );
00163   while ( it.current() )
00164   {
00165     ImapJob *job = it.current();
00166     ++it;
00167     if ( job->msgList().findRef( msg ) != -1 )
00168     {
00169       job->kill();
00170     }
00171   }
00172 }
00173 
00174 //-----------------------------------------------------------------------------
00175 void KMAcctImap::ignoreJobsForFolder( KMFolder* folder )
00176 {
00177   QPtrListIterator<ImapJob> it( mJobList );
00178   while ( it.current() )
00179   {
00180     ImapJob *job = it.current();
00181     ++it;
00182     if ( !job->msgList().isEmpty() && job->msgList().first()->parent() == folder )
00183     {
00184       job->kill();
00185     }
00186   }
00187 }
00188 
00189 //-----------------------------------------------------------------------------
00190 void KMAcctImap::removeSlaveJobsForFolder( KMFolder* folder )
00191 {
00192   // Make sure the folder is not referenced in any kio slave jobs
00193   QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00194   while ( it != mapJobData.end() ) {
00195      QMap<KIO::Job*, jobData>::Iterator i = it;
00196      it++;
00197      if ( (*i).parent ) {
00198         if ( (*i).parent == folder ) {
00199            mapJobData.remove(i);
00200         }
00201      }
00202   }
00203 }
00204 
00205 //-----------------------------------------------------------------------------
00206 void KMAcctImap::cancelMailCheck()
00207 {
00208   // Make list of folders to reset, like in killAllJobs
00209   QValueList<KMFolderImap*> folderList;
00210   QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
00211   for (; it != mapJobData.end(); ++it) {
00212     if ( (*it).cancellable && (*it).parent ) {
00213       folderList << static_cast<KMFolderImap*>((*it).parent->storage());
00214     }
00215   }
00216   // Kill jobs
00217   // FIXME
00218   // ImapAccountBase::cancelMailCheck();
00219   killAllJobs( true );
00220   // emit folderComplete, this is important for
00221   // KMAccount::checkingMail() to be reset, in case we restart checking mail later.
00222   for( QValueList<KMFolderImap*>::Iterator it = folderList.begin(); it != folderList.end(); ++it ) {
00223     KMFolderImap *fld = *it;
00224     fld->sendFolderComplete(FALSE);
00225   }
00226 }
00227 
00228 //-----------------------------------------------------------------------------
00229 void KMAcctImap::processNewMail(bool interactive)
00230 {
00231   if (!mFolder || !mFolder->folder() || !mFolder->folder()->child() ||
00232       makeConnection() == ImapAccountBase::Error)
00233   {
00234     mCountRemainChecks = 0;
00235     checkDone( false, CheckError );
00236     return;
00237   }
00238   // if necessary then initialize the list of folders which should be checked
00239   if( mMailCheckFolders.isEmpty() )
00240   {
00241     slotUpdateFolderList();
00242     // if no folders should be checked then the check is finished
00243     if( mMailCheckFolders.isEmpty() )
00244     {
00245       checkDone( false, CheckOK );
00246       return;
00247     }
00248   }
00249 
00250   mInteractive = interactive;
00251   // For full mailchecks trigger a folder listing, and continue when it's done
00252   if ( mMailCheckFolders.count() > 1 ) {
00253     connect( listDirProgressItem(), SIGNAL( progressItemCompleted( ProgressItem *) ),
00254            this, SLOT( slotContinueMailCheck() ) );
00255     listDirectory();
00256   } else{
00257     slotContinueMailCheck();
00258   }
00259 }
00260 
00261 void KMAcctImap::slotContinueMailCheck()
00262 {
00263   // Ok, we're really checking, get a progress item;
00264   Q_ASSERT( !mMailCheckProgressItem );
00265   mMailCheckProgressItem =
00266     ProgressManager::createProgressItem(
00267         "MailCheckAccount" + name(),
00268         i18n("Checking account: " ) + name(),
00269         QString::null, // status
00270         true, // can be canceled
00271         useSSL() || useTLS() );
00272 
00273   mMailCheckProgressItem->setTotalItems( mMailCheckFolders.count() );
00274   connect ( mMailCheckProgressItem,
00275             SIGNAL( progressItemCanceled( ProgressItem*) ),
00276             this,
00277             SLOT( slotMailCheckCanceled() ) );
00278 
00279   QValueList<QGuardedPtr<KMFolder> >::Iterator it;
00280   // first get the current count of unread-messages
00281   mCountRemainChecks = 0;
00282   mCountUnread = 0;
00283   mUnreadBeforeCheck.clear();
00284   for (it = mMailCheckFolders.begin(); it != mMailCheckFolders.end(); it++)
00285   {
00286     KMFolder *folder = *it;
00287     if (folder && !folder->noContent())
00288     {
00289       mUnreadBeforeCheck[folder->idString()] = folder->countUnread();
00290     }
00291   }
00292   bool gotError = false;
00293   // then check for new mails
00294   for (it = mMailCheckFolders.begin(); it != mMailCheckFolders.end(); it++)
00295   {
00296     KMFolder *folder = *it;
00297     if (folder && !folder->noContent())
00298     {
00299       KMFolderImap *imapFolder = static_cast<KMFolderImap*>(folder->storage());
00300       if (imapFolder->getContentState() != KMFolderImap::imapInProgress)
00301       {
00302         // connect the result-signals for new-mail-notification
00303         mCountRemainChecks++;
00304         if (imapFolder->isSelected()) {
00305           connect(imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)),
00306               this, SLOT(postProcessNewMail(KMFolderImap*, bool)));
00307           imapFolder->getFolder();
00308         }
00309         else {
00310           connect(imapFolder, SIGNAL(numUnreadMsgsChanged(KMFolder*)),
00311               this, SLOT(postProcessNewMail(KMFolder*)));
00312           bool ok = imapFolder->processNewMail(mInteractive);
00313           if (!ok)
00314           {
00315             // there was an error so cancel
00316             mCountRemainChecks--;
00317             gotError = true;
00318             if ( mMailCheckProgressItem ) {
00319               mMailCheckProgressItem->incCompletedItems();
00320               mMailCheckProgressItem->updateProgress();
00321             }
00322           }
00323         }
00324       }
00325     }
00326   } // end for
00327   if ( gotError )
00328     slotUpdateFolderList();
00329   // for the case the account is down and all folders report errors
00330   if ( mCountRemainChecks == 0 )
00331   {
00332     mCountLastUnread = 0; // => mCountUnread - mCountLastUnread == new count
00333     ImapAccountBase::postProcessNewMail();
00334     mUnreadBeforeCheck.clear();
00335   }
00336 }
00337 
00338 //-----------------------------------------------------------------------------
00339 void KMAcctImap::postProcessNewMail(KMFolderImap* folder, bool)
00340 {
00341   disconnect(folder, SIGNAL(folderComplete(KMFolderImap*, bool)),
00342       this, SLOT(postProcessNewMail(KMFolderImap*, bool)));
00343   postProcessNewMail(static_cast<KMFolder*>(folder->folder()));
00344 }
00345 
00346 void KMAcctImap::postProcessNewMail( KMFolder * folder ) {
00347 
00348   disconnect( folder->storage(), SIGNAL(numUnreadMsgsChanged(KMFolder*)),
00349               this, SLOT(postProcessNewMail(KMFolder*)) );
00350 
00351   if ( mMailCheckProgressItem ) {
00352     mMailCheckProgressItem->incCompletedItems();
00353     mMailCheckProgressItem->updateProgress();
00354     mMailCheckProgressItem->setStatus( folder->prettyURL() + i18n(" completed") );
00355   }
00356   mCountRemainChecks--;
00357 
00358   // count the unread messages
00359   const QString folderId = folder->idString();
00360   int newInFolder = folder->countUnread();
00361   if ( mUnreadBeforeCheck.find( folderId ) != mUnreadBeforeCheck.end() )
00362     newInFolder -= mUnreadBeforeCheck[folderId];
00363   if ( newInFolder > 0 ) {
00364     addToNewInFolder( folderId, newInFolder );
00365     mCountUnread += newInFolder;
00366   }
00367   if (mCountRemainChecks == 0)
00368   {
00369     // all checks are done
00370     mCountLastUnread = 0; // => mCountUnread - mCountLastUnread == new count
00371     ImapAccountBase::postProcessNewMail();
00372     mUnreadBeforeCheck.clear();
00373   }
00374 }
00375 
00376 //-----------------------------------------------------------------------------
00377 void KMAcctImap::slotUpdateFolderList()
00378 {
00379   if ( !mFolder || !mFolder->folder() || !mFolder->folder()->child() )
00380   {
00381     kdWarning(5006) << "KMAcctImap::slotUpdateFolderList return" << endl;
00382     return;
00383   }
00384   QStringList strList;
00385   mMailCheckFolders.clear();
00386   kmkernel->imapFolderMgr()->createFolderList(&strList, &mMailCheckFolders,
00387     mFolder->folder()->child(), QString::null, false);
00388   // the new list
00389   QValueList<QGuardedPtr<KMFolder> > includedFolders;
00390   // check for excluded folders
00391   QValueList<QGuardedPtr<KMFolder> >::Iterator it;
00392   for (it = mMailCheckFolders.begin(); it != mMailCheckFolders.end(); it++)
00393   {
00394     KMFolderImap* folder = static_cast<KMFolderImap*>(((KMFolder*)(*it))->storage());
00395     if (folder->includeInMailCheck())
00396       includedFolders.append(*it);
00397   }
00398   mMailCheckFolders = includedFolders;
00399 }
00400 
00401 //-----------------------------------------------------------------------------
00402 void KMAcctImap::listDirectory()
00403 {
00404   mFolder->listDirectory();
00405 }
00406 
00407 //-----------------------------------------------------------------------------
00408 void KMAcctImap::setPrefixHook() {
00409   if ( mFolder ) mFolder->setImapPath( prefix() );
00410 }
00411 
00412 //-----------------------------------------------------------------------------
00413 void KMAcctImap::readConfig(KConfig& config)
00414 {
00415   ImapAccountBase::readConfig( config );
00416 }
00417 
00418 //-----------------------------------------------------------------------------
00419 void KMAcctImap::slotMailCheckCanceled()
00420 {
00421   if( mMailCheckProgressItem )
00422     mMailCheckProgressItem->setComplete();
00423   cancelMailCheck();
00424 }
00425 
00426 //-----------------------------------------------------------------------------
00427 FolderStorage* const KMAcctImap::rootFolder() const
00428 {
00429   return mFolder;
00430 }
00431 
00432 ImapAccountBase::ConnectionState KMAcctImap::makeConnection() 
00433 {
00434     if ( mSlaveConnectionError )
00435     {
00436        mErrorTimer.start(100, true); // Clear error flag
00437        return Error;
00438     }
00439     return ImapAccountBase::makeConnection();
00440 }
00441 
00442 void KMAcctImap::slotResetConnectionError()
00443 {
00444   mSlaveConnectionError = false;
00445   kdDebug(5006) << k_funcinfo << endl;
00446 }
00447 
00448 #include "kmacctimap.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Aug 23 18:21:12 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003