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 "kmacctmaildir.h"
00011 #include "kmacctlocal.h"
00012 #include "popaccount.h"
00013 #include "kmacctimap.h"
00014 #include "networkaccount.h"
00015 #include "kmacctcachedimap.h"
00016 #include "broadcaststatus.h"
00017 #include "kmfiltermgr.h"
00018 #include "globalsettings.h"
00019
00020 #include <dcopclient.h>
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 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 AccountManager::processNextCheck( bool _newMail )
00131 {
00132 kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
00133 if ( _newMail )
00134 mNewMailArrived = true;
00135
00136 for ( AccountList::Iterator it( mAcctChecking.begin() ), end( mAcctChecking.end() ); it != end; ) {
00137 KMAccount* acct = *it;
00138 ++it;
00139 if ( acct->checkingMail() )
00140 continue;
00141
00142 kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
00143 mAcctChecking.remove( acct );
00144 kmkernel->filterMgr()->deref();
00145 disconnect( acct, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00146 this, SLOT( processNextCheck( bool ) ) );
00147 }
00148 if ( mAcctChecking.isEmpty() ) {
00149
00150 if ( mDisplaySummary )
00151 KPIM::BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00152 mTotalNewMailsArrived );
00153 emit checkedMail( mNewMailArrived, mInteractive, mTotalNewInFolder );
00154 mTotalNewMailsArrived = 0;
00155 mTotalNewInFolder.clear();
00156 mDisplaySummary = false;
00157 }
00158 if ( mAcctTodo.isEmpty() ) return;
00159
00160 QString accountHostName;
00161
00162 KMAccount *curAccount = 0;
00163 for ( AccountList::Iterator it ( mAcctTodo.begin() ), last ( mAcctTodo.end() ); it != last; ) {
00164 KMAccount *acct = *it;
00165 ++it;
00166 if ( !acct->checkingMail() && acct->mailCheckCanProceed() ) {
00167 curAccount = acct;
00168 mAcctTodo.remove( acct );
00169 break;
00170 }
00171 }
00172 if ( !curAccount ) return;
00173
00174 if ( curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
00175 curAccount->folder() == 0 ) {
00176 QString tmp = i18n("Account %1 has no mailbox defined:\n"
00177 "mail checking aborted;\n"
00178 "check your account settings.")
00179 .arg(curAccount->name());
00180 KMessageBox::information(0,tmp);
00181 emit checkedMail( false, mInteractive, mTotalNewInFolder );
00182 mTotalNewMailsArrived = 0;
00183 mTotalNewInFolder.clear();
00184 return;
00185 }
00186
00187 if ( curAccount->type() == "imap" || curAccount->type() == "cachedimap" || curAccount->type() == "pop" )
00188 {
00189
00190 const int NetWorkStatusUnknown = 1;
00191 const int NetWorkStatusOnline = 8;
00192 QCString replyType;
00193 QByteArray params;
00194 QByteArray reply;
00195
00196 QDataStream stream( params, IO_WriteOnly );
00197 stream << static_cast<NetworkAccount*>( curAccount )->host();
00198
00199 if ( kapp->dcopClient()->call( "kded", "networkstatus", "status(QString)",
00200 params, replyType, reply ) && ( replyType == "int" ) )
00201 {
00202 int result;
00203 QDataStream stream2( reply, IO_ReadOnly );
00204 stream2 >> result;
00205 kdDebug() << k_funcinfo << "networkstatus status = " << result << endl;
00206
00207 if ( ( result != NetWorkStatusUnknown ) && ( result != NetWorkStatusOnline ) )
00208 {
00209 emit checkedMail( false, mInteractive, mTotalNewInFolder );
00210 return;
00211 }
00212 }
00213 }
00214
00215 connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00216 this, SLOT( processNextCheck( bool ) ) );
00217
00218 KPIM::BroadcastStatus::instance()->setStatusMsg(
00219 i18n("Checking account %1 for new mail").arg(curAccount->name()));
00220
00221 kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00222
00223 curAccount->setCheckingMail( true );
00224 mAcctChecking.append( curAccount );
00225 kmkernel->filterMgr()->ref();
00226 curAccount->processNewMail( mInteractive );
00227 }
00228
00229
00230 KMAccount* AccountManager::create( const QString &aType, const QString &aName, uint id )
00231 {
00232 KMAccount* act = 0;
00233 if ( id == 0 )
00234 id = createId();
00235
00236 if ( aType == "local" ) {
00237 act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00238 act->setFolder( kmkernel->inboxFolder() );
00239 } else if ( aType == "maildir" ) {
00240 act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00241 act->setFolder( kmkernel->inboxFolder() );
00242 } else if ( aType == "pop" ) {
00243 act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
00244 act->setFolder( kmkernel->inboxFolder() );
00245 } else if ( aType == "imap" ) {
00246 act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00247 } else if (aType == "cachedimap") {
00248 act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00249 }
00250 if ( !act ) {
00251 kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
00252 return 0;
00253 }
00254 connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00255 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00256 return act;
00257 }
00258
00259
00260
00261 void AccountManager::add( KMAccount *account )
00262 {
00263 if ( account ) {
00264 mAcctList.append( account );
00265 emit accountAdded( account );
00266 account->installTimer();
00267 }
00268 }
00269
00270
00271
00272 KMAccount* AccountManager::findByName(const QString &aName) const
00273 {
00274 if ( aName.isEmpty() ) return 0;
00275
00276 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00277 if ( (*it)->name() == aName ) return (*it);
00278 }
00279 return 0;
00280 }
00281
00282
00283
00284 KMAccount* AccountManager::find( const uint id ) const
00285 {
00286 if (id == 0) return 0;
00287 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00288 if ( (*it)->id() == id ) return (*it);
00289 }
00290 return 0;
00291 }
00292
00293
00294
00295 KMAccount* AccountManager::first()
00296 {
00297 if ( !mAcctList.empty() ) {
00298 mPtrListInterfaceProxyIterator = mAcctList.begin();
00299 return *mPtrListInterfaceProxyIterator;
00300 } else {
00301 return 0;
00302 }
00303 }
00304
00305
00306 KMAccount* AccountManager::next()
00307 {
00308 ++mPtrListInterfaceProxyIterator;
00309 if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
00310 return 0;
00311 else
00312 return *mPtrListInterfaceProxyIterator;
00313 }
00314
00315
00316 bool AccountManager::remove( KMAccount* acct )
00317 {
00318 if( !acct )
00319 return false;
00320 mAcctList.remove( acct );
00321 emit accountRemoved( acct );
00322 return true;
00323 }
00324
00325
00326 void AccountManager::checkMail( bool _interactive )
00327 {
00328 mNewMailArrived = false;
00329
00330 if ( mAcctList.isEmpty() ) {
00331 KMessageBox::information( 0,i18n("You need to add an account in the network "
00332 "section of the settings in order to receive mail.") );
00333 return;
00334 }
00335 mDisplaySummary = true;
00336
00337 mTotalNewMailsArrived=0;
00338 mTotalNewInFolder.clear();
00339
00340 for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00341 if ( !(*it)->checkExclude() )
00342 singleCheckMail( (*it), _interactive);
00343 }
00344 }
00345
00346
00347
00348 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
00349 account->invalidateIMAPFolders();
00350 }
00351
00352
00353 void AccountManager::invalidateIMAPFolders()
00354 {
00355 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00356 singleInvalidateIMAPFolders( *it );
00357 }
00358
00359
00360
00361 QStringList AccountManager::getAccounts() const
00362 {
00363 QStringList strList;
00364 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00365 strList.append( (*it)->name() );
00366 }
00367 return strList;
00368 }
00369
00370
00371 void AccountManager::intCheckMail(int item, bool _interactive)
00372 {
00373 mNewMailArrived = false;
00374 mTotalNewMailsArrived = 0;
00375 mTotalNewInFolder.clear();
00376 if ( KMAccount *acct = mAcctList[ item ] )
00377 singleCheckMail( acct, _interactive );
00378 mDisplaySummary = false;
00379 }
00380
00381
00382
00383 void AccountManager::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00384 {
00385 for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00386 it != newInFolder.end(); ++it ) {
00387 mTotalNewMailsArrived += it.data();
00388 if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00389 mTotalNewInFolder[it.key()] = it.data();
00390 else
00391 mTotalNewInFolder[it.key()] += it.data();
00392 }
00393 }
00394
00395
00396 uint AccountManager::createId()
00397 {
00398 QValueList<uint> usedIds;
00399 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00400 usedIds << (*it)->id();
00401 }
00402
00403 usedIds << 0;
00404 int newId;
00405 do
00406 {
00407 newId = kapp->random();
00408 } while ( usedIds.find(newId) != usedIds.end() );
00409
00410 return newId;
00411 }
00412
00413
00414 void AccountManager::cancelMailCheck()
00415 {
00416 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00417 (*it)->cancelMailCheck();
00418 }
00419 }
00420
00421
00422
00423 void AccountManager::readPasswords()
00424 {
00425 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00426 NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
00427 if ( acct )
00428 acct->readPassword();
00429 }
00430 }
00431
00432 #include "accountmanager.moc"