You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

461 lines
13 KiB

// KMail Account Manager
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "kmacctmgr.h"
#include "kmacctmaildir.h"
#include "kmacctlocal.h"
#include "kmacctexppop.h"
#include "kmacctimap.h"
#include "networkaccount.h"
using KMail::NetworkAccount;
#include "kmacctcachedimap.h"
#include "broadcaststatus.h"
#include "kmfiltermgr.h"
#include "globalsettings.h"
#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kapplication.h>
#include <qregexp.h>
#include <qvaluelist.h>
using KPIM::BroadcastStatus;
//-----------------------------------------------------------------------------
KMAcctMgr::KMAcctMgr(): QObject()
{
mAcctList.setAutoDelete(TRUE);
mAcctChecking.clear();
mAcctTodo.clear();
mTotalNewMailsArrived=0;
mDisplaySummary = false;
}
//-----------------------------------------------------------------------------
KMAcctMgr::~KMAcctMgr()
{
writeConfig(FALSE);
}
//-----------------------------------------------------------------------------
void KMAcctMgr::writeConfig(bool withSync)
{
KConfig* config = KMKernel::config();
QString groupName;
KConfigGroupSaver saver(config, "General");
config->writeEntry("accounts", mAcctList.count());
// first delete all account groups in the config file:
QStringList accountGroups =
config->groupList().grep( QRegExp( "Account \\d+" ) );
for ( QStringList::Iterator it = accountGroups.begin() ;
it != accountGroups.end() ; ++it )
config->deleteGroup( *it );
// now write new account groups:
int i = 1;
for ( QPtrListIterator<KMAccount> it(mAcctList) ;
it.current() ; ++it, ++i ) {
groupName.sprintf("Account %d", i);
KConfigGroupSaver saver(config, groupName);
(*it)->writeConfig(*config);
}
if (withSync) config->sync();
}
//-----------------------------------------------------------------------------
void KMAcctMgr::readConfig(void)
{
KConfig* config = KMKernel::config();
KMAccount* acct;
QString acctType, acctName;
QCString groupName;
int i, num;
uint id;
mAcctList.clear();
KConfigGroup general(config, "General");
num = general.readNumEntry("accounts", 0);
for (i=1; i<=num; i++)
{
groupName.sprintf("Account %d", i);
KConfigGroupSaver saver(config, groupName);
acctType = config->readEntry("Type");
// Provide backwards compatibility
if (acctType == "advanced pop" || acctType == "experimental pop")
acctType = "pop";
acctName = config->readEntry("Name");
id = config->readUnsignedNumEntry("Id", 0);
if (acctName.isEmpty()) acctName = i18n("Account %1").arg(i);
acct = create(acctType, acctName, id);
if (!acct) continue;
add(acct);
acct->readConfig(*config);
}
}
//-----------------------------------------------------------------------------
void KMAcctMgr::singleCheckMail(KMAccount *account, bool _interactive)
{
newMailArrived = false;
interactive = _interactive;
// queue the account
mAcctTodo.append(account);
if (account->checkingMail())
{
kdDebug(5006) << "account " << account->name() << " busy, queuing" << endl;
return;
}
processNextCheck(false);
}
//-----------------------------------------------------------------------------
void KMAcctMgr::processNextCheck(bool _newMail)
{
kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
KMAccount *curAccount = 0;
newMailArrived |= _newMail;
KMAccount* acct;
for ( acct = mAcctChecking.first(); acct; acct = mAcctChecking.next() )
{
if ( !acct->checkingMail() )
{
// check done
kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
mAcctChecking.removeRef( acct );
kmkernel->filterMgr()->deref();
disconnect( acct, SIGNAL( finishedCheck( bool, CheckStatus ) ),
this, SLOT( processNextCheck( bool ) ) );
QString hostname = hostForAccount( acct );
if ( !hostname.isEmpty() ) {
if ( mServerConnections.find( hostname ) != mServerConnections.end() ) {
mServerConnections[hostname] -= 1;
kdDebug(5006) << "connections to server " << hostname
<< " now " << mServerConnections[hostname] << endl;
}
}
}
}
if (mAcctChecking.isEmpty())
{
// all checks finished, display summary
if ( mDisplaySummary )
BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
mTotalNewMailsArrived );
emit checkedMail( newMailArrived, interactive, mTotalNewInFolder );
mTotalNewMailsArrived = 0;
mTotalNewInFolder.clear();
mDisplaySummary = false;
}
if (mAcctTodo.isEmpty()) return;
QString accountHostName;
curAccount = 0;
KMAcctList::Iterator it ( mAcctTodo.begin() );
KMAcctList::Iterator last ( mAcctTodo.end() );
for ( ; it != last; it++ )
{
accountHostName = hostForAccount(*it);
kdDebug(5006) << "for host " << accountHostName
<< " current connections="
<< (mServerConnections.find(accountHostName)==mServerConnections.end() ? 0 : mServerConnections[accountHostName])
<< " and limit is " << GlobalSettings::self()->maxConnectionsPerHost()
<< endl;
bool connectionLimitForHostReached =
!accountHostName.isNull() &&
GlobalSettings::self()->maxConnectionsPerHost() > 0 &&
mServerConnections.find( accountHostName ) != mServerConnections.end() &&
mServerConnections[accountHostName] >= GlobalSettings::self()->maxConnectionsPerHost();
kdDebug(5006) << "connection limit reached: "
<< connectionLimitForHostReached << endl;
if ( !(*it)->checkingMail() && !connectionLimitForHostReached && !kmkernel->isOffline() ) {
curAccount = (*it);
mAcctTodo.remove( curAccount );
break;
}
}
if ( !curAccount ) return; // no account or all of them are already checking
if (curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
curAccount->folder() == 0)
{
QString tmp = i18n("Account %1 has no mailbox defined:\n"
"mail checking aborted;\n"
"check your account settings.")
.arg(curAccount->name());
KMessageBox::information(0,tmp);
emit checkedMail( false, interactive, mTotalNewInFolder );
mTotalNewMailsArrived = 0;
mTotalNewInFolder.clear();
return;
}
connect( curAccount, SIGNAL( finishedCheck( bool, CheckStatus ) ),
this, SLOT( processNextCheck( bool ) ) );
BroadcastStatus::instance()->setStatusMsg(
i18n("Checking account %1 for new mail").arg(curAccount->name()));
kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
curAccount->setCheckingMail(true);
mAcctChecking.append(curAccount);
kmkernel->filterMgr()->ref();
curAccount->processNewMail(interactive);
if ( !accountHostName.isEmpty() ) {
if ( mServerConnections.find( accountHostName ) != mServerConnections.end() )
mServerConnections[accountHostName] += 1;
else
mServerConnections[accountHostName] = 1;
kdDebug(5006) << "check mail started - connections for host "
<< accountHostName << " now is "
<< mServerConnections[accountHostName] << endl;
}
}
//-----------------------------------------------------------------------------
KMAccount* KMAcctMgr::create(const QString &aType, const QString &aName, uint id)
{
KMAccount* act = 0;
if (id == 0)
id = createId();
if (aType == "local")
act = new KMAcctLocal(this, aName, id);
if (aType == "maildir")
act = new KMAcctMaildir(this, aName, id);
else if (aType == "pop")
act = new KMAcctExpPop(this, aName, id);
else if (aType == "imap")
act = new KMAcctImap(this, aName, id);
else if (aType == "cachedimap")
act = new KMAcctCachedImap(this, aName, id);
if (act)
{
if (aType != "imap" && aType != "cachedimap")
act->setFolder(kmkernel->inboxFolder());
connect( act, SIGNAL( newMailsProcessed( const QMap<QString, int> & ) ),
this, SLOT( addToTotalNewMailCount( const QMap<QString, int> & ) ) );
}
return act;
}
//-----------------------------------------------------------------------------
void KMAcctMgr::add(KMAccount *account)
{
if (account) {
mAcctList.append( account );
emit accountAdded( account );
}
}
//-----------------------------------------------------------------------------
KMAccount* KMAcctMgr::findByName(const QString &aName)
{
if (aName.isEmpty()) return 0;
for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
{
if ((*it)->name() == aName) return (*it);
}
return 0;
}
//-----------------------------------------------------------------------------
KMAccount* KMAcctMgr::find(const uint id)
{
if (id == 0) return 0;
for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
{
if ((*it)->id() == id) return (*it);
}
return 0;
}
//-----------------------------------------------------------------------------
KMAccount* KMAcctMgr::first(void)
{
return mAcctList.first();
}
//-----------------------------------------------------------------------------
KMAccount* KMAcctMgr::next(void)
{
return mAcctList.next();
}
//-----------------------------------------------------------------------------
bool KMAcctMgr::remove( KMAccount* acct )
{
if( !acct )
return false;
mAcctList.removeRef( acct );
emit accountRemoved( acct );
return true;
}
//-----------------------------------------------------------------------------
void KMAcctMgr::checkMail(bool _interactive)
{
newMailArrived = false;
if (mAcctList.isEmpty())
{
KMessageBox::information(0,i18n("You need to add an account in the network "
"section of the settings in order to "
"receive mail."));
return;
}
mDisplaySummary = true;
mTotalNewMailsArrived=0;
mTotalNewInFolder.clear();
for ( QPtrListIterator<KMAccount> it(mAcctList) ;
it.current() ; ++it )
{
if (!it.current()->checkExclude())
singleCheckMail(it.current(), _interactive);
}
}
//-----------------------------------------------------------------------------
void KMAcctMgr::singleInvalidateIMAPFolders(KMAccount *account) {
account->invalidateIMAPFolders();
}
void KMAcctMgr::invalidateIMAPFolders()
{
if (mAcctList.isEmpty()) {
KMessageBox::information(0,i18n("You need to add an account in the network "
"section of the settings in order to "
"receive mail."));
return;
}
for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
singleInvalidateIMAPFolders(it.current());
}
//-----------------------------------------------------------------------------
QStringList KMAcctMgr::getAccounts(bool noImap) {
KMAccount *cur;
QStringList strList;
for (cur=mAcctList.first(); cur; cur=mAcctList.next()) {
if (!noImap || cur->type() != "imap") strList.append(cur->name());
}
return strList;
}
//-----------------------------------------------------------------------------
void KMAcctMgr::intCheckMail(int item, bool _interactive)
{
KMAccount* cur;
newMailArrived = false;
mTotalNewMailsArrived = 0;
mTotalNewInFolder.clear();
int x = 0;
cur = mAcctList.first();
while (cur)
{
x++;
if (x > item) break;
cur=mAcctList.next();
}
mDisplaySummary = false;
singleCheckMail(cur, _interactive);
}
//-----------------------------------------------------------------------------
void KMAcctMgr::addToTotalNewMailCount( const QMap<QString, int> & newInFolder )
{
for ( QMap<QString, int>::const_iterator it = newInFolder.begin();
it != newInFolder.end();
++it )
{
mTotalNewMailsArrived += it.data();
if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
mTotalNewInFolder[it.key()] = it.data();
else
mTotalNewInFolder[it.key()] += it.data();
}
}
//-----------------------------------------------------------------------------
uint KMAcctMgr::createId()
{
QValueList<uint> usedIds;
for ( QPtrListIterator<KMAccount> it(mAcctList) ; it.current() ; ++it )
usedIds << it.current()->id();
usedIds << 0; // 0 is default for unknown
int newId;
do
{
newId = kapp->random();
} while ( usedIds.find(newId) != usedIds.end() );
return newId;
}
//-----------------------------------------------------------------------------
void KMAcctMgr::cancelMailCheck()
{
for ( QPtrListIterator<KMAccount> it(mAcctList) ;
it.current() ; ++it ) {
it.current()->cancelMailCheck();
}
}
//-----------------------------------------------------------------------------
QString KMAcctMgr::hostForAccount( const KMAccount *acct ) const
{
const NetworkAccount *net_acct = dynamic_cast<const NetworkAccount*>( acct );
return net_acct ? net_acct->host() : QString::null;
}
#include "kmacctmgr.moc"