Files
kmess/src/contact/contact.cpp
T
2026-07-06 09:37:59 +02:00

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 );
}
}