summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/irc/ircaccount.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/irc/ircaccount.cpp')
-rw-r--r--kopete/protocols/irc/ircaccount.cpp904
1 files changed, 904 insertions, 0 deletions
diff --git a/kopete/protocols/irc/ircaccount.cpp b/kopete/protocols/irc/ircaccount.cpp
new file mode 100644
index 00000000..1a1bf75f
--- /dev/null
+++ b/kopete/protocols/irc/ircaccount.cpp
@@ -0,0 +1,904 @@
+/*
+ ircaccount.cpp - IRC Account
+
+ Copyright (c) 2002 by Nick Betcher <nbetcher@kde.org>
+ Copyright (c) 2003-2004 by Jason Keirstead <jason@keirstead.org>
+ Copyright (c) 2003-2005 by Michel Hermier <michel.hermier@wanadoo.fr>
+
+ Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * 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 "ircaccount.h"
+#include "irccontact.h"
+#include "irccontactmanager.h"
+#include "ircprotocol.h"
+
+#include "ircservercontact.h"
+#include "ircchannelcontact.h"
+#include "ircusercontact.h"
+
+#include "channellistdialog.h"
+
+#include "kircengine.h"
+
+#include "kopeteaccountmanager.h"
+#include "kopeteaway.h"
+#include "kopeteawayaction.h"
+#include "kopetecommandhandler.h"
+#include "kopetecontactlist.h"
+#include "kopetemetacontact.h"
+#include "kopeteuiglobal.h"
+#include "kopeteview.h"
+#include "kopetepassword.h"
+
+#include <kaction.h>
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcompletionbox.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kinputdialog.h>
+#include <klineedit.h>
+#include <klineeditdlg.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <kpopupmenu.h>
+
+#include <qlayout.h>
+#include <qtimer.h>
+
+const QString IRCAccount::CONFIG_CODECMIB = QString::fromLatin1("Codec");
+const QString IRCAccount::CONFIG_NETWORKNAME = QString::fromLatin1("NetworkName");
+const QString IRCAccount::CONFIG_NICKNAME = QString::fromLatin1("NickName");
+const QString IRCAccount::CONFIG_USERNAME = QString::fromLatin1("UserName");
+const QString IRCAccount::CONFIG_REALNAME = QString::fromLatin1("RealName");
+
+IRCAccount::IRCAccount(IRCProtocol *protocol, const QString &accountId, const QString &autoChan, const QString& netName, const QString &nickName)
+ : Kopete::PasswordedAccount(protocol, accountId, 0, true), autoConnect( autoChan ), commandSource(0)
+{
+ m_manager = 0L;
+ m_channelList = 0L;
+ m_network = 0L;
+
+ triedAltNick = false;
+
+ m_contactManager = 0;
+ m_engine = new KIRC::Engine(this);
+
+ QMap< QString, QString> replies = customCtcpReplies();
+ for( QMap< QString, QString >::ConstIterator it = replies.begin(); it != replies.end(); ++it )
+ m_engine->addCustomCtcp( it.key(), it.data() );
+
+ QString version=i18n("Kopete IRC Plugin %1 [http://kopete.kde.org]").arg(kapp->aboutData()->version());
+ m_engine->setVersionString( version );
+
+ QObject::connect(m_engine, SIGNAL(successfullyChangedNick(const QString &, const QString &)),
+ this, SLOT(successfullyChangedNick(const QString &, const QString &)));
+
+ QObject::connect(m_engine, SIGNAL(incomingFailedServerPassword()),
+ this, SLOT(slotFailedServerPassword()));
+
+ QObject::connect(m_engine, SIGNAL(incomingNickInUse(const QString &)),
+ this, SLOT(slotNickInUseAlert( const QString &)) );
+
+ QObject::connect(m_engine, SIGNAL(incomingFailedNickOnLogin(const QString &)),
+ this, SLOT(slotNickInUse( const QString &)) );
+
+ QObject::connect(m_engine, SIGNAL(incomingJoinedChannel(const QString &, const QString &)),
+ this, SLOT(slotJoinedUnknownChannel(const QString &, const QString &)));
+
+ QObject::connect(m_engine, SIGNAL(incomingCtcpReply(const QString &, const QString &, const QString &)),
+ this, SLOT( slotNewCtcpReply(const QString&, const QString &, const QString &)));
+
+ QObject::connect(m_engine, SIGNAL(statusChanged(KIRC::Engine::Status)),
+ this, SLOT(engineStatusChanged(KIRC::Engine::Status)));
+
+ QObject::connect(m_engine, SIGNAL(incomingServerLoadTooHigh()),
+ this, SLOT(slotServerBusy()));
+
+ QObject::connect(m_engine, SIGNAL(incomingNoSuchNickname(const QString &)),
+ this, SLOT(slotNoSuchNickname(const QString &)));
+
+ mAwayAction = new Kopete::AwayAction ( i18n("Set Away"),
+ m_protocol->m_UserStatusAway.iconFor( this ), 0, this,
+ SLOT(slotGoAway( const QString & )), this );
+
+ currentHost = 0;
+
+ KConfigGroup *config = configGroup();
+
+ QString networkName = netName;
+ if (networkName.isNull())
+ networkName = config->readEntry(CONFIG_NETWORKNAME);
+
+ if (!nickName.isNull())
+ setNickName(nickName);
+ else
+ mNickName = config->readEntry(CONFIG_NICKNAME);
+
+ QString codecMib = config->readEntry(CONFIG_CODECMIB);
+ // int codecMib = config->readNumEntry(CONFIG_CODECMIB, UTF-8);
+
+ m_serverNotices = (MessageDestination)config->readNumEntry( "ServerNotices", ServerWindow );
+ m_serverMessages = (MessageDestination)config->readNumEntry( "ServerMessages", ServerWindow );
+ m_informationReplies = (MessageDestination)config->readNumEntry( "InformationReplies", ActiveWindow );
+ m_errorMessages = (MessageDestination)config->readNumEntry( "ErrorMessages", ActiveWindow );
+ autoShowServerWindow = config->readBoolEntry( "AutoShowServerWindow", false );
+
+ if( !codecMib.isEmpty() )
+ {
+ mCodec = QTextCodec::codecForMib( codecMib.toInt() );
+ m_engine->setDefaultCodec( mCodec );
+ }
+ else
+ mCodec = 0;
+
+ QString m_accountId = this->accountId();
+ if( networkName.isEmpty() && QRegExp( "[^#+&\\s]+@[\\w-\\.]+:\\d+" ).exactMatch( m_accountId ) )
+ {
+ kdDebug(14120) << "Creating account from " << m_accountId << endl;
+
+ mNickName = m_accountId.section('@',0,0);
+ QString serverInfo = m_accountId.section('@',1);
+ QString hostName = serverInfo.section(':',0,0);
+
+ for( QDictIterator<IRCNetwork> it( m_protocol->networks() ); it.current(); ++it )
+ {
+ IRCNetwork *net = it.current();
+ for( QValueList<IRCHost*>::iterator it2 = net->hosts.begin(); it2 != net->hosts.end(); ++it2 )
+ {
+ if( (*it2)->host == hostName )
+ {
+ setNetwork(net->name);
+ break;
+ }
+ }
+
+ if( !networkName.isEmpty() )
+ break;
+ }
+
+ if( networkName.isEmpty() )
+ {
+ /* Could not find this host. Add it to the networks structure */
+
+ m_network = new IRCNetwork;
+ m_network->name = i18n("Temporary Network - %1").arg( hostName );
+ m_network->description = i18n("Network imported from previous version of Kopete, or an IRC URI");
+
+ IRCHost *host = new IRCHost;
+ host->host = hostName;
+ host->port = serverInfo.section(':',1).toInt();
+ if( !password().cachedValue().isEmpty() )
+ host->password = password().cachedValue();
+ host->ssl = false;
+
+ m_network->hosts.append( host );
+ m_protocol->addNetwork( m_network );
+
+ config->writeEntry(CONFIG_NETWORKNAME, m_network->name);
+ config->writeEntry(CONFIG_NICKNAME, mNickName);
+ }
+ }
+ else if( !networkName.isEmpty() )
+ {
+ setNetwork(networkName);
+ }
+ else
+ {
+ kdError() << "No network name defined, and could not import network information from ID" << endl;
+ }
+
+ m_engine->setUserName(userName());
+ m_engine->setRealName(realName());
+
+ m_contactManager = new IRCContactManager(mNickName, this);
+ setMyself( m_contactManager->mySelf() );
+ setAccountLabel( QString::fromLatin1("%1@%2").arg(mNickName,networkName) );
+ m_myServer = m_contactManager->myServer();
+
+ m_joinChannelAction = new KAction ( i18n("Join Channel..."), QString::null, 0, this,
+ SLOT(slotJoinChannel()), this);
+ m_searchChannelAction = new KAction ( i18n("Search Channels..."), QString::null, 0, this,
+ SLOT(slotSearchChannels()), this);
+}
+
+IRCAccount::~IRCAccount()
+{
+ if (m_engine->isConnected())
+ m_engine->quit(i18n("Plugin Unloaded"), true);
+}
+
+void IRCAccount::slotNickInUse( const QString &nick )
+{
+ QString altNickName = altNick();
+ if( triedAltNick || altNickName.isEmpty() )
+ {
+ QString newNick = KInputDialog::getText(
+ i18n("IRC Plugin"),
+ i18n("The nickname %1 is already in use. Please enter an alternate nickname:").arg(nick),
+ nick);
+
+ if (newNick.isNull())
+ disconnect();
+ else
+ m_engine->nick(newNick);
+ }
+ else
+ {
+ triedAltNick = true;
+ m_engine->nick(altNickName);
+ }
+}
+
+void IRCAccount::slotNickInUseAlert( const QString &nick )
+{
+ KMessageBox::error(Kopete::UI::Global::mainWidget(), i18n("The nickname %1 is already in use").arg(nick), i18n("IRC Plugin"));
+}
+
+void IRCAccount::setAltNick( const QString &altNick )
+{
+ configGroup()->writeEntry(QString::fromLatin1( "altNick" ), altNick);
+}
+
+const QString IRCAccount::altNick() const
+{
+ return configGroup()->readEntry(QString::fromLatin1("altNick"));
+}
+
+void IRCAccount::setAutoShowServerWindow( bool show )
+{
+ autoShowServerWindow = show;
+ configGroup()->writeEntry(QString::fromLatin1( "AutoShowServerWindow" ), autoShowServerWindow);
+}
+
+const QString IRCAccount::networkName() const
+{
+ if( m_network )
+ return m_network->name;
+ else
+ return i18n("Unknown");
+}
+
+void IRCAccount::setUserName( const QString &userName )
+{
+ m_engine->setUserName(userName);
+ configGroup()->writeEntry(CONFIG_USERNAME, userName);
+}
+
+const QString IRCAccount::userName() const
+{
+ return configGroup()->readEntry(CONFIG_USERNAME);
+}
+
+void IRCAccount::setRealName( const QString &userName )
+{
+ m_engine->setRealName(userName);
+ configGroup()->writeEntry(CONFIG_REALNAME, userName);
+}
+
+const QString IRCAccount::realName() const
+{
+ return configGroup()->readEntry(CONFIG_REALNAME);
+}
+
+void IRCAccount::setNetwork( const QString &network )
+{
+ IRCNetwork *net = m_protocol->networks()[ network ];
+ if( net )
+ {
+ m_network = net;
+ configGroup()->writeEntry(CONFIG_NETWORKNAME, network);
+ setAccountLabel(network);
+ }
+ else
+ {
+ KMessageBox::queuedMessageBox(
+ Kopete::UI::Global::mainWidget(), KMessageBox::Error,
+ i18n("<qt>The network associated with this account, <b>%1</b>, no longer exists. Please"
+ " ensure that the account has a valid network. The account will not be enabled until you do so.</qt>").arg(network),
+ i18n("Problem Loading %1").arg( accountId() ), 0 );
+ }
+}
+
+void IRCAccount::setNickName( const QString &nick )
+{
+ mNickName = nick;
+ configGroup()->writeEntry(CONFIG_NICKNAME, mNickName);
+
+ if( mySelf() )
+ mySelf()->setNickName( mNickName );
+}
+
+// FIXME: Possible null pointer usage here
+void IRCAccount::setCodec( QTextCodec *codec )
+{
+ mCodec = codec;
+ configGroup()->writeEntry(CONFIG_CODECMIB, codec->mibEnum());
+
+ if( mCodec )
+ m_engine->setDefaultCodec( mCodec );
+}
+
+QTextCodec *IRCAccount::codec() const
+{
+ return mCodec;
+}
+
+// FIXME: Move this to a dictionnary
+void IRCAccount::setDefaultPart( const QString &defaultPart )
+{
+ configGroup()->writeEntry( QString::fromLatin1( "defaultPart" ), defaultPart );
+}
+
+// FIXME: Move this to a dictionnary
+void IRCAccount::setDefaultQuit( const QString &defaultQuit )
+{
+ configGroup()->writeEntry( QString::fromLatin1( "defaultQuit" ), defaultQuit );
+}
+
+// FIXME: Move this to a dictionnary
+const QString IRCAccount::defaultPart() const
+{
+ QString partMsg = configGroup()->readEntry(QString::fromLatin1("defaultPart"));
+ if( partMsg.isEmpty() )
+ return QString::fromLatin1("Kopete %1 : http://kopete.kde.org").arg( kapp->aboutData()->version() );
+ return partMsg;
+}
+
+const QString IRCAccount::defaultQuit() const
+{
+ QString quitMsg = configGroup()->readEntry(QString::fromLatin1("defaultQuit"));
+ if( quitMsg.isEmpty() )
+ return QString::fromLatin1("Kopete %1 : http://kopete.kde.org").arg(kapp->aboutData()->version());
+ return quitMsg;
+}
+
+void IRCAccount::setCustomCtcpReplies( const QMap< QString, QString > &replies ) const
+{
+ QStringList val;
+ for( QMap< QString, QString >::ConstIterator it = replies.begin(); it != replies.end(); ++it )
+ {
+ m_engine->addCustomCtcp( it.key(), it.data() );
+ val.append( QString::fromLatin1("%1=%2").arg( it.key() ).arg( it.data() ) );
+ }
+
+ configGroup()->writeEntry( "CustomCtcp", val );
+}
+
+const QMap< QString, QString > IRCAccount::customCtcpReplies() const
+{
+ QMap< QString, QString > replies;
+ QStringList replyList;
+
+ replyList = configGroup()->readListEntry( "CustomCtcp" );
+
+ for( QStringList::Iterator it = replyList.begin(); it != replyList.end(); ++it )
+ replies[ (*it).section('=', 0, 0 ) ] = (*it).section('=', 1 );
+
+ return replies;
+}
+
+void IRCAccount::setConnectCommands( const QStringList &commands ) const
+{
+ configGroup()->writeEntry( "ConnectCommands", commands );
+}
+
+const QStringList IRCAccount::connectCommands() const
+{
+ return configGroup()->readListEntry( "ConnectCommands" );
+}
+
+void IRCAccount::setMessageDestinations( int serverNotices, int serverMessages,
+ int informationReplies, int errorMessages )
+{
+ KConfigGroup *config = configGroup();
+ config->writeEntry( "ServerNotices", serverNotices );
+ config->writeEntry( "ServerMessages", serverMessages );
+ config->writeEntry( "InformationReplies", informationReplies );
+ config->writeEntry( "ErrorMessages", errorMessages );
+
+ m_serverNotices = (MessageDestination)serverNotices;
+ m_serverMessages = (MessageDestination)serverMessages;
+ m_informationReplies = (MessageDestination)informationReplies;
+ m_errorMessages = (MessageDestination)errorMessages;
+}
+
+KActionMenu *IRCAccount::actionMenu()
+{
+ QString menuTitle = QString::fromLatin1( " %1 <%2> " ).arg( accountId() ).arg( myself()->onlineStatus().description() );
+
+ KActionMenu *mActionMenu = Kopete::Account::actionMenu();
+
+ m_joinChannelAction->setEnabled( isConnected() );
+ m_searchChannelAction->setEnabled( isConnected() );
+
+ mActionMenu->popupMenu()->insertSeparator();
+ mActionMenu->insert(m_joinChannelAction);
+ mActionMenu->insert(m_searchChannelAction);
+ mActionMenu->insert( new KAction ( i18n("Show Server Window"), QString::null, 0, this, SLOT(slotShowServerWindow()), mActionMenu ) );
+
+ if( m_engine->isConnected() && m_engine->useSSL() )
+ {
+ mActionMenu->insert( new KAction ( i18n("Show Security Information"), "", 0, m_engine,
+ SLOT(showInfoDialog()), mActionMenu ) );
+ }
+
+ return mActionMenu;
+}
+
+void IRCAccount::connectWithPassword(const QString &password)
+{
+ //TODO: honor the initial status
+
+ if( m_engine->isConnected() )
+ {
+ if( isAway() )
+ setAway( false );
+ }
+ else if( m_engine->isDisconnected() )
+ {
+ if( m_network )
+ {
+ QValueList<IRCHost*> &hosts = m_network->hosts;
+ if( hosts.count() == 0 )
+ {
+ KMessageBox::queuedMessageBox(
+ Kopete::UI::Global::mainWidget(), KMessageBox::Error,
+ i18n("<qt>The network associated with this account, <b>%1</b>, has no valid hosts. Please ensure that the account has a valid network.</qt>").arg(m_network->name),
+ i18n("Network is Empty"), 0 );
+ }
+ else if( currentHost == hosts.count() )
+ {
+ KMessageBox::queuedMessageBox(
+ Kopete::UI::Global::mainWidget(), KMessageBox::Error,
+ i18n("<qt>Kopete could not connect to any of the servers in the network associated with this account (<b>%1</b>). Please try again later.</qt>").arg(m_network->name),
+ i18n("Network is Unavailable"), 0 );
+
+ currentHost = 0;
+ }
+ else
+ {
+ // if prefer SSL is set, sort by SSL first
+ if (configGroup()->readBoolEntry("PreferSSL"))
+ {
+ typedef QValueList<IRCHost*> IRCHostList;
+ IRCHostList sslFirst;
+ IRCHostList::iterator it;
+ for ( it = hosts.begin(); it != hosts.end(); ++it )
+ {
+ if ( (*it)->ssl == true )
+ {
+ sslFirst.append( *it );
+ it = hosts.remove( it );
+ }
+ }
+ for ( it = hosts.begin(); it != hosts.end(); ++it )
+ sslFirst.append( *it );
+
+ hosts = sslFirst;
+ }
+
+ IRCHost *host = hosts[ currentHost++ ];
+ myServer()->appendMessage( i18n("Connecting to %1...").arg( host->host ) );
+ if( host->ssl )
+ myServer()->appendMessage( i18n("Using SSL") );
+
+ m_engine->setPassword(password);
+ m_engine->connectToServer( host->host, host->port, mNickName, host->ssl );
+ }
+ }
+ else
+ {
+ kdWarning() << "No network defined!" << endl;
+ }
+ }
+}
+
+void IRCAccount::engineStatusChanged(KIRC::Engine::Status newStatus)
+{
+ kdDebug(14120) << k_funcinfo << endl;
+
+ mySelf()->updateStatus();
+
+ switch (newStatus)
+ {
+ case KIRC::Engine::Idle:
+ // Do nothing.
+ break;
+ case KIRC::Engine::Connecting:
+ {
+ if( autoShowServerWindow )
+ myServer()->startChat();
+ break;
+ }
+ case KIRC::Engine::Authentifying:
+ break;
+ case KIRC::Engine::Connected:
+ {
+ //Reset the host so re-connection will start over at first server
+ currentHost = 0;
+ m_contactManager->addToNotifyList( m_engine->nickName() );
+
+ // HACK! See bug #85200 for details. Some servers still cannot accept commands
+ // after the 001 is sent, you need to wait until all the init junk is done.
+ // Unfortunatly, there is no way for us to know when it is done (it could be
+ // spewing out any number of replies), so just try delaying it
+ QTimer::singleShot( 250, this, SLOT( slotPerformOnConnectCommands() ) );
+ }
+ break;
+ case KIRC::Engine::Closing:
+ triedAltNick = false;
+// mySelf()->setOnlineStatus( m_protocol->m_UserStatusOffline );
+ m_contactManager->removeFromNotifyList( m_engine->nickName() );
+
+// if (m_contactManager && !autoConnect.isNull())
+// Kopete::AccountManager::self()->removeAccount( this );
+ break;
+ case KIRC::Engine::AuthentifyingFailed:
+ break;
+ case KIRC::Engine::Timeout:
+ //Try next server
+ connect();
+ break;
+ case KIRC::Engine::Disconnected:
+ break;
+ }
+}
+
+void IRCAccount::slotPerformOnConnectCommands()
+{
+ Kopete::ChatSession *manager = myServer()->manager(Kopete::Contact::CanCreate);
+ if (!manager)
+ return;
+
+ if (!autoConnect.isEmpty())
+ Kopete::CommandHandler::commandHandler()->processMessage( QString::fromLatin1("/join %1").arg(autoConnect), manager);
+
+ QStringList commands(connectCommands());
+ for (QStringList::Iterator it=commands.begin(); it != commands.end(); ++it)
+ Kopete::CommandHandler::commandHandler()->processMessage(*it, manager);
+}
+
+void IRCAccount::slotJoinedUnknownChannel(const QString &channel, const QString &nick)
+{
+ if ( nick.lower() == m_contactManager->mySelf()->nickName().lower() )
+ {
+ m_contactManager->findChannel(channel)->join();
+ }
+}
+
+void IRCAccount::disconnect()
+{
+ quit();
+}
+
+void IRCAccount::slotServerBusy()
+{
+ KMessageBox::queuedMessageBox(
+ Kopete::UI::Global::mainWidget(), KMessageBox::Error,
+ i18n("The IRC server is currently too busy to respond to this request."),
+ i18n("Server is Busy"), 0
+ );
+}
+
+void IRCAccount::slotSearchChannels()
+{
+ if( !m_channelList )
+ {
+ m_channelList = new ChannelListDialog( m_engine,
+ i18n("Channel List for %1").arg( m_engine->currentHost() ), this,
+ SLOT( slotJoinNamedChannel( const QString & ) ) );
+ }
+ else
+ m_channelList->clear();
+
+ m_channelList->show();
+}
+
+void IRCAccount::listChannels()
+{
+ slotSearchChannels();
+ m_channelList->search();
+}
+
+void IRCAccount::quit( const QString &quitMessage )
+{
+ kdDebug(14120) << "Quitting IRC: " << quitMessage << endl;
+
+ if( quitMessage.isNull() || quitMessage.isEmpty() )
+ m_engine->quit( defaultQuit() );
+ else
+ m_engine->quit( quitMessage );
+}
+
+void IRCAccount::setAway(bool isAway, const QString &awayMessage)
+{
+ kdDebug(14120) << k_funcinfo << isAway << " " << awayMessage << endl;
+ if(m_engine->isConnected())
+ {
+ static_cast<IRCUserContact *>( myself() )->setAway( isAway );
+ engine()->away(isAway, awayMessage);
+ }
+}
+
+/*
+ * Ask for server password, and reconnect
+ */
+void IRCAccount::slotFailedServerPassword()
+{
+ // JLN
+ password().setWrong();
+ connect();
+}
+void IRCAccount::slotGoAway( const QString &reason )
+{
+ setAway( true, reason );
+}
+
+void IRCAccount::slotShowServerWindow()
+{
+ m_myServer->startChat();
+}
+
+bool IRCAccount::isConnected()
+{
+// return ( myself()->onlineStatus().status() != Kopete::OnlineStatus::Offline );
+ return m_engine->isConnected();
+}
+
+void IRCAccount::setOnlineStatus( const Kopete::OnlineStatus& status , const QString &reason )
+{
+ if ( status.status() == Kopete::OnlineStatus::Online &&
+ myself()->onlineStatus().status() == Kopete::OnlineStatus::Offline )
+ connect();
+ else if (status.status() == Kopete::OnlineStatus::Online &&
+ myself()->onlineStatus().status() == Kopete::OnlineStatus::Away )
+ setAway( false );
+ else if ( status.status() == Kopete::OnlineStatus::Offline )
+ disconnect();
+ else if ( status.status() == Kopete::OnlineStatus::Away )
+ slotGoAway( reason );
+}
+
+
+void IRCAccount::successfullyChangedNick(const QString &oldnick, const QString &newnick)
+{
+ kdDebug(14120) << k_funcinfo << "Changing nick to " << newnick << endl;
+ mNickName = newnick;
+ mySelf()->setNickName( mNickName );
+ m_contactManager->removeFromNotifyList( oldnick );
+ m_contactManager->addToNotifyList( newnick );
+}
+
+bool IRCAccount::createContact( const QString &contactId, Kopete::MetaContact *m )
+{
+ kdDebug(14120) << k_funcinfo << contactManager() << endl;
+ IRCContact *c;
+
+ if( !m )
+ {//This should NEVER happen
+ m = new Kopete::MetaContact();
+ Kopete::ContactList::self()->addMetaContact(m);
+ }
+
+ if( contactId == mNickName )
+ {
+ KMessageBox::error( Kopete::UI::Global::mainWidget(),
+ i18n("\"You are not allowed to add yourself to your contact list."), i18n("IRC Plugin")
+ );
+
+ return false;
+ }
+ else if (contactId.startsWith(QString::fromLatin1("#")))
+ {
+ c = static_cast<IRCContact*>(contactManager()->findChannel(contactId, m));
+ }
+ else
+ {
+ m_contactManager->addToNotifyList( contactId );
+ c = static_cast<IRCContact*>(contactManager()->findUser(contactId, m));
+ }
+
+ if( c->metaContact() != m )
+ {//This should NEVER happen
+ Kopete::MetaContact *old = c->metaContact();
+ c->setMetaContact( m );
+ Kopete::ContactPtrList children = old->contacts();
+ if (children.isEmpty())
+ Kopete::ContactList::self()->removeMetaContact( old );
+ }
+ else if( c->metaContact()->isTemporary() )
+ m->setTemporary(false);
+
+ return true;
+}
+
+void IRCAccount::slotJoinNamedChannel(const QString &chan)
+{
+ contactManager()->findChannel(chan)->startChat();
+}
+
+void IRCAccount::setCurrentCommandSource( Kopete::ChatSession *session )
+{
+ commandSource = session;
+}
+
+Kopete::ChatSession *IRCAccount::currentCommandSource()
+{
+ return commandSource;
+}
+
+void IRCAccount::slotJoinChannel()
+{
+ if (!isConnected())
+ return;
+
+ QStringList chans = configGroup()->readListEntry( "Recent Channel list" );
+ //kdDebug(14120) << "Recent channel list from config: " << chans << endl;
+
+ KLineEditDlg dlg(
+ i18n("Please enter name of the channel you want to join:"),
+ QString::null,
+ Kopete::UI::Global::mainWidget()
+ );
+
+ KCompletion comp;
+ comp.insertItems( chans );
+
+ dlg.lineEdit()->setCompletionObject( &comp );
+ dlg.lineEdit()->setCompletionMode( KGlobalSettings::CompletionPopup );
+
+ while( true )
+ {
+ if( dlg.exec() != QDialog::Accepted )
+ break;
+
+ QString chan = dlg.text();
+ if( chan.isNull() )
+ break;
+
+ if( KIRC::Entity::isChannel( chan ) )
+ {
+ contactManager()->findChannel( chan )->startChat();
+
+ // push the joined channel to first in list
+ chans.remove( chan );
+ chans.prepend( chan );
+
+ configGroup()->writeEntry( "Recent Channel list", chans );
+ break;
+ }
+
+ KMessageBox::error( Kopete::UI::Global::mainWidget(),
+ i18n("\"%1\" is an invalid channel. Channels must start with '#', '!', '+', or '&'.").arg(chan),
+ i18n("IRC Plugin")
+ );
+ }
+}
+
+void IRCAccount::slotNewCtcpReply(const QString &type, const QString &/*target*/, const QString &messageReceived)
+{
+ appendMessage( i18n("CTCP %1 REPLY: %2").arg(type).arg(messageReceived), InfoReply );
+}
+
+void IRCAccount::slotNoSuchNickname( const QString &nick )
+{
+ if( KIRC::Entity::isChannel(nick) )
+ appendMessage( i18n("The channel \"%1\" does not exist").arg(nick), UnknownReply );
+ else
+ appendMessage( i18n("The nickname \"%1\" does not exist").arg(nick), UnknownReply );
+}
+
+void IRCAccount::appendMessage( const QString &message, MessageType type )
+{
+ // TODO: Impliment a UI where people can pick multiple destinations
+ // for a message type, and make codethis handle it
+
+ MessageDestination destination;
+
+ switch( type )
+ {
+ case ConnectReply:
+ destination = m_serverMessages;
+ break;
+ case InfoReply:
+ destination = m_informationReplies;
+ break;
+ case NoticeReply:
+ destination = m_serverNotices;
+ break;
+ case ErrorReply:
+ destination = m_errorMessages;
+ break;
+ case UnknownReply:
+ default:
+ destination = ActiveWindow;
+ break;
+ }
+
+ if( destination == ActiveWindow )
+ {
+ KopeteView *activeView = Kopete::ChatSessionManager::self()->activeView();
+ if( activeView && activeView->msgManager()->account() == this )
+ {
+ Kopete::ChatSession *manager = activeView->msgManager();
+ Kopete::Message msg( manager->myself(), manager->members(), message,
+ Kopete::Message::Internal, Kopete::Message::RichText, CHAT_VIEW );
+ activeView->appendMessage(msg);
+ }
+ }
+
+ if( destination == AnonymousWindow )
+ {
+ //TODO: Create an anonymous window??? What will this mean...
+ }
+
+ if( destination == ServerWindow )
+ {
+ myServer()->appendMessage(message);
+ }
+
+ if( destination == KNotify )
+ {
+ KNotifyClient::event(
+ Kopete::UI::Global::mainWidget()->winId(), QString::fromLatin1("irc_event"), message
+ );
+ }
+}
+
+IRCUserContact *IRCAccount::mySelf() const
+{
+ return static_cast<IRCUserContact *>( myself() );
+}
+
+IRCServerContact *IRCAccount::myServer() const
+{
+ return m_myServer;
+}
+
+IRCContact *IRCAccount::getContact(const QString &name, Kopete::MetaContact *metac)
+{
+ return getContact(m_engine->getEntity(name), metac);
+}
+
+IRCContact *IRCAccount::getContact(KIRC::EntityPtr entity, Kopete::MetaContact *metac)
+{
+ IRCContact *contact = 0;
+
+#ifdef __GNUC__
+ #warning Do the search code here.
+#endif
+
+ if (!contact)
+ {
+#ifdef __GNUC__
+ #warning Make a temporary meta contact if metac is null
+#endif
+ contact = new IRCContact(this, entity, metac);
+ m_contacts.append(contact);
+ }
+
+ QObject::connect(contact, SIGNAL(destroyed(IRCContact *)), SLOT(destroyed(IRCContact *)));
+ return contact;
+}
+
+void IRCAccount::destroyed(IRCContact *contact)
+{
+ m_contacts.remove(contact);
+}
+
+#include "ircaccount.moc"
+
+// vim: set noet ts=4 sts=4 sw=4:
+