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 )
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   // Ok, we're really checking, get a progress item;
00250   Q_ASSERT( !mMailCheckProgressItem );
00251   mMailCheckProgressItem =
00252     ProgressManager::createProgressItem(
00253         "MailCheckAccount" + name(),
00254         i18n("Checking account: " ) + name(),
00255         QString::null, // status
00256         true, // can be canceled
00257         useSSL() || useTLS() );
00258 
00259   mMailCheckProgressItem->setTotalItems( mMailCheckFolders.count() );
00260   connect ( mMailCheckProgressItem,
00261             SIGNAL( progressItemCanceled( ProgressItem*) ),
00262             this,
00263             SLOT( slotMailCheckCanceled() ) );
00264 
00265   QValueList<QGuardedPtr<KMFolder> >::Iterator it;
00266   // first get the current count of unread-messages
00267   mCountRemainChecks = 0;
00268   mCountUnread = 0;
00269   mUnreadBeforeCheck.clear();
00270   for (it = mMailCheckFolders.begin(); it != mMailCheckFolders.end(); it++)
00271   {
00272     KMFolder *folder = *it;
00273     if (folder && !folder->noContent())
00274     {
00275       mUnreadBeforeCheck[folder->idString()] = folder->countUnread();
00276     }
00277   }
00278   bool gotError = false;
00279   // then check for new mails
00280   for (it = mMailCheckFolders.begin(); it != mMailCheckFolders.end(); it++)
00281   {
00282     KMFolder *folder = *it;
00283     if (folder && !folder->noContent())
00284     {
00285       KMFolderImap *imapFolder = static_cast<KMFolderImap*>(folder->storage());
00286       if (imapFolder->getContentState() != KMFolderImap::imapInProgress)
00287       {
00288         // connect the result-signals for new-mail-notification
00289         mCountRemainChecks++;
00290         if (imapFolder->isSelected()) {
00291           connect(imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)),
00292               this, SLOT(postProcessNewMail(KMFolderImap*, bool)));
00293           imapFolder->getFolder();
00294         }
00295         else {
00296           connect(imapFolder, SIGNAL(numUnreadMsgsChanged(KMFolder*)),
00297               this, SLOT(postProcessNewMail(KMFolder*)));
00298           bool ok = imapFolder->processNewMail(interactive);
00299           if (!ok)
00300           {
00301             // there was an error so cancel
00302             mCountRemainChecks--;
00303             gotError = true;
00304             if ( mMailCheckProgressItem ) {
00305               mMailCheckProgressItem->incCompletedItems();
00306               mMailCheckProgressItem->updateProgress();
00307             }
00308           }
00309         }
00310       }
00311     }
00312   } // end for
00313   if ( gotError )
00314     slotUpdateFolderList();
00315   // for the case the account is down and all folders report errors
00316   if ( mCountRemainChecks == 0 )
00317   {
00318     mCountLastUnread = 0; // => mCountUnread - mCountLastUnread == new count
00319     ImapAccountBase::postProcessNewMail();
00320     mUnreadBeforeCheck.clear();
00321   }
00322 }
00323 
00324 //-----------------------------------------------------------------------------
00325 void KMAcctImap::postProcessNewMail(KMFolderImap* folder, bool)
00326 {
00327   disconnect(folder, SIGNAL(folderComplete(KMFolderImap*, bool)),
00328       this, SLOT(postProcessNewMail(KMFolderImap*, bool)));
00329   postProcessNewMail(static_cast<KMFolder*>(folder->folder()));
00330 }
00331 
00332 void KMAcctImap::postProcessNewMail( KMFolder * folder ) {
00333 
00334   disconnect( folder->storage(), SIGNAL(numUnreadMsgsChanged(KMFolder*)),
00335               this, SLOT(postProcessNewMail(KMFolder*)) );
00336 
00337   if ( mMailCheckProgressItem ) {
00338     mMailCheckProgressItem->incCompletedItems();
00339     mMailCheckProgressItem->updateProgress();
00340     mMailCheckProgressItem->setStatus( folder->prettyURL() + i18n(" completed") );
00341   }
00342   mCountRemainChecks--;
00343 
00344   // count the unread messages
00345   const QString folderId = folder->idString();
00346   int newInFolder = folder->countUnread();
00347   if ( mUnreadBeforeCheck.find( folderId ) != mUnreadBeforeCheck.end() )
00348     newInFolder -= mUnreadBeforeCheck[folderId];
00349   if ( newInFolder > 0 ) {
00350     addToNewInFolder( folderId, newInFolder );
00351     mCountUnread += newInFolder;
00352   }
00353   if (mCountRemainChecks == 0)
00354   {
00355     // all checks are done
00356     mCountLastUnread = 0; // => mCountUnread - mCountLastUnread == new count
00357     ImapAccountBase::postProcessNewMail();
00358     mUnreadBeforeCheck.clear();
00359   }
00360 }
00361 
00362 //-----------------------------------------------------------------------------
00363 void KMAcctImap::slotUpdateFolderList()
00364 {
00365   if ( !mFolder || !mFolder->folder() || !mFolder->folder()->child() )
00366   {
00367     kdWarning(5006) << "KMAcctImap::slotUpdateFolderList return" << endl;
00368     return;
00369   }
00370   QStringList strList;
00371   mMailCheckFolders.clear();
00372   kmkernel->imapFolderMgr()->createFolderList(&strList, &mMailCheckFolders,
00373     mFolder->folder()->child(), QString::null, false);
00374   // the new list
00375   QValueList<QGuardedPtr<KMFolder> > includedFolders;
00376   // check for excluded folders
00377   QValueList<QGuardedPtr<KMFolder> >::Iterator it;
00378   for (it = mMailCheckFolders.begin(); it != mMailCheckFolders.end(); it++)
00379   {
00380     KMFolderImap* folder = static_cast<KMFolderImap*>(((KMFolder*)(*it))->storage());
00381     if (folder->includeInMailCheck())
00382       includedFolders.append(*it);
00383   }
00384   mMailCheckFolders = includedFolders;
00385 }
00386 
00387 //-----------------------------------------------------------------------------
00388 void KMAcctImap::listDirectory()
00389 {
00390   mFolder->listDirectory();
00391 }
00392 
00393 //-----------------------------------------------------------------------------
00394 void KMAcctImap::setPrefixHook() {
00395   if ( mFolder ) mFolder->setImapPath( prefix() );
00396 }
00397 
00398 //-----------------------------------------------------------------------------
00399 void KMAcctImap::readConfig(KConfig& config)
00400 {
00401   ImapAccountBase::readConfig( config );
00402 }
00403 
00404 //-----------------------------------------------------------------------------
00405 void KMAcctImap::slotMailCheckCanceled()
00406 {
00407   if( mMailCheckProgressItem )
00408     mMailCheckProgressItem->setComplete();
00409   cancelMailCheck();
00410 }
00411 
00412 //-----------------------------------------------------------------------------
00413 FolderStorage* const KMAcctImap::rootFolder() const
00414 {
00415   return mFolder;
00416 }
00417 
00418 ImapAccountBase::ConnectionState KMAcctImap::makeConnection() 
00419 {
00420     if ( mSlaveConnectionError )
00421     {
00422        mErrorTimer.start(100, true); // Clear error flag
00423        return Error;
00424     }
00425     return ImapAccountBase::makeConnection();
00426 }
00427 
00428 void KMAcctImap::slotResetConnectionError()
00429 {
00430   mSlaveConnectionError = false;
00431   kdDebug(5006) << k_funcinfo << endl;
00432 }
00433 
00434 #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 Wed Mar 23 22:43:42 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003