609 lines
14 KiB
C++
609 lines
14 KiB
C++
/***************************************************************************
|
|
contact.cpp - description
|
|
-------------------
|
|
begin : Sun Jan 5 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 "contact.h"
|
|
|
|
#include "../contact/msnobject.h"
|
|
#include "../utils/kmessconfig.h"
|
|
#include "../currentaccount.h"
|
|
#include "../kmessdebug.h"
|
|
#include "contactextension.h"
|
|
|
|
|
|
#ifdef KMESSDEBUG_CONTACT
|
|
#define KMESSDEBUG_CONTACT_GENERAL
|
|
#endif
|
|
|
|
|
|
|
|
// The constructor
|
|
Contact::Contact( const QString& handle, const QString& friendlyName, int lists,
|
|
const QStringList& groupIds, const QString& guid )
|
|
: ContactBase(handle, friendlyName),
|
|
allowed_(false),
|
|
blocked_(false),
|
|
friend_(false),
|
|
groupIds_(groupIds),
|
|
guid_(guid),
|
|
isMessengerUser_( true ),
|
|
lastStatus_(STATUS_OFFLINE),
|
|
movingFrom_(""),
|
|
msnObject_(0),
|
|
pending_(false),
|
|
reverse_(false),
|
|
status_(STATUS_OFFLINE)
|
|
{
|
|
#ifdef KMESSTEST
|
|
KMESS_ASSERT( ! handle_.isEmpty() );
|
|
KMESS_ASSERT( ! friendlyName_.getOriginal().isEmpty() );
|
|
KMESS_ASSERT( lists != 0 );
|
|
#endif
|
|
|
|
if(lists & MSN_LIST_FRIEND) friend_ = true;
|
|
if(lists & MSN_LIST_ALLOWED) allowed_ = true;
|
|
if(lists & MSN_LIST_BLOCKED) blocked_ = true;
|
|
if(lists & MSN_LIST_REVERSE) reverse_ = true;
|
|
if(lists & MSN_LIST_PENDING) pending_ = true;
|
|
|
|
// The extension stores additional properties not found in
|
|
// the official client/protocol, but only found in KMess.
|
|
// Pictures are stored there because you can assign one
|
|
// (KMess implemented this before the official client supported
|
|
// msnobject transfers). Names can be aliased, which is why there're
|
|
// also there.
|
|
extension_ = new ContactExtension( this );
|
|
|
|
// Relay some signals needed externally
|
|
connect ( extension_, SIGNAL( changedFriendlyName() ),
|
|
this, SIGNAL( changedFriendlyName() ) );
|
|
connect ( extension_, SIGNAL( changedPicture() ),
|
|
this, SLOT ( slotChangedPicture() ) );
|
|
|
|
// need to know when the emoticon theme changes
|
|
// so we can re-parse our friendly name and personal message
|
|
// and update the smileys there.
|
|
connect ( CurrentAccount::instance(), SIGNAL( changedEmoticonSettings() ),
|
|
this, SLOT ( slotEmoticonSettingsChanged() ) );
|
|
}
|
|
|
|
|
|
|
|
// The destructor
|
|
Contact::~Contact()
|
|
{
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "DESTROYED. [handle=" << handle_ << "]";
|
|
#endif
|
|
|
|
delete extension_;
|
|
if(msnObject_) delete msnObject_;
|
|
}
|
|
|
|
|
|
|
|
// Add the groupID to the list of current groups
|
|
void Contact::addGroupId(const QString &groupId)
|
|
{
|
|
// Protect against invalid use, causes problems in KMessView.
|
|
if( groupId.isEmpty() )
|
|
{
|
|
kmWarning() << "Group-ID is empty (contact=" << handle_ << ")!";
|
|
return;
|
|
}
|
|
// Check whether contact is already added to the group.
|
|
if( groupIds_.contains(groupId) )
|
|
{
|
|
kmWarning() << handle_ << " is already a member of group " << groupId << ".";
|
|
return;
|
|
}
|
|
|
|
// Append to groups
|
|
groupIds_.append(groupId);
|
|
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "groups of " << handle_ << " are '" << groupIds_.join(",") << "'";
|
|
#endif
|
|
|
|
emit changedGroup(this);
|
|
}
|
|
|
|
|
|
|
|
// Return the path to the contact's picture
|
|
const QString Contact::getContactPicturePath() const
|
|
{
|
|
// Check before if there is some alternative contact's picture
|
|
QString picturePath( extension_->getContactAlternativePicturePath() );
|
|
|
|
if( ! picturePath.isEmpty() )
|
|
{
|
|
return picturePath;
|
|
}
|
|
|
|
// Check for contact picture ( sended by msn object )
|
|
picturePath = extension_->getContactPicturePath();
|
|
|
|
if( ! picturePath.isEmpty() )
|
|
{
|
|
return picturePath;
|
|
}
|
|
|
|
// else return the default contact picture path
|
|
return getContactDefaultPicturePath();
|
|
}
|
|
|
|
|
|
|
|
// return the scaled display picture for this contact.
|
|
// this is used for display in the contact list.
|
|
QPixmap & Contact::getScaledDisplayPicture()
|
|
{
|
|
int dpSize = CurrentAccount::instance()->getListPictureSize();
|
|
if ( dpSize == scaledDPSize_ && ! scaledDisplayPicture_.isNull() )
|
|
{
|
|
return scaledDisplayPicture_;
|
|
}
|
|
|
|
// here either the scaling size has changed or we have no cache.
|
|
scaledDisplayPicture_.load( getContactPicturePath() );
|
|
scaledDisplayPicture_ = scaledDisplayPicture_.scaled( dpSize, dpSize, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
|
|
|
scaledDPSize_ = dpSize;
|
|
|
|
return scaledDisplayPicture_;
|
|
}
|
|
|
|
|
|
|
|
// Return the current media type
|
|
const QString & Contact::getCurrentMediaType() const
|
|
{
|
|
return currentMediaType_;
|
|
}
|
|
|
|
|
|
|
|
// Return the current media type
|
|
const QString & Contact::getCurrentMediaString() const
|
|
{
|
|
return currentMediaString_;
|
|
}
|
|
|
|
|
|
|
|
// Return a pointer to the extension class
|
|
ContactExtension *Contact::getExtension() const
|
|
{
|
|
return extension_;
|
|
}
|
|
|
|
|
|
// Return the contact's friendly name
|
|
const QString& Contact::getFriendlyName( FormattingMode mode ) const
|
|
{
|
|
// Check if alternative friendly name is set
|
|
if( extension_->getUseAlternativeName() )
|
|
{
|
|
return extension_->getAlternativeName( mode );
|
|
}
|
|
// Else return the string contained in friendlyName
|
|
return friendlyName_.getString( mode );
|
|
}
|
|
|
|
|
|
|
|
// Return the contact's previous status
|
|
Status Contact::getLastStatus() const
|
|
{
|
|
return lastStatus_;
|
|
}
|
|
|
|
|
|
|
|
// Return the contact's globally unique identifier
|
|
const QString &Contact::getGuid() const
|
|
{
|
|
return guid_;
|
|
}
|
|
|
|
|
|
|
|
// Return the group ID's the contact is added to
|
|
const QStringList& Contact::getGroupIds() const
|
|
{
|
|
return groupIds_;
|
|
}
|
|
|
|
|
|
|
|
// Return the contact's information
|
|
const QVariant Contact::getInformation( const QString &information ) const
|
|
{
|
|
return informations_.value( information, QVariant() );
|
|
}
|
|
|
|
|
|
// Return the MSNObject
|
|
const MsnObject* Contact::getMsnObject() const
|
|
{
|
|
return msnObject_;
|
|
}
|
|
|
|
|
|
|
|
// Return the contact's personal message
|
|
const QString & Contact::getPersonalMessage( FormattingMode mode ) const
|
|
{
|
|
return personalMessage_.getString( mode );
|
|
}
|
|
|
|
|
|
|
|
// Return the contact's status
|
|
Status Contact::getStatus() const
|
|
{
|
|
return status_;
|
|
}
|
|
|
|
|
|
|
|
// Return the contact's true friendly name, regardless of extension
|
|
const QString& Contact::getTrueFriendlyName( FormattingMode mode ) const
|
|
{
|
|
return friendlyName_.getString( mode );
|
|
}
|
|
|
|
|
|
|
|
// Whether or not the contact is allowed
|
|
bool Contact::isAllowed() const
|
|
{
|
|
return allowed_;
|
|
}
|
|
|
|
|
|
|
|
// Whether or not the contact is blocked
|
|
bool Contact::isBlocked() const
|
|
{
|
|
return blocked_;
|
|
}
|
|
|
|
|
|
|
|
// Whether or not the contact is on the friends list
|
|
bool Contact::isFriend() const
|
|
{
|
|
return friend_;
|
|
}
|
|
|
|
|
|
|
|
// Whether the contact is a Messenger user
|
|
bool Contact::isMessengerUser() const
|
|
{
|
|
return isMessengerUser_;
|
|
}
|
|
|
|
|
|
|
|
// Whether or not the contact is on the pending list
|
|
bool Contact::isPending() const
|
|
{
|
|
return pending_;
|
|
}
|
|
|
|
|
|
|
|
// Whether or not the contact is on the reverse list
|
|
bool Contact::isReverse() const
|
|
{
|
|
return reverse_;
|
|
}
|
|
|
|
|
|
|
|
// Setup and load an MSN Object
|
|
void Contact::loadMsnObject( QString msnObject )
|
|
{
|
|
// Contact removed his picture.
|
|
if( msnObject.isEmpty() )
|
|
{
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "Contact " << getHandle() << " - MSN Object Removed!";
|
|
#endif
|
|
|
|
delete msnObject_;
|
|
msnObject_ = 0;
|
|
emit changedMsnObject( this );
|
|
}
|
|
|
|
// Contact set his picture, or changed it.
|
|
if( msnObject_ )
|
|
{
|
|
// Actually not changed...
|
|
if( ! msnObject_->hasChanged( msnObject ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Delete previous object.
|
|
delete msnObject_;
|
|
msnObject_= 0;
|
|
}
|
|
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "Contact " << getHandle() << " - MSN Object Changed!";
|
|
#endif
|
|
|
|
msnObject_ = new MsnObject( msnObject );
|
|
emit changedMsnObject( this );
|
|
}
|
|
|
|
|
|
|
|
// clear contact dp cache.
|
|
void Contact::slotChangedPicture()
|
|
{
|
|
scaledDisplayPicture_ = QPixmap();
|
|
emit changedPicture();
|
|
}
|
|
|
|
|
|
|
|
// re-parse the friendly name and personal message
|
|
void Contact::slotEmoticonSettingsChanged()
|
|
{
|
|
friendlyName_.setString( friendlyName_.getOriginal() );
|
|
personalMessage_.setString( personalMessage_.getOriginal() );
|
|
}
|
|
|
|
|
|
|
|
// Load extension settings for a contact
|
|
void Contact::readProperties( const KConfigGroup &config )
|
|
{
|
|
// Get the configuration group where this contact's data is stored
|
|
KConfigGroup contactConfig = config.group( handle_ );
|
|
|
|
// Restore cached state of this class
|
|
|
|
// the data that comes from the address book service (as of 14 Oct 09)
|
|
// is rubbish - the friendly name is totally out of date or missing.
|
|
// cache it here. it will get overwritten the next time the contact comes online,
|
|
// then saved upon kmess close.
|
|
QString cachedFriendlyName = contactConfig.readEntry( "lastFriendlyName", QString() );
|
|
if ( ! cachedFriendlyName.isEmpty() )
|
|
{
|
|
friendlyName_ = cachedFriendlyName;
|
|
}
|
|
|
|
capabilities_ = contactConfig.readEntry( "capabilities", 0 );
|
|
clientName_ = contactConfig.readEntry( "clientName", QString() );
|
|
clientFullName_ = contactConfig.readEntry( "clientFullName", QString() );
|
|
personalMessage_.setString( contactConfig.readEntry( "lastPersonalMessage", "" ) );
|
|
emoticonBlackList_ = contactConfig.readEntry( "emoticonBlackList", QStringList() );
|
|
|
|
// TODO: restore more state variables here, to implement contact list caching.
|
|
|
|
// Restore extension
|
|
extension_->readProperties( contactConfig );
|
|
}
|
|
|
|
|
|
|
|
// Remove the group from the list of group IDs
|
|
void Contact::removeGroupId( const QString &groupId )
|
|
{
|
|
int removeCount = groupIds_.removeAll( groupId );
|
|
if(removeCount == 0)
|
|
{
|
|
kmWarning() << handle_ << " was not registered to group " << groupId << ".";
|
|
return;
|
|
}
|
|
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "groups of " << handle_ << " are '" << groupIds_.join(",") << "'";
|
|
#endif
|
|
|
|
emit changedGroup( this );
|
|
}
|
|
|
|
|
|
|
|
// Save extension settings for a contact
|
|
void Contact::saveProperties( KConfigGroup &config )
|
|
{
|
|
// Get the configuration group where this contact's data is stored
|
|
KConfigGroup contactConfig = config.group( handle_ );
|
|
|
|
// Save state of this class
|
|
contactConfig.writeEntry( "lastFriendlyName", friendlyName_.getOriginal() );
|
|
contactConfig.writeEntry( "capabilities", getCapabilities() );
|
|
contactConfig.writeEntry( "clientName", getClientName( false ) );
|
|
contactConfig.writeEntry( "clientFullName", getClientFullName() );
|
|
contactConfig.writeEntry( "lastPersonalMessage", getPersonalMessage( STRING_ORIGINAL ) );
|
|
contactConfig.writeEntry( "emoticonBlackList", getEmoticonBlackList() );
|
|
|
|
// store extension
|
|
extension_->saveProperties( contactConfig );
|
|
}
|
|
|
|
|
|
|
|
// Set whether or not the contact is allowed
|
|
void Contact::setAllowed( bool allowed )
|
|
{
|
|
if( allowed_ != allowed )
|
|
{
|
|
allowed_ = allowed;
|
|
emit changedList(this);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Set whether or not the contact is blocked
|
|
void Contact::setBlocked( bool blocked )
|
|
{
|
|
if( blocked_ != blocked )
|
|
{
|
|
blocked_ = blocked;
|
|
emit changedList(this);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Set whether or not the contact is on the friends list
|
|
void Contact::setFriend( bool isFriend )
|
|
{
|
|
if( friend_ != isFriend )
|
|
{
|
|
friend_ = isFriend;
|
|
|
|
// If the contact is no longer at the FL, remove from all groups
|
|
if(! isFriend)
|
|
{
|
|
groupIds_.clear();
|
|
setStatus( STATUS_OFFLINE, false );
|
|
}
|
|
|
|
emit changedList(this);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Change the contact's friendly name
|
|
void Contact::setFriendlyName( QString newName )
|
|
{
|
|
if( newName.isEmpty() )
|
|
{
|
|
kmWarning() << "Not setting the friendly name of " << handle_ << " to an empty value (previously: " << friendlyName_.getCleaned() << ")";
|
|
return;
|
|
}
|
|
|
|
friendlyName_.setString( newName );
|
|
|
|
emit changedFriendlyName();
|
|
}
|
|
|
|
|
|
|
|
// Change the "IsMessengerUser" property for this contact.
|
|
void Contact::setMessengerUser( bool isMessengerUser )
|
|
{
|
|
isMessengerUser_ = isMessengerUser;
|
|
}
|
|
|
|
|
|
|
|
// Change the GUID of the contact, this is only known when the contact is added to the friends list.
|
|
void Contact::setGuid( const QString &guid )
|
|
{
|
|
guid_ = guid;
|
|
}
|
|
|
|
|
|
|
|
// Set the extra information retrieved by soap response
|
|
void Contact::setInformations( const QHash<QString, QVariant> &informations )
|
|
{
|
|
informations_ = informations;
|
|
}
|
|
|
|
|
|
|
|
// Set wether or not the contact is on pending list
|
|
void Contact::setPending( bool isPending )
|
|
{
|
|
pending_ = isPending;
|
|
}
|
|
|
|
|
|
|
|
// Set the personal message of the contact
|
|
void Contact::setPersonalStatus( const QString &message, const QString &mediaType, const QString &mediaString )
|
|
{
|
|
// If no information is changed
|
|
if( personalMessage_.getOriginal() == message
|
|
&& currentMediaType_ == mediaType
|
|
&& currentMediaString_ == mediaString )
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentMediaType_ = mediaType;
|
|
currentMediaString_ = mediaString;
|
|
personalMessage_.setString( message );
|
|
|
|
emit changedPersonalMessage(this);
|
|
}
|
|
|
|
|
|
|
|
// Set whether or not the contact is on the reverse list
|
|
void Contact::setReverse( bool reverse )
|
|
{
|
|
if( reverse_ != reverse )
|
|
{
|
|
reverse_ = reverse;
|
|
emit changedList(this);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Set the contact's status
|
|
void Contact::setStatus( const Status newStatus, bool showBaloon )
|
|
{
|
|
if( status_ == newStatus )
|
|
{
|
|
return;
|
|
}
|
|
|
|
lastStatus_ = status_;
|
|
status_ = newStatus;
|
|
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "Contact " << handle_ << " went from " << MsnStatus::getCode( lastStatus_ )
|
|
<< " to " << MsnStatus::getCode( status_ ) << ".";
|
|
#endif
|
|
|
|
// Signal the UI
|
|
emit changedStatus();
|
|
|
|
// Check if the contact went offline
|
|
if( status_ == STATUS_OFFLINE && lastStatus_ != STATUS_OFFLINE )
|
|
{
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "Contact went offline.";
|
|
#endif
|
|
emit contactOffline( this, showBaloon );
|
|
}
|
|
// Check if the contact went online
|
|
else if( status_ != STATUS_OFFLINE && lastStatus_ == STATUS_OFFLINE )
|
|
{
|
|
// showBaloon is here to avoid showing notification when we connect
|
|
#ifdef KMESSDEBUG_CONTACT_GENERAL
|
|
kmDebug() << "Contact went online.";
|
|
#endif
|
|
emit contactOnline( this, showBaloon );
|
|
}
|
|
}
|