Logo Search packages:      
Sourcecode: kmess version File versions  Download package

kmess.cpp

/***************************************************************************
                          kmess.cpp  -  description
                             -------------------
    begin                : Sun Jan  5 15:18:36 CST 2003
    copyright            : (C) 2003 by Mike K. Bennett
    email                : mkb137b@hotmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "kmess.h"

#include <qdir.h>

#include <kaction.h>
#include <kconfig.h>
#include <kdebug.h>
#include <klistview.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <krun.h>
#include <kstandarddirs.h>
#include <kurl.h>

#if KDE_IS_VERSION(3,2,0)
#include <kinputdialog.h>
#else
#include <klineeditdlg.h>
#endif

#include "actions/accountaction.h"
#include "chat/chatmaster.h"
#include "chat/chatwindow.h"
#include "contact/contact.h"
#include "contact/contactlist.h"
#include "contact/group.h"
#include "dialogs/contactaddeduserdialoginterface.h"
#include "dialogs/contactaddeduserdialog.h"
#include "dialogs/awaymessagedialog.h"
#include "dialogs/networkwindow.h"
#include "dialogs/transferwindow.h"
#include "network/msnnotificationconnection.h"
#include "notification/passivepopupinterface.h"
#include "notification/notificationmanager.h"
#include "notification/notificationchat.h"
#include "notification/notificationcontactstatus.h"
#include "notification/notificationnewemail.h"
#include "settings/settingsdialog.h"
#include "account.h"
#include "autologinview.h"
#include "currentaccount.h"
#include "emoticonmanager.h"
#include "idletimer.h"
#include "initialview.h"
#include "kmessdebug.h"
#include "kmessinterface.h"
#include "kmessview.h"
#include "nowlisteningclient.h"
#include "systemtraywidget.h"



// The constructor
KMess::KMess(QWidget *parent, const char *name)
 : KMessInterface(parent, name),
   autologinView_(0),
   chatMaster_(0),
   notificationChat_(0),
   notificationContactStatus_(0),
   notificationNewEmail_(0),
   currentStatus_("FLN"),
   idleTimer_(0),
   initialized_(false),
   initialView_(0),
   nowListeningClient_(0),
   msnNotificationConnection_(0),
   view_(0)
{

}



// The destructor
KMess::~KMess()
{
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess destructor: shutting down KMess..." << endl;
#endif

  Account *account;

  /*
   * The destructor is called after closeEvent(),
   * when KMess is quit by the user.
   *
   * If the KDE session ends, the destructor won't be called.
   * only saveProperties() will be called, and the execution ends.
   */


  // Saving properties manually.
  saveProperties( kapp->config() );

  // Delete all chat windows
  if(chatMaster_ != 0)
  {
    chatMaster_->disconnected();
    chatMaster_->deleteLater();
    chatMaster_ = 0;
  }

  // Disconnect main connection so views can clean up/save properties.
  if(msnNotificationConnection_->isConnected())
  {
    // Make sure KMess::disconnected() does attempt to update
    // the user interface when we're trying to kill it
    disconnect(msnNotificationConnection_, SIGNAL(disconnected()), this, SLOT(disconnected()) );

    // This also destroys all contacts
    msnNotificationConnection_->closeConnection();
  }

  // Delete other created objects
  delete idleTimer_;
  delete view_;
  delete initialView_;
  delete autologinView_;
  delete notificationChat_;
  delete notificationContactStatus_;
  delete notificationNewEmail_;
  delete nowListeningClient_;
  delete systemTrayWidget_;
  delete msnNotificationConnection_;
  CurrentAccount::destroy();
  TransferWindow::destroy();

  // Delete the accounts
  for ( account = accounts_.first(); account; account = accounts_.next() )
  {
    delete account;
  }
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "DESTROYED KMess" << endl;
#endif
}



// The account changed it's status to invisible
void KMess::accountInvisible()
{
  // Disable the now listening detection
  nowListeningClient_->setEnabled( false );

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess: account went invisible, disabled now listening detection." << endl;
#endif
}



// The account changed it's status to offline
void KMess::accountOffline()
{
  // Disable the now listening detection
  nowListeningClient_->setEnabled( false );

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess: account went offline, disabled now listening detection." << endl;
#endif
}



// The account changed it's status to online
void KMess::accountOnline()
{
  // Enable the now listening detection if needed.
  nowListeningClient_->setEnabled( currentAccount_->getShowNowListening() );

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess: account went online. Now listening is "
            << ( currentAccount_->getShowNowListening() ? "enabled" : "disabled") << "." << endl;
#endif
}



// Add the account and create the GUI elements
void KMess::addAccount(Account *account)
{
  AccountAction *accountAction;
  QString handle = account->getHandle();

  // Append account
  accounts_.append(account);

  // Make the action for the "Connect..." menu
  accountAction = new AccountAction( account, this, account->getHandle() );
  connectActionMenu_->insert( accountAction );
  connectMenuItems_.insert( handle, accountAction );

  connect( accountAction, SIGNAL(          activated(Account*) ),
           this,          SLOT  ( connectWithAccount(Account*) ) );


  // Make the action for the "Settings..." menu
  accountAction = new AccountAction( account, this,  account->getHandle() );
  settingsActionMenu_->insert( accountAction );
  settingsMenuItems_.insert( handle, accountAction );

  connect( accountAction, SIGNAL(              activated(Account*) ),
           this,          SLOT  ( showSettingsForAccount(Account*) ) );


  // Add the account to the initial view's dropdown list.
  initialView_->addAccount( account );
}



// "Add a new contact" was selected from the menu.
void KMess::addNewContact()
{
#ifdef KMESSTEST
  ASSERT( msnNotificationConnection_ != 0 );
#endif
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::addNewContact()" << endl;
#endif
  QString newHandle;
  bool    okPressed = false;

  // Launch a dialog to get a new group name
#if KDE_IS_VERSION(3,2,0)
  newHandle = KInputDialog::getText(i18n("Add a contact"),
                                    i18n("Enter the email address of the person you wish to add:"),
                                    newHandle, &okPressed, this);
#else
  newHandle = KLineEditDlg::getText(i18n("Add a contact"),
                                    i18n("Enter the email address of the person you wish to add:"),
                                    newHandle, &okPressed, this);
#endif

  if( ! okPressed )
  {
    return;
  }

  // Check if the handle is valid, or we'll get server errors.
  if( ! isValidEmail( newHandle ) )
  {
    KMessageBox::error( 0, i18n( "The contact address you have entered is not valid: '%1'").arg( newHandle ) );
    return;
  }

  // Ask the server to add the contact
  msnNotificationConnection_->addNewContact(newHandle);
}



// "Add a new group" was selected from the menu.
void KMess::addNewGroup()
{
#ifdef KMESSTEST
  ASSERT( msnNotificationConnection_ != 0 );
#endif
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::addNewGroup()" << endl;
#endif
  QString newGroupName;
  bool    okPressed = false;

  // Set a default group name
  newGroupName = "New Group";

  // Launch a dialog to get a new group name
#if KDE_IS_VERSION(3,2,0)
  newGroupName = KInputDialog::getText(i18n("Add a group"),
                                       i18n("Enter the new name for this group:"),
                                       newGroupName, &okPressed, this);
#else
  newGroupName = KLineEditDlg::getText(i18n("Add a group"),
                                       i18n("Enter the new name for this group:"),
                                       newGroupName, &okPressed, this);
#endif

  if(okPressed)
  {
    // Ask the server to add the group
    msnNotificationConnection_->addGroup( newGroupName );
  }
}



