00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006
00007 #include "kmacctmgr.h"
00008
00009 #include "kmacctmaildir.h"
00010 #include "kmacctlocal.h"
00011 #include "kmacctexppop.h"
00012 #include "kmacctimap.h"
00013 #include "networkaccount.h"
00014 using KMail::NetworkAccount;
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 KPIM::BroadcastStatus;
00030
00031
00032 KMAcctMgr::KMAcctMgr(): QObject()
00033 {
00034 mAcctList.setAutoDelete(TRUE);
00035 mAcctChecking.clear();
00036 mAcctTodo.clear();
00037 mTotalNewMailsArrived=0;
00038 mDisplaySummary = false;
00039 }
00040
00041
00042
00043 KMAcctMgr::~KMAcctMgr()
00044 {
00045 writeConfig(FALSE);
00046 }
00047
00048
00049
00050 void KMAcctMgr::writeConfig(bool withSync)
00051 {
00052 KConfig* config = KMKernel::config();
00053 QString groupName;
00054
00055 KConfigGroupSaver saver(config, "General");
00056 config->writeEntry("accounts", mAcctList.count());
00057
00058
00059 QStringList accountGroups =
00060 config->groupList().grep( QRegExp( "Account \\d+" ) );
00061 for ( QStringList::Iterator it = accountGroups.begin() ;
00062 it != accountGroups.end() ; ++it )
00063 config->deleteGroup( *it );
00064
00065
00066 int i = 1;
00067 for ( QPtrListIterator<KMAccount> it(mAcctList) ;
00068 it.current() ; ++it, ++i ) {
00069 groupName.sprintf("Account %d", i);
00070 KConfigGroupSaver saver(config, groupName);
00071 (*it)->writeConfig(*config);
00072 }
00073 if (withSync) config->sync();
00074 }
00075
00076
00077
00078 void KMAcctMgr::readConfig(void)
00079 {
00080 KConfig* config = KMKernel::config();
00081 KMAccount* acct;
00082 QString acctType, acctName;
00083 QCString groupName;
00084 int i, num;
00085 uint id;
00086
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 KMAcctMgr::singleCheckMail(KMAccount *account, bool _interactive)
00113 {
00114 newMailArrived = false;
00115 interactive = _interactive;
00116
00117
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 KMAcctMgr::processNextCheck(bool _newMail)
00131 {
00132 kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
00133 KMAccount *curAccount = 0;
00134 newMailArrived |= _newMail;
00135
00136 KMAccount* acct;
00137 for ( acct = mAcctChecking.first(); acct; acct = mAcctChecking.next() )
00138 {
00139 if ( !acct->checkingMail() )
00140 {
00141
00142 kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
00143 mAcctChecking.removeRef( acct );
00144 kmkernel->filterMgr()->deref();
00145 disconnect( acct, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00146 this, SLOT( processNextCheck( bool ) ) );
00147 QString hostname = hostForAccount( acct );
00148 if ( !hostname.isEmpty() ) {
00149 if ( mServerConnections.find( hostname ) != mServerConnections.end() ) {
00150 mServerConnections[hostname] -= 1;
00151 kdDebug(5006) << "connections to server " << hostname
00152 << " now " << mServerConnections[hostname] << endl;
00153 }
00154 }
00155 }
00156 }
00157 if (mAcctChecking.isEmpty())
00158 {
00159
00160 if ( mDisplaySummary )
00161 BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00162 mTotalNewMailsArrived );
00163 emit checkedMail( newMailArrived, interactive, mTotalNewInFolder );
00164 mTotalNewMailsArrived = 0;
00165 mTotalNewInFolder.clear();
00166 mDisplaySummary = false;
00167 }
00168 if (mAcctTodo.isEmpty()) return;
00169
00170 QString accountHostName;
00171
00172 curAccount = 0;
00173 KMAcctList::Iterator it ( mAcctTodo.begin() );
00174 KMAcctList::Iterator last ( mAcctTodo.end() );
00175 for ( ; it != last; it++ )
00176 {
00177 accountHostName = hostForAccount(*it);
00178 kdDebug(5006) << "for host " << accountHostName
00179 << " current connections="
00180 << (mServerConnections.find(accountHostName)==mServerConnections.end() ? 0 : mServerConnections[accountHostName])
00181 << " and limit is " << GlobalSettings::maxConnectionsPerHost()
00182 << endl;
00183 bool connectionLimitForHostReached =
00184 !accountHostName.isNull() &&
00185 GlobalSettings::maxConnectionsPerHost() > 0 &&
00186 mServerConnections.find( accountHostName ) != mServerConnections.end() &&
00187 mServerConnections[accountHostName] >= GlobalSettings::maxConnectionsPerHost();
00188 kdDebug(5006) << "connection limit reached: "
00189 << connectionLimitForHostReached << endl;
00190 if ( !(*it)->checkingMail() && !connectionLimitForHostReached ) {
00191 curAccount = (*it);
00192 mAcctTodo.remove( curAccount );
00193 break;
00194 }
00195 }
00196 if ( !curAccount ) return;
00197
00198 if (curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
00199 curAccount->folder() == 0)
00200 {
00201 QString tmp = i18n("Account %1 has no mailbox defined:\n"
00202 "mail checking aborted;\n"
00203 "check your account settings.")
00204 .arg(curAccount->name());
00205 KMessageBox::information(0,tmp);
00206 emit checkedMail( false, interactive, mTotalNewInFolder );
00207 mTotalNewMailsArrived = 0;
00208 mTotalNewInFolder.clear();
00209 return;
00210 }
00211
00212 connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00213 this, SLOT( processNextCheck( bool ) ) );
00214
00215 BroadcastStatus::instance()->setStatusMsg(
00216 i18n("Checking account %1 for new mail").arg(curAccount->name()));
00217
00218 kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00219
00220 curAccount->setCheckingMail(true);
00221 mAcctChecking.append(curAccount);
00222 kmkernel->filterMgr()->ref();
00223 curAccount->processNewMail(interactive);
00224
00225 if ( !accountHostName.isEmpty() ) {
00226 if ( mServerConnections.find( accountHostName ) != mServerConnections.end() )
00227 mServerConnections[accountHostName] += 1;
00228 else
00229 mServerConnections[accountHostName] = 1;
00230 kdDebug(5006) << "check mail started - connections for host "
00231 << accountHostName << " now is "
00232 << mServerConnections[accountHostName] << endl;
00233 }
00234 }
00235
00236
00237 KMAccount* KMAcctMgr::create(const QString &aType, const QString &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, id);
00245
00246 if (aType == "maildir")
00247 act = new KMAcctMaildir(this, aName, id);
00248
00249 else if (aType == "pop")
00250 act = new KMAcctExpPop(this, aName, id);
00251
00252 else if (aType == "imap")
00253 act = new KMAcctImap(this, aName, id);
00254
00255 else if (aType == "cachedimap")
00256 act = new KMAcctCachedImap(this, aName, id);
00257
00258 if (act)
00259 {
00260 if (aType != "imap" && aType != "cachedimap")
00261 act->setFolder(kmkernel->inboxFolder());
00262 connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00263 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00264 }
00265
00266 return act;
00267 }
00268
00269
00270
00271 void KMAcctMgr::add(KMAccount *account)
00272 {
00273 if (account) {
00274 mAcctList.append( account );
00275 emit accountAdded( account );
00276 }
00277 }
00278
00279
00280
00281 KMAccount* KMAcctMgr::findByName(const QString &aName)
00282 {
00283 if (aName.isEmpty()) return 0;
00284
00285 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00286 {
00287 if ((*it)->name() == aName) return (*it);
00288 }
00289
00290 return 0;
00291 }
00292
00293
00294
00295 KMAccount* KMAcctMgr::find(const uint id)
00296 {
00297 if (id == 0) return 0;
00298
00299 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00300 {
00301 if ((*it)->id() == id) return (*it);
00302 }
00303
00304 return 0;
00305 }
00306
00307
00308
00309 KMAccount* KMAcctMgr::first(void)
00310 {
00311 return mAcctList.first();
00312 }
00313
00314
00315
00316 KMAccount* KMAcctMgr::next(void)
00317 {
00318 return mAcctList.next();
00319 }
00320
00321
00322
00323 bool KMAcctMgr::remove( KMAccount* acct )
00324 {
00325 if( !acct )
00326 return false;
00327 mAcctList.removeRef( acct );
00328 emit accountRemoved( acct );
00329 return true;
00330 }
00331
00332
00333 void KMAcctMgr::checkMail(bool _interactive)
00334 {
00335 newMailArrived = false;
00336
00337 if (mAcctList.isEmpty())
00338 {
00339 KMessageBox::information(0,i18n("You need to add an account in the network "
00340 "section of the settings in order to "
00341 "receive mail."));
00342 return;
00343 }
00344 mDisplaySummary = true;
00345
00346 mTotalNewMailsArrived=0;
00347 mTotalNewInFolder.clear();
00348
00349 for ( QPtrListIterator<KMAccount> it(mAcctList) ;
00350 it.current() ; ++it )
00351 {
00352 if (!it.current()->checkExclude())
00353 singleCheckMail(it.current(), _interactive);
00354 }
00355 }
00356
00357
00358
00359 void KMAcctMgr::singleInvalidateIMAPFolders(KMAccount *account) {
00360 account->invalidateIMAPFolders();
00361 }
00362
00363
00364 void KMAcctMgr::invalidateIMAPFolders()
00365 {
00366 if (mAcctList.isEmpty()) {
00367 KMessageBox::information(0,i18n("You need to add an account in the network "
00368 "section of the settings in order to "
00369 "receive mail."));
00370 return;
00371 }
00372
00373 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00374 singleInvalidateIMAPFolders(it.current());
00375 }
00376
00377
00378
00379 QStringList KMAcctMgr::getAccounts(bool noImap) {
00380
00381 KMAccount *cur;
00382 QStringList strList;
00383 for (cur=mAcctList.first(); cur; cur=mAcctList.next()) {
00384 if (!noImap || cur->type() != "imap") strList.append(cur->name());
00385 }
00386
00387 return strList;
00388
00389 }
00390
00391
00392 void KMAcctMgr::intCheckMail(int item, bool _interactive)
00393 {
00394 KMAccount* cur;
00395 newMailArrived = false;
00396
00397 mTotalNewMailsArrived = 0;
00398 mTotalNewInFolder.clear();
00399 int x = 0;
00400 cur = mAcctList.first();
00401 while (cur)
00402 {
00403 x++;
00404 if (x > item) break;
00405 cur=mAcctList.next();
00406 }
00407 mDisplaySummary = false;
00408
00409 singleCheckMail(cur, _interactive);
00410 }
00411
00412
00413
00414 void KMAcctMgr::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00415 {
00416 for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00417 it != newInFolder.end();
00418 ++it )
00419 {
00420 mTotalNewMailsArrived += it.data();
00421 if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00422 mTotalNewInFolder[it.key()] = it.data();
00423 else
00424 mTotalNewInFolder[it.key()] += it.data();
00425 }
00426 }
00427
00428
00429 uint KMAcctMgr::createId()
00430 {
00431 QValueList<uint> usedIds;
00432 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00433 usedIds << it.current()->id();
00434
00435 usedIds << 0;
00436 int newId;
00437 do
00438 {
00439 newId = kapp->random();
00440 } while ( usedIds.find(newId) != usedIds.end() );
00441
00442 return newId;
00443 }
00444
00445
00446 void KMAcctMgr::cancelMailCheck()
00447 {
00448 for ( QPtrListIterator<KMAccount> it(mAcctList) ;
00449 it.current() ; ++it ) {
00450 it.current()->cancelMailCheck();
00451 }
00452 }
00453
00454
00455 QString KMAcctMgr::hostForAccount( const KMAccount *acct ) const
00456 {
00457 const NetworkAccount *net_acct = dynamic_cast<const NetworkAccount*>( acct );
00458 return net_acct ? net_acct->host() : QString::null;
00459 }
00460
00461 #include "kmacctmgr.moc"