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

contactlist.cpp

/***************************************************************************
                          contactlist.cpp  -  description
                             -------------------
    begin                : Sun Jan 5 2003
    copyright            : (C) 2003 by Mike K. Bennett
                           (C) 2005 by Diederik van der Boor
    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 "contactlist.h"

#include <qfile.h>

#include <kconfig.h>
#include <kdebug.h>
#include <klocale.h>

#include "contact.h"
#include "contactextension.h"
#include "group.h"
#include "../currentaccount.h"
#include "../kmessdebug.h"
#include "../specialgroups.h"
#include "../msnobject.h"

#ifdef KMESSDEBUG_CONTACTLIST
  #define KMESSDEBUG_CONTACTLIST_GENERAL
  #define KMESSDEBUG_CONTACTLIST_TOOLTIP
  #define KMESSDEBUG_CONTACTLIST_DISCONNECTION
#endif



// The constructor
ContactList::ContactList()
{
#ifdef KMESSTEST
  ASSERT( contacts_.count() == 0 );
  ASSERT( groups_.count() == 0 );
#endif
}



// The destructor
ContactList::~ContactList()
{
  Group   *group;

  // Delete all contacts
  QDictIterator<Contact> contactIt( contacts_ );
  while( contactIt.current() != 0 )
  {
    delete contactIt.current();
    ++contactIt;
  }
  contacts_.clear();

  // Delete all groups
  for ( group = groups_.first(); group; group = groups_.next() )
  {
    delete group;
  }
  groups_.clear();

#ifdef KMESSTEST
  ASSERT( contacts_.count() == 0 );
  ASSERT( groups_.count() == 0 );
#endif

#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  kdDebug() << "DESTROYED ContactList " << endl;
#endif
}



// Add a contact to the contact list
Contact * ContactList::addContact( QString handle, QString friendlyName, int lists, QString groupIds, QString guid )
{
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  kdDebug() << "ContactList::addContact " << handle << endl;
#endif
#ifdef KMESSTEST
  ASSERT( ! handle.isEmpty() );
#endif

  if(getContactByHandle(handle) != 0)
  {
    kdDebug () << "ContactList::addContact - WARNING - attempted to add contact " << handle << " twice." << endl;
    return 0;
  }

  Contact *contact;

  if(handle.isEmpty())
  {
    return 0;
  }

  // Create the contact
  contact = new Contact( handle, friendlyName, lists, groupIds, guid );
  contacts_.insert( handle, contact );


  // Attach the signals
  connect( contact, SIGNAL(                   changedMsnObject(Contact*)      ),   // Contact changed msnobject.
           this,    SLOT  ( slotForwardContactChangedMsnObject(Contact*)      ));
  connect( contact, SIGNAL(                     contactOffline(Contact*,bool) ),   // Contact went offline
           this,    SLOT  (          slotForwardContactOffline(Contact*,bool) ));
  connect( contact, SIGNAL(                      contactOnline(Contact*,bool) ),   // Contact went online
           this,    SLOT  (           slotForwardContactOnline(Contact*,bool) ));
  connect( contact, SIGNAL(                       changedGroup(Contact*)      ),   // Contact moved
           this,    SLOT  (            slotForwardContactMoved(Contact*)      ));
  connect( contact, SIGNAL(                        changedList(Contact*)      ),   // Contact was added/removed from certain lists
           this,    SLOT  (            slotForwardContactMoved(Contact*)      ));

  // HACK: It would be nicer if the GUI desided whether a contact-item should be moved if it's lists changed.
  //       Currently these signal connection of changedList() assumes the GUI uses "groups to sort various lists".

  // Signal the UI
  emit contactAdded(contact);

  return contact;
}



// Add a group to the contact list
Group * ContactList::addGroup( QString groupId, QString groupName )
{
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  kdDebug() << "ContactList::addGroup " << groupId << " " << groupName << endl;
#endif

  Group *group;

  // Check if the group already exists
  if ( groupExists( groupId ) )
  {
    kdDebug() << "ContactList - addGroup - Group " << groupId << " already exists." << endl;
    return 0;
  }

  // Create the group
  group = new Group( groupId, groupName  );
  groups_.append( group );

  // Signal the UI
  emit groupAdded(group);

  return group;
}



// Change a contact's status (and update the friendly name)
void ContactList::changeContactStatus( QString handle, QString friendlyName, QString status,
                                       uint capabilities, QString msnObject, bool showBaloon )
{
  // Get the contact
  Contact *contact;
  bool     wasOnline;
  QString  oldStatus;

  contact = getContactByHandle( handle );
  if ( contact == 0 )
  {
    kdDebug() << "ContactList - changeContactStatus - Couldn't find contact " << handle << " in the contact list." << endl;
    return;
  }

  // Store the old online state to detect a change
  wasOnline = contact->isOnline();
  oldStatus = contact->getStatus();

  // Update the settings
  contact->setFriendlyName( friendlyName );
  contact->setStatus( status, showBaloon );
  contact->setCapabilities( capabilities );
  contact->loadMsnObject( msnObject );

  if( wasOnline && oldStatus != status )
  {
    emit contactChangeStatus( contact, showBaloon );
  }
}



// Return whether or not the contact with the given handle exists
bool ContactList::contactExists( QString handle )
{
  return getContactByHandle( handle ) != 0;
}



// Delete all the contacts
void ContactList::deleteAllContacts()
{
#ifdef KMESSDEBUG_CONTACTLIST_DISCONNECTION
  kdDebug() << "ContactList - Deleting all contacts." << endl;
#endif

  // Delete all contacts
  QDictIterator<Contact> it( contacts_ );
  while( it.current() != 0 )
  {
    delete it.current();
    ++it;
  }
  contacts_.clear();
}



// Delete all non-special groups
void ContactList::deleteNonSpecialGroups()
{
  Group     *group;
  QString   id;
  QPtrList<Group> groupsToDelete;

#ifdef KMESSDEBUG_CONTACTLIST_DISCONNECTION
  kdDebug() << "ContactList - Deleting non-special groups." << endl;
#endif

  // Delete all groups
  for ( group = groups_.first(); group; group = groups_.next() )
  {
    id = group->getId();
    if (    ( id != SpecialGroups::ONLINE )
         && ( id != SpecialGroups::OFFLINE )
         && ( id != SpecialGroups::ALLOWED )
         && ( id != SpecialGroups::REMOVED ) )
//         && ( id != SpecialGroups::INDIVIDUALS ) ) // Also not added persistently, so I don't keep it either.
    {
      groupsToDelete.append( group );
    }
  }

  // Remove the groups to delete from the groups
  for ( group = groupsToDelete.first(); group; group = groupsToDelete.next() )
  {
    groups_.remove( group );
    emit groupRemoved( group );
    delete group;
  }

#ifdef KMESSTEST
  ASSERT( groups_.count() == 4 );
#endif
}



// Return the contact with the given guid
Contact* ContactList::getContactByGuid( QString guid ) const
{
  // No need to optimize, only called for ADC en REM now.
  QDictIterator<Contact> iterator(contacts_);
  Contact *contact;

  while(iterator.current() != 0)
  {
    contact = iterator.current();
    if(contact->getGuid() == guid)
    {
      return contact;
    }
    ++iterator;
  }

  return 0;
}



// Return the contact with the given handle
Contact* ContactList::getContactByHandle( QString handle ) const
{
  // Optimized with hashing because it's called a lot
  return contacts_[handle];
}



// Return the list of contacts
const QDict<Contact>& ContactList::getContactList() const
{
  return contacts_;
}



// Return the group with the given id
Group* ContactList::getGroupById( QString groupId ) const
{
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  kdDebug() << "ContactList::getGroupById(" << groupId << ")" << endl;
#endif

  QPtrListIterator<Group> iterator(groups_);
  Group *group;

  while(iterator.current() != 0)
  {
    group = iterator.current();
    if ( group->getId() == groupId )
    {
      return group;
    }
    ++iterator;
  }

  return 0;
}



// Return the group with the given sort position
Group* ContactList::getGroupBySortPosition(int sortPosition) const
{
  QPtrListIterator<Group> iterator(groups_);
  Group *group;

  while(iterator.current() != 0)
  {
    group = iterator.current();
    if ( group->getSortPosition() == sortPosition )
    {
      return group;
    }
    ++iterator;
  }

  return 0;
}



// Return the list of groups
const QPtrList<Group>& ContactList::getGroupList() const
{
  return groups_;
}



// Return whether or not a group with the given id exists
bool ContactList::groupExists( QString groupId )
{
  return getGroupById( groupId ) != 0;
}



// Forward from a contact that it's msn object changed
void ContactList::slotForwardContactChangedMsnObject(Contact *contact)
{
  emit contactChangedMsnObject( contact );
}



// Forward from a contact that is has moved
void ContactList::slotForwardContactMoved(Contact *contact)
{
  emit contactMoved(contact);
}



// Forward from a contact that it is offline
void ContactList::slotForwardContactOffline(Contact *contact, bool showBaloon)
{
#ifdef KMESSTEST
  ASSERT( contact != 0 );
#endif

#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  if ( contact != 0 )
  {
    kdDebug() << "ContactList - Forwarding that " << contact->getHandle() << " went offline." << endl;
  }
#endif

  emit contactOffline( contact, showBaloon );
}



// Forward from a contact that it is online
void ContactList::slotForwardContactOnline(Contact *contact, bool showBaloon)
{
#ifdef KMESSTEST
  ASSERT( contact != 0 );
#endif

#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  if ( contact != 0 )
  {
    kdDebug() << "ContactList - Forwarding that " << contact->getHandle() << " went online." << endl;
  }
#endif

  emit contactOnline( contact, showBaloon );
}



// Read in account and other properties
void ContactList::readProperties(KConfig */*config*/)
{
}