// The application is closing, after queryExit() was approved
void KMess::applicationClosing()
{
  if(chatMaster_ != 0)
  {
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::applicationClosing: destroying chat master" << endl;
#endif

    // Close the chat windows earlier, so logs are saved.
    chatMaster_->disconnected();
    chatMaster_->deleteLater();
    chatMaster_ = 0;
  }
}



// An account's settings have been changed
void KMess::changedAccountSettings( Account *account, QString oldHandle, QString oldFriendlyName )
{
  QString newHandle = account->getHandle();

  // We're saving settings for a new account
  if( accounts_.contains( account ) == 0 )
  {

    // Make sure the account handle was changed off the default
    if( ! newHandle.isEmpty() && newHandle != i18n( "you@hotmail.com" ) && isValidEmail( newHandle ) )
    {
      // Avoid recognizing the new account handle and friendly name as changed,
      // since that would mean changing an entry which doesn't exists yet.
      oldHandle = newHandle;
      oldFriendlyName = account->getFriendlyName();

      // Add the account to the account list.
      addAccount(account);
    }
    else if( ! newHandle.isEmpty() && ! isValidEmail( newHandle ) )
    {
      KMessageBox::error( 0, i18n( "The contact address you have entered is not valid: '%1'").arg( newHandle ) );
      delete account;
      return;
    }
    else
    {
      // The account wasn't changed, so delete it.
      delete account;
      return;
    }
  }

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::changedAccountSettings() - Saving settings for " << account->getHandle() << endl;
#endif
#ifdef KMESSTEST
  ASSERT( msnNotificationConnection_ != 0 );
#endif

  bool isCurrentAccount = false;
  bool isConnectedCurrentAccount = false;

  if ( msnNotificationConnection_ != 0 )
  {
    isCurrentAccount          = ( oldHandle == currentAccount_->getHandle() );
    isConnectedCurrentAccount = ( isCurrentAccount && msnNotificationConnection_->isConnected() );
  }

  // If the account matches the current account..
  if( isCurrentAccount )
  {
    // If the friendly name was changed, ask the server to change it
    if ( account->isVerified() && account->getFriendlyName() != oldFriendlyName )
    {
      msnNotificationConnection_->changeFriendlyName( account->getFriendlyName() );
    }

    // Copy the account settings to the current account
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::changedAccountSettings() - Copying modified Account settings to CurrentAccount." << endl;
#endif
    currentAccount_->copyAccount( account );
  }

  // If the account is set to use autologin, make sure that all other accounts are not
  if( ! account->isDeleted() && account->getUseAutologin() )
  {
    QPtrListIterator<Account>  it(accounts_);
    while ( it.current() != 0 )
    {
      // For each account that is not the account just changed...
      if ( it.current() != account )
      {
        it.current()->setUseAutologin( false );
      }
      ++it;
    }
  }

  // Change the account name in the UI when it's been changed
  if( oldHandle != newHandle )
  {
    // Remove from connect menu.
    connectActionMenu_->remove( connectMenuItems_[ oldHandle ] );
    connectMenuItems_.remove( oldHandle );

    // Remove from settings menu.
    settingsActionMenu_->remove( settingsMenuItems_[ oldHandle ] );
    settingsMenuItems_.remove( oldHandle );

    // Make the action for the "Connect..." menu
    AccountAction *accountAction;
    accountAction = new AccountAction( account, this, newHandle );
    connectActionMenu_->insert( accountAction );
    connectMenuItems_.insert( newHandle, accountAction );
    connect( accountAction, SIGNAL(          activated(Account*) ),
             this,          SLOT  ( connectWithAccount(Account*) ) );

    // Make the action for the "Settings..." menu
    accountAction = new AccountAction( account, this,  newHandle );
    settingsActionMenu_->insert( accountAction );
    settingsMenuItems_.insert( newHandle, accountAction );
    connect( accountAction, SIGNAL(              activated(Account*) ),
             this,          SLOT  ( showSettingsForAccount(Account*) ) );

    // Notify the initial view when the account handle has changed.
    initialView_->changedAccount( oldHandle, newHandle );
  }
}



// A status was selected from the menu.
void KMess::changeStatus(const QString &statusName)
{
  QString            newStatus = "";
  bool               useAutoreply;
  AwayMessageDialog *awayMessageDialog;
  QString            awayMessage;

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "Selected status " << statusName << endl;
#endif
  currentAccount_->setAutoreply( false );
  if ( statusName == i18n("Away") )
  { // Change status to AWAY
    newStatus = "AWY";
  }
  else if ( statusName == i18n("Away with auto-reply") )
  { // Change status to AWAY
    newStatus = "AWY";
    // Create the away message dialog
    awayMessageDialog = new AwayMessageDialog( this, "awaymessagedialog" );
    // Confirm the auto-away message with the user
    awayMessage = CurrentAccount::instance()->getAutoreplyMessage();
    useAutoreply = false;
    useAutoreply = awayMessageDialog->useMessage( awayMessage );
    if ( useAutoreply )
    {
      // Tell the account to respond with an autoreply message
      CurrentAccount::instance()->setAutoreplyMessage( awayMessage );
      CurrentAccount::instance()->setAutoreply( true );
    }
    delete awayMessageDialog;
  }
  else if ( statusName == i18n("Be Right Back") )
  { // Change status to BE RIGHT BACK
    newStatus = "BRB";
  }
  else if ( statusName == i18n("Busy") )
  { // Change status to BUSY
    newStatus = "BSY";
  }
  else if ( statusName == i18n("Invisible") )
  { // Change status to INVISIBLE
    newStatus = "HDN";
  }
  else if ( statusName == i18n("Out to Lunch") )
  { // Change status to OUT TO LUNCH
    newStatus = "LUN";
  }
  else if ( statusName == i18n("Online") )
  { // Change status to ONLINE
    newStatus = "NLN";
  }
  else if ( statusName == i18n("On the Phone") )
  { // Change status to ON THE PHONE
    newStatus = "PHN";
  }
  if ( newStatus != "" )
  {
    msnNotificationConnection_->changeStatus( newStatus );
  }
}



// Tray notifications settings were changed
void KMess::changedNotificationsSettings()
{
  notificationChat_->setEnabled( currentAccount_->getNotifyContactsChatStart(), currentAccount_->getNotifyContactsChatMessages() );
  notificationContactStatus_->setEnabled( currentAccount_->getNotifyContactsOnline(), currentAccount_->getNotifyContactsOffline(), currentAccount_->getNotifyContactsStatus() );
  notificationNewEmail_->setEnabled( currentAccount_->getNotifyEmails() );
}



// The current now listening settings have changed.
void KMess::changedNowListeningSettings()
{
  // Enable now listening if current account is online and likes to enable now listening.
  QString status = currentAccount_->getStatus();
  bool isOnline = status != "FLN" && status != "HDN";  // not offline or invisible.
  nowListeningClient_->setEnabled( currentAccount_->getShowNowListening() && isOnline );

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess: now listening settings changed. Now listening is "
            << ( currentAccount_->getShowNowListening() ? "enabled" : "disabled") << endl;
#endif
}



// The currently playing song was changed.
void KMess::changedSong( const QString &artist, const QString &album, const QString &track, bool playing )
{
  if( msnNotificationConnection_->isConnected() )
  {
    if( ! playing )
    {
      // Update notification connection and KMessView.
      msnNotificationConnection_->removeCurrentMedia();
    }
    else
    {
      // Update notification connection.
      QStringList arguments;
      arguments << track << artist << album << "" << "";
      msnNotificationConnection_->changeCurrentMedia( "", "Music", true, "{0} - {1}", arguments );
    }

    // Update KMessView
    view_->changedSong( artist, album, track, playing );
  }
}



