00001
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 <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
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
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
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
00118
00119
00120 if ( mInteractive )
00121 account->readTimerConfig();
00122
00123
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
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
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;
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 connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00194 this, SLOT( processNextCheck( bool ) ) );
00195
00196 KPIM::BroadcastStatus::instance()->setStatusMsg(
00197 i18n("Checking account %1 for new mail").arg(curAccount->name()));
00198
00199 kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00200
00201 curAccount->setCheckingMail( true );
00202 mAcctChecking.append( curAccount );
00203 kmkernel->filterMgr()->ref();
00204 curAccount->processNewMail( mInteractive );
00205 }
00206
00207
00208 KMAccount* AccountManager::create( const QString &aType, const QString &aName, uint id )
00209 {
00210 KMAccount* act = 0;
00211 if ( id == 0 )
00212 id = createId();
00213
00214 if ( aType == "local" ) {
00215 act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00216 act->setFolder( kmkernel->inboxFolder() );
00217 } else if ( aType == "maildir" ) {
00218 act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00219 act->setFolder( kmkernel->inboxFolder() );
00220 } else if ( aType == "pop" ) {
00221 act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
00222 act->setFolder( kmkernel->inboxFolder() );
00223 } else if ( aType == "imap" ) {
00224 act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00225 } else if (aType == "cachedimap") {
00226 act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00227 }
00228 if ( !act ) {
00229 kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
00230 return 0;
00231 }
00232 connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00233 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00234 return act;
00235 }
00236
00237
00238
00239 void AccountManager::add( KMAccount *account )
00240 {
00241 if ( account ) {
00242 mAcctList.append( account );
00243
00244 KMAcctFolder *folder = static_cast<KMAcctFolder*>( account->folder() );
00245 if ( folder && !folder->hasAccounts() ) {
00246 folder->addAccount( account );
00247 }
00248 emit accountAdded( account );
00249 account->installTimer();
00250 }
00251 }
00252
00253
00254
00255 KMAccount* AccountManager::findByName(const QString &aName) const
00256 {
00257 if ( aName.isEmpty() ) return 0;
00258
00259 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00260 if ( (*it)->name() == aName ) return (*it);
00261 }
00262 return 0;
00263 }
00264
00265
00266
00267 KMAccount* AccountManager::find( const uint id ) const
00268 {
00269 if (id == 0) return 0;
00270 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00271 if ( (*it)->id() == id ) return (*it);
00272 }
00273 return 0;
00274 }
00275
00276
00277
00278 KMAccount* AccountManager::first()
00279 {
00280 if ( !mAcctList.empty() ) {
00281 mPtrListInterfaceProxyIterator = mAcctList.begin();
00282 return *mPtrListInterfaceProxyIterator;
00283 } else {
00284 return 0;
00285 }
00286 }
00287
00288
00289 KMAccount* AccountManager::next()
00290 {
00291 ++mPtrListInterfaceProxyIterator;
00292 if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
00293 return 0;
00294 else
00295 return *mPtrListInterfaceProxyIterator;
00296 }
00297
00298
00299 bool AccountManager::remove( KMAccount* acct )
00300 {
00301 if( !acct )
00302 return false;
00303 mAcctList.remove( acct );
00304 emit accountRemoved( acct );
00305 return true;
00306 }
00307
00308
00309 void AccountManager::checkMail( bool _interactive )
00310 {
00311 mNewMailArrived = false;
00312
00313 if ( mAcctList.isEmpty() ) {
00314 KMessageBox::information( 0,i18n("You need to add an account in the network "
00315 "section of the settings in order to receive mail.") );
00316 return;
00317 }
00318 mDisplaySummary = true;
00319
00320 mTotalNewMailsArrived=0;
00321 mTotalNewInFolder.clear();
00322
00323 for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00324 if ( !(*it)->checkExclude() )
00325 singleCheckMail( (*it), _interactive);
00326 }
00327 }
00328
00329
00330
00331 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
00332 account->invalidateIMAPFolders();
00333 }
00334
00335
00336 void AccountManager::invalidateIMAPFolders()
00337 {
00338 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00339 singleInvalidateIMAPFolders( *it );
00340 }
00341
00342
00343
00344 QStringList AccountManager::getAccounts() const
00345 {
00346 QStringList strList;
00347 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00348 strList.append( (*it)->name() );
00349 }
00350 return strList;
00351 }
00352
00353
00354 void AccountManager::intCheckMail(int item, bool _interactive)
00355 {
00356 mNewMailArrived = false;
00357 mTotalNewMailsArrived = 0;
00358 mTotalNewInFolder.clear();
00359 if ( KMAccount *acct = mAcctList[ item ] )
00360 singleCheckMail( acct, _interactive );
00361 mDisplaySummary = false;
00362 }
00363
00364
00365
00366 void AccountManager::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00367 {
00368 for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00369 it != newInFolder.end(); ++it ) {
00370 mTotalNewMailsArrived += it.data();
00371 if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00372 mTotalNewInFolder[it.key()] = it.data();
00373 else
00374 mTotalNewInFolder[it.key()] += it.data();
00375 }
00376 }
00377
00378
00379 uint AccountManager::createId()
00380 {
00381 QValueList<uint> usedIds;
00382 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00383 usedIds << (*it)->id();
00384 }
00385
00386 usedIds << 0;
00387 int newId;
00388 do
00389 {
00390 newId = kapp->random();
00391 } while ( usedIds.find(newId) != usedIds.end() );
00392
00393 return newId;
00394 }
00395
00396
00397 void AccountManager::cancelMailCheck()
00398 {
00399 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00400 (*it)->cancelMailCheck();
00401 }
00402 }
00403
00404
00405
00406 void AccountManager::readPasswords()
00407 {
00408 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00409 NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
00410 if ( acct )
00411 acct->readPassword();
00412 }
00413 }
00414
00415 #include "accountmanager.moc"