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   // queue the account
00118   mAcctTodo.append(account);
00119 
00120   if (account->checkingMail())
00121   {
00122     kdDebug(5006) << "account " << account->name() << " busy, queuing" << endl;
00123     return;
00124   }
00125 
00126   processNextCheck(false);
00127 }
00128 
00129 //-----------------------------------------------------------------------------
00130 void AccountManager::processNextCheck( bool _newMail )
00131 {
00132   kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
00133   if ( _newMail )
00134     mNewMailArrived = true;
00135 
00136   for ( AccountList::Iterator it( mAcctChecking.begin() ), end( mAcctChecking.end() ); it != end;  ) {
00137     KMAccount* acct = *it;
00138     ++it;
00139     if ( acct->checkingMail() )
00140       continue;
00141     // check done
00142     kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
00143     mAcctChecking.remove( acct );
00144     kmkernel->filterMgr()->deref();
00145     disconnect( acct, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00146                       this, SLOT( processNextCheck( bool ) ) );
00147   }
00148   if ( mAcctChecking.isEmpty() ) {
00149     // all checks finished, display summary
00150     if ( mDisplaySummary )
00151       KPIM::BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00152           mTotalNewMailsArrived );
00153     emit checkedMail( mNewMailArrived, mInteractive, mTotalNewInFolder );
00154     mTotalNewMailsArrived = 0;
00155     mTotalNewInFolder.clear();
00156     mDisplaySummary = false;
00157   }
00158   if ( mAcctTodo.isEmpty() ) return;
00159 
00160   QString accountHostName;
00161 
00162   KMAccount *curAccount = 0;
00163   for ( AccountList::Iterator it ( mAcctTodo.begin() ), last ( mAcctTodo.end() ); it != last; ) {
00164     KMAccount *acct = *it;
00165     ++it;
00166     if ( !acct->checkingMail() && acct->mailCheckCanProceed() ) {
00167       curAccount = acct;
00168       mAcctTodo.remove( acct );
00169       break;
00170     }
00171   }
00172   if ( !curAccount ) return; // no account or all of them are already checking
00173 
00174   if ( curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
00175        curAccount->folder() == 0 ) {
00176     QString tmp = i18n("Account %1 has no mailbox defined:\n"
00177         "mail checking aborted;\n"
00178         "check your account settings.")
00179       .arg(curAccount->name());
00180     KMessageBox::information(0,tmp);
00181     emit checkedMail( false, mInteractive, mTotalNewInFolder );
00182     mTotalNewMailsArrived = 0;
00183     mTotalNewInFolder.clear();
00184     return;
00185   }
00186 
00187   if ( curAccount->type() == "imap" || curAccount->type() == "cachedimap" || curAccount->type() == "pop" )
00188   {
00189     // Check with the network status daemon whether the network is available
00190     const int NetWorkStatusUnknown = 1;
00191     const int NetWorkStatusOnline = 8;
00192     QCString replyType;
00193     QByteArray params;
00194     QByteArray reply;
00195 
00196     QDataStream stream( params, IO_WriteOnly );
00197     stream << static_cast<NetworkAccount*>( curAccount )->host();
00198 
00199     if ( kapp->dcopClient()->call( "kded", "networkstatus", "status(QString)",
00200                             params, replyType, reply ) && ( replyType == "int" ) )
00201     {
00202       int result;
00203       QDataStream stream2(  reply, IO_ReadOnly );
00204       stream2 >> result;
00205       kdDebug() << k_funcinfo << "networkstatus status = " << result << endl;
00206       // if it's not unknown (no networks announced by network control apps), and not offline, give up now
00207       if ( ( result != NetWorkStatusUnknown ) && ( result != NetWorkStatusOnline ) )
00208       {
00209         emit checkedMail( false, mInteractive, mTotalNewInFolder );
00210         return;
00211      }
00212     }
00213   }
00214 
00215   connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00216                 this, SLOT( processNextCheck( bool ) ) );
00217 
00218   KPIM::BroadcastStatus::instance()->setStatusMsg(
00219       i18n("Checking account %1 for new mail").arg(curAccount->name()));
00220 
00221   kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00222 
00223   curAccount->setCheckingMail( true );
00224   mAcctChecking.append( curAccount );
00225   kmkernel->filterMgr()->ref();
00226   curAccount->processNewMail( mInteractive );
00227 }
00228 
00229 //-----------------------------------------------------------------------------
00230 KMAccount* AccountManager::create( const QString &aType, const QString &aName, uint id )
00231 {
00232   KMAccount* act = 0;
00233   if ( id == 0 )
00234     id = createId();
00235 
00236   if ( aType == "local" ) {
00237     act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00238     act->setFolder( kmkernel->inboxFolder() );
00239   } else if ( aType == "maildir" ) {
00240     act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00241     act->setFolder( kmkernel->inboxFolder() );
00242   } else if ( aType == "pop" ) {
00243     act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
00244     act->setFolder( kmkernel->inboxFolder() );
00245   } else if ( aType == "imap" ) {
00246     act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00247   } else if (aType == "cachedimap") {
00248     act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00249   }
00250   if ( !act ) {
00251       kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
00252       return 0;
00253   }
00254   connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00255                 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00256   return act;
00257 }
00258 
00259 
00260 //-----------------------------------------------------------------------------
00261 void AccountManager::add( KMAccount *account )
00262 {
00263   if ( account ) {
00264     mAcctList.append( account );
00265     emit accountAdded( account );
00266     account->installTimer();
00267   }
00268 }
00269 
00270 
00271 //-----------------------------------------------------------------------------
00272 KMAccount* AccountManager::findByName(const QString &aName) const
00273 {
00274   if ( aName.isEmpty() ) return 0;
00275 
00276   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00277     if ( (*it)->name() == aName ) return (*it);
00278   }
00279   return 0;
00280 }
00281 
00282 
00283 //-----------------------------------------------------------------------------
00284 KMAccount* AccountManager::find( const uint id ) const
00285 {
00286   if (id == 0) return 0;
00287   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00288     if ( (*it)->id() == id ) return (*it);
00289   }
00290   return 0;
00291 }
00292 
00293 
00294 //-----------------------------------------------------------------------------
00295 KMAccount* AccountManager::first()
00296 {
00297   if ( !mAcctList.empty() ) {
00298     mPtrListInterfaceProxyIterator = mAcctList.begin();
00299     return *mPtrListInterfaceProxyIterator;
00300   } else {
00301     return 0;
00302   }
00303 }
00304 
00305 //-----------------------------------------------------------------------------
00306 KMAccount* AccountManager::next()
00307 {
00308     ++mPtrListInterfaceProxyIterator;
00309     if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
00310         return 0;
00311     else
00312         return *mPtrListInterfaceProxyIterator;
00313 }
00314 
00315 //-----------------------------------------------------------------------------
00316 bool AccountManager::remove( KMAccount* acct )
00317 {
00318   if( !acct )
00319     return false;
00320   mAcctList.remove( acct );
00321   emit accountRemoved( acct );
00322   return true;
00323 }
00324 
00325 //-----------------------------------------------------------------------------
00326 void AccountManager::checkMail( bool _interactive )
00327 {
00328   mNewMailArrived = false;
00329 
00330   if ( mAcctList.isEmpty() ) {
00331     KMessageBox::information( 0,i18n("You need to add an account in the network "
00332                     "section of the settings in order to receive mail.") );
00333     return;
00334   }
00335   mDisplaySummary = true;
00336 
00337   mTotalNewMailsArrived=0;
00338   mTotalNewInFolder.clear();
00339 
00340   for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00341     if ( !(*it)->checkExclude() )
00342       singleCheckMail( (*it), _interactive);
00343   }
00344 }
00345 
00346 
00347 //-----------------------------------------------------------------------------
00348 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
00349   account->invalidateIMAPFolders();
00350 }
00351 
00352 
00353 void AccountManager::invalidateIMAPFolders()
00354 {
00355   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00356     singleInvalidateIMAPFolders( *it );
00357 }
00358 
00359 
00360 //-----------------------------------------------------------------------------
00361 QStringList  AccountManager::getAccounts() const
00362 {
00363   QStringList strList;
00364   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00365     strList.append( (*it)->name() );
00366   }
00367   return strList;
00368 }
00369 
00370 //-----------------------------------------------------------------------------
00371 void AccountManager::intCheckMail(int item, bool _interactive)
00372 {
00373   mNewMailArrived = false;
00374   mTotalNewMailsArrived = 0;
00375   mTotalNewInFolder.clear();
00376   if ( KMAccount *acct = mAcctList[ item ] )
00377     singleCheckMail( acct, _interactive );
00378   mDisplaySummary = false;
00379 }
00380 
00381 
00382 //-----------------------------------------------------------------------------
00383 void AccountManager::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00384 {
00385   for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00386         it != newInFolder.end(); ++it ) {
00387     mTotalNewMailsArrived += it.data();
00388     if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00389       mTotalNewInFolder[it.key()] = it.data();
00390     else
00391       mTotalNewInFolder[it.key()] += it.data();
00392   }
00393 }
00394 
00395 //-----------------------------------------------------------------------------
00396 uint AccountManager::createId()
00397 {
00398   QValueList<uint> usedIds;
00399   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00400     usedIds << (*it)->id();
00401   }
00402 
00403   usedIds << 0; // 0 is default for unknown
00404   int newId;
00405   do
00406   {
00407     newId = kapp->random();
00408   } while ( usedIds.find(newId) != usedIds.end() );
00409 
00410   return newId;
00411 }
00412 
00413 //-----------------------------------------------------------------------------
00414 void AccountManager::cancelMailCheck()
00415 {
00416   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00417     (*it)->cancelMailCheck();
00418   }
00419 }
00420 
00421 
00422 //-----------------------------------------------------------------------------
00423 void AccountManager::readPasswords()
00424 {
00425   for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00426     NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
00427     if ( acct )
00428       acct->readPassword();
00429   }
00430 }
00431 
00432 #include "accountmanager.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys