You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/protocols/oscar/icq/icqcontact.cpp

940 lines
29 KiB

/*
icqontact.cpp - Oscar Protocol Plugin
Copyright (c) 2003 by Stefan Gehn <metz AT gehn.net>
Copyright (c) 2003 by Olivier Goffart
Kopete (c) 2003-2004 by the Kopete developers <kopete-devel@kde.org>
*************************************************************************
* *
* 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 "icqcontact.h"
#include <tqtimer.h>
#include <tqimage.h>
#include <tqfile.h>
#include <kaction.h>
#include <kactionclasses.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <knotifyclient.h>
#include <kpassivepopup.h>
#include <kinputdialog.h>
#include <kmdcodec.h>
#include <kstandarddirs.h>
#include "kopetechatsessionmanager.h"
#include "kopeteuiglobal.h"
#include "kopetemetacontact.h"
#include "icquserinfo.h"
#include "icqreadaway.h"
#include "icqprotocol.h"
#include "icqaccount.h"
#include "icqpresence.h"
#include "icquserinfowidget.h"
#include "icqauthreplydialog.h"
#include "client.h"
#include "oscarutils.h"
#include "oscarencodingselectiondialog.h"
#include "ssimanager.h"
ICQContact::ICQContact( ICQAccount *account, const TQString &name, Kopete::MetaContact *parent,
const TQString& icon, const Oscar::SSI& ssiItem )
: OscarContact( account, name, parent, icon, ssiItem )
{
mProtocol = static_cast<ICQProtocol *>(protocol());
m_infoWidget = 0L;
m_requestingNickname = false;
m_oesd = 0;
m_buddyIconDirty = false;
if ( ssiItem.waitingAuth() )
setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
else
setOnlineStatus( ICQ::Presence( ICQ::Presence::Offline, ICQ::Presence::Visible ).toOnlineStatus() );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( loggedIn() ), this, TQT_SLOT( loggedIn() ) );
//TQObject::connect( mAccount->engine(), TQT_SIGNAL( userIsOnline( const TQString& ) ), this, TQT_SLOT( userOnline( const TQString&, UserDetails ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( userIsOffline( const TQString& ) ), this, TQT_SLOT( userOffline( const TQString& ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( authRequestReceived( const TQString&, const TQString& ) ),
this, TQT_SLOT( slotGotAuthRequest( const TQString&, const TQString& ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( authReplyReceived( const TQString&, const TQString&, bool ) ),
this, TQT_SLOT( slotGotAuthReply(const TQString&, const TQString&, bool ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( receivedIcqShortInfo( const TQString& ) ),
this, TQT_SLOT( receivedShortInfo( const TQString& ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( receivedIcqLongInfo( const TQString& ) ),
this, TQT_SLOT( receivedLongInfo( const TQString& ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( receivedUserInfo( const TQString&, const UserDetails& ) ),
this, TQT_SLOT( userInfoUpdated( const TQString&, const UserDetails& ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( receivedAwayMessage( const TQString&, const TQString& ) ),
this, TQT_SLOT( receivedStatusMessage( const TQString&, const TQString& ) ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( receivedAwayMessage( const Oscar::Message& ) ),
this, TQT_SLOT( receivedStatusMessage( const Oscar::Message& ) ) );
TQObject::connect( this, TQT_SIGNAL( featuresUpdated() ), this, TQT_SLOT( updateFeatures() ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( iconServerConnected() ),
this, TQT_SLOT( requestBuddyIcon() ) );
TQObject::connect( mAccount->engine(), TQT_SIGNAL( haveIconForContact( const TQString&, TQByteArray ) ),
this, TQT_SLOT( haveIcon( const TQString&, TQByteArray ) ) );
}
ICQContact::~ICQContact()
{
delete m_infoWidget;
}
void ICQContact::updateSSIItem()
{
//kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << endl;
if ( m_ssiItem.waitingAuth() )
setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
if ( m_ssiItem.type() != 0xFFFF && m_ssiItem.waitingAuth() == false &&
onlineStatus() == Kopete::OnlineStatus::Unknown )
{
//make sure they're offline
setOnlineStatus( ICQ::Presence( ICQ::Presence::Offline, ICQ::Presence::Visible ).toOnlineStatus() );
}
}
void ICQContact::userInfoUpdated( const TQString& contact, const UserDetails& details )
{
//kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << contact << contactId() << endl;
if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
return;
// invalidate old away message if user was offline
if ( !isOnline() )
removeProperty( mProtocol->awayMessage );
kdDebug( OSCAR_ICQ_DEBUG ) << k_funcinfo << "extendedStatus is " << details.extendedStatus() << endl;
ICQ::Presence presence = ICQ::Presence::fromOscarStatus( details.extendedStatus() & 0xffff );
setOnlineStatus( presence.toOnlineStatus() );
// ICQ does not support status messages for state Online
if ( presence.type() == ICQ::Presence::Online )
{
mAccount->engine()->removeICQAwayMessageRequest( contactId() );
removeProperty( mProtocol->awayMessage );
}
else
{
if ( ICQ::Presence::fromOnlineStatus( account()->myself()->onlineStatus() ).visibility() == ICQ::Presence::Visible )
{
switch ( presence.type() )
{
case ICQ::Presence::Away:
mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQAway );
break;
case ICQ::Presence::NotAvailable:
mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQNotAvailable );
break;
case ICQ::Presence::Occupied:
mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQOccupied );
break;
case ICQ::Presence::DoNotDisturb:
mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQDoNotDisturb );
break;
case ICQ::Presence::FreeForChat:
mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQFreeForChat );
break;
default:
break;
}
}
else
{
mAccount->engine()->removeICQAwayMessageRequest( contactId() );
}
}
if ( details.dcOutsideSpecified() )
{
if ( details.dcExternalIp().isUnspecified() )
removeProperty( mProtocol->ipAddress );
else
setProperty( mProtocol->ipAddress, details.dcExternalIp().toString() );
}
if ( details.capabilitiesSpecified() )
{
if ( details.clientName().isEmpty() )
removeProperty( mProtocol->clientFeatures );
else
setProperty( mProtocol->clientFeatures, details.clientName() );
}
if ( details.buddyIconHash().size() > 0 && details.buddyIconHash() != m_details.buddyIconHash() )
{
m_buddyIconDirty = true;
if ( cachedBuddyIcon( details.buddyIconHash() ) == false )
{
if ( !mAccount->engine()->hasIconConnection() )
{
mAccount->engine()->connectToIconServer();
}
else
{
int time = ( KApplication::random() % 10 ) * 1000;
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "updating buddy icon in "
<< time/1000 << " seconds" << endl;
TQTimer::singleShot( time, this, TQT_SLOT( requestBuddyIcon() ) );
}
}
}
OscarContact::userInfoUpdated( contact, details );
}
void ICQContact::userOnline( const TQString& userId )
{
if ( Oscar::normalize( userId ) != Oscar::normalize( contactId() ) )
return;
kdDebug(OSCAR_ICQ_DEBUG) << "Setting " << userId << " online" << endl;
ICQ::Presence online = mProtocol->statusManager()->presenceOf( ICQ::Presence::Online );
//mAccount->engine()->requestStatusInfo( contactId() );
}
void ICQContact::userOffline( const TQString& userId )
{
if ( Oscar::normalize( userId ) != Oscar::normalize( contactId() ) )
return;
kdDebug(OSCAR_ICQ_DEBUG) << "Setting " << userId << " offline" << endl;
ICQ::Presence offline = mProtocol->statusManager()->presenceOf( ICQ::Presence::Offline );
setOnlineStatus( mProtocol->statusManager()->onlineStatusOf( offline ) );
}
void ICQContact::loggedIn()
{
if ( metaContact()->isTemporary() )
return;
if ( m_ssiItem.waitingAuth() )
setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
if ( ( ( hasProperty( Kopete::Global::Properties::self()->nickName().key() )
&& nickName() == contactId() )
|| !hasProperty( Kopete::Global::Properties::self()->nickName().key() ) ) &&
!m_requestingNickname && m_ssiItem.alias().isEmpty() )
{
m_requestingNickname = true;
int time = ( KApplication::random() % 20 ) * 1000;
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "updating nickname in " << time/1000 << " seconds" << endl;
TQTimer::singleShot( time, this, TQT_SLOT( requestShortInfo() ) );
}
}
void ICQContact::requestShortInfo()
{
if ( mAccount->isConnected() )
mAccount->engine()->requestShortInfo( contactId() );
}
void ICQContact::slotRequestAuth()
{
TQString reason = KInputDialog::getText( i18n("Request Authorization"),
i18n("Reason for requesting authorization:") );
if ( !reason.isNull() )
mAccount->engine()->requestAuth( contactId(), reason );
}
void ICQContact::slotSendAuth()
{
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "Sending auth reply" << endl;
ICQAuthReplyDialog replyDialog( 0, "replyDialog", false );
replyDialog.setUser( property( Kopete::Global::Properties::self()->nickName() ).value().toString() );
if ( replyDialog.exec() )
mAccount->engine()->sendAuth( contactId(), replyDialog.reason(), replyDialog.grantAuth() );
}
void ICQContact::slotGotAuthReply( const TQString& contact, const TQString& reason, bool granted )
{
if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
return;
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << endl;
TQString message;
if( granted )
{
message = i18n( "User %1 has granted your authorization request.\nReason: %2" )
.arg( property( Kopete::Global::Properties::self()->nickName() ).value().toString() )
.arg( reason );
// remove the unknown status
setOnlineStatus( ICQ::Presence( ICQ::Presence::Offline, ICQ::Presence::Visible ).toOnlineStatus() );
}
else
{
message = i18n( "User %1 has rejected the authorization request.\nReason: %2" )
.arg( property( Kopete::Global::Properties::self()->nickName() ).value().toString() )
.arg( reason );
}
KNotifyClient::event( Kopete::UI::Global::sysTrayWId(), "icq_authorization", message );
}
void ICQContact::slotGotAuthRequest( const TQString& contact, const TQString& reason )
{
if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
return;
ICQAuthReplyDialog *replyDialog = new ICQAuthReplyDialog();
connect( replyDialog, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( slotAuthReplyDialogOkClicked() ) );
replyDialog->setUser( property( Kopete::Global::Properties::self()->nickName() ).value().toString() );
replyDialog->setRequestReason( reason );
replyDialog->setModal( TRUE );
replyDialog->show();
}
void ICQContact::slotAuthReplyDialogOkClicked()
{
// Do not need to delete will delete itself automatically
ICQAuthReplyDialog *replyDialog = (ICQAuthReplyDialog*)sender();
if (replyDialog)
mAccount->engine()->sendAuth( contactId(), replyDialog->reason(), replyDialog->grantAuth() );
}
void ICQContact::receivedLongInfo( const TQString& contact )
{
if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
{
if ( m_infoWidget )
m_infoWidget->delayedDestruct();
return;
}
TQTextCodec* codec = contactCodec();
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "received long info from engine" << endl;
ICQGeneralUserInfo genInfo = mAccount->engine()->getGeneralInfo( contact );
if ( m_ssiItem.alias().isEmpty() && !genInfo.nickname.isEmpty() )
setNickName( codec->toUnicode( genInfo.nickname ) );
emit haveBasicInfo( genInfo );
ICQWorkUserInfo workInfo = mAccount->engine()->getWorkInfo( contact );
emit haveWorkInfo( workInfo );
ICQMoreUserInfo moreInfo = mAccount->engine()->getMoreInfo( contact );
emit haveMoreInfo( moreInfo );
ICQInterestInfo interestInfo = mAccount->engine()->getInterestInfo( contact );
emit haveInterestInfo( interestInfo );
}
void ICQContact::receivedShortInfo( const TQString& contact )
{
if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
return;
TQTextCodec* codec = contactCodec();
m_requestingNickname = false; //done requesting nickname
ICQShortInfo shortInfo = mAccount->engine()->getShortInfo( contact );
/*
if(!shortInfo.firstName.isEmpty())
setProperty( mProtocol->firstName, codec->toUnicode( shortInfo.firstName ) );
else
removeProperty(mProtocol->firstName);
if(!shortInfo.lastName.isEmpty())
setProperty( mProtocol->lastName, codec->toUnicode( shortInfo.lastName ) );
else
removeProperty(mProtocol->lastName);
*/
if ( m_ssiItem.alias().isEmpty() && !shortInfo.nickname.isEmpty() )
{
kdDebug(14153) << k_funcinfo <<
"setting new displayname for former UIN-only Contact" << endl;
setProperty( Kopete::Global::Properties::self()->nickName(), codec->toUnicode( shortInfo.nickname ) );
}
}
void ICQContact::receivedStatusMessage( const TQString &contact, const TQString &message )
{
if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
return;
if ( ! message.isEmpty() )
setProperty( mProtocol->awayMessage, message );
else
removeProperty( mProtocol->awayMessage );
}
void ICQContact::receivedStatusMessage( const Oscar::Message &message )
{
if ( Oscar::normalize( message.sender() ) != Oscar::normalize( contactId() ) )
return;
//decode message
TQTextCodec* codec = contactCodec();
TQString realText = message.text(codec);
if ( !realText.isEmpty() )
setProperty( mProtocol->awayMessage, realText );
else
removeProperty( mProtocol->awayMessage );
}
void ICQContact::slotSendMsg( Kopete::Message& msg, Kopete::ChatSession* session )
{
//Why is this unused?
Q_UNUSED( session );
TQTextCodec* codec = contactCodec();
int messageChannel = 0x01;
Oscar::Message::Encoding messageEncoding;
if ( isOnline() && m_details.hasCap( CAP_UTF8 ) )
messageEncoding = Oscar::Message::UCS2;
else
messageEncoding = Oscar::Message::UserDefined;
TQString msgText( msg.plainBody() );
// TODO: More intelligent handling of message length.
uint chunk_length = !isOnline() ? 450 : 4096;
uint msgPosition = 0;
do
{
TQString msgChunk( msgText.mid( msgPosition, chunk_length ) );
// Try to split on space if needed
if ( msgChunk.length() == chunk_length )
{
for ( int i = 0; i < 100; i++ )
{
if ( msgChunk[chunk_length - i].isSpace() )
{
msgChunk = msgChunk.left( chunk_length - i );
msgPosition++;
}
}
}
msgPosition += msgChunk.length();
Oscar::Message message( messageEncoding, msgChunk, messageChannel, 0, msg.timestamp(), codec );
message.setSender( mAccount->accountId() );
message.setReceiver( mName );
mAccount->engine()->sendMessage( message );
} while ( msgPosition < msgText.length() );
manager(Kopete::Contact::CanCreate)->appendMessage(msg);
manager(Kopete::Contact::CanCreate)->messageSucceeded();
}
void ICQContact::updateFeatures()
{
setProperty( static_cast<ICQProtocol*>(protocol())->clientFeatures, m_clientFeatures );
}
void ICQContact::requestBuddyIcon()
{
if ( m_buddyIconDirty && m_details.buddyIconHash().size() > 0 )
{
account()->engine()->requestBuddyIcon( contactId(), m_details.buddyIconHash(),
m_details.iconCheckSumType() );
}
}
void ICQContact::haveIcon( const TQString& user, TQByteArray icon )
{
if ( Oscar::normalize( user ) != Oscar::normalize( contactId() ) )
return;
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "Updating icon for " << contactId() << endl;
KMD5 buddyIconHash( icon );
if ( memcmp( buddyIconHash.rawDigest(), m_details.buddyIconHash().data(), 16 ) == 0 )
{
TQString iconLocation( locateLocal( "appdata", "oscarpictures/"+ contactId() ) );
TQFile iconFile( iconLocation );
if ( !iconFile.open( IO_WriteOnly ) )
{
kdDebug(14153) << k_funcinfo << "Cannot open file"
<< iconLocation << " for writing!" << endl;
return;
}
iconFile.writeBlock( icon );
iconFile.close();
setProperty( Kopete::Global::Properties::self()->photo(), TQString::null );
setProperty( Kopete::Global::Properties::self()->photo(), iconLocation );
m_buddyIconDirty = false;
}
else
{
kdDebug(14153) << k_funcinfo << "Buddy icon hash does not match!" << endl;
removeProperty( Kopete::Global::Properties::self()->photo() );
}
}
bool ICQContact::cachedBuddyIcon( TQByteArray hash )
{
TQString iconLocation( locateLocal( "appdata", "oscarpictures/"+ contactId() ) );
TQFile iconFile( iconLocation );
if ( !iconFile.open( IO_ReadOnly ) )
return false;
KMD5 buddyIconHash;
buddyIconHash.update( iconFile );
iconFile.close();
if ( memcmp( buddyIconHash.rawDigest(), hash.data(), 16 ) == 0 )
{
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "Updating icon for "
<< contactId() << " from local cache" << endl;
setProperty( Kopete::Global::Properties::self()->photo(), TQString::null );
setProperty( Kopete::Global::Properties::self()->photo(), iconLocation );
m_buddyIconDirty = false;
return true;
}
else
{
return false;
}
}
#if 0
void ICQContact::slotContactChanged(const UserInfo &u)
{
if (u.sn != contactName())
return;
// update mInfo and general stuff from OscarContact
slotParseUserInfo(u);
/*kdDebug(14190) << k_funcinfo << "Called for '"
<< displayName() << "', contactName()=" << contactName() << endl;*/
TQStringList capList;
// Append client name and version in case we found one
if (!mInfo.clientName.isEmpty())
{
if (!mInfo.clientVersion.isEmpty())
{
capList << i18n("Translators: client-name client-version",
"%1 %2").arg(mInfo.clientName, mInfo.clientVersion);
}
else
{
capList << mInfo.clientName;
}
}
// and now for some general informative capabilities
if (hasCap(CAP_UTF8))
capList << i18n("UTF-8");
if (hasCap(CAP_RTFMSGS))
capList << i18n("RTF-Messages");
if (hasCap(CAP_IMIMAGE))
capList << i18n("DirectIM/IMImage");
if (hasCap(CAP_CHAT))
capList << i18n("Groupchat");
if (capList.count() > 0)
setProperty(mProtocol->clientFeatures, capList.join(", "));
else
removeProperty(mProtocol->clientFeatures);
unsigned int newStatus = 0;
mInvisible = (mInfo.icqextstatus & ICQ_STATUS_IS_INVIS);
if (mInfo.icqextstatus & ICQ_STATUS_IS_FFC)
newStatus = OSCAR_FFC;
else if (mInfo.icqextstatus & ICQ_STATUS_IS_DND)
newStatus = OSCAR_DND;
else if (mInfo.icqextstatus & ICQ_STATUS_IS_OCC)
newStatus = OSCAR_OCC;
else if (mInfo.icqextstatus & ICQ_STATUS_IS_NA)
newStatus = OSCAR_NA;
else if (mInfo.icqextstatus & ICQ_STATUS_IS_AWAY)
newStatus = OSCAR_AWAY;
else
newStatus = OSCAR_ONLINE;
if (this != account()->myself())
{
if(newStatus != onlineStatus().internalStatus())
{
if(newStatus != OSCAR_ONLINE) // if user changed to some state other than online
{
mAccount->engine()->requestAwayMessage(this);
}
else // user changed to "Online" status and has no away message anymore
{
removeProperty(mProtocol->awayMessage);
}
}
}
setStatus(newStatus);
}
void ICQContact::slotOffgoingBuddy(TQString sender)
{
if(sender != contactName())
return;
removeProperty(mProtocol->clientFeatures);
removeProperty(mProtocol->awayMessage);
setOnlineStatus(mProtocol->statusOffline);
}
void ICQContact::gotIM(OscarSocket::OscarMessageType /*type*/, const TQString &message)
{
// Build a Kopete::Message and set the body as Rich Text
Kopete::ContactPtrList tmpList;
tmpList.append(account()->myself());
Kopete::Message msg(this, tmpList, message, Kopete::Message::Inbound,
Kopete::Message::RichText);
manager(true)->appendMessage(msg);
}
void ICQContact::slotSendMsg(Kopete::Message& message, Kopete::ChatSession *)
{
if (message.plainBody().isEmpty()) // no text, do nothing
return;
// Check to see if we're even online
if(!account()->isConnected())
{
KMessageBox::sorry(Kopete::UI::Global::mainWidget(),
i18n("<qt>You must be logged on to ICQ before you can "
"send a message to a user.</qt>"),
i18n("Not Signed On"));
return;
}
// FIXME: We don't do HTML in ICQ
// we might be able to do that in AIM and we might also convert
// HTML to RTF for ICQ type-2 messages [mETz]
static_cast<OscarAccount*>(account())->engine()->sendIM(
message.plainBody(), this, false);
// Show the message we just sent in the chat window
manager(Kopete::Contact::CanCreate)->appendMessage(message);
manager(Kopete::Contact::CanCreate)->messageSucceeded();
}
#endif
bool ICQContact::isReachable()
{
return account()->isConnected();
}
TQPtrList<KAction> *ICQContact::customContextMenuActions()
{
TQPtrList<KAction> *actionCollection = new TQPtrList<KAction>();
/*
TQString awTxt;
TQString awIcn;
unsigned int status = onlineStatus().internalStatus();
if (status >= 15)
status -= 15; // get rid of invis addon
switch(status)
{
case OSCAR_FFC:
awTxt = i18n("Read 'Free For Chat' &Message");
awIcn = "icq_ffc";
break;
case OSCAR_DND:
awTxt = i18n("Read 'Do Not Disturb' &Message");
awIcn = "icq_dnd";
break;
case OSCAR_NA:
awTxt = i18n("Read 'Not Available' &Message");
awIcn = "icq_na";
break;
case OSCAR_OCC:
awTxt = i18n("Read 'Occupied' &Message");
awIcn = "icq_occ";
break;
default:
awTxt = i18n("Read 'Away' &Message");
awIcn = "icq_away";
break;
}
if(actionReadAwayMessage==0)
{
actionReadAwayMessage = new KAction(awTxt, awIcn, 0,
this, TQT_SLOT(slotReadAwayMessage()), this, "actionReadAwayMessage");
*/
actionRequestAuth = new KAction(i18n("&Request Authorization"), "mail_reply", 0,
this, TQT_SLOT(slotRequestAuth()), this, "actionRequestAuth");
actionSendAuth = new KAction(i18n("&Grant Authorization"), "mail_forward", 0,
this, TQT_SLOT(slotSendAuth()), this, "actionSendAuth");
/*
}
else
{
actionReadAwayMessage->setText(awTxt);
actionReadAwayMessage->setIconSet(SmallIconSet(awIcn));
}
*/
m_actionIgnore = new KToggleAction(i18n("&Ignore"), "", 0,
this, TQT_SLOT(slotIgnore()), this, "actionIgnore");
m_actionVisibleTo = new KToggleAction(i18n("Always &Visible To"), "", 0,
this, TQT_SLOT(slotVisibleTo()), this, "actionVisibleTo");
m_actionInvisibleTo = new KToggleAction(i18n("Always &Invisible To"), "", 0,
this, TQT_SLOT(slotInvisibleTo()), this, "actionInvisibleTo");
bool on = account()->isConnected();
if ( m_ssiItem.waitingAuth() )
actionRequestAuth->setEnabled(on);
else
actionRequestAuth->setEnabled(false);
actionSendAuth->setEnabled(on);
m_selectEncoding = new KAction( i18n( "Select Encoding..." ), "charset", 0,
this, TQT_SLOT( changeContactEncoding() ), this, "changeEncoding" );
/*
actionReadAwayMessage->setEnabled(status != OSCAR_OFFLINE && status != OSCAR_ONLINE);
*/
m_actionIgnore->setEnabled(on);
m_actionVisibleTo->setEnabled(on);
m_actionInvisibleTo->setEnabled(on);
SSIManager* ssi = account()->engine()->ssiManager();
m_actionIgnore->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_IGNORE ));
m_actionVisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_VISIBLE ));
m_actionInvisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_INVISIBLE ));
actionCollection->append(actionRequestAuth);
actionCollection->append(actionSendAuth);
actionCollection->append( m_selectEncoding );
actionCollection->append(m_actionIgnore);
actionCollection->append(m_actionVisibleTo);
actionCollection->append(m_actionInvisibleTo);
// actionCollection->append(actionReadAwayMessage);
return actionCollection;
}
void ICQContact::slotUserInfo()
{
m_infoWidget = new ICQUserInfoWidget( Kopete::UI::Global::mainWidget(), "icq info" );
TQObject::connect( m_infoWidget, TQT_SIGNAL( finished() ), this, TQT_SLOT( closeUserInfoDialog() ) );
m_infoWidget->setContact( this );
m_infoWidget->show();
if ( account()->isConnected() )
mAccount->engine()->requestFullInfo( contactId() );
}
void ICQContact::closeUserInfoDialog()
{
TQObject::disconnect( this, 0, m_infoWidget, 0 );
m_infoWidget->delayedDestruct();
m_infoWidget = 0L;
}
void ICQContact::changeContactEncoding()
{
if ( m_oesd )
return;
m_oesd = new OscarEncodingSelectionDialog( Kopete::UI::Global::mainWidget(), property(mProtocol->contactEncoding).value().toInt() );
connect( m_oesd, TQT_SIGNAL( closing( int ) ),
this, TQT_SLOT( changeEncodingDialogClosed( int ) ) );
m_oesd->show();
}
void ICQContact::changeEncodingDialogClosed( int result )
{
if ( result == TQDialog::Accepted )
{
int mib = m_oesd->selectedEncoding();
if ( mib != 0 )
{
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "setting encoding mib to "
<< m_oesd->selectedEncoding() << endl;
setProperty( mProtocol->contactEncoding, m_oesd->selectedEncoding() );
}
else
{
kdDebug(OSCAR_ICQ_DEBUG) << k_funcinfo
<< "setting encoding to default" << endl;
removeProperty( mProtocol->contactEncoding );
}
}
if ( m_oesd )
{
m_oesd->delayedDestruct();
m_oesd = 0L;
}
}
void ICQContact::slotIgnore()
{
account()->engine()->setIgnore( contactId(), m_actionIgnore->isChecked() );
}
void ICQContact::slotVisibleTo()
{
account()->engine()->setVisibleTo( contactId(), m_actionVisibleTo->isChecked() );
}
void ICQContact::slotInvisibleTo()
{
account()->engine()->setInvisibleTo( contactId(), m_actionInvisibleTo->isChecked() );
}
#if 0
void ICQContact::slotReadAwayMessage()
{
kdDebug(14153) << k_funcinfo << "account='" << account()->accountId() <<
"', contact='" << displayName() << "'" << endl;
if (!awayMessageDialog)
{
awayMessageDialog = new ICQReadAway(this, 0L, "awayMessageDialog");
if(!awayMessageDialog)
return;
TQObject::connect(awayMessageDialog, TQT_SIGNAL(closing()), this, TQT_SLOT(slotCloseAwayMessageDialog()));
awayMessageDialog->show();
}
else
{
awayMessageDialog->raise();
}
}
void ICQContact::slotCloseAwayMessageDialog()
{
awayMessageDialog->delayedDestruct();
awayMessageDialog = 0L;
}
const TQString ICQContact::awayMessage()
{
kdDebug(14150) << k_funcinfo << property(mProtocol->awayMessage).value().toString() << endl;
return property(mProtocol->awayMessage).value().toString();
}
void ICQContact::setAwayMessage(const TQString &message)
{
/*kdDebug(14150) << k_funcinfo <<
"Called for '" << displayName() << "', away msg='" << message << "'" << endl;*/
setProperty(mProtocol->awayMessage, message);
emit awayMessageChanged();
}
void ICQContact::slotUpdGeneralInfo(const int seq, const ICQGeneralUserInfo &inf)
{
// compare reply's sequence with the one we sent with our last request
if(seq != userinfoRequestSequence)
return;
generalInfo = inf;
if(!generalInfo.firstName.isEmpty())
setProperty(mProtocol->firstName, generalInfo.firstName);
else
removeProperty(mProtocol->firstName);
if(!generalInfo.lastName.isEmpty())
setProperty(mProtocol->lastName, generalInfo.lastName);
else
removeProperty(mProtocol->lastName);
if(!generalInfo.eMail.isEmpty())
setProperty(mProtocol->emailAddress, generalInfo.eMail);
else
removeProperty(mProtocol->emailAddress);
/*
if(!generalInfo.phoneNumber.isEmpty())
setProperty("privPhoneNum", generalInfo.phoneNumber);
else
removeProperty("privPhoneNum");
if(!generalInfo.faxNumber.isEmpty())
setProperty("privFaxNum", generalInfo.faxNumber);
else
removeProperty("privFaxNum");
if(!generalInfo.cellularNumber.isEmpty())
setProperty("privMobileNum", generalInfo.cellularNumber);
else
removeProperty("privMobileNum");
*/
if(contactName() == displayName() && !generalInfo.nickName.isEmpty())
{
kdDebug(14153) << k_funcinfo << "setting new displayname for former UIN-only Contact" << endl;
setDisplayName(generalInfo.nickName);
}
incUserInfoCounter();
}
void ICQContact::slotSnacFailed(WORD snacID)
{
if (userinfoRequestSequence != 0)
kdDebug(14153) << k_funcinfo << "snacID = " << snacID << " seq = " << userinfoRequestSequence << endl;
//TODO: ugly interaction between snacID and request sequence, see OscarSocket::sendCLI_TOICQSRV
if (snacID == (0x0000 << 16) | userinfoRequestSequence)
{
userinfoRequestSequence = 0;
emit userInfoRequestFailed();
}
}
void ICQContact::slotIgnore()
{
kdDebug(14150) << k_funcinfo <<
"Called; ignore = " << actionIgnore->isChecked() << endl;
setIgnore(actionIgnore->isChecked(), true);
}
void ICQContact::slotVisibleTo()
{
kdDebug(14150) << k_funcinfo <<
"Called; visible = " << actionVisibleTo->isChecked() << endl;
setVisibleTo(actionVisibleTo->isChecked(), true);
}
#endif
#include "icqcontact.moc"
//kate: indent-mode csands; tab-width 4; replace-tabs off; space-indent off;