kmail

accountmanager.cpp

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 "kmacctmaildir.h"
00011 #include "kmacctlocal.h"
00012 #include "popaccount.h"
00013 #include "kmacctimap.h"
00014 #include "networkaccount.h"
00015 #include "kmacctcachedimap.h"
00016 #include "broadcaststatus.h"
00017 #include "kmfiltermgr.h"
00018 #include "globalsettings.h"
00019 
00020 #include <dcopclient.h>
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   if ( curAccount->type() == "imap" || curAccount->type() == "cachedimap" || curAccount->type() == "pop" )
00194   {
00195     // Check with the network status daemon whether the network is available
00196     const int NetWorkStatusUnknown = 1;
00197     const int NetWorkStatusOnline = 8;
00198     QCString replyType;
00199     QByteArray params;
00200     QByteArray reply;
00201 
00202     QDataStream stream( params, IO_WriteOnly );
00203     stream << static_cast<NetworkAccount*>( curAccount )->host();
00204 
00205     if ( kapp->dcopClient()->call( "kded", "networkstatus", "status(QString)",
00206                             params, replyType, reply ) && ( replyType == "int" ) )
00207     {
00208       int result;
00209       QDataStream stream2(  reply, IO_ReadOnly );
00210       stream2 >> result;
00211       kdDebug() << k_funcinfo << "networkstatus status = " << result << endl;
00212       // if it's not unknown (no networks announced by network control apps), and not offline, give up now
00213       if ( ( result != NetWorkStatusUnknown ) && ( result != NetWorkStatusOnline ) )
00214       {
00215         emit checkedMail( false, mInteractive, mTotalNewInFolder );
00216         return;
00217      }
00218     }
00219   }
00220 
00221   connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00222                 this, SLOT( processNextCheck( bool ) ) );
00223 
00224   KPIM::BroadcastStatus::instance()->setStatusMsg(
00225       i18n("Checking account %1 for new mail").arg(curAccount->name()));
00226 
00227   kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00228 
00229   curAccount->setCheckingMail( true );
00230   mAcctChecking.append( curAccount );
00231   kmkernel->filterMgr()->ref();
00232   curAccount->processNewMail( mInteractive );
00233 }
00234 
00235 //-----------------------------------------------------------------------------
00236 KMAccount* AccountManager::create( const QString &aType, const QString &aName, uint id )
00237 {
00238   KMAccount* act = 0;
00239   if ( id == 0 )
00240     id = createId();
00241 
00242   if ( aType == "local" ) {
00243     act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00244     act->setFolder( kmkernel->inboxFolder() );
00245   } else if ( aType == "maildir" ) {
00246     act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00247     act->setFolder( kmkernel->inboxFolder() );
00248   } else if ( aType == "pop" ) {
00249     act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
00250     act->setFolder( kmkernel->inboxFolder() );
00251   } else if ( aType == "imap" ) {
00252     act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00253   } else if (aType == "cachedimap") {
00254     act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00255   }
00256   if ( !act ) {
00257       kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
00258       return 0;
00259   }
00260   connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00261                 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00262   return act;
00263 }
00264 
00265 
00266 //-----------------------------------------------------------------------------
00267 void AccountManager::add( KMAccount *account )
00268 {
00269   if ( account ) {
00270     mAcctList.append( account );
00271     emit accountAdded( account );
00272     account->installTimer();
00273   }
00274 }
00275 
00276 
00277 //-----------------------------------------------------------------------------
00278 KMAccount* AccountManager::findByName(const QString &aName) const
00279 {
00280   if ( aName.isEmpty() ) return 0;
00281 
00282   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00283     if ( (*it)->name() == aName ) return (*it);
00284   }
00285   return 0;
00286 }
00287 
00288 
00289 //-----------------------------------------------------------------------------
00290 KMAccount* AccountManager::find( const uint id ) const
00291 {
00292   if (id == 0) return 0;
00293   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00294     if ( (*it)->id() == id ) return (*it);
00295   }
00296   return 0;
00297 }
00298 
00299 
00300 //-----------------------------------------------------------------------------
00301 KMAccount* AccountManager::first()
00302 {
00303   if ( !mAcctList.empty() ) {
00304     mPtrListInterfaceProxyIterator = mAcctList.begin();
00305     return *mPtrListInterfaceProxyIterator;
00306   } else {
00307     return 0;
00308   }
00309 }
00310 
00311 //-----------------------------------------------------------------------------
00312 KMAccount* AccountManager::next()
00313 {
00314     ++mPtrListInterfaceProxyIterator;
00315     if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
00316         return 0;
00317     else
00318         return *mPtrListInterfaceProxyIterator;
00319 }
00320 
00321 //-----------------------------------------------------------------------------
00322 bool AccountManager::remove( KMAccount* acct )
00323 {
00324   if( !acct )
00325     return false;
00326   mAcctList.remove( acct );
00327   emit accountRemoved( acct );
00328   return true;
00329 }
00330 
00331 //-----------------------------------------------------------------------------
00332 void AccountManager::checkMail( bool _interactive )
00333 {
00334   mNewMailArrived = false;
00335 
00336   if ( mAcctList.isEmpty() ) {
00337     KMessageBox::information( 0,i18n("You need to add an account in the network "
00338                     "section of the settings in order to receive mail.") );
00339     return;
00340   }
00341   mDisplaySummary = true;
00342 
00343   mTotalNewMailsArrived=0;
00344   mTotalNewInFolder.clear();
00345 
00346   for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00347     if ( !(*it)->checkExclude() )
00348       singleCheckMail( (*it), _interactive);
00349   }
00350 }
00351 
00352 
00353 //-----------------------------------------------------------------------------
00354 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
00355   account->invalidateIMAPFolders();
00356 }
00357 
00358 
00359 void AccountManager::invalidateIMAPFolders()
00360 {
00361   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00362     singleInvalidateIMAPFolders( *it );
00363 }
00364 
00365 
00366 //-----------------------------------------------------------------------------
00367 QStringList  AccountManager::getAccounts() const
00368 {
00369   QStringList strList;
00370   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00371     strList.append( (*it)->name() );
00372   }
00373   return strList;
00374 }
00375 
00376 //-----------------------------------------------------------------------------
00377 void AccountManager::intCheckMail(int item, bool _interactive)
00378 {
00379   mNewMailArrived = false;
00380   mTotalNewMailsArrived = 0;
00381   mTotalNewInFolder.clear();
00382   if ( KMAccount *acct = mAcctList[ item ] )
00383     singleCheckMail( acct, _interactive );
00384   mDisplaySummary = false;
00385 }
00386 
00387 
00388 //-----------------------------------------------------------------------------
00389 void AccountManager::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00390 {
00391   for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00392         it != newInFolder.end(); ++it ) {
00393     mTotalNewMailsArrived += it.data();
00394     if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00395       mTotalNewInFolder[it.key()] = it.data();
00396     else
00397       mTotalNewInFolder[it.key()] += it.data();
00398   }
00399 }
00400 
00401 //-----------------------------------------------------------------------------
00402 uint AccountManager::createId()
00403 {
00404   QValueList<uint> usedIds;
00405   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00406     usedIds << (*it)->id();
00407   }
00408 
00409   usedIds << 0; // 0 is default for unknown
00410   int newId;
00411   do
00412   {
00413     newId = kapp->random();
00414   } while ( usedIds.find(newId) != usedIds.end() );
00415 
00416   return newId;
00417 }
00418 
00419 //-----------------------------------------------------------------------------
00420 void AccountManager::cancelMailCheck()
00421 {
00422   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00423     (*it)->cancelMailCheck();
00424   }
00425 }
00426 
00427 
00428 //-----------------------------------------------------------------------------
00429 void AccountManager::readPasswords()
00430 {
00431   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00432     NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
00433     if ( acct )
00434       acct->readPassword();
00435   }
00436 }
00437 
00438 #include "accountmanager.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys