/* icqontact.cpp - Oscar Protocol Plugin Copyright (c) 2003 by Stefan Gehn Copyright (c) 2003 by Olivier Goffart Kopete (c) 2003-2004 by the Kopete developers ************************************************************************* * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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(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 = ( TDEApplication::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 = ( TDEApplication::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(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() ); 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( *TQT_TQIODEVICE(&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() ); 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("You must be logged on to ICQ before you can " "send a message to a user."), 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(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 *ICQContact::customContextMenuActions() { TQPtrList *actionCollection = new TQPtrList(); /* 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 TDEAction(awTxt, awIcn, 0, this, TQT_SLOT(slotReadAwayMessage()), this, "actionReadAwayMessage"); */ actionRequestAuth = new TDEAction(i18n("&Request Authorization"), "mail_reply", 0, this, TQT_SLOT(slotRequestAuth()), this, "actionRequestAuth"); actionSendAuth = new TDEAction(i18n("&Grant Authorization"), "mail_forward", 0, this, TQT_SLOT(slotSendAuth()), this, "actionSendAuth"); /* } else { actionReadAwayMessage->setText(awTxt); actionReadAwayMessage->setIconSet(SmallIconSet(awIcn)); } */ m_actionIgnore = new TDEToggleAction(i18n("&Ignore"), "", 0, this, TQT_SLOT(slotIgnore()), this, "actionIgnore"); m_actionVisibleTo = new TDEToggleAction(i18n("Always &Visible To"), "", 0, this, TQT_SLOT(slotVisibleTo()), this, "actionVisibleTo"); m_actionInvisibleTo = new TDEToggleAction(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 TDEAction( 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;