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::self()->maxConnectionsPerHost()
00182 << endl;
00183 bool connectionLimitForHostReached =
00184 !accountHostName.isNull() &&
00185 GlobalSettings::self()->maxConnectionsPerHost() > 0 &&
00186 mServerConnections.find( accountHostName ) != mServerConnections.end() &&
00187 mServerConnections[accountHostName] >= GlobalSettings::self()->maxConnectionsPerHost();
00188 kdDebug(5006) << "connection limit reached: "
00189 << connectionLimitForHostReached << endl;
00190 if ( !(*it)->checkingMail() && !connectionLimitForHostReached && !kmkernel->isOffline() ) {
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 account->installTimer();
00277 }
00278 }
00279
00280
00281
00282 KMAccount* KMAcctMgr::findByName(const QString &aName)
00283 {
00284 if (aName.isEmpty()) return 0;
00285
00286 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00287 {
00288 if ((*it)->name() == aName) return (*it);
00289 }
00290
00291 return 0;
00292 }
00293
00294
00295
00296 KMAccount* KMAcctMgr::find(const uint id)
00297 {
00298 if (id == 0) return 0;
00299
00300 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00301 {
00302 if ((*it)->id() == id) return (*it);
00303 }
00304
00305 return 0;
00306 }
00307
00308
00309
00310 KMAccount* KMAcctMgr::first(void)
00311 {
00312 return mAcctList.first();
00313 }
00314
00315
00316
00317 KMAccount* KMAcctMgr::next(void)
00318 {
00319 return mAcctList.next();
00320 }
00321
00322
00323
00324 bool KMAcctMgr::remove( KMAccount* acct )
00325 {
00326 if( !acct )
00327 return false;
00328 mAcctList.removeRef( acct );
00329 emit accountRemoved( acct );
00330 return true;
00331 }
00332
00333
00334 void KMAcctMgr::checkMail(bool _interactive)
00335 {
00336 newMailArrived = false;
00337
00338 if (mAcctList.isEmpty())
00339 {
00340 KMessageBox::information(0,i18n("You need to add an account in the network "
00341 "section of the settings in order to "
00342 "receive mail."));
00343 return;
00344 }
00345 mDisplaySummary = true;
00346
00347 mTotalNewMailsArrived=0;
00348 mTotalNewInFolder.clear();
00349
00350 for ( QPtrListIterator<KMAccount> it(mAcctList) ;
00351 it.current() ; ++it )
00352 {
00353 if (!it.current()->checkExclude())
00354 singleCheckMail(it.current(), _interactive);
00355 }
00356 }
00357
00358
00359
00360 void KMAcctMgr::singleInvalidateIMAPFolders(KMAccount *account) {
00361 account->invalidateIMAPFolders();
00362 }
00363
00364
00365 void KMAcctMgr::invalidateIMAPFolders()
00366 {
00367 if (mAcctList.isEmpty()) {
00368 KMessageBox::information(0,i18n("You need to add an account in the network "
00369 "section of the settings in order to "
00370 "receive mail."));
00371 return;
00372 }
00373
00374 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00375 singleInvalidateIMAPFolders(it.current());
00376 }
00377
00378
00379
00380 QStringList KMAcctMgr::getAccounts(bool noImap) {
00381
00382 KMAccount *cur;
00383 QStringList strList;
00384 for (cur=mAcctList.first(); cur; cur=mAcctList.next()) {
00385 if (!noImap || cur->type() != "imap") strList.append(cur->name());
00386 }
00387
00388 return strList;
00389
00390 }
00391
00392
00393 void KMAcctMgr::intCheckMail(int item, bool _interactive)
00394 {
00395 KMAccount* cur;
00396 newMailArrived = false;
00397
00398 mTotalNewMailsArrived = 0;
00399 mTotalNewInFolder.clear();
00400 int x = 0;
00401 cur = mAcctList.first();
00402 while (cur)
00403 {
00404 x++;
00405 if (x > item) break;
00406 cur=mAcctList.next();
00407 }
00408 mDisplaySummary = false;
00409
00410 singleCheckMail(cur, _interactive);
00411 }
00412
00413
00414
00415 void KMAcctMgr::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00416 {
00417 for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00418 it != newInFolder.end();
00419 ++it )
00420 {
00421 mTotalNewMailsArrived += it.data();
00422 if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00423 mTotalNewInFolder[it.key()] = it.data();
00424 else
00425 mTotalNewInFolder[it.key()] += it.data();
00426 }
00427 }
00428
00429
00430 uint KMAcctMgr::createId()
00431 {
00432 QValueList<uint> usedIds;
00433 for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
00434 usedIds << it.current()->id();
00435
00436 usedIds << 0;
00437 int newId;
00438 do
00439 {
00440 newId = kapp->random();
00441 } while ( usedIds.find(newId) != usedIds.end() );
00442
00443 return newId;
00444 }
00445
00446
00447 void KMAcctMgr::cancelMailCheck()
00448 {
00449 for ( QPtrListIterator<KMAccount> it(mAcctList) ;
00450 it.current() ; ++it ) {
00451 it.current()->cancelMailCheck();
00452 }
00453 }
00454
00455
00456 QString KMAcctMgr::hostForAccount( const KMAccount *acct ) const
00457 {
00458 const NetworkAccount *net_acct = dynamic_cast<const NetworkAccount*>( acct );
00459 return net_acct ? net_acct->host() : QString::null;
00460 }
00461
00462 #include "kmacctmgr.moc"