// The status was changed
void KMess::changedStatus( Account *account )
{
  int item = -1;
  QString newStatus;

  if( account != 0 )
  {
    newStatus = account->getInitialStatus();
  }
  else if ( currentAccount_ != 0 )
  {
    newStatus = currentAccount_->getStatus();
  }
  else
  {
    kdWarning() << "KMess::changedStatus() - Changed status dropdown without an account set!" << endl;
    return;
  }

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Changed status to " << newStatus << " from " << currentStatus_ << ". "
            << "Autoreply is " <<  currentAccount_->getAutoreply() << endl;
#endif

  // Make sure the drop down list matches the user's status
  if ( newStatus == "AWY" )
  {
    if ( !currentAccount_->getAutoreply() )
    {
      // Change status to AWAY
      item = 1;
    }
    else
    {
      // Change status to AWAY with autoreply
      item = 2;
    }
  }
  else if ( newStatus == "BRB" )
  { // Change status to BE RIGHT BACK
    item = 3;
  }
  else if ( newStatus == "BSY" )
  { // Change status to BUSY
    item = 4;
  }
  else if ( newStatus == "HDN" )
  { // Change status to INVISIBLE
    item = 7;
  }
  else if ( newStatus == "LUN" )
  { // Change status to OUT TO LUNCH
    item = 5;
  }
  else if ( newStatus == "NLN" )
  { // Change status to ONLINE
    item = 0;
  }
  else if ( newStatus == "PHN" )
  { // Change status to ON THE PHONE
    item = 6;
  }

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Changed the select status to item " << item << endl;
#endif

  if ( item >= 0 )
  {
    status_->setCurrentItem( item );
  }
}



// A view mode has been selected from the menu.
void KMess::changeViewMode(int mode)
{
#ifdef KMESSTEST
  ASSERT( ( mode == 0 ) || ( mode == 1 ) );
#endif
  if ( mode == 0 )
  {
    CurrentAccount::instance()->setShowContactsByGroup( true );
  }
  else if ( mode == 1 )
  {
    CurrentAccount::instance()->setShowContactsByGroup( false );
  }
  else
  {
    kdDebug() << "KMess - changeViewMode() - WARNING - Invalid view mode = " << mode << endl;
  }
}



// Show a "Contact added you" dialog
void KMess::showContactAddedUserDialog(const Contact *contact)
{
  // Note that this function isn't well tested because the case where
  //  somebody adds you to their contact list doesn't occur very often,
  //  not when you've been using messenger for a while.
  QString                 handle;
  ContactAddedUserDialog *dialog;
  int                     returnValue;

  handle = contact->getHandle();
  dialog = new ContactAddedUserDialog();

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "Contact added user" << endl;
#endif

  // Show a dialog and let the user choose whether to add, allow,
  //  or block the contact.
  returnValue = dialog->launch(handle, contact->getFriendlyName());
  delete dialog;

  if ( returnValue == ContactAddedUserDialog::ADD )
  {
    // Add the contact to the allowed and friends lists
    msnNotificationConnection_->addNewContact(handle);
  }
  else if ( returnValue == ContactAddedUserDialog::ALLOW )
  {
    // Add the contact to the allowed list
    msnNotificationConnection_->allowContact(handle);
  }
  else if ( returnValue == ContactAddedUserDialog::BLOCK )
  {
    // Add the contact to the blocked list.
    msnNotificationConnection_->blockContact(handle);
  }
}


#ifdef KMESS_NETWORK_WINDOW
// Opens the network window
void KMess::showNetworkWindow()
{
  NetworkWindow::instance()->show();
}
#endif


// Show a dialog before removing the contact
void KMess::showRemoveContactDialog(QString handle)
{
  QString message = i18n( "<qt>Are you sure you want to remove the contact <b>%1</b> from your contact list?</qt>" )
                    .arg(handle);

  int result = KMessageBox::warningYesNoCancel( this, message, i18n( "Remove contact" )
                                              , KGuiItem(i18n("Remove"), "editdelete")             // Yes
                                              , KGuiItem(i18n("Remove and block"), "remove")       // No
                                              , 0
#if KDE_IS_VERSION(3,2,0)
                                              , KMessageBox::Dangerous
#endif
                                              );

  switch( result )
  {
    // User has pressed "Remove and block"
    case KMessageBox::No :
      msnNotificationConnection_->removeContact( handle, true );
      break;

    // User has pressed "Remove only"
    case KMessageBox::Yes :
      msnNotificationConnection_->removeContact( handle, false );
      break;

    // User has canceled the action, no nothing
    case KMessageBox::Cancel :
    default:
      break;
  }

}


// Show a dialog before removing the group
void KMess::showRemoveGroupDialog(QString groupId)
{
  Group *group = currentAccount_->getContactList()->getGroupById(groupId);
 
  // If the group was found
  if(group == 0)
  {
    kdDebug() << "KMess::showRemoveGroupDialog() - Couldn't find a matching group." << endl;
    return;
  }

  QString message = i18n( "<qt>Are you sure you want to remove the group <b>%1</b> from your contact list?</qt>" )
                    .arg(group->getName());

  int result = KMessageBox::warningContinueCancel( this, message, i18n( "Remove group" ),
                                                   KGuiItem(i18n("Remove"), "editdelete"), 0
#if KDE_IS_VERSION(3,2,0)
                                                   , KMessageBox::Dangerous
#endif
                                                  );

  if(result == KMessageBox::Continue)
  {
    msnNotificationConnection_->removeGroup(groupId);
  }
}


// Show a "Rename group" dialog
void KMess::showRenameGroupDialog(QString groupId)
{
  Group  *group = currentAccount_->getContactList()->getGroupById(groupId);
  QString newGroupName;
  bool    okPressed = false;

  // If the group was found
  if ( group == 0 )
  {
    kdDebug() << "KMess::showRenameGroupDialog() - Couldn't find a matching group." << endl;
    return;
  }

  // If the group is not a special group...
  if(group->isSpecialGroup())
  {
    // Show a message that it can't be deleted
    KMessageBox::error( 0, i18n("This is a special group and can't be changed.") );
    return;
  }
  else
  {
    // Otherwise, get the new group name..
    newGroupName = group->getName();

    // Launch a dialog to get a new group name
#if KDE_IS_VERSION(3,2,0)
  newGroupName = KInputDialog::getText(i18n("Rename group"),
                                       i18n("Enter the new name for this group:"),
                                       newGroupName, &okPressed, this);
#else
  newGroupName = KLineEditDlg::getText(i18n("Rename group"),
                                       i18n("Enter the new name for this group:"),
                                       newGroupName, &okPressed, this);
#endif

    if(okPressed)
    {
      // Request that the group be renamed
      msnNotificationConnection_->renameGroup(groupId, newGroupName);
    }
  }
}


// Opens the transfer manager
void KMess::showTransferWindow()
{
  TransferWindow *transferWindow = TransferWindow::getInstance();
  transferWindow->show();
}


