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