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