// Autologin with the first account that has autologin enabled
void KMess::checkAutologin(QString handle)
{
  Account *loginAccount = 0;

  // If no handle was given...
  if ( handle.isEmpty() )
  {
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::checkAutologin: No handle was given, find an account that uses autologin." << endl;
#endif
    for ( Account *account = accounts_.first(); account; account = accounts_.next() )
    {
      // For completeness, also test for guest accounts.
      if( account->isGuestAccount() )
      {
        continue;
      }

#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KMess: Account " << account->getHandle()
                << " useAutologin = " << account->getUseAutologin() << "." << endl;
#endif
      if ( account->getUseAutologin() )
      {
        loginAccount = account;
        break;
      }
    }
  }
  else
  {
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::checkAutologin finding account: " << handle << "." << endl;
#endif
    loginAccount = getAccountByHandle(handle);
  }

  if ( loginAccount != 0 )
  {
    // Use the autologin view as the main view
    //initialView_->hide();
    //autologinView_->show();
    
    autologinView_->setEnabled( true );
    setCentralWidget( autologinView_ );
    connectWithAccount( loginAccount );
  }
}



// A connection has been made with the notification server.
void KMess::connected()
{
#ifdef KMESSTEST
  ASSERT( view_ != 0 );
  ASSERT( initialView_ != 0 );
  ASSERT( autologinView_ != 0 );
#endif

  // Enable/disable the menus
  enableMenus( true );

  // Set up the toggle and view mode tools to match the account settings
  showAllowedAction_->setChecked( currentAccount_->getShowAllowedContacts() );
  showOfflineAction_->setChecked( currentAccount_->getShowOfflineContacts() );
  showRemovedAction_->setChecked( currentAccount_->getShowRemovedContacts() );
  if ( currentAccount_->getShowContactsByGroup() )
  {
    viewMode_->setCurrentItem( 0 );
  }
  else
  {
    viewMode_->setCurrentItem( 1 );
  }
  // Show the connected message
  statusMessage( i18n("Connected"), TYPE_MESSAGE );

  // Swap the initial and main views
  initialView_->setEnabled( false );
  initialView_->hide();

  autologinView_->setEnabled( false );
  autologinView_->hide();

  // Give the view widget some info
  view_->connected();

  view_->setEnabled( true );
  view_->show();

  // Set it as the application's main widget
  setCentralWidget( view_ );

  // Set the caption
  setCaptionToUser();

  // The connection was successful, this means the supplied
  // email and password were correct: save the KMess settings now
  KConfig *config = kapp->config();
  saveProperties( config );
}



// Connect to the server with the given account
void KMess::connectWithAccount(Account *account)
{
  if(KMESS_NULL(account)) return;

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::connectWithAccount: " << account->getHandle() << "." << endl;
#endif

  // First disconnect, to unregister all contacts
  if(msnNotificationConnection_->isConnected())
  {
    msnNotificationConnection_->closeConnection();
  }

  // Update the main view's controls to match this account's details.
  changedStatus( account );

  // Swap widget.
  initialView_->setEnabled( false );
  initialView_->hide();

  autologinView_->setEnabled( true );
  autologinView_->show();

  setCentralWidget( autologinView_ );

  // Copy the account to the current account
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess: copying account data for '" << account->getHandle() << "' to the CurrentAccount object." << endl;
#endif
  currentAccount_->copyAccount( account );

  // Allow users to cancel the login attempt
  disconnect_->setEnabled( true );

  // Connect to the server.
  msnNotificationConnection_->openConnection();
}



// Connect to the server with the given account, possibly temporary or new.
void KMess::connectWithAccount(QString handle, QString password, bool rememberMe, QString initialStatus )
{
  // Try to find an existing account
  Account *account = getAccountByHandle(handle);
  if( account != 0 )
  {
    // Found an existing account.
    // The user may enter a new password at the login dialog.
    // When the login succeeds, save the new temporary password as new account password.
    account->setTemporaryPassword( password );
    account->setInitialStatus( initialStatus );
    connectWithAccount( account );
    return;
  }

  // No account found, create a new account.
  account = new Account();
  account->setLoginInformation( handle, handle, password );
  account->setGuestAccount( ! rememberMe );
  account->setInitialStatus( initialStatus );
  addAccount( account );

  // Connect
  connectWithAccount( account );
}



// Create the program's default directories in .kde/share/apps/
bool KMess::createDirectories()
{
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Creating default directories." << endl;
#endif
  KStandardDirs *dirs   = KGlobal::dirs();
  QString        localKdeDir;
  QDir           appsDir, kmessDir, emoticonsDir, picsDir;

  localKdeDir = dirs->localkdedir();
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Local KDE dir is " << localKdeDir << "." << endl;
#endif
  appsDir.setPath( localKdeDir + "/share/apps" );

  if ( appsDir.exists() )
  {
    kmessDir.setPath( appsDir.absPath() + "/kmess" );
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess - kmess dir should be at " << kmessDir.absPath() << "." << endl;
#endif
    if ( !kmessDir.exists() )
    {
#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KMess - Creating kmess dir." << endl;
#endif
      appsDir.mkdir( kmessDir.absPath(), true );
    }
    // Create the pics and emoticons directories
    emoticonsDir.setPath( kmessDir.absPath() + "/emoticons" );
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess - emoticons dir should be at " << emoticonsDir.absPath() << "." << endl;
#endif
    if ( !emoticonsDir.exists() )
    {
#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KMess - Creating emoticons dir." << endl;
#endif
      kmessDir.mkdir( emoticonsDir.absPath(), true );
    }
    picsDir.setPath( kmessDir.absPath() + "/pics" );
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess - pics dir should be at " << picsDir.absPath() << "." << endl;
#endif
    if ( !picsDir.exists() )
    {
#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KMess - Creating pics dir." << endl;
#endif
      kmessDir.mkdir( picsDir.absPath(), true );
    }
  }
#ifdef KMESSDEBUG_KMESS
  else
  {
    kdDebug() << "KMess - " << appsDir.absPath() << " doesn't exist!" << endl;
  }
#endif
#ifdef KMESSTEST
  ASSERT(     kmessDir.exists() );
  ASSERT( emoticonsDir.exists() );
  ASSERT(      picsDir.exists() );
#endif
  return true;
}



// "Add new account" has been selected from the menu.
void KMess::createNewAccount()
{
  Account *account;
  // If there are no profiles, create a "default" account
  // Create an account to store the profile information
  account = new Account();

  // Assume the user *does* want to save it's settings,
  // otherwise he/she would have used the main login dialog.
  account->setGuestAccount(false);

  // Show the settings dialog for the new account
  showSettingsForAccount( account );
}



// The current account changed its name, so set the corresponding account's name
void KMess::currentAccountChangedName()
{
  Account *account = getAccountByHandle( currentAccount_->getHandle() );
  if( account != 0 )
  {
    // Set the account's name to the current account's name
    account->setFriendlyName( currentAccount_->getFriendlyName() );
  }

  // Set the caption to the account's new name
  setCaptionToUser();
}



