begin my work on the IRC-protocol, making the editaccount dialog and the network...
[kdenetwork.git] / kopete / protocols / irc / irccontact.cpp
blob98d040e24dc37b62e0f6e41134eb71420c82e46e
1 /*
2 irccontact.cpp - IRC Contact
4 Copyright (c) 2002 by Nick Betcher <nbetcher@kde.org>
5 Copyright (c) 2004-2007 by Michel Hermier <michel.hermier@gmail.com>
7 Kopete (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
9 *************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 *************************************************************************
19 #include "irccontact.moc"
21 #include "ircaccount.h"
22 #include "ircprotocol.h"
23 #include "ksparser.h"
25 #include "kircclientsocket.h"
26 #include "kircentity.h"
28 #include "kopetechatsessionmanager.h"
29 #include "kopeteglobal.h"
30 #include "kopeteuiglobal.h"
31 #include "kopetemetacontact.h"
32 #include "kopeteview.h"
34 #include <kdebug.h>
35 #include <klocale.h>
36 #include <qregexp.h>
38 #include <qtimer.h>
39 #include <qtextcodec.h>
41 using namespace IRC;
42 using namespace Kopete;
44 class IRCContact::Private
46 public:
47 KIrc::Entity::Ptr entity;
49 QMap<ChatSessionType, ChatSession *> chatSessions;
51 // QList<IRContact *> members;
53 // QList<Kopete::Contact *> mMyself;
54 Kopete::Message::MessageDirection execDir;
56 QList<KAction *> actions;
57 QList<KAction *> serverActions;
58 QList<KAction *> channelActions;
59 QList<KAction *> userActions;
62 IRCContact::IRCContact(IRCAccount *account, const KIrc::Entity::Ptr &entity, MetaContact *metac, const QString& icon)
63 : Contact(account, entity->name(), metac, icon)
64 , d (new IRCContact::Private)
66 Q_ASSERT(entity);
68 kDebug(14120) <<"Entity name: "<< entity->name();
70 d->entity = entity;
72 if (!metac)
74 metac = new MetaContact();
75 metac->setTemporary(true);
76 setMetaContact(metac);
79 KIrc::ClientSocket *client = kircClient();
81 // ChatSessionManager stuff
82 // mMyself.append( static_cast<Contact*>( this ) );
84 // KIRC stuff
85 connect(client, SIGNAL(connectionStateChanged(KIrc::ConnectionState)),
86 this, SLOT(updateStatus()));
88 connect(entity, SIGNAL(updated()),
89 this, SLOT(entityUpdated()));
91 entityUpdated();
94 IRCContact::~IRCContact()
96 // kDebug(14120) << entity->name();
97 // if (metaContact() && metaContact()->isTemporary() && !isChatting(m_chatSession))
98 // metaContact()->deleteLater();
100 emit destroyed(this);
102 delete d;
105 void IRCContact::deleteContact()
107 // delete m_chatSession; // qDeleteAll(d->chatSessions) ?
109 if (!isChatting())
111 Contact::deleteContact();
113 else
115 metaContact()->removeContact(this);
116 MetaContact *m = new MetaContact();
117 m->setTemporary(true);
118 setMetaContact(m);
122 IRCAccount *IRCContact::ircAccount() const
124 return static_cast<IRCAccount *>(account());
127 KIrc::ClientSocket *IRCContact::kircClient() const
129 return ircAccount()->client();
132 void IRCContact::entityUpdated()
134 Global::Properties *prop = Global::Properties::self();
136 // Basic entity properties.
137 setProperty(prop->nickName(), d->entity->name());
138 // setProperty(???->serverName(), d->entity->server());
139 // setProperty(???->type(), d->entity->type());
141 // Server properties
143 // Channel properties
144 // setProperty(???->topic(), d->entity->topic());
146 // Contact properties
148 // Update Icon properties
149 switch(m_entity->type())
151 // case KIrc::Entity::Unknown: // Use default
152 case KIrc::Entity::Server:
153 setIcon("irc_server");
154 break;
155 case KIrc::Entity::Channel:
156 setIcon("irc_channel");
157 break;
158 // case KIrc::Entity::Service: // Use default for now
159 // setIcon("irc_service");
160 // break;
161 case KIrc::Entity::User:
162 setIcon("irc_user");
163 break;
164 default:
165 // setIcon("irc_unknown");
166 setIcon(QString::null); //krazy:exclude=nullstrassign for old broken gcc
167 break;
170 updateStatus();
173 QString IRCContact::caption() const
176 QString caption = QString::fromLatin1("%1 @ %2")
177 .arg(d->entity->name()) // nickName
178 .arg(ircAccount()->networkName());
180 QString topic = d->entity->topic();
181 if(!topic.isEmpty())
182 caption.append( QString::fromLatin1(" - %1").arg(Kopete::Message::unescape(topic)) );
184 return caption;
186 return QLatin1String("FIXME");
189 void IRCContact::updateStatus()
191 setOnlineStatus(IRCProtocol::self()->onlineStatusFor(d->entity));
194 bool IRCContact::isReachable()
196 if (onlineStatus().status() != OnlineStatus::Offline &&
197 onlineStatus().status() != OnlineStatus::Unknown)
198 return true;
200 return false;
203 void IRCContact::setCodec(QTextCodec *codec)
205 d->entity->setCodec(codec);
206 if (codec)
207 metaContact()->setPluginData(IRCProtocol::self(), QString::fromLatin1("Codec"), QString::number(codec->mibEnum()));
208 // else
209 // metaContact()->removePluginData(m_protocol, QString::fromLatin1("Codec"));
212 QTextCodec *IRCContact::codec()
214 QString codecId = metaContact()->pluginData(IRCProtocol::self(), QString::fromLatin1("Codec"));
215 QTextCodec *codec = ircAccount()->codec();
217 if( !codecId.isEmpty() )
219 bool test = true;
220 uint mib = codecId.toInt(&test);
221 if (test)
222 codec = QTextCodec::codecForMib(mib);
223 else
224 codec = QTextCodec::codecForName(codecId.toLatin1());
227 #if 0
228 // FIXME: use context defaultCodec
229 if (!codec)
230 return kircClient()->defaultCodec();
231 #endif
233 return codec;
236 ChatSession *IRCContact::manager(CanCreateFlags create)
238 return chatSession(IRC::SERVER, create);
241 ChatSession *IRCContact::chatSession(IRC::ChatSessionType type, CanCreateFlags create)
243 IRCAccount *account = ircAccount();
244 KIrc::ClientSocket *engine = kircClient();
246 Kopete::ChatSession *chatSession = d->chatSessions.get();
247 if (!chatSession)
249 // if (engine->status() == KIrc::ClientSocket::Idle && dynamic_cast<IRCServerContact*>(this) == 0)
250 // account->connect();
252 chatSession = ChatSessionManager::self()->create(account->myself(), mMyself, account->protocol());
253 chatSession->setDisplayName(caption());
255 connect(chatSession, SIGNAL(messageSent(Message&, ChatSession *)),
256 this, SLOT(slotSendMsg(Message&, ChatSession *)));
257 connect(chatSession, SIGNAL(closing(ChatSession *)),
258 this, SLOT(chatSessionDestroyed(ChatSession *)));
260 d->chatSessions.add(type, chatSession);
263 return chatSession;
265 return 0;
268 void IRCContact::chatSessionDestroyed(ChatSession *chatSession)
270 // m_chatSession = 0; // d->chatSessions.remove(chatSession);
272 if (metaContact()->isTemporary() && !isChatting())
273 deleteLater();
276 void IRCContact::slotSendMsg(Message &message, ChatSession *chatSession)
278 QString htmlString = message.escapedBody();
280 if (htmlString.indexOf(QString::fromLatin1("</span")) > -1)
282 QRegExp findTags( QString::fromLatin1("<span style=\"(.*)\">(.*)</span>") );
283 findTags.setMinimal( true );
284 int pos = 0;
286 while (pos >= 0)
288 pos = findTags.indexIn(htmlString);
289 if (pos > -1)
291 QString styleHTML = findTags.cap(1);
292 QString replacement = findTags.cap(2);
293 QStringList styleAttrs = styleHTML.split(';');
295 for (QStringList::Iterator attrPair = styleAttrs.begin(); attrPair != styleAttrs.end(); ++attrPair)
297 QString attribute = (*attrPair).section(':',0,0);
298 QString value = (*attrPair).section(':',1);
300 if( attribute == QString::fromLatin1("color") )
302 int ircColor = KSParser::colorForHTML( value );
303 if( ircColor > -1 )
304 replacement.prepend( QString( QChar(0x03) ).append( QString::number(ircColor) ) ).append( QChar( 0x03 ) );
306 else if( attribute == QString::fromLatin1("font-weight") && value == QString::fromLatin1("600") )
307 replacement.prepend( QChar(0x02) ).append( QChar(0x02) );
308 else if( attribute == QString::fromLatin1("text-decoration") && value == QString::fromLatin1("underline") )
309 replacement.prepend( QChar(31) ).append( QChar(31) );
312 htmlString = htmlString.left( pos ) + replacement + htmlString.mid( pos + findTags.matchedLength() );
317 htmlString = Message::unescape(htmlString);
319 if (htmlString.indexOf('\n') > -1)
321 QStringList messages = htmlString.split('\n');
323 for( QStringList::Iterator it = messages.begin(); it != messages.end(); ++it )
325 #warning FIXME
326 Message msg(message.from(), message.to());
327 msg.setHtmlBody(Kopete::Message::escape(sendMessage(*it)));
328 msg.setDirection(message.direction());
329 // Message::RichText, CHAT_VIEW, message.type());
331 // msg.setBackgroundColor(QColor());
332 // msg.setForegroundColor(QColor());
334 appendMessage(msg);
335 chatSession->messageSucceeded();
338 else
340 message.setHtmlBody(Kopete::Message::escape(sendMessage(htmlString)));
342 // message.setBackgroundColor(QColor());
343 // message.setForegroundColor(QColor());
345 appendMessage(message);
346 chatSession->messageSucceeded();
350 QString IRCContact::sendMessage(const QString &msg)
353 QString newMessage = msg;
354 uint trueLength = msg.length() + m_nickName.length() + 12;
355 if( trueLength > 512 )
357 //TODO: tell them it is truncated
358 kWarning() << "Message was to long (" << trueLength << "), it has been truncated to 512 characters";
359 newMessage.truncate( 512 - ( m_nickName.length() + 12 ) );
362 kircClient()->privmsg(m_nickName, newMessage );
364 return newMessage;
366 return QString();
369 Contact *IRCContact::locateUser(const QString &nick)
372 IRCAccount *account = ircAccount();
374 if (m_chatSession)
376 if( nick == account->mySelf()->nickName() )
377 return account->mySelf();
378 else
380 ContactPtrList mMembers = m_chatSession->members();
381 for (Contact *it = mMembers.first(); it; it = mMembers.next())
383 if (static_cast<IRCContact*>(it)->nickName() == nick)
384 return it;
389 return 0;
392 bool IRCContact::isChatting(ChatSession *avoid) const
394 IRCAccount *account = ircAccount();
396 if (!account)
397 return false;
399 foreach (ChatSession *chatSession, ChatSessionManager::self()->sessions())
402 if( chatSession != avoid &&
403 chatSession->account() == account &&
404 chatSession->members().contains(this) )
406 return true;
410 return false;
413 void IRCContact::appendMessage(Message &msg)
415 // manager(Contact::CanCreate)->appendMessage(msg);
418 void IRCServerContact::appendMessage(Kopete::Message &msg)
420 msg.setImportance( Kopete::Message::Low ); //to don't distrub the user
422 if (m_chatSession && m_chatSession->view(false))
423 m_chatSession->appendMessage(msg);
424 else
425 mMsgBuffer.append( msg );
429 void IRCContact::serialize(QMap<QString, QString> & /*serializedData*/, QMap<QString, QString> &addressBookData)
431 addressBookData[protocol()->addressBookIndexField()] = contactId() + QChar(0xE120) + account()->accountId();