/* irccontact.cpp - IRC Contact Copyright (c) 2002 by Nick Betcher Copyright (c) 2004 by Michel Hermier Copyright (c) 2005 by Tommi Rantala Kopete (c) 2002-2005 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 #include #include #include #include #include "ircaccount.h" #include "kopeteglobal.h" #include "kopeteuiglobal.h" #include "kopetemetacontact.h" #include "kopeteview.h" #include "ircusercontact.h" #include "irccontact.h" #include "ircprotocol.h" #include "ircservercontact.h" #include "irccontactmanager.h" #include "ksparser.h" IRCContact::IRCContact(IRCAccount *account, KIRC::EntityPtr entity, Kopete::MetaContact *metac, const TQString& icon) : Kopete::Contact(account, entity->name(), metac, icon), m_chatSession(0) { } IRCContact::IRCContact(IRCContactManager *contactManager, const TQString &nick, Kopete::MetaContact *metac, const TQString& icon) : Kopete::Contact(contactManager->account(), nick, metac, icon), m_nickName(nick), m_chatSession(0) { KIRC::Engine *engine = kircEngine(); // Contact list display name setProperty( Kopete::Global::Properties::self()->nickName(), m_nickName ); // IRCContactManager stuff TQObject::connect(contactManager, TQT_SIGNAL(privateMessage(IRCContact *, IRCContact *, const TQString &)), this, TQT_SLOT(privateMessage(IRCContact *, IRCContact *, const TQString &))); // Kopete::ChatSessionManager stuff mMyself.append( static_cast( this ) ); // KIRC stuff TQObject::connect(engine, TQT_SIGNAL(incomingNickChange(const TQString &, const TQString &)), this, TQT_SLOT( slotNewNickChange(const TQString&, const TQString&))); TQObject::connect(engine, TQT_SIGNAL(successfullyChangedNick(const TQString &, const TQString &)), this, TQT_SLOT(slotNewNickChange(const TQString &, const TQString &))); TQObject::connect(engine, TQT_SIGNAL(incomingQuitIRC(const TQString &, const TQString &)), this, TQT_SLOT( slotUserDisconnected(const TQString&, const TQString&))); TQObject::connect(engine, TQT_SIGNAL(statusChanged(KIRC::Engine::tqStatus)), this, TQT_SLOT(updatetqStatus())); engine->setCodec( m_nickName, codec() ); } IRCContact::~IRCContact() { // kdDebug(14120) << k_funcinfo << m_nickName << endl; if (metaContact() && metaContact()->isTemporary() && !isChatting(m_chatSession)) metaContact()->deleteLater(); emit destroyed(this); } IRCAccount *IRCContact::ircAccount() const { return static_cast(account()); } KIRC::Engine *IRCContact::kircEngine() const { return ircAccount()->engine(); } bool IRCContact::isReachable() { if (onlinetqStatus().status() != Kopete::OnlineStatus::Offline && onlinetqStatus().status() != Kopete::OnlineStatus::Unknown) return true; return false; } const TQString IRCContact::caption() const { return TQString(); } /* const TQString IRCContact::formatedName() const { return TQString(); } */ void IRCContact::updatetqStatus() { } void IRCContact::privateMessage(IRCContact *, IRCContact *, const TQString &) { } void IRCContact::setCodec(const TQTextCodec *codec) { kircEngine()->setCodec(m_nickName, codec); metaContact()->setPluginData(m_protocol, TQString::tqfromLatin1("Codec"), TQString::number(codec->mibEnum())); } const TQTextCodec *IRCContact::codec() { TQString codecId = metaContact()->pluginData(m_protocol, TQString::tqfromLatin1("Codec")); TQTextCodec *codec = ircAccount()->codec(); if( !codecId.isEmpty() ) { bool test = true; uint mib = codecId.toInt(&test); if (test) codec = TQTextCodec::codecForMib(mib); else codec = TQTextCodec::codecForName(codecId.latin1()); } if( !codec ) return kircEngine()->codec(); return codec; } Kopete::ChatSession *IRCContact::manager(Kopete::Contact::CanCreateFlags canCreate) { IRCAccount *account = ircAccount(); KIRC::Engine *engine = kircEngine(); if (canCreate == Kopete::Contact::CanCreate && !m_chatSession) { if( engine->status() == KIRC::Engine::Idle && dynamic_cast(this) == 0 ) account->connect(); m_chatSession = Kopete::ChatSessionManager::self()->create(account->myself(), mMyself, account->protocol()); m_chatSession->setDisplayName(caption()); TQObject::connect(m_chatSession, TQT_SIGNAL(messageSent(Kopete::Message&, Kopete::ChatSession *)), this, TQT_SLOT(slotSendMsg(Kopete::Message&, Kopete::ChatSession *))); TQObject::connect(m_chatSession, TQT_SIGNAL(closing(Kopete::ChatSession *)), this, TQT_SLOT(chatSessionDestroyed())); initConversation(); } return m_chatSession; } void IRCContact::chatSessionDestroyed() { m_chatSession = 0; if (metaContact()->isTemporary() && !isChatting()) deleteLater(); } void IRCContact::slotUserDisconnected(const TQString &user, const TQString &reason) { if (m_chatSession) { TQString nickname = user.section('!', 0, 0); Kopete::Contact *c = locateUser( nickname ); if ( c ) { m_chatSession->removeContact(c, i18n("Quit: \"%1\" ").tqarg(reason), Kopete::Message::RichText); c->setOnlineStatus(m_protocol->m_UserStatusOffline); } } } void IRCContact::setNickName( const TQString &nickname ) { kdDebug(14120) << k_funcinfo << m_nickName << " changed to " << nickname << endl; m_nickName = nickname; Kopete::Contact::setNickName( nickname ); } void IRCContact::slotNewNickChange(const TQString &oldnickname, const TQString &newnickname) { IRCAccount *account = ircAccount(); IRCContact *user = static_cast( locateUser(oldnickname) ); if( user ) { user->setNickName( newnickname ); //If the user is in our contact list, then change the notify list nickname if (!user->metaContact()->isTemporary()) { account->contactManager()->removeFromNotifyList( oldnickname ); account->contactManager()->addToNotifyList( newnickname ); } } } void IRCContact::slotSendMsg(Kopete::Message &message, Kopete::ChatSession *) { TQString htmlString = message.escapedBody(); // Messages we get with RichText enabled: // // Hello world in bold and color: // Hello World // // Two-liner in color: // Hello
World
if (htmlString.tqfind(TQString::tqfromLatin1(" -1) { TQRegExp findTags( TQString::tqfromLatin1("(.*)") ); findTags.setMinimal( true ); int pos = 0; while (pos >= 0) { pos = findTags.search(htmlString); if (pos > -1) { TQString styleHTML = findTags.cap(1); TQString replacement = findTags.cap(2); TQStringList styleAttrs = TQStringList::split(';', styleHTML); for (TQStringList::Iterator attrPair = styleAttrs.begin(); attrPair != styleAttrs.end(); ++attrPair) { TQString attribute = (*attrPair).section(':',0,0); TQString value = (*attrPair).section(':',1); if( attribute == TQString::tqfromLatin1("color") ) { int ircColor = KSParser::colorForHTML( value ); if( ircColor > -1 ) replacement.prepend( TQString( TQChar(0x03) ).append( TQString::number(ircColor) ) ).append( TQChar( 0x03 ) ); } else if( attribute == TQString::tqfromLatin1("font-weight") && value == TQString::tqfromLatin1("600") ) { // Bolding replacement.prepend( TQChar(0x02) ).append( TQChar(0x02) ); } else if( attribute == TQString::tqfromLatin1("text-decoration") && value == TQString::tqfromLatin1("underline") ) { replacement.prepend( TQChar(31) ).append( TQChar(31) ); } } htmlString = htmlString.left( pos ) + replacement + htmlString.mid( pos + findTags.matchedLength() ); } } } htmlString = Kopete::Message::unescape(htmlString); TQStringList messages = TQStringList::split( '\n', htmlString ); for( TQStringList::Iterator it = messages.begin(); it != messages.end(); ++it ) { // Dont use the resulting string(s). The problem is that we'd have to parse them // back to format that would be suitable for appendMessage(). // // TODO: If the given message was plaintext, we could easily show what was // actually sent. sendMessage(*it); } if (message.requestedPlugin() != CHAT_VIEW) { Kopete::Message msg(message.from(), message.to(), message.escapedBody(), message.direction(), Kopete::Message::RichText, CHAT_VIEW, message.type()); msg.setBg(TQColor()); msg.setFg(TQColor()); appendMessage(msg); } else { // Lets not modify the given message object. Kopete::Message msg = message; msg.setBg(TQColor()); appendMessage(msg); } manager(Kopete::Contact::CanCreate)->messageSucceeded(); } TQStringList IRCContact::sendMessage( const TQString &msg ) { TQStringList messages; TQString newMessage = msg; // IRC limits the message size to 512 characters. So split the given // message into pieces. // // This can of course give nasty results, but most of us dont write // that long lines anyway ;-)... And this is how other clients also // seem to behave. int l = 500 - m_nickName.length(); do { messages.append(newMessage.mid(0, l)); newMessage.remove(0, l); } while (!newMessage.isEmpty()); for (TQStringList::const_iterator it = messages.begin(); it != messages.end(); ++it) kircEngine()->privmsg(m_nickName, *it); return messages; } Kopete::Contact *IRCContact::locateUser(const TQString &nick) { IRCAccount *account = ircAccount(); if (m_chatSession) { if( nick == account->mySelf()->nickName() ) return account->mySelf(); else { Kopete::ContactPtrList mMembers = m_chatSession->members(); for (Kopete::Contact *it = mMembers.first(); it; it = mMembers.next()) { if (static_cast(it)->nickName() == nick) return it; } } } return 0; } bool IRCContact::isChatting(const Kopete::ChatSession *avoid) const { IRCAccount *account = ircAccount(); if (!account) return false; TQValueList sessions = Kopete::ChatSessionManager::self()->sessions(); for (TQValueList::Iterator it= sessions.begin(); it!=sessions.end() ; ++it) { if( (*it) != avoid && (*it)->account() == account && (*it)->members().tqcontains(this) ) { return true; } } return false; } void IRCContact::deleteContact() { kdDebug(14120) << k_funcinfo << m_nickName << endl; delete m_chatSession; if (!isChatting()) { kdDebug(14120) << k_funcinfo << "will delete " << m_nickName << endl; Kopete::Contact::deleteContact(); } else { metaContact()->removeContact(this); Kopete::MetaContact *m = new Kopete::MetaContact(); m->setTemporary(true); setMetaContact(m); } } void IRCContact::appendMessage(Kopete::Message &msg) { manager(Kopete::Contact::CanCreate)->appendMessage(msg); } KopeteView *IRCContact::view() { if (m_chatSession) return m_chatSession->view(false); return 0L; } void IRCContact::serialize(TQMap & /*serializedData*/, TQMap &addressBookData) { // write the addressBookData[ protocol()->addressBookIndexField() ] = ( contactId() + TQChar(0xE120) + account()->accountId() ); } void IRCContact::receivedMessage( KIRC::Engine::ServerMessageType type, const KIRC::EntityPtr &from, const KIRC::EntityPtrList &to, const TQString &msg) { if (to.tqcontains(m_entity)) { IRCContact *fromContact = ircAccount()->getContact(from); Kopete::Message message(fromContact, manager()->members(), msg, Kopete::Message::Inbound, Kopete::Message::RichText, CHAT_VIEW); appendMessage(message); } } #include "irccontact.moc"