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