// Delete the given account
void KMess::deleteAccount(Account *account)
{
  AccountAction *accountAction;
  if( KMESS_NULL(account) ) return;

  QString handle = account->getHandle();
  if( handle == currentAccount_->getHandle() && msnNotificationConnection_->isConnected() )
  {
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::deleteAccount: Not deleting account " << account->getHandle() << " yet." << endl;
#endif

    // Already delete account data.
    // NOTE: when more classes have an Account* object, consider creating a setDeleted(true)
    // method, and let deleteAccountData() fire a deleteAccount(this) signal.
    account->deleteAccountData();
    return;
  }

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess: Deleting account for " << handle << "." << endl;
#endif

  // Remove the account from the list of accounts
  if( ! accounts_.remove( account ) )
  {
    kdWarning() << "KMess::deleteAccount: account not found in collection!" << endl;
  }

  // Remove from other GUI parts
  initialView_->deleteAccount(account);

  // Remove from connect menu.
  accountAction = connectMenuItems_[handle];
  if( ! KMESS_NULL(accountAction) )
  {
    connectActionMenu_->remove(accountAction);
    connectMenuItems_.remove(handle);
  }

  // Remove from settings menu.
  // This can't be done from AccountAction, because the menu item should
  // remain accessable when you're logged in.
  accountAction = settingsMenuItems_[handle];
  if( ! KMESS_NULL(accountAction) )
  {
    settingsActionMenu_->remove(accountAction);
    settingsMenuItems_.remove(handle);
  }

  // Delete here as this class maintains the collection.
  // No need to call deleteAccountData(), it triggered this slot.
  account->deleteAccountData();
  account->deleteLater();
}



// Disconnect was selected from the menu.
void KMess::disconnectClicked()
{
#ifdef KMESSTEST
  ASSERT( msnNotificationConnection_ != 0 );
#endif
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMess: Disconnecting." << endl;
#endif
  msnNotificationConnection_->closeConnection();
}



// The program is not connected (initially) or no longer connected (after a disconnect) to the notification server.
void KMess::disconnected()
{
#ifdef KMESSTEST
  ASSERT( view_ != 0 );
  ASSERT( chatMaster_ != 0 );
  ASSERT( initialView_ != 0 );
  ASSERT( autologinView_ != 0 );
#endif
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Disconnected." << endl;
#endif

  // this method is also called when initializing the GUI, avoid manging the settings at that point.
  if( initialized_ )
  {
    // ContactList is saved by the MsnNotificationConnection already.
    // A nice alternative would be currentAccount_->disconnected() saving the list,
    // however CurrentAccount has a const reference to the list
    // because MsnNotificationConnection maintains the list instead.

    // Transfer account settings that are made in the GUI.
    Account *account = getAccountByHandle(currentAccount_->getHandle());
    if( ! KMESS_NULL(account) )
    {
      if( account->isDeleted() )
      {
#ifdef KMESSDEBUG_KMESS
        kdDebug() << "KMess::disconnected: account was deleted, removing menu items." << endl;
#endif
        deleteAccount(account);
      }
      else
      {
#ifdef KMESSDEBUG_KMESS
        kdDebug() << "KMess::disconnected: copying global user-interface settings from CurrentAccount to the Account object." << endl;
#endif

        account->copyAccountUISettings( currentAccount_ );
      }
    }
  }

  // Update the GUI
  disconnect_->setEnabled( false );
  enableMenus(false);
  statusMessage( i18n("Disconnected"), TYPE_ERROR );

  // Inform other classes we're disconnected
  view_->disconnected();
  chatMaster_->disconnected();

  // Update the current account
  currentAccount_->setStatus( "FLN" );
  currentAccount_->setAutoreply( false );
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Swap views." << endl;
#endif

  // Swap the initial and main views
  view_->setEnabled( false );
  view_->hide();

  autologinView_->setEnabled( false );
  autologinView_->hide();
  initialView_->setEnabled( true );
  initialView_->show();
  initialView_->updateView();
  // Set it as the application's main widget
  setCentralWidget( initialView_ );

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - Blank the caption." << endl;
#endif
  // Set the caption
  setCaption( QString::null );
}



// Initialize the class
bool KMess::initialize()
{
  if ( initialized_ )
  {
    kdDebug() << "KMess - Already initialized." << endl;
    return false;
  }

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::initialize: initializing main class." << endl;
#endif

  // Create current account instance
  currentAccount_ = CurrentAccount::instance();
  if ( currentAccount_ == 0 )
  {
    kdDebug() << "KMess - Couldn't get a pointer to the instance of the current account." << endl;
    return false;
  }
  if ( !KMessInterface::initialize() )
  {
    kdDebug() << "KMess - Couldn't initialize ancestor." << endl;
    return false;
  }
  if ( !initMsnNotificationConnection() )
  {
    kdDebug() << "KMess - Couldn't initialize the MsnNotificationConnection class." << endl;
    return false;
  }
  if ( !initIdleTimer() )
  {
    kdDebug() << "KMess - Couldn't initialize the IdleTimer class." << endl;
    return false;
  }
  if ( !initAutologinView() )
  {
    kdDebug() << "KMess - Couldn't initialize the AutologinView widget." << endl;
    return false;
  }
  if ( !initInitialView() )
  {
    kdDebug() << "KMess - Couldn't initialize the InitialView widget." << endl;
    return false;
  }
  if ( !initChatMaster() )
  {
    kdDebug() << "KMess - Couldn't initialize the Chat master." << endl;
    return false;
  }
  if ( !initKMessView() )
  {
    kdDebug() << "KMess - Couldn't initialize the KMessView widget." << endl;
    return false;
  }
  if ( !initSystemTrayWidget() )
  {
    kdDebug() << "KMess - Couldn't initialize the system tray widget." << endl;
    return false;
  }
  if ( !initNotifications() )
  {
    kdDebug() << "KMess - Couldn't initialize the notifications." << endl;
    return false;
  }
  if ( !initNowListening() )
  {
    kdDebug() << "KMess - Couldn't initialize the now listening support." << endl;
    return false;
  }
  if ( !initEmoticonManager() )
  {
    kdDebug() << "KMess - Couldn't initialize the emoticon manager." << endl;
    return false;
  }
  if ( !createDirectories() )
  {
    kdDebug() << "KMess - Couldn't create local KDE directories." << endl;
    return false;
  }


  // Start reading the properties
  readProperties( kapp->config() );


  // Connect current account
  connect( currentAccount_, SIGNAL(            accountInvisible() ),
           this,            SLOT  (            accountInvisible() ));
  connect( currentAccount_, SIGNAL(              accountOffline() ),
           this,            SLOT  (              accountOffline() ));
  connect( currentAccount_, SIGNAL(               accountOnline() ),
           this,            SLOT  (               accountOnline() ));
  connect( currentAccount_, SIGNAL(         changedFriendlyName() ),
           this,            SLOT  (   currentAccountChangedName() ));
  connect( currentAccount_, SIGNAL( changedNowListeningSettings() ),
           this,            SLOT  ( changedNowListeningSettings() ));
  connect( currentAccount_, SIGNAL(changedNotificationsSettings() ),
           this,            SLOT  (changedNotificationsSettings() ));
  connect( currentAccount_, SIGNAL(               changedStatus() ),
           this,            SLOT  (               changedStatus() ));
  connect( currentAccount_, SIGNAL(            changedMsnObject() ),
           msnNotificationConnection_, SLOT(   changedMsnObject() ));

  // connect a shutDown() signal
  connect( KApplication::kApplication(),  SIGNAL(    shutDown() ),
           this,                          SLOT  (    shutDown() ) );


  // Start disconnected.
  // Added debug here because this has a potential to cause problems..
  // It would be better if each class got things right from it's construtor or initialize method.
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::initialize: faking disconnect signal." << endl;
#endif
  disconnected();


  // All done, mark as initialized
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::initialize: main class is initialized." << endl;
#endif

  initialized_ = true;
  return true;
}



// Return the account for a given handle
Account * KMess::getAccountByHandle( const QString &handle )
{
  Account *account = 0;
  QPtrListIterator<Account> it( accounts_ );
  while( it.current() != 0 )
  {
    account = it.current();
    if( account->getHandle() == handle )
    {
      return account;
    }

    ++it;
  }

  return 0;
}


