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 <dcopclient.h>
00022 #include <klocale.h>
00023 #include <kmessagebox.h>
00024 #include <kdebug.h>
00025 #include <kconfig.h>
00026 #include <kapplication.h>
00027
00028 #include <qregexp.h>
00029 #include <qvaluelist.h>
00030
00031 using namespace KMail;
00032
00033
00034 AccountManager::AccountManager()
00035 :QObject(), mNewMailArrived( false ), mInteractive( false ),
00036 mTotalNewMailsArrived( 0 ), mDisplaySummary( false )
00037 {
00038 mAcctChecking.clear();
00039 mAcctTodo.clear();
00040 }
00041
00042
00043 AccountManager::~AccountManager()
00044 {
00045 writeConfig( false );
00046 }
00047
00048
00049
00050 void AccountManager::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 ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it, ++i ) {
00068 groupName.sprintf("Account %d", i);
00069 KConfigGroupSaver saver(config, groupName);
00070 (*it)->writeConfig(*config);
00071 }
00072 if (withSync) config->sync();
00073 }
00074
00075
00076
00077 void AccountManager::readConfig(void)
00078 {
00079 KConfig* config = KMKernel::config();
00080 KMAccount* acct;
00081 QString acctType, acctName;
00082 QCString groupName;
00083 int i, num;
00084 uint id;
00085
00086 for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00087 delete *it;
00088 mAcctList.clear();
00089
00090 KConfigGroup general(config, "General");
00091 num = general.readNumEntry("accounts", 0);
00092
00093 for (i=1; i<=num; i++)
00094 {
00095 groupName.sprintf("Account %d", i);
00096 KConfigGroupSaver saver(config, groupName);
00097 acctType = config->readEntry("Type");
00098
00099 if (acctType == "advanced pop" || acctType == "experimental pop")
00100 acctType = "pop";
00101 acctName = config->readEntry("Name");
00102 id = config->readUnsignedNumEntry("Id", 0);
00103 if (acctName.isEmpty()) acctName = i18n("Account %1").arg(i);
00104 acct = create(acctType, acctName, id);
00105 if (!acct) continue;
00106 add(acct);
00107 acct->readConfig(*config);
00108 }
00109 }
00110
00111
00112
00113 void AccountManager::singleCheckMail(KMAccount *account, bool interactive)
00114 {
00115 mNewMailArrived = false;
00116 mInteractive = interactive;
00117
00118
00119
00120
00121 if ( mInteractive )
00122 account->readTimerConfig();
00123
00124
00125 mAcctTodo.append(account);
00126
00127 if (account->checkingMail())
00128 {
00129 kdDebug(5006) << "account " << account->name() << " busy, queuing" << endl;
00130 return;
00131 }
00132
00133 processNextCheck(false);
00134 }
00135
00136
00137 void AccountManager::processNextCheck( bool _newMail )
00138 {
00139 kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
00140 if ( _newMail )
00141 mNewMailArrived = true;
00142
00143 for ( AccountList::Iterator it( mAcctChecking.begin() ), end( mAcctChecking.end() ); it != end; ) {
00144 KMAccount* acct = *it;
00145 ++it;
00146 if ( acct->checkingMail() )
00147 continue;
00148
00149 kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
00150 mAcctChecking.remove( acct );
00151 kmkernel->filterMgr()->deref();
00152 disconnect( acct, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00153 this, SLOT( processNextCheck( bool ) ) );
00154 }
00155 if ( mAcctChecking.isEmpty() ) {
00156
00157 if ( mDisplaySummary )
00158 KPIM::BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
00159 mTotalNewMailsArrived );
00160 emit checkedMail( mNewMailArrived, mInteractive, mTotalNewInFolder );
00161 mTotalNewMailsArrived = 0;
00162 mTotalNewInFolder.clear();
00163 mDisplaySummary = false;
00164 }
00165 if ( mAcctTodo.isEmpty() ) return;
00166
00167 QString accountHostName;
00168
00169 KMAccount *curAccount = 0;
00170 for ( AccountList::Iterator it ( mAcctTodo.begin() ), last ( mAcctTodo.end() ); it != last; ) {
00171 KMAccount *acct = *it;
00172 ++it;
00173 if ( !acct->checkingMail() && acct->mailCheckCanProceed() ) {
00174 curAccount = acct;
00175 mAcctTodo.remove( acct );
00176 break;
00177 }
00178 }
00179 if ( !curAccount ) return;
00180
00181 if ( curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
00182 curAccount->folder() == 0 ) {
00183 QString tmp = i18n("Account %1 has no mailbox defined:\n"
00184 "mail checking aborted;\n"
00185 "check your account settings.")
00186 .arg(curAccount->name());
00187 KMessageBox::information(0,tmp);
00188 emit checkedMail( false, mInteractive, mTotalNewInFolder );
00189 mTotalNewMailsArrived = 0;
00190 mTotalNewInFolder.clear();
00191 return;
00192 }
00193
00194 if ( curAccount->type() == "imap" || curAccount->type() == "cachedimap" || curAccount->type() == "pop" )
00195 {
00196
00197 const int NetWorkStatusUnknown = 1;
00198 const int NetWorkStatusOnline = 8;
00199 QCString replyType;
00200 QByteArray params;
00201 QByteArray reply;
00202
00203 QDataStream stream( params, IO_WriteOnly );
00204 stream << static_cast<NetworkAccount*>( curAccount )->host();
00205
00206 if ( kapp->dcopClient()->call( "kded", "networkstatus", "status(QString)",
00207 params, replyType, reply ) && ( replyType == "int" ) )
00208 {
00209 int result;
00210 QDataStream stream2( reply, IO_ReadOnly );
00211 stream2 >> result;
00212 kdDebug() << k_funcinfo << "networkstatus status = " << result << endl;
00213
00214 if ( ( result != NetWorkStatusUnknown ) && ( result != NetWorkStatusOnline ) )
00215 {
00216 emit checkedMail( false, mInteractive, mTotalNewInFolder );
00217 return;
00218 }
00219 }
00220 }
00221
00222 connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
00223 this, SLOT( processNextCheck( bool ) ) );
00224
00225 KPIM::BroadcastStatus::instance()->setStatusMsg(
00226 i18n("Checking account %1 for new mail").arg(curAccount->name()));
00227
00228 kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
00229
00230 curAccount->setCheckingMail( true );
00231 mAcctChecking.append( curAccount );
00232 kmkernel->filterMgr()->ref();
00233 curAccount->processNewMail( mInteractive );
00234 }
00235
00236
00237 KMAccount* AccountManager::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.isEmpty() ? i18n("Local Account") : aName, id);
00245 act->setFolder( kmkernel->inboxFolder() );
00246 } else if ( aType == "maildir" ) {
00247 act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
00248 act->setFolder( kmkernel->inboxFolder() );
00249 } else if ( aType == "pop" ) {
00250 act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
00251 act->setFolder( kmkernel->inboxFolder() );
00252 } else if ( aType == "imap" ) {
00253 act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00254 } else if (aType == "cachedimap") {
00255 act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
00256 }
00257 if ( !act ) {
00258 kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
00259 return 0;
00260 }
00261 connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
00262 this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
00263 return act;
00264 }
00265
00266
00267
00268 void AccountManager::add( KMAccount *account )
00269 {
00270 if ( account ) {
00271 mAcctList.append( account );
00272
00273 KMAcctFolder *folder = static_cast<KMAcctFolder*>( account->folder() );
00274 if ( folder && !folder->hasAccounts() ) {
00275 folder->addAccount( account );
00276 }
00277 emit accountAdded( account );
00278 account->installTimer();
00279 }
00280 }
00281
00282
00283
00284 KMAccount* AccountManager::findByName(const QString &aName) const
00285 {
00286 if ( aName.isEmpty() ) return 0;
00287
00288 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00289 if ( (*it)->name() == aName ) return (*it);
00290 }
00291 return 0;
00292 }
00293
00294
00295
00296 KMAccount* AccountManager::find( const uint id ) const
00297 {
00298 if (id == 0) return 0;
00299 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00300 if ( (*it)->id() == id ) return (*it);
00301 }
00302 return 0;
00303 }
00304
00305
00306
00307 KMAccount* AccountManager::first()
00308 {
00309 if ( !mAcctList.empty() ) {
00310 mPtrListInterfaceProxyIterator = mAcctList.begin();
00311 return *mPtrListInterfaceProxyIterator;
00312 } else {
00313 return 0;
00314 }
00315 }
00316
00317
00318 KMAccount* AccountManager::next()
00319 {
00320 ++mPtrListInterfaceProxyIterator;
00321 if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
00322 return 0;
00323 else
00324 return *mPtrListInterfaceProxyIterator;
00325 }
00326
00327
00328 bool AccountManager::remove( KMAccount* acct )
00329 {
00330 if( !acct )
00331 return false;
00332 mAcctList.remove( acct );
00333 emit accountRemoved( acct );
00334 return true;
00335 }
00336
00337
00338 void AccountManager::checkMail( bool _interactive )
00339 {
00340 mNewMailArrived = false;
00341
00342 if ( mAcctList.isEmpty() ) {
00343 KMessageBox::information( 0,i18n("You need to add an account in the network "
00344 "section of the settings in order to receive mail.") );
00345 return;
00346 }
00347 mDisplaySummary = true;
00348
00349 mTotalNewMailsArrived=0;
00350 mTotalNewInFolder.clear();
00351
00352 for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00353 if ( !(*it)->checkExclude() )
00354 singleCheckMail( (*it), _interactive);
00355 }
00356 }
00357
00358
00359
00360 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
00361 account->invalidateIMAPFolders();
00362 }
00363
00364
00365 void AccountManager::invalidateIMAPFolders()
00366 {
00367 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
00368 singleInvalidateIMAPFolders( *it );
00369 }
00370
00371
00372
00373 QStringList AccountManager::getAccounts() const
00374 {
00375 QStringList strList;
00376 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00377 strList.append( (*it)->name() );
00378 }
00379 return strList;
00380 }
00381
00382
00383 void AccountManager::intCheckMail(int item, bool _interactive)
00384 {
00385 mNewMailArrived = false;
00386 mTotalNewMailsArrived = 0;
00387 mTotalNewInFolder.clear();
00388 if ( KMAccount *acct = mAcctList[ item ] )
00389 singleCheckMail( acct, _interactive );
00390 mDisplaySummary = false;
00391 }
00392
00393
00394
00395 void AccountManager::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
00396 {
00397 for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
00398 it != newInFolder.end(); ++it ) {
00399 mTotalNewMailsArrived += it.data();
00400 if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
00401 mTotalNewInFolder[it.key()] = it.data();
00402 else
00403 mTotalNewInFolder[it.key()] += it.data();
00404 }
00405 }
00406
00407
00408 uint AccountManager::createId()
00409 {
00410 QValueList<uint> usedIds;
00411 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00412 usedIds << (*it)->id();
00413 }
00414
00415 usedIds << 0;
00416 int newId;
00417 do
00418 {
00419 newId = kapp->random();
00420 } while ( usedIds.find(newId) != usedIds.end() );
00421
00422 return newId;
00423 }
00424
00425
00426 void AccountManager::cancelMailCheck()
00427 {
00428 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00429 (*it)->cancelMailCheck();
00430 }
00431 }
00432
00433
00434
00435 void AccountManager::readPasswords()
00436 {
00437 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
00438 NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
00439 if ( acct )
00440 acct->readPassword();
00441 }
00442 }
00443
00444 #include "accountmanager.moc"