/***************************************************************************
                          configlist.cpp  -  description
                             -------------------
    begin                : Tue May 9 2000
    copyright            : (C) 2000-2001 by Eggert Ehmke
    email                : eggert.ehmke@berlin.de

    26 Sep 2002 - Allow for columns to be hidden. Allistar Melville
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#include <qfile.h>

#include <kconfig.h>
#include <ksavefile.h>
#include <kapplication.h>
#include <kstandarddirs.h>
#include <kaudioplayer.h>
#include <kdebug.h>

#include "configlist.h"

ConfigList::ConfigList() : QObject()
{
	setAutoDelete (true);

    //assume, no window to show a mail is open at beginning
    ctrOpenMessageWindows = 0;

    //set default values
    m_bShowMessage = DEFAULT_ACTION_NEW_MAIL_ALERTWINDOW;
    m_bShowMainWindow = DEFAULT_ACTION_NEW_MAIL_MAINWINDOW;
    m_bBeep = DEFAULT_ACTION_NEW_MAIL_BEEP;
    m_bSound = DEFAULT_ACTION_NEW_MAIL_SOUND;
    m_bCommand = DEFAULT_ACTION_NEW_MAIL_COMMAND;
    m_bMinimize = DEFAULT_ACTION_NO_NEW_MAIL_MINIMIZE;
    m_bTerminate = DEFAULT_ACTION_NO_NEW_MAIL_TERMINATE;

    m_bConfirmClose = DEFAULT_CONFIRM_CLOSE;
    m_bConfirmDelete = DEFAULT_CONFIRM_DELETE;
    m_bStartMinimized = DEFAULT_START_MINIMIZED;
    m_bCloseMinimizes = DEFAULT_CLOSE_TO_TRAY;
    m_bMinimizeToTray = DEFAULT_MINIMIZE_TO_TRAY;
    m_bShowConnectionErrors = DEFAULT_SHOW_CONNECTION_ERRORS;
    m_bKeepNew = DEFAULT_KEEP_NEW;
    m_nInitTimer = DEFAULT_INITIAL_TIME;
    m_nIntervalTimer = DEFAULT_INTERVAL_TIME;
    m_nPop3Timer = DEFAULT_TIMEOUT_TIME;

}

int ConfigList::compareItems( QCollection::Item item1, QCollection::Item item2 )
{
  ConfigElem* p1 = (ConfigElem*)item1;
  ConfigElem* p2 = (ConfigElem*)item2;

  return strcmp( p1->getAccountName(), p2->getAccountName() );
}

QCollection::Item ConfigList::newItem( QCollection::Item item )
{
  return new ConfigElem( (ConfigElem*)item );
}

void ConfigList::saveOptions ()
{
  kdDebug () << "ConfigList::saveOptions" << endl;

  //create XML document
  QDomDocument doc( "KShowmail" );

  //create root element
  QDomElement accounts = doc.createElement( ROOT_ELEMENT );

  //create for every account an element
  //the account saves its mails into this element
  //after that the element will be appended to the root element
  int i = 0;
  ConfigElem* account = NULL;               //current processed account
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    //save mails
    QDomElement accElem = doc.createElement( QString( ACCOUNT_ELEMENT ) + QString( "%1" ).arg( i++ ) );
    account->saveOptions( doc, accElem ); //account saves the mails into given XML document and the setup into the application config file
    accounts.appendChild( accElem );

  }

  //append root element to XML document
  doc.appendChild( accounts );

  //save XML document
  QCString str = doc.toCString(); //convert XML document to a string
  QString cachefilename = locateLocal( "config", MAIL_FILE ); //get file path
  KSaveFile file( cachefilename, 0600 );  //create file

  if( file.status() != 0 )
  {
    kdError() << "Couldn't save mail cache. " << strerror( file.status() );
    return;
  }

    //write data
  file.file()->writeBlock( str.data(), str.length() );

    //close file
  if( !file.close() )
  {
    kdError () << "Couldn't save mail cache. " << strerror(file.status());
    return;
  }
}


void ConfigList::setList (QListView* list)
{
	QPixmap pix (::locate ("data", "kshowmail/pics/ok.png"));
	list->clear ();
	int nIndex = at ();
	QListViewItem* last = NULL;
	for (ConfigElem* pElem = first(); pElem; pElem = next())
	{
		last = new QListViewItem (list, last, "", pElem->getAccountName(), pElem->getURL().host(), pElem->getURL().user(), "?");
        pElem->setListViewItem( last );
		if (pElem->isActive())
			pElem->getListViewItem()->setPixmap (0, pix);
	}

	if (nIndex >= 0)
	{
		at (nIndex);
//		list->setCurrentItem (nIndex);
	}
}


bool ConfigList::setItem (const char* item)
{
	int nPos = at ();
	ConfigElem* pActive = new ConfigElem (this, item);
	bool result = (find (pActive) >= 0);
	delete pActive;
	if (result)
		return true;
	else
	{
		at (nPos);
		return false;
	}
}

void ConfigList::beep ()
{
	if (m_bBeep)
		kapp->beep ();
}

void ConfigList::playSound ()
{
	if (m_bSound)
  	playSound (m_strSoundFile);
}

void ConfigList::playSound (const char* file)
{
	KAudioPlayer::play(file);
}

int ConfigList::getRefreshTimeInterval( ) const
{
  return m_nIntervalTimer;
}

void ConfigList::setRefreshTimeInterval( unsigned int interval )
{
  m_nIntervalTimer = interval;
}

bool ConfigList::AutoRefreshOn( ) const
{
  return ( m_nIntervalTimer > 0 );
}

bool ConfigList::hasActiveAccounts( )
{
  bool activeAccountFound = false;    //when a active account was found, this will be set to TRUE
  ConfigElem* currentAccount;         //saved current account
  ConfigElem* Account;                //used by the search

  //save the current account
  currentAccount = current();

  //get the first account
  Account = first();

  //looking for an active account
  while( Account != NULL && !activeAccountFound )
  {
    //have we found one?
    activeAccountFound = Account->isActive();

    //get next account
    Account = next();
  }

  //set the saved account to current
  if( currentAccount != NULL )
    findRef( currentAccount );

  //return the result
  return activeAccountFound;
}


uint ConfigList::getTimeoutTime( ) const
{
  return m_nPop3Timer;
}

void ConfigList::setTimeoutTime( uint time )
{
  if( time < MINIMUM_TIMEOUT_TIME )
    m_nPop3Timer = MINIMUM_TIMEOUT_TIME;
  else
    m_nPop3Timer = time;
}

ConfigElem* ConfigList::getSelectedAccount( )
{
  //get the first account in the list
  ConfigElem* account = first();

  //return NULL if there are no accounts
  if( account == NULL )
    return NULL;

  //return the account, if it is selected
  if( account->isSelected() )
    return account;

  //iterate over all accounts
  bool selectedAccountFound = false;  //is TRUE, if a selected account was found
  while( account != NULL && !selectedAccountFound )
  {
    //get next account
    account = next();

    //is the account selected?
    if( account != NULL )
      selectedAccountFound = account->isSelected();
    else
      selectedAccountFound = false;
  }

  //return the current account if we have found a selected account
  //otherwise return FALSE
  if( selectedAccountFound )
    return account;
  else
    return NULL;
}

void ConfigList::deleteSelectedMails( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process

  //clear the map, which contains the names of the accounts,
  //which have gotten an order to delete
  AccountDeletionMap.clear();

  //refresh connects
  connectAccounts();

  //inserts an item for every account which will get an order to delete
  //its selected mails. The key is the account name and the data is TRUE.
  //it is important to do this in a seperate iteration because this avoids
  //race conditions
  while( ( account = it.current() ) != NULL )
  {
    //insert item
    AccountDeletionMap.insert( account->getAccountName(), true );

    //get next account
    ++it;
  }

  //order all accounts to delete its selected mail
  it.toFirst();
  while( ( account = it.current() ) != NULL )
  {
    account->deleteSelectedMails();

    //get next account
    ++it;
  }
}

void ConfigList::slotAccountConfigChanged( )
{
  emit sigConfigChanged();
}

void ConfigList::slotCheckDeletionState( QString account )
{
  bool accountDeleting = false;     //set to TRUE if an account is still deleting
  AccountTaskMap_Type::Iterator it; //iterator over the account deletion map

  //set the appropriate item in AccountDeletionMap to FALSE
  AccountDeletionMap[ account ] = false;

  //iterate over the account deletion map to check, whether all accounts
  //are ready
  for ( it = AccountDeletionMap.begin(); it != AccountDeletionMap.end(); ++it )
  {
    if( *it == true )
      accountDeleting = true;
  }

  //emit sigDeleteReady if all accounts are ready
  if( !accountDeleting )
    emit sigDeleteReady();
}

void ConfigList::connectAccounts( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to connect

  while( ( account = it.current() ) != NULL )
  {
    //disconnect old connections
    account->disconnect();

    //connect
    connect( account, SIGNAL( sigConfigChanged() ), this, SLOT( slotAccountConfigChanged() ) );
    connect( account, SIGNAL( sigDeleteReady( QString ) ), this, SLOT( slotCheckDeletionState( QString ) ) );
    connect( account, SIGNAL( sigShowBodiesReady( QString ) ), this, SLOT( slotCheckShowBodiesState( QString ) ) );
    connect( account, SIGNAL( sigMessageWindowOpened() ), this, SLOT( slotMessageWindowOpened() ) );
    connect( account, SIGNAL( sigMessageWindowClosed() ), this, SLOT( slotMessageWindowClosed() ) );
    connect( account, SIGNAL( sigRefreshReady( QString ) ), this, SLOT( slotCheckRefreshState( QString ) ) );

    //get next account
    ++it;
  }
}

void ConfigList::setConfirmDeletion( bool confirm )
{
  m_bConfirmDelete = confirm;
}

bool ConfigList::confirmDeletion( )
{
  return m_bConfirmDelete;
}

QStringList ConfigList::getSelectedSubjects( ) const
{
  QStringList subjects;                       //contains all subjects
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //current account

  while( ( account = it.current() ) != NULL )
  {
    //get subjects of the current account and append them to the list
    subjects += account->getSelectedSubjects();

    //get next account
    ++it;
  }

  return subjects;
}

bool ConfigList::hasSelectedMails( )
{
  bool foundSelected = false;                 //set to TRUE, when an account with selected mails was found
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //current account

  while( ( account = it.current() ) != NULL && !foundSelected )
  {
    foundSelected = account->hasSelectedMails();

    //get next account
    ++it;
  }

  return foundSelected;

}

void ConfigList::showSelectedMails( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process

  //clear the map, which contains the names of the accounts,
  //which have gotten an order to show mails
  AccountShowBodiesMap.clear();

  //refresh connects
  connectAccounts();

  //inserts an item for every account which will get an order to show
  //its selected mails. The key is the account name and the data is TRUE.
  //it is important to do this in a seperate iteration because this avoids
  //race conditions
  while( ( account = it.current() ) != NULL )
  {
    //insert item
    AccountShowBodiesMap.insert( account->getAccountName(), true );

    //get next account
    ++it;
  }

  //order all accounts to show its selected mail
  it.toFirst();
  while( ( account = it.current() ) != NULL )
  {
    account->showSelectedMails();

    //get next account
    ++it;
  }

}

void ConfigList::slotCheckShowBodiesState( QString account )
{
  bool accountDownloading = false;    //set to TRUE if an account is downloading mail body yet
  AccountTaskMap_Type::Iterator it;   //iterator over the account map

  //set the appropriate item in AccountShowBodiesMap to FALSE
  AccountShowBodiesMap[ account ] = false;

  //iterate over the account map to check, whether all accounts
  //are ready
  for ( it = AccountShowBodiesMap.begin(); it != AccountShowBodiesMap.end(); ++it )
  {
    if( *it == true )
      accountDownloading = true;
  }

  //emit sigShowBodiesReady if all accounts are ready
  //and assume all windows to show the mails are closed
  if( !accountDownloading )
  {
    emit sigShowBodiesReady();
    ctrOpenMessageWindows = 0;
  }
}

void ConfigList::setAllowHTML( bool allowHTML )
{
  m_bAllowHTML = allowHTML;
}

bool ConfigList::allowHTML( ) const
{
  return m_bAllowHTML;
}

void ConfigList::slotMessageWindowOpened( )
{
  //increment the window counter
  ctrOpenMessageWindows++;

  //if the counter was incremented from zero
  //(the first window was opened), emit the
  //signal
  if( ctrOpenMessageWindows == 1 )
    emit sigMessageWindowOpened();
}

void ConfigList::slotMessageWindowClosed( )
{
  //decrement the window counter
  ctrOpenMessageWindows--;
  if( ctrOpenMessageWindows < 0 )
    ctrOpenMessageWindows = 0;

  //if counter is zero (all windows was closed),
  //emit signal
  if( ctrOpenMessageWindows == 0 )
    emit sigAllMessageWindowsClosed();
}

void ConfigList::refreshMailLists( FilterLog* log )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process

  //return, if no accounts available
  if( count() == 0 )
  {
    emit sigRefreshReady();
    return;
  }

  //clear the map, which contains the names of the accounts,
  //which have gotten an order to show mails
  AccountRefreshMap.clear();

  //refresh connects
  connectAccounts();

  //inserts an item for every account which will get an order to refresh
  //its mail list. The key is the account name and the data is TRUE.
  //it is important to do this in a seperate iteration because this avoids
  //race conditions
  while( ( account = it.current() ) != NULL )
  {
    //insert item
    AccountRefreshMap.insert( account->getAccountName(), true );

    //get next account
    ++it;
  }

  //order all accounts to refresh their mail lists
  it.toFirst();
  while( ( account = it.current() ) != NULL )
  {
    account->refreshMailList( log );

    //get next account
    ++it;
  }

}

void ConfigList::slotCheckRefreshState( QString account )
{
  bool accountRefreshing = false;    //set to TRUE if an account is still refreshing
  AccountTaskMap_Type::Iterator it;   //iterator over the account map

  //set the appropriate item in AccountRefreshMap to FALSE
  AccountRefreshMap[ account ] = false;

  //iterate over the account map to check whether all accounts
  //are ready
  for ( it = AccountRefreshMap.begin(); it != AccountRefreshMap.end(); ++it )
  {
    if( *it == true )
      accountRefreshing = true;
  }

  //emit sigRefreshReady if all accounts are ready
  if( !accountRefreshing )
  {
    emit sigRefreshReady();
  }

}

int ConfigList::getNumberNewMails( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process
  int number = 0;                             //number of new mails

  //iterate over all accounts and sum up the number of new mails
  while( ( account = it.current() ) != NULL )
  {
    if( account->isActive() )
      number += account->getNumberNewMails();

    //get next account
    ++it;
  }

  return number;
}

int ConfigList::getNumberMails( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process
  int number = 0;                             //number of mails

  //iterate over all accounts and sum up the number of mails
  while( ( account = it.current() ) != NULL )
  {
    if( account->isActive() )
      number += account->getNumberMails();

    //get next account
    ++it;
  }

  return number;
}

long ConfigList::getTotalSize( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process
  long size = 0;                               //total size of all mails

  //iterate over all accounts and sum up the size of all mails
  while( ( account = it.current() ) != NULL )
  {
    if( account->isActive() )
      size += account->getTotalSize();

    //get next account
    ++it;
  }

  return size;
}

void ConfigList::fillMailListView( KshowmailView * view )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process

  //iterate over all accounts and order the active accounts to fill their mails
  //into the list view
  while( ( account = it.current() ) != NULL )
  {
    if( account->isActive() )
      account->fillMailListView( view );

    //get next account
    ++it;
  }

}

bool ConfigList::showMainWindowForNewMails( )
{
  return m_bShowMainWindow;
}

bool ConfigList::showAlertMessageForNewMails( )
{
  return m_bShowMessage;
}

bool ConfigList::quitNoNewMails( )
{
  return m_bTerminate;
}

bool ConfigList::minimizeMainWindowNoNewMails( )
{
  return m_bMinimize;
}

int ConfigList::getInitTime( )
{
  return m_nInitTimer;
}

void ConfigList::setInitTime( int time )
{
  if( time >= 0 )
    m_nInitTimer = time;
  else
    m_nInitTimer = 0;
}

bool ConfigList::hasInitTime( )
{
  return m_nInitTimer > 0;
}

void ConfigList::refreshAccountList( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process

  //iterate over all accounts and order the account to refresh its
  //account list view item
  while( ( account = it.current() ) != NULL )
  {
    account->refreshAccountListItem();

    //get next account
    ++it;
  }

}

void ConfigList::killPOP3Jobs( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process

  //iterate over all accounts and order the account to kill
  //a running pop3 job
  while( ( account = it.current() ) != NULL )
  {
    account->killPOP3Job();

    //get next account
    ++it;
  }
}

void ConfigList::showSelectedHeaders( )
{
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //account to process
  int showNextHeader = ConfigElem::continueShowHeaders; //return value of ConfigElem::showSelectedHeaders

  //iterate over all accounts and order the account to show
  //the headers of all selected mails.
  while( ( account = it.current() ) != NULL && showNextHeader == ConfigElem::continueShowHeaders )
  {
    if( account->hasSelectedMails() )
      showNextHeader = account->showSelectedHeaders();

    //get next account
    ++it;
  }
}

void ConfigList::refreshSetup( KListView* view )
{
  //get application config object (kshowmailrc)
  config = KApplication::kApplication()->config();

  //read actions group
  config->setGroup( CONFIG_GROUP_ACTIONS );

  m_bShowMessage = config->readBoolEntry( CONFIG_ENTRY_NEW_MAIL_ALERTWINDOW, DEFAULT_ACTION_NEW_MAIL_ALERTWINDOW );
  m_bShowMainWindow = config->readBoolEntry( CONFIG_ENTRY_NEW_MAIL_MAINWINDOW, DEFAULT_ACTION_NEW_MAIL_MAINWINDOW );
  m_bBeep = config->readBoolEntry( CONFIG_ENTRY_NEW_MAIL_BEEP, DEFAULT_ACTION_NEW_MAIL_BEEP );
  m_bSound = config->readBoolEntry( CONFIG_ENTRY_NEW_MAIL_SOUND, DEFAULT_ACTION_NEW_MAIL_SOUND );
  m_strSoundFile = config->readEntry( CONFIG_ENTRY_NEW_MAIL_SOUNDPATH );
  m_bCommand = config->readBoolEntry( CONFIG_ENTRY_NEW_MAIL_COMMAND, DEFAULT_ACTION_NEW_MAIL_COMMAND );
  m_strCommandPath = config->readEntry( CONFIG_ENTRY_NEW_MAIL_COMMANDPATH );
  m_bMinimize = config->readBoolEntry( CONFIG_ENTRY_NO_NEW_MAIL_MINIMIZE, DEFAULT_ACTION_NO_NEW_MAIL_MINIMIZE );
  m_bTerminate = config->readBoolEntry( CONFIG_ENTRY_NO_NEW_MAIL_TERMINATE, DEFAULT_ACTION_NO_NEW_MAIL_TERMINATE );

  //read general group
  config->setGroup( CONFIG_GROUP_GENERAL );
  m_bConfirmClose = config->readBoolEntry( CONFIG_ENTRY_CONFIRM_CLOSE, DEFAULT_CONFIRM_CLOSE );
  m_bConfirmDelete = config->readBoolEntry( CONFIG_ENTRY_CONFIRM_DELETE, DEFAULT_CONFIRM_DELETE );
  m_bStartMinimized = config->readBoolEntry( CONFIG_ENTRY_START_MINIMIZED, DEFAULT_START_MINIMIZED );
  m_bCloseMinimizes = config->readBoolEntry( CONFIG_ENTRY_CLOSE_TO_TRAY, DEFAULT_CLOSE_TO_TRAY );
  m_bMinimizeToTray = config->readBoolEntry( CONFIG_ENTRY_MINIMIZE_TO_TRAY, DEFAULT_MINIMIZE_TO_TRAY );
  m_bShowConnectionErrors = config->readBoolEntry( CONFIG_ENTRY_SHOW_CONNECTION_ERRORS, DEFAULT_SHOW_CONNECTION_ERRORS );
  m_bKeepNew = config->readBoolEntry( CONFIG_ENTRY_KEEP_NEW, DEFAULT_KEEP_NEW );

  m_nInitTimer = config->readNumEntry( CONFIG_ENTRY_INITIAL_TIME, DEFAULT_INITIAL_TIME );
  m_nIntervalTimer = config->readNumEntry( CONFIG_ENTRY_INTERVAL_TIME, DEFAULT_INTERVAL_TIME);
  m_nPop3Timer = config->readNumEntry( CONFIG_ENTRY_TIMEOUT_TIME, DEFAULT_TIMEOUT_TIME );

  //read display group
  config->setGroup( CONFIG_GROUP_VIEW );
  m_bAllowHTML = config->readBoolEntry( CONFIG_ENTRY_VIEW_USE_HTML, DEFAULT_VIEW_USE_HTML );

  //read Spam configs
  config->setGroup( CONFIG_GROUP_SPAMCHECK );
  int intSpamAction = config->readNumEntry( CONFIG_ENTRY_SPAMCHECK_ACTION, DEFAULT_SPAMCHECK_ACTION );

  switch( intSpamAction )
  {
    case CONFIG_VALUE_SPAMCHECK_ACTION_DELETE       : spamAction = FActDelete; break;
    case CONFIG_VALUE_SPAMCHECK_ACTION_MARK         : spamAction = FActMark; break;
    case CONFIG_VALUE_SPAMCHECK_ACTION_MOVE         : spamAction = FActMove; break;
    default                                         :
      kdError() << "Invalid value in " << CONFIG_ENTRY_SPAMCHECK_ACTION << ". Set default value." << endl;
      switch( DEFAULT_SPAMCHECK_ACTION )
      {
        case CONFIG_VALUE_SPAMCHECK_ACTION_DELETE       : spamAction = FActDelete; break;
        case CONFIG_VALUE_SPAMCHECK_ACTION_MARK         : spamAction = FActMark; break;
        case CONFIG_VALUE_SPAMCHECK_ACTION_MOVE         : spamAction = FActMove; break;
        default                                         : spamAction = FActMark; break;
      }

  }

  if( spamAction == FActMove )
    spamMailbox = config->readEntry( CONFIG_ENTRY_SPAMCHECK_MOVE_MAILBOX, DEFAULT_SPAMCHECK_ACTION_MOVE_MAILBOX );


  //read account configuration and setup accounts
  //---------------------------------------------

  //get account names from the config file
  config->setGroup( CONFIG_GROUP_ACCOUNTS );
  QStringList accounts = config->readListEntry( CONFIG_ENTRY_ACCOUNTS_LIST, QStringList() );

  //remove deleted accounts from the account list
  //accounts are deleted, if the are in ConfigList yet, but not in the list of the config file (accounts)
  ConfigElem* accountDel = NULL;               //current processed account
  QPtrListIterator<ConfigElem> iter( *this ); //iterator for the account list (ConfigList)

    //iterate over all accounts (ConfigList)
  while( ( accountDel = iter.current() ) != NULL )
  {
    //increment iterator to get next account
    ++iter;

    //search for the current account in the account list of the config file
    QStringList::Iterator foundAccount = accounts.find( accountDel->getAccountName() );

    //remove account from ConfigList, if it is not in the list of the config file
    if( foundAccount == accounts.end() )
      remove( accountDel );
  }

  //add or edit accounts
  ConfigElem* acc;
    //iterate over all items of the account list of the config file
  for( QStringList::Iterator it = accounts.begin(); it != accounts.end(); ++it )
  {
    //create a new account, if it is not in the list yet (ConfigList)
    //or get the account
    if( !hasAccount( *it ) )
    {
      //create new account
      acc = new ConfigElem( this, *it );
      inSort( acc );

      //the pointer list inserts a copy of the new account object
      //we have to delete the original
      delete acc;
    }

    //get account from ConfigList
    acc = getAccount( *it );

    //get the setup of the account from the config file and setup the account
    config->setGroup( *it );

    acc->setHost( config->readEntry( CONFIG_ENTRY_ACCOUNT_SERVER, DEFAULT_ACCOUNT_SERVER ) );

    //set protocol and security
    //if the read protocol is POP3 and SSL is enabled, the account protocol will set to "pop3s"
    QString proto = config->readEntry( CONFIG_ENTRY_ACCOUNT_PROTOCOL, DEFAULT_ACCOUNT_PROTOCOL ).lower();
    int secureTransfer = config->readNumEntry( CONFIG_ENTRY_ACCOUNT_SECTRANSFER, DEFAULT_ACCOUNT_SECTRANSFER );

    if( proto == "pop3" &&  secureTransfer == CONFIG_VALUE_ACCOUNT_SECTRANSFER_SSL )
    {
      acc->setProtocol( "pop3s" );
    }
    else
    {
      acc->setProtocol(  proto );
    }

    if( secureTransfer == CONFIG_VALUE_ACCOUNT_SECTRANSFER_TLS )
      acc->setTLS( true );
    else
      acc->setTLS( false );


    acc->setPort( config->readNumEntry( CONFIG_ENTRY_ACCOUNT_PORT, DEFAULT_ACCOUNT_PORT_POP3 ) );
    acc->setUser( config->readEntry( CONFIG_ENTRY_ACCOUNT_USER, DEFAULT_ACCOUNT_USER ) );
    acc->setActive( config->readBoolEntry( CONFIG_ENTRY_ACCOUNT_ACTIVE, DEFAULT_ACCOUNT_ACTIVE ) );
    int StorageType = config->readNumEntry( CONFIG_ENTRY_ACCOUNT_PASSWORD_STORAGE, DEFAULT_ACCOUNT_PASSWORD_STORAGE );

    switch( StorageType )
    {
      case CONFIG_VALUE_ACCOUNT_PASSWORD_DONT_SAVE:
        acc->setPasswordStorage( CONFIG_VALUE_ACCOUNT_PASSWORD_DONT_SAVE );
        acc->setPassword( QString::null );
        break;

      case CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_FILE:
        acc->setPasswordStorage( CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_FILE );
        acc->setPassword( Encryption::decrypt( config->readEntry( CONFIG_ENTRY_ACCOUNT_PASSWORD, DEFAULT_ACCOUNT_PASSWORD ) ) );
        break;

      case CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_KWALLET:
        acc->setPasswordStorage( CONFIG_VALUE_ACCOUNT_PASSWORD_SAVE_KWALLET );
        acc->setPassword( KWalletAccess::getPassword( *it ) );
        break;

      default:
        acc->setPasswordStorage( DEFAULT_ACCOUNT_PASSWORD_STORAGE );
        acc->setPassword( QString::null );
    }

    //order the account to reloads its filter setup
    acc->reloadFilterSettings();
  }

  //connect the signals of the accounts with ConfigList
  connectAccounts();

  //refresh account list view
  setList( view );
}

void ConfigList::executeNewMailCommand( )
{
  if( m_bCommand )
  {
    if( m_strCommandPath != QString::null && m_strCommandPath != "" )
    {
      KShellProcess proc;    //process handler to execute the binary

      proc << m_strCommandPath;

      proc.start( KShellProcess::DontCare );
    }
  }
}

bool ConfigList::keepNew( )
{
  return m_bKeepNew;
}

bool ConfigList::confirmClose( ) const
{
  return m_bConfirmClose;
}

bool ConfigList::startMinimized( ) const
{
  return m_bStartMinimized;
}

bool ConfigList::closeToTray( ) const
{
  return m_bCloseMinimizes;
}

bool ConfigList::minimizesToTray( ) const
{
  return m_bMinimizeToTray;
}

bool ConfigList::showConnectionErrors( ) const
{
  return m_bShowConnectionErrors;
}

bool ConfigList::hasAccount( const QString & name ) const
{
  bool found = false;                       //TRUE if we have found the given account
  ConfigElem* account;                      //account from which we want to get its name
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list

  //iterate over all accounts
  while( ( account = it.current() ) != NULL && !found )
  {
    //increment iterator to next account
    ++it;

    //if current account is the searched one set found to TRUE
    if( account->getAccountName() == name )
      found = true;
  }

  return found;
}

ConfigElem * ConfigList::getAccount( const QString & name ) const
{
  bool found = false;                       //TRUE if we have found the given account
  ConfigElem* account = NULL;               //account from which we want to get its name
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list
  ConfigElem* returnValue = NULL;

  //iterate over all accounts
  while( ( account = it.current() ) != NULL && !found )
  {
    //increment iterator to next account
    ++it;

    //if current account is the searched one set found to TRUE
    if( account->getAccountName() == name )
    {
      found = true;
      returnValue = account;
    }
  }

  return returnValue;
}

void ConfigList::printSetup( )
{
  ConfigElem* account = NULL;               //account from which we want to print the setup
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    //print setup
    account->printSetup();
  }
}

void ConfigList::readStoredMails( )
{
  //open file
  QString MailFileName = locateLocal( "config", MAIL_FILE );
  QFile file( MailFileName );
  bool fileOpen = file.open( IO_ReadOnly );

  //return, if the file could not be opened
  if( !fileOpen )
  {
    kdError() << "ConfigList::readStoredMails: File " << MailFileName << " could not be opened." << endl;
    return;
  }

  //create DOM document with the content read from the file
  QDomDocument doc( MAIL_FILE_DOCTYPE );
  QString* errorMsg = new QString();

  bool success = doc.setContent( &file );
  if( !success )
  {
    kdError() << "ConfigList::readStoredMails: Invalid content in " << MAIL_FILE << ". " << *errorMsg << endl;
  }

  //get the root element
  QDomElement accounts = doc.namedItem ( ROOT_ELEMENT ).toElement();

  //get the first account element
  QDomNode accNode = accounts.firstChild();

  //get all account elements
  while( !accNode.isNull() )
  {
    //convert account node to DOM element
    QDomElement accElem = accNode.toElement();

    //get the account name
    QString accName = accElem.attribute( ATTRIBUTE_ACCOUNT_NAME );

    //get the proper account object
    ConfigElem* account = getAccount( accName );

    //order the account to read its stored mails
    account->readStoredMails( accElem );

    //get next account node
    accNode = accNode.nextSibling();
  }

  //close file
  file.close();
}

FilterAction_Type ConfigList::getSpamAction( )
{
  return spamAction;
}

QString ConfigList::getSpamMailbox( )
{
  return spamMailbox;
}

int ConfigList::numberDeletedMailsLastRefresh( )
{
  ConfigElem* account = NULL;
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list
  int number = 0;

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    number += account->numberDeletedMailsLastRefresh();
  }

  return number;
}

int ConfigList::numberDeletedMailsStart( )
{
  ConfigElem* account = NULL;
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list
  int number = 0;

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    number += account->numberDeletedMailsStart();
  }

  return number;
}

int ConfigList::numberMovedMailsLastRefresh( )
{
  ConfigElem* account = NULL;
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list
  int number = 0;

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    number += account->numberMovedMailsLastRefresh();
  }

  return number;
}

int ConfigList::numberMovedMailsStart( )
{
  ConfigElem* account = NULL;
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list
  int number = 0;

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    number += account->numberMovedMailsStart();
  }

  return number;
}

int ConfigList::numberIgnoredMails( )
{
  ConfigElem* account = NULL;
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list
  int number = 0;

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    number += account->numberIgnoredMails();
  }

  return number;
}

QStringList ConfigList::getSelectedSenders( ) const
{
  QStringList senders;                       //contains all senders
  QPtrListIterator<ConfigElem> it( *this );   //to iterate over all accounts
  ConfigElem* account;                        //current account

  while( ( account = it.current() ) != NULL )
  {
    //get senders of the current account and append them to the list
    senders += account->getSelectedSenders();

    //get next account
    ++it;
  }

  return senders;
}

void ConfigList::refreshFilterSetup( )
{
  ConfigElem* account;                      //account
  QPtrListIterator<ConfigElem> it( *this ); //iterator for the account list

  //iterate over all accounts
  while( ( account = it.current() ) != NULL )
  {
    //increment iterator to next account
    ++it;

    //reload filter setup of the current account
    account->reloadFilterSettings();
  }

}