// Initialize the autologin view
bool KMess::initAutologinView()
{
  autologinView_ = new AutologinView( this, "autologinView" );
  if ( autologinView_ == 0 )
  {
    kdDebug() << "KMess - Couldn't create the autologin view" << endl;
    return false;
  }
  autologinView_->setEnabled( false );
  autologinView_->hide();
  return true;
}



// Initialize the chat master
bool KMess::initChatMaster()
{
#ifdef KMESSTEST
  ASSERT( chatMaster_ == 0 );
#endif
  if ( msnNotificationConnection_ == 0 )
  {
    kdDebug() << "KMess - The notification connection must be initialized before the chat master." << endl;
    return false;
  }
  chatMaster_ = new ChatMaster( this );
  if ( chatMaster_ == 0 )
  {
    kdDebug() << "KMess - Couldn't create the chat master." << endl;
    return false;
  }
  if ( !chatMaster_->initialize() )
  {
    kdDebug() << "KMess - Couldn't initialize the chat master." << endl;
    return false;
  }

  // Make the chat master's connections
  connect( chatMaster_,                SIGNAL( requestSwitchboard(QString,ChatInformation::ConnectionType) ),
           msnNotificationConnection_, SLOT  ( requestSwitchboard(QString,ChatInformation::ConnectionType) ));
  connect( chatMaster_,                SIGNAL(       blockContact(QString) ),
           msnNotificationConnection_, SLOT  (       blockContact(QString) ) );
  connect( chatMaster_,                SIGNAL(     unblockContact(QString) ),
           msnNotificationConnection_, SLOT  (     unblockContact(QString) ) );
  connect( chatMaster_,                SIGNAL(         addContact(QString) ),
           msnNotificationConnection_, SLOT  (      addNewContact(QString) ) );
  connect( chatMaster_,                SIGNAL(      removeContact(QString,bool) ),
           msnNotificationConnection_, SLOT  (      removeContact(QString,bool) ) );
  connect( chatMaster_,                SIGNAL(       allowContact(QString) ),
           msnNotificationConnection_, SLOT  (       allowContact(QString) ) );

  connect( msnNotificationConnection_, SIGNAL( startedSwitchboard(const ChatInformation&) ),
           chatMaster_,                SLOT  (   startSwitchboard(const ChatInformation&) ) );
  connect( msnNotificationConnection_, SIGNAL(     offlineMessage(const ChatMessage&) ),
           chatMaster_,                SLOT  ( showSpecialMessage(const ChatMessage&) ));
  connect( msnNotificationConnection_, SIGNAL(           pingSent() ),
           chatMaster_,                SLOT  (        timedUpdate() ));

#ifdef KMESSTEST
  ASSERT( chatMaster_ != 0 );
#endif
  return true;
}



// Initialize the emoticon manager
bool KMess::initEmoticonManager()
{
  if ( msnNotificationConnection_ == 0 )
  {
    kdDebug() << "KMess - MsnNotificationConnection must be initialized before EmoticonManager" << endl;
    return false;
  }

  EmoticonManager *manager = EmoticonManager::instance();

  connect( msnNotificationConnection_, SIGNAL(     connected() ),
           manager,                    SLOT  (     connected() ) );
  connect( msnNotificationConnection_, SIGNAL(  disconnected() ),
           manager,                    SLOT  (  disconnected() ) );

  return true;
}



// Initialize the idle timer
bool KMess::initIdleTimer()
{
#ifdef KMESSTEST
  ASSERT( idleTimer_ == 0 );
#endif
  idleTimer_ = new IdleTimer();
  if ( idleTimer_ == 0 )
  {
    kdDebug() << "KMess - Couldn't create the idle timer." << endl;
    return false;
  }
  // Connect the timer to signal when the user is away.
  connect( idleTimer_, SIGNAL( timeout()       ),
           this,       SLOT  ( userIsIdle() )    );
  connect( idleTimer_, SIGNAL( activity()      ),
           this,       SLOT  ( userIsNotIdle() ) );
#ifdef KMESSTEST
  ASSERT( idleTimer_ != 0 );
#endif
  return true;
}



// Initialize the initial view
bool KMess::initInitialView()
{
  initialView_ = new InitialView( this, "initialview" );
  initialView_->show();

  connect( initialView_, SIGNAL( connectWithAccount(QString,QString,bool,QString) ),
           this,         SLOT  ( connectWithAccount(QString,QString,bool,QString) ) );

  return true;
}



// Initialize the main view
bool KMess::initKMessView()
{
  bool initialized;

  if ( msnNotificationConnection_ == 0 )
  {
    kdDebug() << "KMess - MsnNotificationConnection must be initialized before KMessView" << endl;
    return false;
  }

  view_        = new KMessView(this, "kmessview");
  view_->setEnabled( false );

  initialized  = view_->initialize();
  if ( !initialized )
  {
    kdDebug() << "KMess - Couldn't initialize KMessView." << endl;
    return false;
  }


  // Connect other signals to msnNotificationConnection
  connect( view_,                      SIGNAL(    addContact(QString)                   ),   // Add a contact
           msnNotificationConnection_, SLOT  (addExistingContact(QString)               ) );
  connect( view_,                      SIGNAL(  allowContact(QString)                   ),   // Allow the contact
           msnNotificationConnection_, SLOT  (  allowContact(QString)                   ) );
  connect( view_,                      SIGNAL(  blockContact(QString)                   ),   // Block the contact
           msnNotificationConnection_, SLOT  (  blockContact(QString)                   ) );
  connect( view_,                      SIGNAL( changePersonalMessage(QString)           ),   // Change the personal message.
           msnNotificationConnection_, SLOT  ( changePersonalMessage(QString)           ) );
  connect( view_,                      SIGNAL(       copyContact(QString, QString)      ),
           msnNotificationConnection_, SLOT  ( addContactToGroup(QString, QString)      ) );
  connect( view_,                      SIGNAL( moveContact(QString, QString, QString)   ),   // Move the contact
           msnNotificationConnection_, SLOT  ( moveContact(QString, QString, QString)   ) );
  connect( view_,                      SIGNAL( showSettings()                           ),   // Show settings
           this,                       SLOT  ( showSettingsForCurrentAccount()          ) );
  connect( view_,                      SIGNAL(requestChat( QString )                    ),   // Start a chat
           chatMaster_,                SLOT  (requestChat( QString )                    ) );
  connect( view_,                      SIGNAL( removeContact(QString)                   ),   // Remove the contact
           this,                       SLOT  ( showRemoveContactDialog(QString)         ) );
  connect( view_,                      SIGNAL( removeContactFromGroup(QString, QString) ),
           msnNotificationConnection_, SLOT  ( removeContactFromGroup(QString, QString) ) );
  connect( view_,                      SIGNAL(   removeGroup(QString)                   ),   // Remove the group
           this,                       SLOT  ( showRemoveGroupDialog(QString)           ) );
  connect( view_,                      SIGNAL(   renameGroup(QString)                   ),   // Rename the group
           this,                       SLOT  ( showRenameGroupDialog(QString)           ) );
  connect( view_,                      SIGNAL( unblockContact(QString)                  ),   // Unblock the contact
           msnNotificationConnection_, SLOT  ( unblockContact(QString)                  ) );

  view_->hide();
  return true;
}



