kmail

accountmanager.cpp

Go to the documentation of this file.
00001 // KMail Account Manager
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #include "accountmanager.h"
00008 
00009 #include "kmaccount.h"
00010 #include "kmacctfolder.h"
00011 #include "kmacctmaildir.h"
00012 #include "kmacctlocal.h"
00013 #include "popaccount.h"
00014 #include "kmacctimap.h"
00015 #include "networkaccount.h"
00016 #include "kmacctcachedimap.h"
00017 #include "broadcaststatus.h"
00018 #include "kmfiltermgr.h"
00019 #include "globalsettings.h"
00020 
00021 #include <klocale.h>
00022 #include <kmessagebox.h>
00023 #include <kdebug.h>
00024 #include <kconfig.h>
00025 #include <kapplication.h>
00026 
00027 #include <qregexp.h>
00028 #include <qvaluelist.h>
00029 
00030 using namespace KMail;
00031 
00032 //-----------------------------------------------------------------------------
00033 AccountManager::AccountManager()
00034     :QObject(), mNewMailArrived( false ), mInteractive( false ),
00035      mTotalNewMailsArrived( 0 ), mDisplaySummary( false )
00036 {
00037   mAcctChecking.clear();
00038   mAcctTodo.clear();
00039 }
00040 
00041 //-----------------------------------------------------------------------------
00042 AccountManager::~AccountManager()
00043 {
00044   writeConfig( false );
00045 }
00046 
00047 
00048 //-----------------------------------------------------------------------------
00049 void AccountManager::writeConfig( bool withSync )
00050 {
00051   KConfig* config = KMKernel::config();
00052   QString groupName;
00053 
00054   KConfigGroupSaver saver(config, "General");
00055   config->writeEntry("accounts", mAcctList.count());
00056 
00057   // first delete all account groups in the config file:
00058   QStringList accountGroups =
00059     config->groupList().grep( QRegExp( "Account \\d+" ) );
00060   for ( QStringList::Iterator it = accountGroups.begin() ;
00061     it != accountGroups.end() ; ++it )
00062     config->deleteGroup( *it );
00063 
00064   // now write new account groups:
00065   int i = 1;
00066   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it, ++i ) {
00067     groupName.sprintf("Account %d", i);
00068     KConfigGroupSaver saver(config, groupName);
00069     (*it)->writeConfig(*config);
00070   }
00071   if (withSync) config->sync();
00072 }
00073 
00074 
00075 //-----------------------------------------------------------------------------
00076 void AccountManager::readConfig(void)
00077 {
00078   KConfig* config = KMKernel::config();
00079   KMAccount* acct;
00080   QString acctType, acctName;
00081   QCString groupName;
00082   int i, num;
00083   uint id;
00084 
00085   for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00086       delete *it;
00087   mAcctList.clear();
00088 
00089   KConfigGroup general(config, "General");
00090   num = general.readNumEntry("accounts", 0);
00091 
00092   for (i=1; i<=num; i++)
00093   {
00094     groupName.sprintf("Account %d", i);
00095     KConfigGroupSaver saver(config, groupName);
00096     acctType = config->readEntry("Type");
00097     // Provide backwards compatibility
00098     if (acctType == "advanced pop" || acctType == "experimental pop")
00099       acctType = "pop";
00100     acctName = config->readEntry("Name");
00101     id = config->readUnsignedNumEntry("Id", 0);
00102     if (acctName.isEmpty()) acctName = i18n("Account %1").arg(i);
00103     acct = create(acctType, acctName, id);
00104     if (!acct) continue;
00105     add(acct);
00106     acct->readConfig(*config);
00107   }
00108 }
00109 
00110 
00111 //-----------------------------------------------------------------------------
00112 void AccountManager::singleCheckMail(KMAccount *account, bool interactive)
00113 {
00114   mNewMailArrived = false;
00115   mInteractive = interactive;
00116 
00117  // if sync has been requested by the user then check if check-interval was disabled by user, if yes, then 
00118  // de-install the timer
00119  // Safe guard against an infinite sync loop (kolab/issue2607)
00120   if ( mInteractive ) 
00121       account->readTimerConfig();
00122 
00123   // queue the account
00124   mAcctTodo.append(account);
00125 
00126   if (account->checkingMail())
00127   {
00128     kdDebug(5006) << "account " << account->name() << " busy, queuing" << endl;
00129     return;
00130   }
00131 
00132   processNextCheck(false);
00133 }
00134 
00135 //-----------------------------------------------------------------------------
00136 void AccountManager::processNextCheck( bool _newMail )
00137 {
00138   kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
00139   if ( _newMail )
00140     mNewMailArrived = true;
00141 
00142   for ( AccountList::Iterator it( mAcctChecking.begin() ), end( mAcctChecking.end() ); it != end;  ) {
00143     KMAccount* acct = *it;
00144     ++it;
00145     if ( acct->checkingMail() )
00146       continue;
00147     // check done
00148     kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
00149     mAcctChecking.remove( acct );
00150     kmkernel->filterMgr()->deref();
00151     disconnect( acct, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00152                       this, SLOT( processNextCheck( bool ) ) );
00153   }
00154   if ( mAcctChecking.isEmpty() ) {
00155     // all checks finished, display summary
00156     if ( mDisplaySummary )
00157       KPIM::BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00158           mTotalNewMailsArrived );
00159     emit checkedMail( mNewMailArrived, mInteractive, mTotalNewInFolder );
00160     mTotalNewMailsArrived = 0;
00161     mTotalNewInFolder.clear();
00162     mDisplaySummary = false;
00163   }
00164   if ( mAcctTodo.isEmpty() ) return;
00165 
00166   QString accountHostName;
00167 
00168   KMAccount *curAccount = 0;
00169   for ( AccountList::Iterator it ( mAcctTodo.begin() ), last ( mAcctTodo.end() ); it != last; ) {
00170     KMAccount *acct = *it;
00171     ++it;
00172     if ( !acct->checkingMail() && acct->mailCheckCanProceed() ) {
00173       curAccount = acct;
00174       mAcctTodo.remove( acct );
00175       break;
00176     }
00177   }
00178   if ( !curAccount ) return; // no account or all of them are already checking
00179 
00180   if ( curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
00181        curAccount->folder() == 0 ) {
00182     QString tmp = i18n("Account %1 has no mailbox defined:\n"
00183         "mail checking aborted;\n"
00184         "check your account settings.")
00185       .arg(curAccount->name());
00186     KMessageBox::information(0,tmp);
00187     emit checkedMail( false, mInteractive, mTotalNewInFolder );
00188     mTotalNewMailsArrived = 0;
00189     mTotalNewInFolder.clear();
00190     return;
00191   }
00192 
00193   connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00194                 this, SLOT( processNextCheck( bool ) ) );
00195 
00196   KPIM::BroadcastStatus::instance()->setStatusMsg(
00197       i18n("Checking account %1 for new mail").arg(curAccount->name()));
00198 
00199   kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00200 
00201   curAccount->setCheckingMail( true );
00202   mAcctChecking.append( curAccount );
00203   kmkernel->filterMgr()->ref();
00204   curAccount->processNewMail( mInteractive );
00205 }
00206 
00207 //-----------------------------------------------------------------------------
00208 KMAccount* AccountManager::create( const QString &aType, const QString &aName, uint id )
00209 {
00210   KMAccount* act = 0;
00211   if ( id == 0 )
00212     id = createId();
00213 
00214   if ( aType == "local" ) {
00215     act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00216     act->setFolder( kmkernel->inboxFolder() );
00217   } else if ( aType == "maildir" ) {
00218     act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00219     act->setFolder( kmkernel->inboxFolder() );
00220   } else if ( aType == "pop" ) {
00221     act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
00222     act->setFolder( kmkernel->inboxFolder() );
00223   } else if ( aType == "imap" ) {
00224     act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00225   } else if (aType == "cachedimap") {
00226     act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00227   }
00228   if ( !act ) {
00229       kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
00230       return 0;
00231   }
00232   connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00233                 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00234   return act;
00235 }
00236 
00237 
00238 //-----------------------------------------------------------------------------
00239 void AccountManager::add( KMAccount *account )
00240 {
00241   if ( account ) {
00242     mAcctList.append( account );
00243     // init folder's account list
00244     KMAcctFolder *folder = static_cast<KMAcctFolder*>( account->folder() );
00245     if ( folder && !folder->hasAccounts() ) {
00246       folder->addAccount( account );
00247     }
00248     emit accountAdded( account );
00249     account->installTimer();
00250   }
00251 }
00252 
00253 
00254 //-----------------------------------------------------------------------------
00255 KMAccount* AccountManager::findByName(const QString &aName) const
00256 {
00257   if ( aName.isEmpty() ) return 0;
00258 
00259   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00260     if ( (*it)->name() == aName ) return (*it);
00261   }
00262   return 0;
00263 }
00264 
00265 
00266 //-----------------------------------------------------------------------------
00267 KMAccount* AccountManager::find( const uint id ) const
00268 {
00269   if (id == 0) return 0;
00270   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00271     if ( (*it)->id() == id ) return (*it);
00272   }
00273   return 0;
00274 }
00275 
00276 
00277 //-----------------------------------------------------------------------------
00278 KMAccount* AccountManager::first()
00279 {
00280   if ( !mAcctList.empty() ) {
00281     mPtrListInterfaceProxyIterator = mAcctList.begin();
00282     return *mPtrListInterfaceProxyIterator;
00283   } else {
00284     return 0;
00285   }
00286 }
00287 
00288 //-----------------------------------------------------------------------------
00289 KMAccount* AccountManager::next()
00290 {
00291     ++mPtrListInterfaceProxyIterator;
00292     if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
00293         return 0;
00294     else
00295         return *mPtrListInterfaceProxyIterator;
00296 }
00297 
00298 //-----------------------------------------------------------------------------
00299 bool AccountManager::remove( KMAccount* acct )
00300 {
00301   if( !acct )
00302     return false;
00303   mAcctList.remove( acct );
00304   emit accountRemoved( acct );
00305   return true;
00306 }
00307 
00308 //-----------------------------------------------------------------------------
00309 void AccountManager::checkMail( bool _interactive )
00310 {
00311   mNewMailArrived = false;
00312 
00313   if ( mAcctList.isEmpty() ) {
00314     KMessageBox::information( 0,i18n("You need to add an account in the network "
00315                     "section of the settings in order to receive mail.") );
00316     return;
00317   }
00318   mDisplaySummary = true;
00319 
00320   mTotalNewMailsArrived=0;
00321   mTotalNewInFolder.clear();
00322 
00323   for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00324     if ( !(*it)->checkExclude() )
00325       singleCheckMail( (*it), _interactive);
00326   }
00327 }
00328 
00329 
00330 //-----------------------------------------------------------------------------
00331 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
00332   account->invalidateIMAPFolders();
00333 }
00334 
00335 
00336 void AccountManager::invalidateIMAPFolders()
00337 {
00338   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00339     singleInvalidateIMAPFolders( *it );
00340 }
00341 
00342 
00343 //-----------------------------------------------------------------------------
00344 QStringList  AccountManager::getAccounts() const
00345 {
00346   QStringList strList;
00347   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00348     strList.append( (*it)->name() );
00349   }
00350   return strList;
00351 }
00352 
00353 //-----------------------------------------------------------------------------
00354 void AccountManager::intCheckMail(int item, bool _interactive)
00355 {
00356   mNewMailArrived = false;
00357   mTotalNewMailsArrived = 0;
00358   mTotalNewInFolder.clear();
00359   if ( KMAccount *acct = mAcctList[ item ] )
00360     singleCheckMail( acct, _interactive );
00361   mDisplaySummary = false;
00362 }
00363 
00364 
00365 //-----------------------------------------------------------------------------
00366 void AccountManager::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00367 {
00368   for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00369         it != newInFolder.end(); ++it ) {
00370     mTotalNewMailsArrived += it.data();
00371     if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00372       mTotalNewInFolder[it.key()] = it.data();
00373     else
00374       mTotalNewInFolder[it.key()] += it.data();
00375   }
00376 }
00377 
00378 //-----------------------------------------------------------------------------
00379 uint AccountManager::createId()
00380 {
00381   QValueList<uint> usedIds;
00382   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00383     usedIds << (*it)->id();
00384   }
00385 
00386   usedIds << 0; // 0 is default for unknown
00387   int newId;
00388   do
00389   {
00390     newId = kapp->random();
00391   } while ( usedIds.find(newId) != usedIds.end() );
00392 
00393   return newId;
00394 }
00395 
00396 //-----------------------------------------------------------------------------
00397 void AccountManager::cancelMailCheck()
00398 {
00399   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00400     (*it)->cancelMailCheck();
00401   }
00402 }
00403 
00404 
00405 //-----------------------------------------------------------------------------
00406 void AccountManager::readPasswords()
00407 {
00408   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00409     NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
00410     if ( acct )
00411       acct->readPassword();
00412   }
00413 }
00414 
00415 #include "accountmanager.moc"