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