// Initialize the MSN notification connection
bool KMess::initMsnNotificationConnection()
{
  bool initialized;
  
  msnNotificationConnection_ = new MsnNotificationConnection();

  initialized = msnNotificationConnection_->initialize();
  if ( !initialized )
  {
    kdDebug() << "KMess - Couldn't initialize MsnNotificationConnection." << endl;
    return false;
  }

  // Connect the signals
  connect( msnNotificationConnection_, SIGNAL(                  connected()               ),   // Connected to msn
           this,                       SLOT  (                  connected()               ) );
  connect( msnNotificationConnection_, SIGNAL(               disconnected()               ),   // Disconnected from msn
           this,                       SLOT  (               disconnected()               ) );
  connect( msnNotificationConnection_, SIGNAL(           contactAddedUser(const Contact*) ),   // Contact added user
           this,                       SLOT  ( showContactAddedUserDialog(const Contact*) ) );
  connect( msnNotificationConnection_, SIGNAL(              statusMessage(QString, KMessInterface::ConnectionStatus)   ),   // Display a status message
           this,                       SLOT  (              statusMessage(QString, KMessInterface::ConnectionStatus)   ) );

  return true;
}



// Initialize notification objects
bool KMess::initNotifications()
{
#ifdef KMESSTEST
  ASSERT( currentAccount_             != 0 );
  ASSERT( systemTrayWidget_           != 0 );
  ASSERT( msnNotificationConnection_  != 0 );

  ASSERT( notificationChat_           == 0 );
  ASSERT( notificationContactStatus_  == 0 );
  ASSERT( notificationNewEmail_       == 0 );
#endif

  const ContactList *contactList;

  if ( systemTrayWidget_ == 0 )
  {
    kdDebug() << "KMess - The system tray widget must be initialized before the notifications!" << endl;
    return false;
  }
  if ( msnNotificationConnection_ == 0 )
  {
    kdDebug() << "KMess - The notification connection must be initialized before the notifications!" << endl;
    return false;
  }


  // Add check whether the 'eventsrc' file can be found.
  // The warning is a bit obtruisive, but should help to user to fix the problem.
  if( KGlobal::dirs()->findResource( "data", "kmess/eventsrc" ).isNull() )
  {
    QString dirs = KGlobal::dirs()->findDirs( "data", QString::null ).join("/kmess<br>- ");
    if( dirs.isEmpty() )
    {
      dirs = "(none)";
    }
    else
    {
      dirs = "<br>- " + dirs + "/kmess";
      dirs = dirs.replace( "//kmess", "/kmess" );  // possibly added by /kmess suffix.
    }

    // Always show warning at the console.
    kdWarning() << "Sounds and notifications will not be available, the file 'kmess/eventsrc' could not be found." << endl;

    // Show the message in the GUI as well.
    // Allow to user to choose "don't show this message again", in case he/she doesn't know how to fix it.
    KMessageBox::information( this, i18n( "<qt><p>KMess will not be able to play sounds and notifications.</p>"
                                          "<p>The KMess file 'eventsrc' could not be found in one of the following folders: %1</p>"
                                          "<p>Please verify your installation, and copy the missing file to one of the listed folders.</p>"
                                          "</qt>" ).arg( dirs ),
                                    i18n( "Error with notifications" ),
                                    "eventsrcNotFound" );
  }


  contactList = currentAccount_->getContactList();
  notificationManager_ = NotificationManager::instance();
  notificationManager_->setTrayWidget( systemTrayWidget_ );

  // Create the notifiers
  notificationChat_          = new NotificationChat         ( notificationManager_ );
  notificationContactStatus_ = new NotificationContactStatus( notificationManager_ );
  notificationNewEmail_      = new NotificationNewEmail     ( notificationManager_ );

    // Connect the chat messages notification signals
  connect( chatMaster_,                 SIGNAL( newChatMessage(const ChatMessage&, ChatWindow*)             ),
           notificationChat_,           SLOT  (         notify(const ChatMessage&, ChatWindow*)             ) );
  connect( notificationChat_,           SIGNAL(      raiseChat(ChatWindow*,bool)                            ),
           chatMaster_,                 SLOT  (      raiseChat(ChatWindow*,bool)                            ) );

    // Connect the status change notification signals
  connect( contactList,                 SIGNAL(       contactOnline(Contact*,bool)                          ),
           notificationContactStatus_,  SLOT  (              notify(Contact*,bool)                          ) );
  connect( contactList,                 SIGNAL(      contactOffline(Contact*,bool)                          ),
           notificationContactStatus_,  SLOT  (              notify(Contact*,bool)                          ) );
  connect( contactList,                 SIGNAL( contactChangeStatus(Contact*,bool)                          ),
           notificationContactStatus_,  SLOT  (              notify(Contact*,bool)                          ) );

    // Connect the "Email notification" signals
  connect( msnNotificationConnection_,  SIGNAL( newEmail(QString, QString, bool, QString, QString, QString) ),
           notificationNewEmail_,       SLOT  (   notify(QString, QString, bool, QString, QString, QString) ) );

  // Connect the "Chat request" signals
  connect( notificationContactStatus_,  SIGNAL(          startChat(QString,ChatInformation::ConnectionType) ),
           msnNotificationConnection_,  SLOT  ( requestSwitchboard(QString,ChatInformation::ConnectionType) ) );


  // If specified in the settings, connect the relative signals
  changedNotificationsSettings();


#ifdef KMESSTEST
  ASSERT( notificationChat_          != 0 );
  ASSERT( notificationContactStatus_ != 0 );
  ASSERT( notificationNewEmail_      != 0 );
#endif

  return true;
}



// Initialize the now listening support.
bool KMess::initNowListening()
{
  if ( msnNotificationConnection_ == 0 )
  {
    kdDebug() << "KMess - The notification connection must be initialized before the now listening support!" << endl;
    return false;
  }

  // Create and connect client.
  nowListeningClient_ = new NowListeningClient();
  connect( nowListeningClient_, SIGNAL( changedSong( const QString&, const QString&, const QString&, bool ) ),
           this,                SLOT  ( changedSong( const QString&, const QString&, const QString&, bool ) ));
  
  return true;
}


// Initialize the system tray widget
bool KMess::initSystemTrayWidget()
{
  bool initialized;

  // Create the widget
  systemTrayWidget_ = new SystemTrayWidget( this, "systemtraywidget" ) ;
  if ( systemTrayWidget_ == 0 )
  {
    kdDebug() << "KMess - Couldn't create system tray widget." << endl;
    return false;
  }

  // Initialize the widget
  initialized = systemTrayWidget_->initialize();
  if ( !initialized )
  {
    kdDebug() << "KMess - Couldn't initialize system tray widget." << endl;
    return false;
  }

  // Plug some of the menu actions into the system tray widget's menu.
  connectActionMenu_-> plug( systemTrayWidget_->menu() );
  disconnect_->        plug( systemTrayWidget_->menu() );
  systemTrayWidget_->  menu()->insertSeparator();
  status_->            plug( systemTrayWidget_->menu() );
  systemTrayWidget_->  menu()->insertSeparator();
  settingsActionMenu_->plug( systemTrayWidget_->menu() );

  // Make the connections for the system tray widget
  connect( systemTrayWidget_, SIGNAL( quitSelected() ),
           this,              SLOT  (     menuQuit() ) );

  systemTrayWidget_->show();
#ifdef KMESSTEST
  ASSERT( systemTrayWidget_ != 0 );
  ASSERT( systemTrayWidget_->isVisible() );
#endif
  return true;
}



// Validate a contact email
bool KMess::isValidEmail( QString email )
{
  return email.contains( QRegExp( "^[A-Z0-9._%\\-]+@(?:[A-Z0-9\\-]+\\.)+[A-Z]{2,4}$", false ) );
}



