kmail

accountmanager.cpp
1 // KMail Account Manager
2 
3 #ifdef HAVE_CONFIG_H
4 #include <config.h>
5 #endif
6 
7 #include "accountmanager.h"
8 
9 #include "kmaccount.h"
10 #include "kmacctfolder.h"
11 #include "kmacctmaildir.h"
12 #include "kmacctlocal.h"
13 #include "popaccount.h"
14 #include "kmacctimap.h"
15 #include "networkaccount.h"
16 #include "kmacctcachedimap.h"
17 #include "broadcaststatus.h"
18 #include "kmfiltermgr.h"
19 #include "globalsettings.h"
20 
21 #include <dcopclient.h>
22 #include <tdelocale.h>
23 #include <tdemessagebox.h>
24 #include <kdebug.h>
25 #include <tdeconfig.h>
26 #include <tdeapplication.h>
27 
28 #include <tqregexp.h>
29 #include <tqvaluelist.h>
30 
31 using namespace KMail;
32 
33 //-----------------------------------------------------------------------------
35  :TQObject(), mNewMailArrived( false ), mInteractive( false ),
36  mTotalNewMailsArrived( 0 ), mDisplaySummary( false )
37 {
38  mAcctChecking.clear();
39  mAcctTodo.clear();
40 }
41 
42 //-----------------------------------------------------------------------------
43 AccountManager::~AccountManager()
44 {
45  writeConfig( false );
46 }
47 
48 
49 //-----------------------------------------------------------------------------
50 void AccountManager::writeConfig( bool withSync )
51 {
52  TDEConfig* config = KMKernel::config();
53  TQString groupName;
54 
55  TDEConfigGroupSaver saver(config, "General");
56  config->writeEntry("accounts", mAcctList.count());
57 
58  // first delete all account groups in the config file:
59  TQStringList accountGroups =
60  config->groupList().grep( TQRegExp( "Account \\d+" ) );
61  for ( TQStringList::Iterator it = accountGroups.begin() ;
62  it != accountGroups.end() ; ++it )
63  config->deleteGroup( *it );
64 
65  // now write new account groups:
66  int i = 1;
67  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it, ++i ) {
68  groupName.sprintf("Account %d", i);
69  TDEConfigGroupSaver saver(config, groupName);
70  (*it)->writeConfig(*config);
71  }
72  if (withSync) config->sync();
73 }
74 
75 
76 //-----------------------------------------------------------------------------
78 {
79  TDEConfig* config = KMKernel::config();
80  KMAccount* acct;
81  TQString acctType, acctName;
82  TQCString groupName;
83  int i, num;
84  uint id;
85 
86  for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
87  delete *it;
88  mAcctList.clear();
89 
90  TDEConfigGroup general(config, "General");
91  num = general.readNumEntry("accounts", 0);
92 
93  for (i=1; i<=num; i++)
94  {
95  groupName.sprintf("Account %d", i);
96  TDEConfigGroupSaver saver(config, groupName);
97  acctType = config->readEntry("Type");
98  // Provide backwards compatibility
99  if (acctType == "advanced pop" || acctType == "experimental pop")
100  acctType = "pop";
101  acctName = config->readEntry("Name");
102  id = config->readUnsignedNumEntry("Id", 0);
103  if (acctName.isEmpty()) acctName = i18n("Account %1").arg(i);
104  acct = create(acctType, acctName, id);
105  if (!acct) continue;
106  add(acct);
107  acct->readConfig(*config);
108  }
109 }
110 
111 
112 //-----------------------------------------------------------------------------
113 void AccountManager::singleCheckMail(KMAccount *account, bool interactive)
114 {
115  mNewMailArrived = false;
116  mInteractive = interactive;
117 
118  // if sync has been requested by the user then check if check-interval was disabled by user, if yes, then
119  // de-install the timer
120  // Safe guard against an infinite sync loop (kolab/issue2607)
121  if ( mInteractive )
122  account->readTimerConfig();
123 
124  // queue the account
125  mAcctTodo.append(account);
126 
127  if (account->checkingMail())
128  {
129  kdDebug(5006) << "account " << account->name() << " busy, queuing" << endl;
130  return;
131  }
132 
133  processNextCheck(false);
134 }
135 
136 //-----------------------------------------------------------------------------
137 void AccountManager::processNextCheck( bool _newMail )
138 {
139  kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
140  if ( _newMail )
141  mNewMailArrived = true;
142 
143  for ( AccountList::Iterator it( mAcctChecking.begin() ), end( mAcctChecking.end() ); it != end; ) {
144  KMAccount* acct = *it;
145  ++it;
146  if ( acct->checkingMail() )
147  continue;
148  // check done
149  kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
150  mAcctChecking.remove( acct );
151  kmkernel->filterMgr()->deref();
152  disconnect( acct, TQ_SIGNAL( finishedCheck( bool, CheckStatus ) ),
153  this, TQ_SLOT( processNextCheck( bool ) ) );
154  }
155  if ( mAcctChecking.isEmpty() ) {
156  // all checks finished, display summary
157  if ( mDisplaySummary )
158  KPIM::BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
159  mTotalNewMailsArrived );
160  emit checkedMail( mNewMailArrived, mInteractive, mTotalNewInFolder );
161  mTotalNewMailsArrived = 0;
162  mTotalNewInFolder.clear();
163  mDisplaySummary = false;
164  }
165  if ( mAcctTodo.isEmpty() ) return;
166 
167  TQString accountHostName;
168 
169  KMAccount *curAccount = 0;
170  for ( AccountList::Iterator it ( mAcctTodo.begin() ), last ( mAcctTodo.end() ); it != last; ) {
171  KMAccount *acct = *it;
172  ++it;
173  if ( !acct->checkingMail() && acct->mailCheckCanProceed() ) {
174  curAccount = acct;
175  mAcctTodo.remove( acct );
176  break;
177  }
178  }
179  if ( !curAccount ) return; // no account or all of them are already checking
180 
181  if ( curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
182  curAccount->folder() == 0 ) {
183  TQString tmp = i18n("Account %1 has no mailbox defined:\n"
184  "mail checking aborted;\n"
185  "check your account settings.")
186  .arg(curAccount->name());
187  KMessageBox::information(0,tmp);
188  emit checkedMail( false, mInteractive, mTotalNewInFolder );
189  mTotalNewMailsArrived = 0;
190  mTotalNewInFolder.clear();
191  return;
192  }
193 
194  if ( curAccount->type() == "imap" || curAccount->type() == "cachedimap" || curAccount->type() == "pop" )
195  {
196  // Check with the network status daemon whether the network is available
197  const int NetWorkStatusUnknown = 1;
198  const int NetWorkStatusOnline = 8;
199  TQCString replyType;
200  TQByteArray params;
201  TQByteArray reply;
202 
203  TQDataStream stream( params, IO_WriteOnly );
204  stream << static_cast<NetworkAccount*>( curAccount )->host();
205 
206  if ( kapp->dcopClient()->call( "kded", "networkstatus", "status(TQString)",
207  params, replyType, reply ) && ( replyType == "int" ) )
208  {
209  int result;
210  TQDataStream stream2( reply, IO_ReadOnly );
211  stream2 >> result;
212  kdDebug() << k_funcinfo << "networkstatus status = " << result << endl;
213  // if it's not unknown (no networks announced by network control apps), and not offline, give up now
214  if ( ( result != NetWorkStatusUnknown ) && ( result != NetWorkStatusOnline ) )
215  {
216  emit checkedMail( false, mInteractive, mTotalNewInFolder );
217  return;
218  }
219  }
220  }
221 
222  connect( curAccount, TQ_SIGNAL( finishedCheck( bool, CheckStatus ) ),
223  this, TQ_SLOT( processNextCheck( bool ) ) );
224 
225  KPIM::BroadcastStatus::instance()->setStatusMsg(
226  i18n("Checking account %1 for new mail").arg(curAccount->name()));
227 
228  kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
229 
230  curAccount->setCheckingMail( true );
231  mAcctChecking.append( curAccount );
232  kmkernel->filterMgr()->ref();
233  curAccount->processNewMail( mInteractive );
234 }
235 
236 //-----------------------------------------------------------------------------
237 KMAccount* AccountManager::create( const TQString &aType, const TQString &aName, uint id )
238 {
239  KMAccount* act = 0;
240  if ( id == 0 )
241  id = createId();
242 
243  if ( aType == "local" ) {
244  act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
245  act->setFolder( kmkernel->inboxFolder() );
246  } else if ( aType == "maildir" ) {
247  act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
248  act->setFolder( kmkernel->inboxFolder() );
249  } else if ( aType == "pop" ) {
250  act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
251  act->setFolder( kmkernel->inboxFolder() );
252  } else if ( aType == "imap" ) {
253  act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
254  } else if (aType == "cachedimap") {
255  act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
256  }
257  if ( !act ) {
258  kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
259  return 0;
260  }
261  connect( act, TQ_SIGNAL( newMailsProcessed( const TQMap<TQString, int> & ) ),
262  this, TQ_SLOT( addToTotalNewMailCount( const TQMap<TQString, int> & ) ) );
263  return act;
264 }
265 
266 
267 //-----------------------------------------------------------------------------
268 void AccountManager::add( KMAccount *account )
269 {
270  if ( account ) {
271  mAcctList.append( account );
272  // init folder's account list
273  KMAcctFolder *folder = static_cast<KMAcctFolder*>( account->folder() );
274  if ( folder && !folder->hasAccounts() ) {
275  folder->addAccount( account );
276  }
277  emit accountAdded( account );
278  account->installTimer();
279  }
280 }
281 
282 
283 //-----------------------------------------------------------------------------
284 KMAccount* AccountManager::findByName(const TQString &aName) const
285 {
286  if ( aName.isEmpty() ) return 0;
287 
288  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
289  if ( (*it)->name() == aName ) return (*it);
290  }
291  return 0;
292 }
293 
294 
295 //-----------------------------------------------------------------------------
296 KMAccount* AccountManager::find( const uint id ) const
297 {
298  if (id == 0) return 0;
299  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
300  if ( (*it)->id() == id ) return (*it);
301  }
302  return 0;
303 }
304 
305 
306 //-----------------------------------------------------------------------------
307 KMAccount* AccountManager::first()
308 {
309  if ( !mAcctList.empty() ) {
310  mPtrListInterfaceProxyIterator = mAcctList.begin();
311  return *mPtrListInterfaceProxyIterator;
312  } else {
313  return 0;
314  }
315 }
316 
317 //-----------------------------------------------------------------------------
318 KMAccount* AccountManager::next()
319 {
320  ++mPtrListInterfaceProxyIterator;
321  if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
322  return 0;
323  else
324  return *mPtrListInterfaceProxyIterator;
325 }
326 
327 //-----------------------------------------------------------------------------
328 bool AccountManager::remove( KMAccount* acct )
329 {
330  if( !acct )
331  return false;
332  mAcctList.remove( acct );
333  emit accountRemoved( acct );
334  return true;
335 }
336 
337 //-----------------------------------------------------------------------------
338 void AccountManager::checkMail( bool _interactive )
339 {
340  mNewMailArrived = false;
341 
342  if ( mAcctList.isEmpty() ) {
343  KMessageBox::information( 0,i18n("You need to add an account in the network "
344  "section of the settings in order to receive mail.") );
345  return;
346  }
347  mDisplaySummary = true;
348 
349  mTotalNewMailsArrived=0;
350  mTotalNewInFolder.clear();
351 
352  for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
353  if ( !(*it)->checkExclude() )
354  singleCheckMail( (*it), _interactive);
355  }
356 }
357 
358 
359 //-----------------------------------------------------------------------------
360 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
361  account->invalidateIMAPFolders();
362 }
363 
364 
366 {
367  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
368  singleInvalidateIMAPFolders( *it );
369 }
370 
371 
372 //-----------------------------------------------------------------------------
373 TQStringList AccountManager::getAccounts() const
374 {
375  TQStringList strList;
376  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
377  strList.append( (*it)->name() );
378  }
379  return strList;
380 }
381 
382 //-----------------------------------------------------------------------------
383 void AccountManager::intCheckMail(int item, bool _interactive)
384 {
385  mNewMailArrived = false;
386  mTotalNewMailsArrived = 0;
387  mTotalNewInFolder.clear();
388  if ( KMAccount *acct = mAcctList[ item ] )
389  singleCheckMail( acct, _interactive );
390  mDisplaySummary = false;
391 }
392 
393 
394 //-----------------------------------------------------------------------------
395 void AccountManager::addToTotalNewMailCount( const TQMap<TQString, int> & newInFolder )
396 {
397  for ( TQMap<TQString, int>::const_iterator it = newInFolder.begin();
398  it != newInFolder.end(); ++it ) {
399  mTotalNewMailsArrived += it.data();
400  if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
401  mTotalNewInFolder[it.key()] = it.data();
402  else
403  mTotalNewInFolder[it.key()] += it.data();
404  }
405 }
406 
407 //-----------------------------------------------------------------------------
408 uint AccountManager::createId()
409 {
410  TQValueList<uint> usedIds;
411  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
412  usedIds << (*it)->id();
413  }
414 
415  usedIds << 0; // 0 is default for unknown
416  int newId;
417  do
418  {
419  newId = kapp->random();
420  } while ( usedIds.find(newId) != usedIds.end() );
421 
422  return newId;
423 }
424 
425 //-----------------------------------------------------------------------------
427 {
428  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
429  (*it)->cancelMailCheck();
430  }
431 }
432 
433 
434 //-----------------------------------------------------------------------------
436 {
437  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
438  NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
439  if ( acct )
440  acct->readPassword();
441  }
442 }
443 
444 #include "accountmanager.moc"
Simple wrapper class that contains the kmail account handling stuff that is usually not required outs...
Definition: kmacctfolder.h:35
void addAccount(KMAccount *)
Add given account to the list.
bool hasAccounts() const
Returns TRUE if accounts are associated with this folder.
Definition: kmfolder.h:128
void checkMail(bool interactive=true)
Processes all accounts looking for new mail.
void accountRemoved(KMAccount *account)
emitted when an account is removed
void readPasswords()
Read passwords of all accounts from the wallet.
void readConfig(void)
Completely reload accounts from config.
KMAccount * findByName(const TQString &name) const
Find account by name.
const KMAccount * first() const
First account of the list.
const KMAccount * next() const
Next account of the list.
void accountAdded(KMAccount *account)
emitted when an account is added
bool remove(KMAccount *)
Physically remove account.
AccountManager()
Initializes the account manager.
void writeConfig(bool withSync=true)
Write accounts to config.
void add(KMAccount *account)
Adds an account to the list of accounts.
void cancelMailCheck()
Called on exit (KMMainWin::queryExit)
void checkedMail(bool newMail, bool interactive, const TQMap< TQString, int > &newInFolder)
Emitted if new mail has been collected.
KMAccount * find(const uint id) const
Find account by id.
void addToTotalNewMailCount(const TQMap< TQString, int > &newInFolder)
this slot increases the count of new mails to show a total number after checking in multiple accounts...
KMAccount * create(const TQString &type, const TQString &name=TQString(), uint id=0)
Create a new account of given type with given name.
void invalidateIMAPFolders()
Delete all IMAP folders and resync them.
KMail account for pop mail account.
Definition: popaccount.h:27
folderdiaquotatab.h
Definition: aboutdata.cpp:40