Merge ICQ/AIM Presence stuff and clean it.
[kdenetwork.git] / kopete / protocols / oscar / icq / icqcontact.cpp
blobd5a08ffc12f2e460c2d230fcd6013e02e808055e
1 /*
2 icqontact.cpp - Oscar Protocol Plugin
4 Copyright (c) 2003 by Stefan Gehn <metz@gehn.net>
5 Copyright (c) 2003 by Olivier Goffart <oggoffart@kde.org>
6 Copyright (c) 2006,2007 by Roman Jarosz <kedgedev@centrum.cz>
8 Kopete (c) 2003-2007 by the Kopete developers <kopete-devel@kde.org>
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 *************************************************************************
20 #include "icqcontact.h"
22 #include <qtimer.h>
23 #include <klocale.h>
24 #include <knotification.h>
25 #include <kinputdialog.h>
26 #include <krandom.h>
27 #include <ktoggleaction.h>
28 #include <kicon.h>
30 #include "kopeteuiglobal.h"
31 #include "kopetemetacontact.h"
33 #include "icqprotocol.h"
34 #include "icqaccount.h"
35 #include "icquserinfowidget.h"
36 #include "icqauthreplydialog.h"
38 #include "oscarutils.h"
39 #include "contactmanager.h"
40 #include "oscarstatusmanager.h"
43 ICQContact::ICQContact( Kopete::Account* account, const QString &name, Kopete::MetaContact *parent,
44 const QString& icon, const OContact& ssiItem )
45 : ICQContactBase( account, name, parent, icon, ssiItem )
47 mProtocol = static_cast<ICQProtocol *>(protocol());
48 m_infoWidget = 0L;
50 if ( ssiItem.waitingAuth() )
51 setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
52 else
53 setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline ) );
55 QObject::connect( mAccount->engine(), SIGNAL( loggedIn() ), this, SLOT( loggedIn() ) );
56 //QObject::connect( mAccount->engine(), SIGNAL( userIsOnline( const QString& ) ), this, SLOT( userOnline( const QString&, UserDetails ) ) );
57 QObject::connect( mAccount->engine(), SIGNAL( userIsOffline( const QString& ) ), this, SLOT( userOffline( const QString& ) ) );
58 QObject::connect( mAccount->engine(), SIGNAL( authRequestReceived( const QString&, const QString& ) ),
59 this, SLOT( slotGotAuthRequest( const QString&, const QString& ) ) );
60 QObject::connect( mAccount->engine(), SIGNAL( authReplyReceived( const QString&, const QString&, bool ) ),
61 this, SLOT( slotGotAuthReply(const QString&, const QString&, bool ) ) );
62 QObject::connect( mAccount->engine(), SIGNAL( receivedIcqLongInfo( const QString& ) ),
63 this, SLOT( receivedLongInfo( const QString& ) ) );
64 QObject::connect( mAccount->engine(), SIGNAL( receivedUserInfo( const QString&, const UserDetails& ) ),
65 this, SLOT( userInfoUpdated( const QString&, const UserDetails& ) ) );
68 ICQContact::~ICQContact()
70 delete m_infoWidget;
73 void ICQContact::updateSSIItem()
75 //kDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << endl;
76 if ( m_ssiItem.waitingAuth() )
77 setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
79 if ( m_ssiItem.type() != 0xFFFF && m_ssiItem.waitingAuth() == false &&
80 onlineStatus() == Kopete::OnlineStatus::Unknown )
82 //make sure they're offline
83 setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline ) );
88 void ICQContact::userInfoUpdated( const QString& contact, const UserDetails& details )
90 //kDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << contact << contactId() << endl;
91 if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
92 return;
94 // invalidate old away message if user was offline
95 if ( !isOnline() )
96 removeProperty( mProtocol->awayMessage );
98 kDebug( OSCAR_ICQ_DEBUG ) << k_funcinfo << "extendedStatus is " << details.extendedStatus() << endl;
99 Oscar::Presence presence = mProtocol->statusManager()->presenceOf( details.extendedStatus(), details.userClass() );
101 if ( details.xtrazStatusSpecified() )
103 presence.setFlags( presence.flags() | Oscar::Presence::XStatus );
104 presence.setDescription( i18n("Online") );
105 presence.setIcon( QString( "icq_xstatus%1" ).arg( details.xtrazStatus() ) );
107 setPresenceTarget( presence );
109 Oscar::Presence selfPres( mProtocol->statusManager()->presenceOf( account()->myself()->onlineStatus() ) );
110 bool selfVisible = !(selfPres.flags() & Oscar::Presence::Invisible);
111 if ( presence.type() == Oscar::Presence::Online )
113 if ( details.xtrazStatusSpecified() )
115 if ( selfVisible )
116 mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQXStatus );
117 else
118 mAccount->engine()->removeICQAwayMessageRequest( contactId() );
120 else
122 mAccount->engine()->removeICQAwayMessageRequest( contactId() );
123 removeProperty( mProtocol->awayMessage );
126 else
128 if ( selfVisible )
130 switch ( presence.type() )
132 case Oscar::Presence::Away:
133 mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQAway );
134 break;
135 case Oscar::Presence::NotAvailable:
136 mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQNotAvailable );
137 break;
138 case Oscar::Presence::Occupied:
139 mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQOccupied );
140 break;
141 case Oscar::Presence::DoNotDisturb:
142 mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQDoNotDisturb );
143 break;
144 case Oscar::Presence::FreeForChat:
145 mAccount->engine()->addICQAwayMessageRequest( contactId(), Client::ICQFreeForChat );
146 break;
147 default:
148 break;
151 else
153 mAccount->engine()->removeICQAwayMessageRequest( contactId() );
158 if ( details.dcOutsideSpecified() )
160 if ( details.dcExternalIp().isUnspecified() )
161 removeProperty( mProtocol->ipAddress );
162 else
163 setProperty( mProtocol->ipAddress, details.dcExternalIp().toString() );
166 if ( details.capabilitiesSpecified() )
168 if ( details.clientName().isEmpty() )
169 removeProperty( mProtocol->clientFeatures );
170 else
171 setProperty( mProtocol->clientFeatures, details.clientName() );
174 OscarContact::userInfoUpdated( contact, details );
177 void ICQContact::userOnline( const QString& userId )
179 if ( Oscar::normalize( userId ) != Oscar::normalize( contactId() ) )
180 return;
182 kDebug(OSCAR_ICQ_DEBUG) << "Setting " << userId << " online" << endl;
183 setPresenceTarget( Oscar::Presence( Oscar::Presence::Online ) );
186 void ICQContact::userOffline( const QString& userId )
188 if ( Oscar::normalize( userId ) != Oscar::normalize( contactId() ) )
189 return;
191 kDebug(OSCAR_ICQ_DEBUG) << "Setting " << userId << " offline" << endl;
192 if ( m_ssiItem.waitingAuth() )
193 setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
194 else
195 setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline ) );
197 removeProperty( mProtocol->awayMessage );
200 void ICQContact::loggedIn()
202 if ( metaContact()->isTemporary() )
203 return;
205 if ( m_ssiItem.waitingAuth() )
206 setOnlineStatus( mProtocol->statusManager()->waitingForAuth() );
208 if ( ( ( hasProperty( Kopete::Global::Properties::self()->nickName().key() )
209 && nickName() == contactId() )
210 || !hasProperty( Kopete::Global::Properties::self()->nickName().key() ) )
211 && !m_requestingNickname && m_ssiItem.alias().isEmpty() )
213 m_requestingNickname = true;
214 int time = ( KRandom::random() % 20 ) * 1000;
215 kDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "updating nickname in " << time/1000 << " seconds" << endl;
216 QTimer::singleShot( time, this, SLOT( requestShortInfo() ) );
221 void ICQContact::slotRequestAuth()
223 QString reason = KInputDialog::getText( i18n("Request Authorization"),
224 i18n("Reason for requesting authorization:") );
225 if ( !reason.isNull() )
226 mAccount->engine()->requestAuth( contactId(), reason );
229 void ICQContact::slotSendAuth()
231 kDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "Sending auth reply" << endl;
232 ICQAuthReplyDialog replyDialog( 0, false );
234 replyDialog.setUser( property( Kopete::Global::Properties::self()->nickName() ).value().toString() );
235 if ( replyDialog.exec() )
236 mAccount->engine()->sendAuth( contactId(), replyDialog.reason(), replyDialog.grantAuth() );
239 void ICQContact::slotGotAuthReply( const QString& contact, const QString& reason, bool granted )
241 if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
242 return;
244 kDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << endl;
245 QString message;
246 if( granted )
248 message = i18n( "User %1 has granted your authorization request.\nReason: %2" ,
249 property( Kopete::Global::Properties::self()->nickName() ).value().toString() ,
250 reason );
252 // remove the unknown status
253 setPresenceTarget( Oscar::Presence( Oscar::Presence::Offline ) );
255 else
257 message = i18n( "User %1 has rejected the authorization request.\nReason: %2" ,
258 property( Kopete::Global::Properties::self()->nickName() ).value().toString() ,
259 reason );
261 KNotification::event( QString::fromLatin1("icq_authorization"), message );
264 void ICQContact::slotGotAuthRequest( const QString& contact, const QString& reason )
266 if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
267 return;
269 ICQAuthReplyDialog *replyDialog = new ICQAuthReplyDialog();
271 connect( replyDialog, SIGNAL( okClicked() ), this, SLOT( slotAuthReplyDialogOkClicked() ) );
272 replyDialog->setUser( property( Kopete::Global::Properties::self()->nickName() ).value().toString() );
273 replyDialog->setRequestReason( reason );
274 replyDialog->setModal( true );
275 replyDialog->show();
278 void ICQContact::slotAuthReplyDialogOkClicked()
280 // Do not need to delete will delete itself automatically
281 ICQAuthReplyDialog *replyDialog = (ICQAuthReplyDialog*)sender();
283 if (replyDialog)
284 mAccount->engine()->sendAuth( contactId(), replyDialog->reason(), replyDialog->grantAuth() );
287 void ICQContact::receivedLongInfo( const QString& contact )
289 if ( Oscar::normalize( contact ) != Oscar::normalize( contactId() ) )
291 if ( m_infoWidget )
292 m_infoWidget->delayedDestruct();
293 return;
296 QTextCodec* codec = contactCodec();
298 kDebug(OSCAR_ICQ_DEBUG) << k_funcinfo << "received long info from engine" << endl;
300 ICQGeneralUserInfo genInfo = mAccount->engine()->getGeneralInfo( contact );
301 if ( m_ssiItem.alias().isEmpty() && !genInfo.nickName.get().isEmpty() )
302 setNickName( codec->toUnicode( genInfo.nickName.get() ) );
303 emit haveBasicInfo( genInfo );
305 ICQWorkUserInfo workInfo = mAccount->engine()->getWorkInfo( contact );
306 emit haveWorkInfo( workInfo );
308 ICQEmailInfo emailInfo = mAccount->engine()->getEmailInfo( contact );
309 emit haveEmailInfo( emailInfo );
311 ICQNotesInfo notesInfo = mAccount->engine()->getNotesInfo( contact );
312 emit haveNotesInfo( notesInfo );
314 ICQMoreUserInfo moreInfo = mAccount->engine()->getMoreInfo( contact );
315 emit haveMoreInfo( moreInfo );
317 ICQInterestInfo interestInfo = mAccount->engine()->getInterestInfo( contact );
318 emit haveInterestInfo( interestInfo );
320 ICQOrgAffInfo orgAffInfo = mAccount->engine()->getOrgAffInfo( contact );
321 emit haveOrgAffInfo( orgAffInfo );
324 #if 0
325 void ICQContact::slotContactChanged(const UserInfo &u)
327 if (u.sn != contactName())
328 return;
330 // update mInfo and general stuff from OscarContact
331 slotParseUserInfo(u);
333 /*kDebug(14190) << k_funcinfo << "Called for '"
334 << displayName() << "', contactName()=" << contactName() << endl;*/
335 QStringList capList;
336 // Append client name and version in case we found one
337 if (!mInfo.clientName.isEmpty())
339 if (!mInfo.clientVersion.isEmpty())
341 capList << i18nc("Translators: client-name client-version",
342 "%1 %2", mInfo.clientName, mInfo.clientVersion);
344 else
346 capList << mInfo.clientName;
349 // and now for some general informative capabilities
350 if (hasCap(CAP_UTF8))
351 capList << i18n("UTF-8");
352 if (hasCap(CAP_RTFMSGS))
353 capList << i18n("RTF-Messages");
354 if (hasCap(CAP_IMIMAGE))
355 capList << i18n("DirectIM/IMImage");
356 if (hasCap(CAP_CHAT))
357 capList << i18n("Groupchat");
359 if (capList.count() > 0)
360 setProperty(mProtocol->clientFeatures, capList.join(", "));
361 else
362 removeProperty(mProtocol->clientFeatures);
364 unsigned int newStatus = 0;
365 mInvisible = (mInfo.icqextstatus & ICQ_STATUS_IS_INVIS);
367 if (mInfo.icqextstatus & ICQ_STATUS_IS_FFC)
368 newStatus = OSCAR_FFC;
369 else if (mInfo.icqextstatus & ICQ_STATUS_IS_DND)
370 newStatus = OSCAR_DND;
371 else if (mInfo.icqextstatus & ICQ_STATUS_IS_OCC)
372 newStatus = OSCAR_OCC;
373 else if (mInfo.icqextstatus & ICQ_STATUS_IS_NA)
374 newStatus = OSCAR_NA;
375 else if (mInfo.icqextstatus & ICQ_STATUS_IS_AWAY)
376 newStatus = OSCAR_AWAY;
377 else
378 newStatus = OSCAR_ONLINE;
380 if (this != account()->myself())
382 if(newStatus != onlineStatus().internalStatus())
384 if(newStatus != OSCAR_ONLINE) // if user changed to some state other than online
386 mAccount->engine()->requestAwayMessage(this);
388 else // user changed to "Online" status and has no away message anymore
390 removeProperty(mProtocol->awayMessage);
395 setStatus(newStatus);
398 void ICQContact::slotOffgoingBuddy(QString sender)
400 if(sender != contactName())
401 return;
403 removeProperty(mProtocol->clientFeatures);
404 removeProperty(mProtocol->awayMessage);
405 setOnlineStatus(mProtocol->statusOffline);
408 void ICQContact::gotIM(OscarSocket::OscarMessageType /*type*/, const QString &message)
410 // Build a Kopete::Message and set the body as Rich Text
411 Kopete::ContactPtrList tmpList;
412 tmpList.append(account()->myself());
413 Kopete::Message msg(this, tmpList, message, Kopete::Message::Inbound,
414 Kopete::Message::RichText);
415 manager(true)->appendMessage(msg);
419 void ICQContact::slotSendMsg(Kopete::Message& message, Kopete::ChatSession *)
421 if (message.plainBody().isEmpty()) // no text, do nothing
422 return;
424 // Check to see if we're even online
425 if(!account()->isConnected())
427 KMessageBox::sorry(Kopete::UI::Global::mainWidget(),
428 i18n("<qt>You must be logged on to ICQ before you can "
429 "send a message to a user.</qt>"),
430 i18n("Not Signed On"));
431 return;
434 // FIXME: We don't do HTML in ICQ
435 // we might be able to do that in AIM and we might also convert
436 // HTML to RTF for ICQ type-2 messages [mETz]
437 static_cast<OscarAccount*>(account())->engine()->sendIM(
438 message.plainBody(), this, false);
440 // Show the message we just sent in the chat window
441 manager(Kopete::Contact::CanCreate)->appendMessage(message);
442 manager(Kopete::Contact::CanCreate)->messageSucceeded();
445 #endif
447 bool ICQContact::isReachable()
449 return account()->isConnected();
452 QList<KAction*> *ICQContact::customContextMenuActions()
454 QList<KAction*> *actionCollection = new QList<KAction*>();
456 actionRequestAuth = new KAction( i18n("&Request Authorization"), this );
457 //, "actionRequestAuth");
458 actionRequestAuth->setIcon( KIcon( "mail_reply" ) );
459 QObject::connect( actionRequestAuth, SIGNAL(triggered(bool)), this, SLOT(slotRequestAuth()) );
461 actionSendAuth = new KAction( i18n("&Grant Authorization"), this );
462 //, "actionSendAuth");
463 actionSendAuth->setIcon( KIcon( "mail_forward" ) );
464 QObject::connect( actionSendAuth, SIGNAL(triggered(bool)), this, SLOT(slotSendAuth()) );
466 m_actionIgnore = new KToggleAction(i18n("&Ignore"), this );
467 //, "actionIgnore");
468 QObject::connect( m_actionIgnore, SIGNAL(triggered(bool)), this, SLOT(slotIgnore()) );
470 m_actionVisibleTo = new KToggleAction(i18n("Always &Visible To"), this );
471 //, "actionVisibleTo");
472 QObject::connect( m_actionVisibleTo, SIGNAL(triggered(bool)), this, SLOT(slotVisibleTo()) );
474 m_actionInvisibleTo = new KToggleAction(i18n("Always &Invisible To"), this );
475 //, "actionInvisibleTo");
476 QObject::connect( m_actionInvisibleTo, SIGNAL(triggered(bool)), this, SLOT(slotInvisibleTo()) );
478 m_selectEncoding = new KAction( i18n( "Select Encoding..." ), this );
479 //, "changeEncoding" );
480 m_selectEncoding->setIcon( KIcon( "charset" ) );
481 QObject::connect( m_selectEncoding, SIGNAL(triggered(bool)), this, SLOT(changeContactEncoding()) );
483 bool on = account()->isConnected();
484 if ( m_ssiItem.waitingAuth() )
485 actionRequestAuth->setEnabled(on);
486 else
487 actionRequestAuth->setEnabled(false);
489 actionSendAuth->setEnabled(on);
490 m_actionIgnore->setEnabled(on);
491 m_actionVisibleTo->setEnabled(on);
492 m_actionInvisibleTo->setEnabled(on);
494 ContactManager* ssi = account()->engine()->ssiManager();
495 m_actionIgnore->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_IGNORE ));
496 m_actionVisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_VISIBLE ));
497 m_actionInvisibleTo->setChecked( ssi->findItem( m_ssiItem.name(), ROSTER_INVISIBLE ));
499 actionCollection->append(actionRequestAuth);
500 actionCollection->append(actionSendAuth);
501 actionCollection->append( m_selectEncoding );
503 actionCollection->append(m_actionIgnore);
504 actionCollection->append(m_actionVisibleTo);
505 actionCollection->append(m_actionInvisibleTo);
507 return actionCollection;
511 void ICQContact::slotUserInfo()
513 m_infoWidget = new ICQUserInfoWidget( Kopete::UI::Global::mainWidget() );
514 QObject::connect( m_infoWidget, SIGNAL( finished() ), this, SLOT( closeUserInfoDialog() ) );
515 m_infoWidget->setContact( this );
516 m_infoWidget->show();
517 if ( account()->isConnected() )
518 mAccount->engine()->requestFullInfo( contactId() );
521 void ICQContact::closeUserInfoDialog()
523 QObject::disconnect( this, 0, m_infoWidget, 0 );
524 m_infoWidget->delayedDestruct();
525 m_infoWidget = 0L;
528 void ICQContact::slotIgnore()
530 account()->engine()->setIgnore( contactId(), m_actionIgnore->isChecked() );
533 void ICQContact::slotVisibleTo()
535 account()->engine()->setVisibleTo( contactId(), m_actionVisibleTo->isChecked() );
538 void ICQContact::slotInvisibleTo()
540 account()->engine()->setInvisibleTo( contactId(), m_actionInvisibleTo->isChecked() );
543 #if 0
545 void ICQContact::slotReadAwayMessage()
547 kDebug(14153) << k_funcinfo << "account='" << account()->accountId() <<
548 "', contact='" << displayName() << "'" << endl;
550 if (!awayMessageDialog)
552 awayMessageDialog = new ICQReadAway(this, 0L, "awayMessageDialog");
553 if(!awayMessageDialog)
554 return;
555 QObject::connect(awayMessageDialog, SIGNAL(closing()), this, SLOT(slotCloseAwayMessageDialog()));
556 awayMessageDialog->show();
558 else
560 awayMessageDialog->raise();
565 void ICQContact::slotCloseAwayMessageDialog()
567 awayMessageDialog->delayedDestruct();
568 awayMessageDialog = 0L;
572 const QString ICQContact::awayMessage()
574 kDebug(14150) << k_funcinfo << property(mProtocol->awayMessage).value().toString() << endl;
575 return property(mProtocol->awayMessage).value().toString();
579 void ICQContact::setAwayMessage(const QString &message)
581 /*kDebug(14150) << k_funcinfo <<
582 "Called for '" << displayName() << "', away msg='" << message << "'" << endl;*/
583 setProperty(mProtocol->awayMessage, message);
584 emit awayMessageChanged();
588 void ICQContact::slotUpdGeneralInfo(const int seq, const ICQGeneralUserInfo &inf)
590 // compare reply's sequence with the one we sent with our last request
591 if(seq != userinfoRequestSequence)
592 return;
593 generalInfo = inf;
595 if(!generalInfo.firstName.isEmpty())
596 setProperty(mProtocol->firstName, generalInfo.firstName);
597 else
598 removeProperty(mProtocol->firstName);
600 if(!generalInfo.lastName.isEmpty())
601 setProperty(mProtocol->lastName, generalInfo.lastName);
602 else
603 removeProperty(mProtocol->lastName);
605 if(!generalInfo.eMail.isEmpty())
606 setProperty(mProtocol->emailAddress, generalInfo.eMail);
607 else
608 removeProperty(mProtocol->emailAddress);
610 if(!generalInfo.phoneNumber.isEmpty())
611 setProperty("privPhoneNum", generalInfo.phoneNumber);
612 else
613 removeProperty("privPhoneNum");
615 if(!generalInfo.faxNumber.isEmpty())
616 setProperty("privFaxNum", generalInfo.faxNumber);
617 else
618 removeProperty("privFaxNum");
620 if(!generalInfo.cellularNumber.isEmpty())
621 setProperty("privMobileNum", generalInfo.cellularNumber);
622 else
623 removeProperty("privMobileNum");
626 if(contactName() == displayName() && !generalInfo.nickName.isEmpty())
628 kDebug(14153) << k_funcinfo << "setting new displayname for former UIN-only Contact" << endl;
629 setDisplayName(generalInfo.nickName);
632 incUserInfoCounter();
636 void ICQContact::slotSnacFailed(WORD snacID)
638 if (userinfoRequestSequence != 0)
639 kDebug(14153) << k_funcinfo << "snacID = " << snacID << " seq = " << userinfoRequestSequence << endl;
641 //TODO: ugly interaction between snacID and request sequence, see OscarSocket::sendCLI_TOICQSRV
642 if (snacID == (0x0000 << 16) | userinfoRequestSequence)
644 userinfoRequestSequence = 0;
645 emit userInfoRequestFailed();
649 void ICQContact::slotIgnore()
651 kDebug(14150) << k_funcinfo <<
652 "Called; ignore = " << actionIgnore->isChecked() << endl;
653 setIgnore(actionIgnore->isChecked(), true);
656 void ICQContact::slotVisibleTo()
658 kDebug(14150) << k_funcinfo <<
659 "Called; visible = " << actionVisibleTo->isChecked() << endl;
660 setVisibleTo(actionVisibleTo->isChecked(), true);
662 #endif
663 #include "icqcontact.moc"
664 //kate: indent-mode csands; tab-width 4; replace-tabs off; space-indent off;