// Read in account and other properties
void KMess::readProperties(KConfig *config)
{
  KMessInterface::readProperties(config);

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - reading properties" << endl;
#endif

  QStringList  accountList;
  Account     *account;

  // Get a list of the profiles stored in the configuration file
  config->setGroup("Profiles");
  accountList = config->readListEntry( "Profiles" );

  // For each listed account, create an account and have it read in its settings
  for ( unsigned int i = 0; i < accountList.count(); i++ )
  {
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::readProperties: initializing account " << accountList[i] << "." << endl;
#endif

    account = new Account();
    account->readProperties( config, accountList[i] );
    addAccount( account );
  }
}



// Save account and other properties
void KMess::saveProperties(KConfig *config)
{
#ifdef KMESSDEBUG_KMESS
  if(config != kapp->config())
  {
    kdDebug() << "For some reason saveProperties(config) != kapp->config(), using kapp->config()." << endl;
  }
#endif

  config = kapp->config();   // Hack, but it seams to work
  KMessInterface::saveProperties(config);

#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess - saving properties" << endl;
#endif

  QStringList  accountList;
  Account *account;

  // Have all the accounts save their properties
  for ( account = accounts_.first(); account; account = accounts_.next() )
  {
    // Avoid saving guest accounts
    if( account->isGuestAccount() || account->isDeleted() ) 
    {
      continue;
    }

    // If the account is the current account...
    if ( account->getHandle() == currentAccount_->getHandle() )
    {
      // Move some settings from the current account to the account that are set by the user interface
#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KMess::saveProperties: copying global user-interface settings from CurrentAccount to the Account object." << endl;
#endif
      account->copyAccountUISettings( currentAccount_ );
    }

    // Save properties of accounts (also saves the contactlist for the current account).
    account->saveProperties( config );
    accountList.append( account->getHandle() );
  }

  // Save the list of profiles
  config->setGroup("Profiles");
  config->writeEntry( "Profiles", accountList );

  // Write data now!
  config->sync();
}



// Set the caption
void KMess::setCaptionToUser()
{
  if ( currentAccount_ != 0 )
  {
    // Set the caption, avoiding newlines which cause problems to the titlebar layout.
    setCaption( currentAccount_->getFriendlyName().replace( "\n", " " ) );
  }
}



// Show the settings dialog for a given account
void KMess::showSettingsForAccount(Account *account)
{
#ifdef KMESSDEBUG_KMESS
  kdDebug() << "KMess::showSettingsForAccount: opening settings for " << account->getHandle() << endl;
#endif
#ifdef KMESSTEST
  ASSERT( msnNotificationConnection_ != 0 );
#endif

  bool isCurrentAccount = false;
  bool isConnectedCurrentAccount = false;

  if ( msnNotificationConnection_ != 0 )
  {
    isCurrentAccount          = ( account->getHandle() == currentAccount_->getHandle() );
    isConnectedCurrentAccount = isCurrentAccount && ( msnNotificationConnection_->isConnected() );
  }

  // Show the settings dialog
  SettingsDialog *settingsDialog = SettingsDialog::instance( this );

  // If a new dialog has not been created, because there already was one, raise that.
  if( ! settingsDialog->isHidden() )
  {
    settingsDialog->show();
    settingsDialog->raise();
    return;
  }

  connect( settingsDialog, SIGNAL(          deleteAccount(Account*)                 ),
           this,           SLOT  (          deleteAccount(Account*)                 ) );
  connect( settingsDialog, SIGNAL(        changedSettings(Account*,QString,QString) ),
           this,           SLOT  ( changedAccountSettings(Account*,QString,QString) ) );

  // If it's the current account, copy some UI settings from the current account to the account
  if( isCurrentAccount )
  {
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::showSettingsForAccount: copying global user-interface settings from CurrentAccount to the Account object." << endl;
#endif
    account->copyAccountUISettings( currentAccount_ );
  }

  settingsDialog->changeAccountSettings( account, isConnectedCurrentAccount );
  settingsDialog->show();
}



// Show the settings dialog for the current account.
void KMess::showSettingsForCurrentAccount()
{
  // Use the Account object so it's consistent with the other AccountAction events.
  Account *accountData = getAccountByHandle( CurrentAccount::instance()->getHandle() );
  if( KMESS_NULL(accountData) ) return;
  showSettingsForAccount( accountData );
}



// Show the user's MSN profile.
void KMess::showUserProfile()
{
  QString       urlPath;
  KURL          *url;
  KRun          *run;

  if ( currentAccount_ != 0 )
  {
    // Set a path to the msn profile page.
    // Internationalization of the resulting page: code seems to be in the form "xx-yy" with
    // xx = language and yy = country information. When there is no country information, yy = xx
    // examples: generic english: en-en ... US english: en-us ... UK english: en-uk ... italian: it-it
    KLocale loc( "kmess" );
    QString code( loc.language() + "-" + loc.country() );
    urlPath = "http://members.msn.com/default.msnw?mkt=" + code.lower() + "&mem=" + currentAccount_->getHandle();
    // Create a URL to the given path
    url = new KURL( urlPath );
    // Launch the default html program for the given URL
    run = new KRun( *url );
  }
}



// We're about to shutdown, apparently
//  make sure we die, rather than just close the main window
void KMess::shutDown()
{
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::shutDown: forcing quit from shutdown signal." << endl;
#endif

  // Called when the app is killed with 'xkill' for example.
  // No user-interaction is possible at this point.

  KApplication::kApplication()->quit();
}



// The "show allowed contacts" menu item has been toggled.
void KMess::toggleShowAllowed(bool show)
{
  currentAccount_->setShowAllowedContacts( show );
}



// The "show offline contacts" menu item has been toggled.
void KMess::toggleShowOffline(bool show)
{
  currentAccount_->setShowOfflineContacts( show );
}



// The "show removed contacts" menu item has been toggled.
void KMess::toggleShowRemoved(bool show)
{
  currentAccount_->setShowRemovedContacts( show );
}



// The user has gone idle
void KMess::userIsIdle()
{
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::userIsIdle()" << endl;
#endif
  if ( ( currentAccount_ != 0 ) && ( msnNotificationConnection_ != 0 ) )
  {
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KM:   Current status is " << currentAccount_->getStatus() << "." << endl;
#endif
    // Only change the state if the user is currently set as online
    if ( currentAccount_->getStatus() == "NLN" )
    {
#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KM:   Change status to IDL." << endl;
#endif
      // Request a status change to "IDL"
      msnNotificationConnection_->changeStatus("IDL");
    }
  }
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KM:   Done userIsIdle()." << endl;
#endif
}



// The user is no longer idle
void KMess::userIsNotIdle()
{
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KMess::userIsNotIdle()" << endl;
#endif
  if ( ( currentAccount_ != 0 ) && ( msnNotificationConnection_ != 0 ) )
  {
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KM:   User is no longer idle, current status is " << currentAccount_->getStatus() << endl;
#endif
    // Only change the state if the user is currently set as idle
    if ( currentAccount_->getStatus() == "IDL" )
    {
#ifdef KMESSDEBUG_KMESS
      kdDebug() << "KM:   Change status to NLN" << endl;
#endif
      // Request a status change to "NLN"
      msnNotificationConnection_->changeStatus("NLN");
    }
  }
#ifdef KMESSDEBUG_KMESS
    kdDebug() << "KM:   Done userIsNotIdle()." << endl;
#endif
}


#include "kmess.moc"

Generated by  Doxygen 1.6.0   Back to index