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