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"