// Remove a group
void ContactList::removeGroup( QString groupId )
{
  Group *group;

  group = getGroupById( groupId );
  if ( group == 0 )
  {
    kdDebug() << "ContactList - removeGroup - Group " << groupId << " doesn't exist in the contact list." << endl;
    return;
  }

  // Remove the group
  groups_.remove(group);
  emit groupRemoved(group); // Signal the UI

  delete group;
}



// Change a contact's name
void ContactList::renameContact( QString handle, QString newName )
{
  Contact *contact;

  contact = getContactByHandle( handle );
  if ( contact == 0 )
  {
    kdDebug() << "ContactList - renameContact - Couldn't find contact " << handle << " in the contact list." << endl;
    return;
  }

  contact->setFriendlyName( newName );
}



// Change a group's name
void ContactList::renameGroup( QString groupId, QString groupName )
{
  Group *group = getGroupById( groupId );
  if( group == 0 )
  {
    kdWarning() << "ContactList::renameGroup: Group '" << groupId << "' "
                << "not found in the contact list." << endl;
    return;
  }

  group->setName( groupName );
}


// Restore the orginal state of the contact list (empty it)
void ContactList::reset()
{
  deleteAllContacts();
  deleteNonSpecialGroups();
}


// Save group properties
void ContactList::saveProperties(KConfig *config)
{
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  kdDebug() << "ContactList::saveProperties() - Saving groups and contacts info..." << endl;
#endif
  if( CurrentAccount::instance()->isGuestAccount() )
  {
    kdWarning() << "ContactList::saveProperties() - This is a guest account, skipping save." << endl;
  }

  // Check if there already are some groups to save (we didn't receive them from the server yet)
  if( groups_.count() > 0 )
  {
    Group *group;

    // Save all groups
    for ( group = groups_.first(); group; group = groups_.next() )
    {
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
      kdDebug() << "ContactList::saveProperties() - Saving group info: " << group->getName() << endl;
#endif

      group->saveProperties( config );
    }
  }
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  else
  {
  kdDebug() << "ContactList::saveProperties() - No groups to save." << endl;
  }
#endif

  // If there are no contacts there's nothing left to do (same as above)
  if( contacts_.count() > 0 )
  {
    // Before saving the contact extensions data, delete any value about contacts which aren't in list anymore
    QString groupsName = "Contact_" + CurrentAccount::instance()->getHandle() + "/";
    QStringList pendingRemoval = config->groupList().grep( groupsName );

    // Save contact extensions
    QDictIterator<Contact> it( contacts_ );
    while( it.current() != 0 )
    {
  #ifdef KMESSDEBUG_CONTACTLIST_GENERAL
      kdDebug() << "ContactList::saveProperties() - Saving contact info: " << it.current()->getHandle() << endl;
  #endif
      pendingRemoval.remove( groupsName + it.current()->getHandle() );
      it.current()->getExtension()->saveProperties( config );
      ++it;
    }

    // Delete the remaining contacts info, which at this point are only old contacts not in list anymore
    QFile picture;
    QStringList::Iterator rit = pendingRemoval.begin();
    for ( ; rit != pendingRemoval.end(); ++rit )
    {
  #ifdef KMESSDEBUG_CONTACTLIST_GENERAL
      kdDebug() << "ContactList::saveProperties() - Deleting unused contact info: " << *rit << endl;
  #endif
      config->setGroup( *rit );
      picture.setName( config->readEntry( "pictureFile", "" ) );
      if( picture.exists() )
      {
        picture.remove();
      }
      config->deleteGroup( *rit, true );
    }
  }
#ifdef KMESSDEBUG_CONTACTLIST_GENERAL
  else
  {
  kdDebug() << "ContactList::saveProperties() - No contacts to save." << endl;
  }
#endif

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

}



// Set a contact to offline
void ContactList::setContactOffline( QString handle )
{
  Contact *contact;

  contact = getContactByHandle( handle );
  if ( contact == 0 )
  {
    kdDebug() << "ContactList - contactOffline - Couldn't find contact " << handle << " in the contact list." << endl;
    return;
  }

  contact->setStatus( "FLN" );
}

#include "contactlist.moc"

Generated by  Doxygen 1.6.0   Back to index