1 /*
2   icqontact.cpp  -  Oscar Protocol Plugin
3 
4   Copyright (c) 2003      by Stefan Gehn <metz@gehn.net>
5   Copyright (c) 2003      by Olivier Goffart <ogoffart@kde.org>
6   Copyright (c) 2006,2007 by Roman Jarosz <kedgedev@centrum.cz>
7 
8   Kopete    (c) 2003-2007 by the Kopete developers  <kopete-devel@kde.org>
9 
10   *************************************************************************
11   *                                                                       *
12   * This program is free software; you can redistribute it and/or modify  *
13   * it under the terms of the GNU General Public License as published by  *
14   * the Free Software Foundation; either version 2 of the License, or     *
15   * (at your option) any later version.                                   *
16   *                                                                       *
17   *************************************************************************
18 */
19 
20 #include "icqcontact.h"
21 
22 #include <qtimer.h>
23 
24 #include <KActionCollection>
25 #include <KLocalizedString>
26 #include <krandom.h>
27 #include <ktoggleaction.h>
28 
29 #include "kopetemetacontact.h"
30 
31 #include "aimprotocol.h"
32 #include "aimaccount.h"
33 
34 #include "oscarutils.h"
35 #include "contactmanager.h"
36 #include "oscarstatusmanager.h"
37 
ICQContact(Kopete::Account * account,const QString & name,Kopete::MetaContact * parent,const QString & icon)38 ICQContact::ICQContact( Kopete::Account* account, const QString &name, Kopete::MetaContact *parent,
39 						const QString& icon )
40 : ICQContactBase( account, name, parent, icon )
41 {
42 	mProtocol = static_cast<AIMProtocol *>(protocol());
43 
44 	setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline, Oscar::Presence::ICQ ) );
45 
46 	QObject::connect( mAccount->engine(), SIGNAL(loggedIn()), this, SLOT(loggedIn()) );
47 	//QObject::connect( mAccount->engine(), SIGNAL(userIsOnline(QString)), this, SLOT(userOnline(QString,UserDetails)) );
48 	QObject::connect( mAccount->engine(), SIGNAL(userIsOffline(QString)), this, SLOT(userOffline(QString)) );
49 	QObject::connect( mAccount->engine(), SIGNAL(receivedUserInfo(QString,UserDetails)),
50 	                  this, SLOT(userInfoUpdated(QString,UserDetails)) );
51 }
52 
~ICQContact()53 ICQContact::~ICQContact()
54 {
55 }
56 
setSSIItem(const OContact & ssiItem)57 void ICQContact::setSSIItem( const OContact& ssiItem )
58 {
59 	if ( ssiItem.waitingAuth() )
60 		setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
61 
62 	if ( ssiItem.type() != 0xFFFF && ssiItem.waitingAuth() == false &&
63 	     onlineStatus().status() == Kopete::OnlineStatus::Unknown )
64 	{
65 		//make sure they're offline
66 		setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline, Oscar::Presence::ICQ ) );
67 	}
68 
69 	ICQContactBase::setSSIItem( ssiItem );
70 }
71 
userInfoUpdated(const QString & contact,const UserDetails & details)72 void ICQContact::userInfoUpdated( const QString& contact, const UserDetails& details )
73 {
74 	//kDebug(OSCAR_AIM_DEBUG) << contact << contactId();
75 	if ( Oscar::normalize( contact  ) != Oscar::normalize( contactId() ) )
76 		return;
77 
78 	// invalidate old away message if user was offline
79 	if ( !isOnline() )
80 		removeProperty( mProtocol->statusMessage );
81 
82 	kDebug( OSCAR_AIM_DEBUG ) << "extendedStatus is " << details.extendedStatus();
83 	Oscar::Presence presence = mProtocol->statusManager()->presenceOf( details.extendedStatus(), details.userClass() );
84 	setPresenceTarget( presence );
85 
86 	setAwayMessage( details.personalMessage() );
87 	if ( presence.type() != Oscar::Presence::Online && m_details.awaySinceTime() < details.awaySinceTime() ) //prevent cyclic away message requests
88 	{
89 		mAccount->engine()->requestAIMAwayMessage( contactId() );
90 	}
91 
92 //TODO: don't know if we need this in aim
93 // 	if ( details.dcOutsideSpecified() )
94 // 	{
95 // 		if ( details.dcExternalIp().isUnspecified() )
96 // 			removeProperty( mProtocol->ipAddress );
97 // 		else
98 // 			setProperty( mProtocol->ipAddress, details.dcExternalIp().toString() );
99 // 	}
100 
101 	if ( details.capabilitiesSpecified() )
102 		setProperty( mProtocol->clientFeatures, details.clientName() );
103 
104 	OscarContact::userInfoUpdated( contact, details );
105 }
106 
userOnline(const QString & userId)107 void ICQContact::userOnline( const QString& userId )
108 {
109 	if ( Oscar::normalize( userId ) != Oscar::normalize( contactId() ) )
110 		return;
111 
112 	kDebug(OSCAR_AIM_DEBUG) << "Setting " << userId << " online";
113 	setPresenceTarget( Oscar::Presence( Oscar::Presence::Online, Oscar::Presence::ICQ ) );
114 }
115 
userOffline(const QString & userId)116 void ICQContact::userOffline( const QString& userId )
117 {
118 	if ( Oscar::normalize( userId ) != Oscar::normalize( contactId() ) )
119 		return;
120 
121 	m_details.clear();
122 
123 	kDebug(OSCAR_AIM_DEBUG) << "Setting " << userId << " offline";
124 	if ( m_ssiItem.waitingAuth() )
125 		setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
126 	else
127 		setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline, Oscar::Presence::ICQ ) );
128 
129 	removeProperty( mProtocol->statusMessage );
130 }
131 
loggedIn()132 void ICQContact::loggedIn()
133 {
134 	if ( metaContact()->isTemporary() )
135 		return;
136 
137 	if ( m_ssiItem.waitingAuth() )
138 		setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
139 }
140 
isReachable()141 bool ICQContact::isReachable()
142 {
143 	return true;
144 }
145 
customContextMenuActions()146 QList<QAction*> *ICQContact::customContextMenuActions()
147 {
148 	QList<QAction*> *actions = new QList<QAction*>();
149 
150 	m_actionVisibleTo = new KToggleAction(i18n("Always &Visible To"), this );
151         //, "actionVisibleTo");
152 	QObject::connect(m_actionVisibleTo, &KToggleAction::triggered, this, &ICQContact::slotVisibleTo);
153 
154 	m_actionInvisibleTo = new KToggleAction(i18n("Always &Invisible To"), this );
155         //, "actionInvisibleTo");
156 	QObject::connect(m_actionInvisibleTo, &KToggleAction::triggered, this, &ICQContact::slotInvisibleTo);
157 
158 	bool on = account()->isConnected();
159 
160 	m_actionVisibleTo->setEnabled(on);
161 	m_actionInvisibleTo->setEnabled(on);
162 
163 	ContactManager* ssi = account()->engine()->ssiManager();
164 	m_actionVisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_VISIBLE ));
165 	m_actionInvisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_INVISIBLE ));
166 
167 	actions->append(m_actionVisibleTo);
168 	actions->append(m_actionInvisibleTo);
169 
170 	// temporary action collection, used to apply Kiosk policy to the actions
171 	KActionCollection tempCollection((QObject*)0);
172 	tempCollection.addAction(QLatin1String("oscarContactAlwaysVisibleTo"), m_actionVisibleTo);
173 	tempCollection.addAction(QLatin1String("oscarContactAlwaysInvisibleTo"), m_actionInvisibleTo);
174 
175 	return actions;
176 }
177 
slotVisibleTo()178 void ICQContact::slotVisibleTo()
179 {
180 	account()->engine()->setVisibleTo( contactId(), m_actionVisibleTo->isChecked() );
181 }
182 
slotInvisibleTo()183 void ICQContact::slotInvisibleTo()
184 {
185 	account()->engine()->setInvisibleTo( contactId(), m_actionInvisibleTo->isChecked() );
186 }
187 
188