2
ircusercontact.cpp - IRC User Contact
4
Copyright (c) 2002 by Nick Betcher <nbetcher@kde.org>
6
Kopete (c) 2002 by the Kopete developers <kopete-devel@kde.org>
8
*************************************************************************
10
* This program is free software; you can redistribute it and/or modify *
11
* it under the terms of the GNU General Public License as published by *
12
* the Free Software Foundation; either version 2 of the License, or *
13
* (at your option) any later version. *
15
*************************************************************************
18
#include "ircaccount.h"
19
#include "irccontact.h"
20
#include "ircprotocol.h"
22
#include "kopetemetacontact.h"
23
#include "kopeteview.h"
27
#include <kfiledialog.h>
32
QString IRCContact::user_caption() const
34
return i18n("%1 @ %2").arg(m_nickName).arg(kircEngine()->currentHost());
37
void IRCContact::user_updateStatus()
39
Kopete::OnlineStatus newStatus;
41
switch (kircEngine()->connectionState())
44
newStatus = m_protocol->m_UserStatusOffline;
47
case KIRC::Connecting:
48
case KIRC::Authentifying:
49
if (this == ircAccount()->mySelf())
50
newStatus = m_protocol->m_UserStatusConnecting;
52
newStatus = m_protocol->m_UserStatusOffline;
57
// newStatus = m_protocol->m_UserStatusAway;
58
// else if (m_isOnline)
59
newStatus = m_protocol->m_UserStatusOnline;
62
newStatus = m_protocol->m_UserStatusOffline;
65
newStatus = m_protocol->m_StatusUnknown;
68
// This may not be created yet ( for myself() on startup )
69
if( ircAccount()->contactManager() )
71
QValueList<IRCChannelContact*> channels = ircAccount()->contactManager()->findChannelsByMember(this);
73
for( QValueList<IRCChannelContact*>::iterator it = channels.begin(); it != channels.end(); ++it )
75
IRCChannelContact *channel = *it;
76
Kopete::OnlineStatus currentStatus = channel->manager()->contactOnlineStatus(this);
78
if( currentStatus.internalStatus() > IRCProtocol::Online )
80
if( !(currentStatus.internalStatus() & IRCProtocol::Away) && newStatus == m_protocol->m_UserStatusAway )
82
channel->manager()->setContactOnlineStatus(
83
this, m_protocol->statusLookup(
84
(IRCProtocol::IRCStatus)(currentStatus.internalStatus()+IRCProtocol::Away)
88
else if( (currentStatus.internalStatus() & IRCProtocol::Away) && newStatus == m_protocol->m_UserStatusOnline )
90
channel->manager()->setContactOnlineStatus(
91
this, m_protocol->statusLookup(
92
(IRCProtocol::IRCStatus)(currentStatus.internalStatus()-IRCProtocol::Away)
96
else if( newStatus.internalStatus() < IRCProtocol::Away )
98
channel->manager()->setContactOnlineStatus( this, newStatus );
103
setOnlineStatus( newStatus );
106
IRCUserContact::IRCUserContact(IRCContactManager *contactManager, const QString &nickname, Kopete::MetaContact *m )
107
: IRCContact(contactManager, nickname, m ),
110
setFileCapable(true);
112
mOnlineTimer = new QTimer( this );
113
m_isOnline = metaContact()->isTemporary();
115
QObject::connect(mOnlineTimer, SIGNAL(timeout()), this, SLOT(slotUserOffline()) );
117
QObject::connect(kircEngine(), SIGNAL(incomingChannelModeChange(QString,QString,QString)),
118
this, SLOT(slotIncomingModeChange(QString,QString,QString)));
122
mInfo.isOperator = false;
123
mInfo.isIdentified = false;
131
void IRCUserContact::sendFile(const KUrl &sourceURL, const QString&, unsigned int)
135
//If the file location is null, then get it from a file open dialog
136
if( !sourceURL.isValid() )
137
filePath = KFileDialog::getOpenFileName(QString::null, "*", 0l , i18n("Kopete File Transfer")); //krazy:exclude=nullstrassign for old broken gcc
139
filePath = sourceURL.path(-1);
141
kDebug(14120) << "File chosen to send:" << filePath;
143
if (!filePath.isEmpty())
144
kircEngine()->CtcpRequest_dcc( m_nickName, filePath, 0, KIRC::Transfer::FileOutgoing);
147
void IRCUserContact::slotUserOffline()
153
if( !metaContact()->isTemporary() )
154
kircEngine()->writeMessage( QString::fromLatin1("WHOWAS %1").arg(m_nickName) );
156
removeProperty( m_protocol->propUserInfo );
157
removeProperty( m_protocol->propServer );
158
removeProperty( m_protocol->propChannels );
161
void IRCUserContact::setAway(bool isAway)
167
void IRCUserContact::incomingUserIsAway(const QString &reason)
169
if( manager( Kopete::Contact::CannotCreate ) )
171
Kopete::Message msg( (Kopete::Contact*)ircAccount()->myServer(), mMyself,
172
i18n("%1 is away (%2)").arg( m_nickName ).arg( reason ),
173
Kopete::Message::Internal, Kopete::Message::RichText, CHAT_VIEW );
174
manager(Kopete::Contact::CanCreate)->appendMessage(msg);
178
void IRCUserContact::userOnline()
182
if (this != ircAccount()->mySelf() && !metaContact()->isTemporary() && ircAccount()->isConnected())
184
mOnlineTimer->start( 45000, true );
185
ircAccount()->setCurrentCommandSource(0);
186
kircEngine()->whois(m_nickName);
189
removeProperty( m_protocol->propLastSeen );
192
void IRCUserContact::slotUserInfo()
196
ircAccount()->setCurrentCommandSource(manager());
197
kircEngine()->whois(m_nickName);
201
void IRCUserContact::slotOp()
203
contactMode( QString::fromLatin1("+o") );
206
void IRCUserContact::slotDeop()
208
contactMode( QString::fromLatin1("-o") );
211
void IRCUserContact::slotVoice()
213
contactMode( QString::fromLatin1("+v") );
216
void IRCUserContact::slotDevoice()
218
contactMode( QString::fromLatin1("-v") );
221
void IRCUserContact::slotBanHost()
226
void IRCUserContact::slotBanUserHost()
231
void IRCUserContact::slotBanDomain()
236
void IRCUserContact::slotBanUserDomain()
241
void IRCUserContact::slotKick()
243
Kopete::ContactPtrList members = mActiveManager->members();
244
QString channelName = static_cast<IRCContact*>(members.first())->nickName();
245
kircEngine()->kick(m_nickName, channelName, QString());
248
void IRCUserContact::contactMode(const QString &mode)
250
Kopete::ContactPtrList members = mActiveManager->members();
251
QString channelName = static_cast<IRCContact*>(members.first())->nickName();
252
kircEngine()->mode(channelName, QString::fromLatin1("%1 %2").arg(mode).arg(m_nickName));
255
void IRCUserContact::slotCtcpPing()
257
kircEngine()->CtcpRequest_ping(m_nickName);
260
void IRCUserContact::slotCtcpVersion()
262
kircEngine()->CtcpRequest_version(m_nickName);
265
void IRCUserContact::newWhoIsUser(const QString &username, const QString &hostname, const QString &realname)
267
mInfo.channels.clear();
268
mInfo.userName = username;
269
mInfo.hostName = hostname;
270
mInfo.realName = realname;
272
if( onlineStatus().status() == Kopete::OnlineStatus::Offline )
274
setProperty( m_protocol->propUserInfo, QString::fromLatin1("%1@%2")
275
.arg(mInfo.userName).arg(mInfo.hostName) );
276
setProperty( m_protocol->propServer, mInfo.serverName );
277
setProperty( m_protocol->propFullName, mInfo.realName );
281
void IRCUserContact::newWhoIsServer(const QString &servername, const QString &serverinfo)
283
// if( metaContact()->isTemporary() || isOnline() )
284
if( metaContact()->isTemporary() || onlineStatus().status() != Kopete::OnlineStatus::Offline )
285
mInfo.serverInfo = serverinfo;
288
// Try to convert first, since server can return depending if
289
// user is online or not:
291
// 312 mynick othernick localhost.localdomain :FooNet Server
292
// 312 mynick othernick localhost.localdomain :Thu Jun 16 21:00:36 2005
294
QDateTime lastSeen = QDateTime::fromString( serverinfo );
295
if( lastSeen.isValid() )
296
setProperty( m_protocol->propLastSeen, lastSeen );
300
void IRCUserContact::newWhoIsIdle(unsigned long idle)
305
void IRCUserContact::newWhoIsOperator()
307
mInfo.isOperator = true;
310
void IRCUserContact::newWhoIsIdentified()
312
mInfo.isIdentified = true;
313
setProperty( m_protocol->propIsIdentified, i18n("True") );
316
void IRCUserContact::newWhoIsChannels(const QString &channel)
318
mInfo.channels.append( channel );
321
void IRCUserContact::whoIsComplete()
323
Kopete::ChatSession *commandSource = ircAccount()->currentCommandSource();
327
if( isChatting() && commandSource &&
328
commandSource == manager(Kopete::Contact::CannotCreate) )
331
QString msg = i18n("%1 is (%2@%3): %4<br/>")
335
.arg(mInfo.realName);
337
if( mInfo.isIdentified )
338
msg += i18n("%1 is authenticated with NICKSERV<br/>").arg(m_nickName);
340
if( mInfo.isOperator )
341
msg += i18n("%1 is an IRC operator<br/>").arg(m_nickName);
344
msg += i18n("on channels %1<br/>").arg(mInfo.channels.join(" ; "));
347
msg += i18n("on IRC via server %1 ( %2 )<br/>").arg(mInfo.serverName).arg(mInfo.serverInfo);
350
QString idleTime = formattedIdleTime();
351
msg += i18n("idle: %2<br/>").arg( idleTime.isEmpty() ? QString::number(0) : idleTime );
354
ircAccount()->appendMessage(msg, IRCAccount::InfoReply );
355
ircAccount()->setCurrentCommandSource(0);
359
void IRCUserContact::whoWasComplete()
361
if( isChatting() && ircAccount()->currentCommandSource() == manager() )
364
QString msg = i18n("%1 was (%2@%3): %4\n")
368
.arg(mInfo.realName);
370
msg += i18n("Last Online: %1\n").arg(
371
KGlobal::locale()->formatDateTime(
372
property( m_protocol->propLastSeen ).value().toDateTime()
376
ircAccount()->appendMessage(msg, IRCAccount::InfoReply );
377
ircAccount()->setCurrentCommandSource(0);
381
QString IRCUserContact::formattedName() const
383
return mInfo.realName;
386
void IRCUserContact::updateInfo()
388
setProperty( m_protocol->propUserInfo, QString::fromLatin1("%1@%2")
389
.arg(mInfo.userName).arg(mInfo.hostName) );
390
setProperty( m_protocol->propServer, mInfo.serverName );
391
setProperty( m_protocol->propChannels, mInfo.channels.join(" ") );
392
setProperty( m_protocol->propHops, QString::number(mInfo.hops) );
393
setProperty( m_protocol->propFullName, mInfo.realName );
395
setIdleTime( mInfo.idle );
397
mInfo.lastUpdate = QTime::currentTime();
400
void IRCUserContact::newWhoReply( const QString &channel, const QString &user, const QString &host,
401
const QString &server, bool away, const QString &flags, uint hops, const QString &realName )
403
if( !mInfo.channels.contains( channel ) )
404
mInfo.channels.append( channel );
406
mInfo.userName = user;
407
mInfo.hostName = host;
408
mInfo.serverName = server;
411
mInfo.realName = realName;
417
if( isChatting() && ircAccount()->currentCommandSource() == manager() )
419
ircAccount()->setCurrentCommandSource(0);
423
QPtrList<KAction> *IRCUserContact::customContextMenuActions( Kopete::ChatSession *manager )
427
QPtrList<KAction> *mCustomActions = new QPtrList<KAction> ();
428
mActiveManager = manager;
429
Kopete::ContactPtrList members = mActiveManager->members();
430
IRCChannelContact *isChannel = dynamic_cast<IRCChannelContact*>( members.first() );
432
if( !actionCtcpMenu )
434
actionCtcpMenu = new KActionMenu(i18n("C&TCP"), 0, this );
435
actionCtcpMenu->insert( new KAction(i18n("&Version"), 0, this,
436
SLOT(slotCtcpVersion()), actionCtcpMenu) );
437
actionCtcpMenu->insert( new KAction(i18n("&Ping"), 0, this,
438
SLOT(slotCtcpPing()), actionCtcpMenu) );
440
actionModeMenu = new KActionMenu(i18n("&Modes"), 0, this, "actionModeMenu");
441
actionModeMenu->insert( new KAction(i18n("&Op"), 0, this,
442
SLOT(slotOp()), actionModeMenu, "actionOp") );
443
actionModeMenu->insert( new KAction(i18n("&Deop"), 0, this,
444
SLOT(slotDeop()), actionModeMenu, "actionDeop") );
445
actionModeMenu->insert( new KAction(i18n("&Voice"), 0, this,
446
SLOT(slotVoice()), actionModeMenu, "actionVoice") );
447
actionModeMenu->insert( new KAction(i18n("Devoice"), 0, this,
448
SLOT(slotDevoice()), actionModeMenu, "actionDevoice") );
449
actionModeMenu->setEnabled( false );
451
actionKick = new KAction(i18n("&Kick"), 0, this, SLOT(slotKick()), this);
452
actionKick->setEnabled( false );
454
actionBanMenu = new KActionMenu(i18n("&Ban"), 0, this, "actionBanMenu");
455
actionBanMenu->insert( new KAction(i18n("Ban *!*@*.host"), 0, this,
456
SLOT(slotBanHost()), actionBanMenu ) );
457
actionBanMenu->insert( new KAction(i18n("Ban *!*@domain"), 0, this,
458
SLOT(slotBanDomain()), actionBanMenu ) );
459
actionBanMenu->insert( new KAction(i18n("Ban *!*user@*.host"), 0, this,
460
SLOT(slotBanUserHost()), actionBanMenu ) );
461
actionBanMenu->insert( new KAction(i18n("Ban *!*user@domain"), 0, this,
462
SLOT(slotBanUserDomain()), actionBanMenu ) );
463
actionBanMenu->setEnabled( false );
465
codecAction = new KCodecAction( i18n("&Encoding"), 0, this, "selectcharset" );
466
connect( codecAction, SIGNAL(activated(const QTextCodec*)),
467
this, SLOT(setCodec(const QTextCodec*)) );
468
codecAction->setCodec( codec() );
471
mCustomActions->append( actionCtcpMenu );
472
mCustomActions->append( actionModeMenu );
473
mCustomActions->append( actionKick );
474
mCustomActions->append( actionBanMenu );
475
mCustomActions->append( codecAction );
479
bool isOperator = ( manager->contactOnlineStatus( account()->myself() ) == m_protocol->m_UserStatusOp );
480
actionModeMenu->setEnabled(isOperator);
481
actionBanMenu->setEnabled(isOperator);
482
actionKick->setEnabled(isOperator);
485
return mCustomActions;
493
void IRCUserContact::slotIncomingModeChange( const QString &channel, const QString &, const QString &mode )
495
IRCChannelContact *chan = ircAccount()->contactManager()->findChannel( channel );
496
if( chan->locateUser( m_nickName ) )
498
QString user = mode.section(' ', 1, 1);
499
kDebug(14120) << mode << ", " << user << ", " << m_nickName;
500
if( user == m_nickName )
502
QString modeChange = mode.section(' ', 0, 0);
503
if(modeChange == QString::fromLatin1("+o"))
504
setManagerStatus( chan, m_protocol->m_UserStatusOp.internalStatus() );
505
else if(modeChange == QString::fromLatin1("-o"))
506
setManagerStatus( chan, -m_protocol->m_UserStatusOp.internalStatus() );
507
else if(modeChange == QString::fromLatin1("+v"))
508
setManagerStatus( chan, m_protocol->m_UserStatusVoice.internalStatus() );
509
else if(modeChange == QString::fromLatin1("-v"))
510
setManagerStatus( chan, -m_protocol->m_UserStatusVoice.internalStatus() );
515
void IRCUserContact::setManagerStatus(IRCChannelContact *channel, int statusAdjustment)
517
Kopete::OnlineStatus currentStatus = channel->manager()->contactOnlineStatus(this);
518
Kopete::OnlineStatus newStatus = m_protocol->statusLookup(
519
(IRCProtocol::IRCStatus)(currentStatus.internalStatus() + statusAdjustment)
522
channel->manager()->setContactOnlineStatus(this, newStatus);