-rw-r--r-- | noncore/net/opieirc/ircchannel.cpp | 3 | ||||
-rw-r--r-- | noncore/net/opieirc/ircchannel.h | 15 | ||||
-rw-r--r-- | noncore/net/opieirc/ircchannellist.cpp | 16 | ||||
-rw-r--r-- | noncore/net/opieirc/ircchannelperson.cpp | 62 | ||||
-rw-r--r-- | noncore/net/opieirc/ircchannelperson.h | 34 | ||||
-rw-r--r-- | noncore/net/opieirc/ircchanneltab.cpp | 18 | ||||
-rw-r--r-- | noncore/net/opieirc/ircconnection.cpp | 24 | ||||
-rw-r--r-- | noncore/net/opieirc/ircconnection.h | 6 | ||||
-rw-r--r-- | noncore/net/opieirc/ircmessageparser.cpp | 100 | ||||
-rw-r--r-- | noncore/net/opieirc/ircmessageparser.h | 2 | ||||
-rw-r--r-- | noncore/net/opieirc/ircservertab.cpp | 3 | ||||
-rw-r--r-- | noncore/net/opieirc/ircsession.cpp | 20 | ||||
-rw-r--r-- | noncore/net/opieirc/ircsession.h | 4 | ||||
-rw-r--r-- | noncore/net/opieirc/mainwindow.cpp | 4 | ||||
-rw-r--r-- | noncore/net/opieirc/opieirc.pro | 6 |
15 files changed, 242 insertions, 75 deletions
diff --git a/noncore/net/opieirc/ircchannel.cpp b/noncore/net/opieirc/ircchannel.cpp index 5c380e5..5d81596 100644 --- a/noncore/net/opieirc/ircchannel.cpp +++ b/noncore/net/opieirc/ircchannel.cpp @@ -1,47 +1,48 @@ #include "ircchannel.h" +#include "ircchannelperson.h" IRCChannel::IRCChannel(QString channelname) { m_hasPeople = FALSE; m_channelname = channelname; } IRCChannel::~IRCChannel() { /* We want this to get deleted */ m_people.setAutoDelete(TRUE); } QString IRCChannel::channelname() { return m_channelname; } bool IRCChannel::hasPeople() { return m_hasPeople; } void IRCChannel::setHasPeople(bool hasPeople) { m_hasPeople = hasPeople; } void IRCChannel::addPerson(IRCChannelPerson *person) { m_people.append(person); } void IRCChannel::removePerson(IRCChannelPerson *person) { m_people.remove(person); } QListIterator<IRCChannelPerson> IRCChannel::people() { QListIterator<IRCChannelPerson> it(m_people); return it; } IRCChannelPerson *IRCChannel::getPerson(QString nickname) { QListIterator<IRCChannelPerson> it(m_people); for (; it.current(); ++it) { - if (it.current()->person->nick() == nickname) { + if (it.current()->nick() == nickname) { return it.current(); } } return 0; } diff --git a/noncore/net/opieirc/ircchannel.h b/noncore/net/opieirc/ircchannel.h index e78f182..a276f10 100644 --- a/noncore/net/opieirc/ircchannel.h +++ b/noncore/net/opieirc/ircchannel.h @@ -1,69 +1,58 @@ /* OpieIRC - An embedded IRC client Copyright (C) 2002 Wenzel Jakob 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IRCCHANNEL_H #define __IRCCHANNEL_H #include <qobject.h> #include <qlist.h> #include <qstring.h> -#include "ircperson.h" -/* Flags which a person can have inside a channel */ -enum IRCChannelPersonFlag { - PERSON_FLAG_OP = 0x01, - PERSON_FLAG_VOICE = 0x02, - PERSON_FLAG_HALFOP = 0x04 -}; +#include "ircperson.h" -/* This struct encapsulates a IRCPerson and adds - channel specific information */ -typedef struct IRCChannelPerson { - IRCPerson *person; - unsigned int flags; -}; +class IRCChannelPerson; /* IRCChannel is the object-oriented representation of an IRC channel. It basically acts as a container for IRCChannelPersons */ class IRCChannel : public QObject { Q_OBJECT public: IRCChannel(QString channelname); ~IRCChannel(); void addPerson(IRCChannelPerson *person); void removePerson(IRCChannelPerson *person); IRCChannelPerson *getPerson(QString nickname); QListIterator<IRCChannelPerson> people(); /* hasPeople identifies whether the irc channel is done synchronizing with the current state - this is only relevant when joining a channel */ void setHasPeople(bool hasPeople); QString channelname(); bool hasPeople(); protected: QList<IRCChannelPerson> m_people; QString m_channelname; bool m_hasPeople; }; #endif /* __IRCCHANNEL_H */ diff --git a/noncore/net/opieirc/ircchannellist.cpp b/noncore/net/opieirc/ircchannellist.cpp index c32c535..8cf144e 100644 --- a/noncore/net/opieirc/ircchannellist.cpp +++ b/noncore/net/opieirc/ircchannellist.cpp @@ -1,65 +1,67 @@ #include <qpe/resource.h> + #include "ircchannellist.h" +#include "ircchannelperson.h" IRCChannelList::IRCChannelList(IRCChannel *channel, QWidget *parent, const char *name, WFlags f) : QListBox(parent, name, f) { m_channel = channel; } void IRCChannelList::update() { QPixmap op = Resource::loadPixmap("opieirc/op"); QPixmap hop = Resource::loadPixmap("opieirc/hop"); QPixmap voice = Resource::loadPixmap("opieirc/voice"); QListIterator<IRCChannelPerson> it = m_channel->people(); clear(); for (; it.current(); ++it) { IRCChannelPerson *person = it.current(); - if (person->flags & PERSON_FLAG_OP) { - insertItem(op, "1" + person->person->nick()); - } else if (person->flags & PERSON_FLAG_HALFOP) { - insertItem(op, "2" + person->person->nick()); - } else if (person->flags & PERSON_FLAG_VOICE) { - insertItem(voice, "3" + person->person->nick()); + if (person->flags() & IRCChannelPerson::PERSON_FLAG_OP) { + insertItem(op, "1" + person->nick()); + } else if (person->flags() & IRCChannelPerson::PERSON_FLAG_HALFOP) { + insertItem(op, "2" + person->nick()); + } else if (person->flags() & IRCChannelPerson::PERSON_FLAG_VOICE) { + insertItem(voice, "3" + person->nick()); } else { - insertItem("4" + person->person->nick()); + insertItem("4" + person->nick()); } } sort(); adjustNicks(); } bool IRCChannelList::hasPerson(QString nick) { for (unsigned int i=0; i<count(); i++) { if (text(i) == nick) return TRUE; } return FALSE; } bool IRCChannelList::removePerson(QString nick) { for (unsigned int i=0; i<count(); i++) { if (text(i) == nick){ removeItem(i); return TRUE; } } return FALSE; } void IRCChannelList::adjustNicks() { QString txt; QPixmap pm; for(unsigned int i=0; i<count(); i++) { txt = text(i).remove(0,1); if(pixmap(i)) { pm = *pixmap(i); removeItem(i); insertItem(pm, txt, i); } else { removeItem(i); insertItem(txt, i); } } } diff --git a/noncore/net/opieirc/ircchannelperson.cpp b/noncore/net/opieirc/ircchannelperson.cpp new file mode 100644 index 0000000..1e8ebe4 --- a/dev/null +++ b/noncore/net/opieirc/ircchannelperson.cpp @@ -0,0 +1,62 @@ +#include "ircperson.h" +#include "ircchannelperson.h" + +#include <qstring.h> +#include <qobject.h> + +IRCChannelPerson::IRCChannelPerson(IRCPerson *person) +{ + m_person = person; + m_flags = 0; +} + +IRCChannelPerson::~IRCChannelPerson() +{ + //if(m_person) + // delete m_person; +} + +QString IRCChannelPerson::setOp(const QString &nickname, bool set) +{ + if(set) { + m_flags |= PERSON_FLAG_OP; + return ( nickname + QObject::tr(" gives channel operator status to ") + nick()); + } + + m_flags &= 0xFFFF - PERSON_FLAG_OP; + return ( nickname + QObject::tr(" removes channel operator status from ") + nick()); +} + +QString IRCChannelPerson::setVoice(const QString &nickname, bool set) +{ + if(set) { + m_flags |= PERSON_FLAG_VOICE; + return ( nickname + QObject::tr(" gives voice to ") + nick() ); + } + + m_flags &= 0xFFFF - PERSON_FLAG_VOICE; + return ( nickname + QObject::tr(" removes voice from ") + nick()); +} + +QString IRCChannelPerson::nick() +{ + if(m_person) + return m_person->nick(); + + return QString::null; +} + +void IRCChannelPerson::setFlags(int flags) +{ + m_flags = flags; +} + +void IRCChannelPerson::setNick(const QString &nickname) +{ + m_person->setNick(nickname); +} + +const unsigned int IRCChannelPerson::flags() +{ + return m_flags; +} diff --git a/noncore/net/opieirc/ircchannelperson.h b/noncore/net/opieirc/ircchannelperson.h new file mode 100644 index 0000000..a8c4791 --- a/dev/null +++ b/noncore/net/opieirc/ircchannelperson.h @@ -0,0 +1,34 @@ +#ifndef IRCCHANNELPERSON_H +#define IRCCHANNELPERSON_H + +class QString; +class IRCPerson; + +/* This class encapsulates a IRCPerson and adds + * channel specific information */ +class IRCChannelPerson { + +public: + /* Flags which a person can have inside a channel */ + enum IRCChannelPersonFlag { + PERSON_FLAG_OP = 0x01, + PERSON_FLAG_VOICE = 0x02, + PERSON_FLAG_HALFOP = 0x04 + }; + + IRCChannelPerson(IRCPerson *person = 0); + ~IRCChannelPerson(); + + QString setOp(const QString &nickname, bool set); + QString setVoice(const QString &nickname, bool set); + QString nick(); + const unsigned int flags(); + void setFlags(int flags); + void setNick(const QString &nickname); + +protected: + IRCPerson *m_person; + unsigned int m_flags; +}; + +#endif diff --git a/noncore/net/opieirc/ircchanneltab.cpp b/noncore/net/opieirc/ircchanneltab.cpp index 4a35929..3272a8a 100644 --- a/noncore/net/opieirc/ircchanneltab.cpp +++ b/noncore/net/opieirc/ircchanneltab.cpp @@ -1,208 +1,216 @@ #include <qpe/resource.h> #include <qwhatsthis.h> #include <qhbox.h> #include <qdict.h> #include "ircchanneltab.h" #include "ircservertab.h" #include "ircmessageparser.h" +#include <opie2/odebug.h> QDict<QString> IRCChannelTab::m_queuedMessages (17); IRCChannelTab::IRCChannelTab(IRCChannel *channel, IRCServerTab *parentTab, MainWindow *mainWindow, QWidget *parent, const char *name, WFlags f) : IRCTab(parent, name, f) { m_mainWindow = mainWindow; m_parentTab = parentTab; m_channel = channel; m_description->setText(tr("Talking on channel") + " <b>" + channel->channelname() + "</b>"); QHBox *hbox = new QHBox(this); m_textview = new QTextView(hbox); m_textview->setHScrollBarMode(QScrollView::AlwaysOff); m_textview->setVScrollBarMode(QScrollView::AlwaysOn); m_listVisible = TRUE; m_listButton = new QPushButton(">", m_textview); m_listButton->setFlat( true ); m_textview->setCornerWidget(m_listButton); m_textview->setTextFormat(RichText); QWhatsThis::add(m_textview, tr("Channel discussion")); connect(m_listButton, SIGNAL(clicked()), this, SLOT(toggleList())); m_list = new IRCChannelList(m_channel, hbox); m_list->update(); m_list->setMaximumWidth(LISTWIDTH); m_field = new IRCHistoryLineEdit(this); connect(m_field, SIGNAL(nextTab()), this, SIGNAL(nextTab())); connect(m_field, SIGNAL(prevTab()), this, SIGNAL(prevTab())); connect(m_field, SIGNAL(closeTab()), this, SLOT(remove())); connect(this, SIGNAL(editFocus()), m_field, SLOT(setEditFocus())); QWhatsThis::add(m_field, tr("Type your message here to participate in the channel discussion")); m_popup = new QPopupMenu(m_list); m_lines = 0; /* Required so that embedded-style "right" clicks work */ QPEApplication::setStylusOperation(m_list->viewport(), QPEApplication::RightOnHold); connect(m_list, SIGNAL(mouseButtonPressed(int,QListBoxItem*,const QPoint&)), this, SLOT(mouseButtonPressed(int,QListBoxItem*,const QPoint&))); /* Construct the popup menu */ - QPopupMenu *ctcpMenu = new QPopupMenu(m_list); + //QPopupMenu *ctcpMenu = new QPopupMenu(m_list); m_popup->insertItem(Resource::loadPixmap("opieirc/query"), tr("Query"), this, SLOT(popupQuery())); - ctcpMenu->insertItem(Resource::loadPixmap("opieirc/ping"), tr("Ping"), this, SLOT(popupPing())); - ctcpMenu->insertItem(Resource::loadPixmap("opieirc/version"), tr("Version"), this, SLOT(popupVersion())); - ctcpMenu->insertItem(Resource::loadPixmap("opieirc/whois"), tr("Whois"), this, SLOT(popupWhois())); + m_popup->insertSeparator(); + m_popup->insertItem(Resource::loadPixmap("opieirc/ping"), tr("Ping"), this, SLOT(popupPing())); + m_popup->insertItem(Resource::loadPixmap("opieirc/version"), tr("Version"), this, SLOT(popupVersion())); + m_popup->insertItem(Resource::loadPixmap("opieirc/whois"), tr("Whois"), this, SLOT(popupWhois())); + //m_popup->insertItem(ctcpMenu, "CTCP"); connect(m_mainWindow, SIGNAL(updateScroll()), this, SLOT(scrolling())); m_layout->add(hbox); hbox->show(); m_layout->add(m_field); m_field->setFocus(); m_field->setActiveWindow(); connect(m_field, SIGNAL(returnPressed()), this, SLOT(processCommand())); connect(m_list, SIGNAL(doubleClicked ( QListBoxItem * ) ), this, SLOT(popupQuery( QListBoxItem * ) )); settingsChanged(); if(m_queuedMessages[m_channel->channelname()]) { appendText(*m_queuedMessages[m_channel->channelname()]); delete m_queuedMessages[m_channel->channelname()]; m_queuedMessages.remove(m_channel->channelname()); } } void IRCChannelTab::scrolling(){ m_textview->ensureVisible(0, m_textview->contentsHeight()); } void IRCChannelTab::appendText(QString text) { /* not using append because it creates layout problems */ QString txt = m_textview->text() + IRCTab::appendTimestamp( text ); if (m_maxLines > 0 && m_lines >= m_maxLines) { int firstBreak = txt.find('\n'); if (firstBreak != -1) { txt = "<qt bgcolor=\"" + m_backgroundColor + "\"/>" + txt.right(txt.length() - (firstBreak + 1)); } } else { m_lines++; } m_textview->ensureVisible(0, m_textview->contentsHeight()); m_textview->setText(txt); m_textview->ensureVisible(0, m_textview->contentsHeight()); int p1, p2; if ( text.contains( IRCMessageParser::tr("Received a CTCP PING from ") ) ) emit ping( title() ); else if ( (p1 = text.find("ping", 0, false) )!= -1 && (p2 = text.find( m_parentTab->server()->nick(), 0,false )) != -1 ) { int col = text.findRev("color", -1, false); if ( col < p2 ) emit ping( title() ); } emit changed(this); } IRCChannelTab::~IRCChannelTab() { m_parentTab->removeChannelTab(this); } void IRCChannelTab::processCommand() { QString text = m_field->text(); if (text.length()>0) { if (session()->isSessionActive()) { if (text.startsWith("/") && !text.startsWith("//")) { /* Command mode */ m_parentTab->executeCommand(this, text);; } else { if (text.startsWith("//")) text = text.right(text.length()-1); session()->sendMessage(m_channel, m_field->text()); appendText("<font color=\"" + m_textColor + "\"><</font><font color=\"" + m_selfColor + "\">"+m_parentTab->server()->nick()+"</font><font color=\"" + m_textColor + "\">> "+IRCOutput::toHTML(m_field->text())+"</font><br>"); } } else { appendText("<font color=\"" + m_errorColor + "\">"+tr("Disconnected")+"</font><br>"); } } m_field->clear(); } void IRCChannelTab::settingsChanged() { m_textview->setText("<qt bgcolor=\"" + m_backgroundColor + "\"/>"); m_lines = 0; } void IRCChannelTab::toggleList() { if (m_listVisible) { m_list->setMaximumWidth(0); m_listButton->setText("<"); } else { m_list->setMaximumWidth(LISTWIDTH); m_listButton->setText(">"); } m_listVisible = !m_listVisible; } void IRCChannelTab::mouseButtonPressed(int mouse, QListBoxItem *, const QPoint &point) { switch (mouse) { case 1: break; case 2: m_popup->popup(point); break; }; } void IRCChannelTab::popupQuery( QListBoxItem *item) { if (item) { IRCPerson *person = session()->getPerson(item->text()); if (person) { IRCQueryTab *tab = m_parentTab->getTabForQuery(person); if (!tab) { tab = new IRCQueryTab(person, m_parentTab, m_mainWindow, (QWidget *)parent()); m_parentTab->addQueryTab(tab); m_mainWindow->addTab(tab); } } } } void IRCChannelTab::popupQuery() { if ( m_list->currentItem() != -1 ) popupQuery( m_list->item(m_list->currentItem())); } void IRCChannelTab::popupPing() { - //HAHA, no wonder these don't work + if(m_list->currentItem() != -1) + m_parentTab->session()->sendCTCPPing(m_list->text(m_list->currentItem())); } void IRCChannelTab::popupVersion() { + if(m_list->currentItem() != -1) + m_parentTab->session()->sendCTCPRequest(m_list->text(m_list->currentItem()), "VERSION", ""); } void IRCChannelTab::popupWhois() { + if(m_list->currentItem() != -1) + m_parentTab->session()->whois(m_list->text(m_list->currentItem())); } QString IRCChannelTab::title() { return m_channel->channelname(); } IRCSession *IRCChannelTab::session() { return m_parentTab->session(); } void IRCChannelTab::remove() { if (session()->isSessionActive()) { session()->part(m_channel); } else { m_mainWindow->killTab(this); } } void IRCChannelTab::enqueue(const QString &channel, const QString &message) { if (m_queuedMessages.count() == (m_queuedMessages.size() - 1) ) /* 17 messages max */ return; m_queuedMessages.insert(channel, new QString(message)); } IRCChannel *IRCChannelTab::channel() { return m_channel; } IRCChannelList *IRCChannelTab::list() { return m_list; } diff --git a/noncore/net/opieirc/ircconnection.cpp b/noncore/net/opieirc/ircconnection.cpp index 2325cca..88e63f7 100644 --- a/noncore/net/opieirc/ircconnection.cpp +++ b/noncore/net/opieirc/ircconnection.cpp @@ -1,102 +1,122 @@ #include <unistd.h> #include <string.h> + +#include <qstringlist.h> +#include <qdatetime.h> + #include "ircconnection.h" IRCConnection::IRCConnection(IRCServer *server) { m_server = server; m_socket = new QSocket(this); m_connected = FALSE; m_loggedIn = FALSE; connect(m_socket, SIGNAL(connected()), this, SLOT(login())); connect(m_socket, SIGNAL(readyRead()), this, SLOT(dataReady())); connect(m_socket, SIGNAL(error(int)), this, SLOT(error(int))); connect(m_socket, SIGNAL(connectionClosed()), this, SLOT(disconnect())); connect(m_socket, SIGNAL(delayedCloseFinished()), this, SLOT(disconnect())); } /* Connect to the IRC server */ void IRCConnection::doConnect() { ASSERT(!m_connected); m_socket->connectToHost(m_server->hostname(), m_server->port()); } /* Send commands to the IRC server */ void IRCConnection::sendLine(QString line) { while((line.right(1) == "\n") || (line.right(1) == "\r")) line = line.left(line.length() - 1); line.append("\r\n"); m_socket->writeBlock(line, line.length()); } -void IRCConnection::sendCTCP(QString nick, QString line) { - sendLine("NOTICE " + nick + " :\001"+line+"\001"); +void IRCConnection::sendCTCPReply(const QString &nickname, const QString &type, const QString &args) { + sendLine("NOTICE " + nickname + " :\001" + type + " " + args + "\001"); +} + +void IRCConnection::sendCTCPRequest(const QString &nickname, const QString &type, const QString &args) { + sendLine("PRIVMSG " + nickname + " :\001" + type + " " + args + "\001"); +} + +void IRCConnection::sendCTCPPing(const QString &nickname) { + QDateTime tm; + tm.setTime_t(0); + QString strtime = QString::number(tm.secsTo(QDateTime::currentDateTime())); + sendCTCPRequest(nickname, "PING", strtime); +} + +void IRCConnection::whois(const QString &nickname) { + sendLine("WHOIS " + nickname); } /* * login() is called right after the connection * to the IRC server has been established */ void IRCConnection::login() { char hostname[256]; QString loginString; emit outputReady(IRCOutput(OUTPUT_CLIENTMESSAGE, tr("Connected, logging in .."))); m_connected = TRUE; gethostname(hostname, sizeof(hostname)-1); hostname[sizeof (hostname) - 1] = 0; /* Create a logon string and send it */ if (m_server->password().length()>0) { loginString += "PASS " + m_server->password() + "\r\n"; } loginString += "NICK " + m_server->nick() + "\r\n" + "USER " + m_server->username() + " " + hostname + " " + m_server->hostname() + " :" + m_server->realname() + "\r\n"; sendLine(loginString); } /* Called when data arrives on the socket */ void IRCConnection::dataReady() { while(m_socket->canReadLine()) { IRCMessage message(m_socket->readLine()); if (!m_loggedIn && message.isNumerical() && message.commandNumber() == 1) { /* Now autojoin all channels specified inside the server profile */ QStringList channels = QStringList::split(QChar(','), m_server->channels()); for (QStringList::Iterator it = channels.begin(); it != channels.end(); ++it) { QString channelName = (*it).stripWhiteSpace(); if (channelName.startsWith("#") || channelName.startsWith("+")) { sendLine("JOIN "+ channelName); } } m_loggedIn = TRUE; emit outputReady(IRCOutput(OUTPUT_CLIENTMESSAGE, tr("Successfully logged in."))); } emit messageArrived(&message); } } /* Called if any type of socket error occurs */ void IRCConnection::error(int num) { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Socket error : ") + strerror(num))); } void IRCConnection::disconnect() { m_connected = FALSE; m_loggedIn = FALSE; emit outputReady(IRCOutput(OUTPUT_CONNCLOSE, tr("Connection closed"))); } bool IRCConnection::isConnected() { return m_connected; } bool IRCConnection::isLoggedIn() { return m_loggedIn; } void IRCConnection::close() { m_socket->close(); if (m_socket->state()==QSocket::Idle) { disconnect(); } } + diff --git a/noncore/net/opieirc/ircconnection.h b/noncore/net/opieirc/ircconnection.h index 75cdf6d..382b1c0 100644 --- a/noncore/net/opieirc/ircconnection.h +++ b/noncore/net/opieirc/ircconnection.h @@ -1,65 +1,69 @@ /* OpieIRC - An embedded IRC client Copyright (C) 2002 Wenzel Jakob 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IRCCONNECTION_H #define __IRCCONNECTION_H #include <qsocket.h> #include "ircserver.h" #include "ircmessage.h" #include "ircoutput.h" /* IRCConnection acts as a wrapper around QSocket and is responsible for the communication with the IRC server */ class IRCConnection : public QObject { Q_OBJECT public: IRCConnection(IRCServer *server); void doConnect(); /* used to send commands to the IRC server */ void sendLine(QString line); /* used to send CTCP commands to the IRC server */ - void sendCTCP(QString nick, QString line); + void sendCTCPReply(const QString &nickname, const QString &type, const QString &args); + void sendCTCPRequest(const QString &nickname, const QString &type, const QString &args); + void sendCTCPPing(const QString &nickname); + void whois(const QString &nickname); + void sendCTCPping(const QString &nickname); void close(); bool isConnected(); bool isLoggedIn(); signals: /* triggered when the server sent us a message */ void messageArrived(IRCMessage *message); /* Used to send commands to the UI (such as displaying text etc) */ void outputReady(IRCOutput output); protected slots: /* automatically executed after the connection is established */ void login(); /* called when there are socket errors */ void error(int num); /* called when data arrived on m_socket (triggers messageArrived) */ void dataReady(); /* called when the IRC server closes the connection */ void disconnect(); protected: IRCServer *m_server; QSocket *m_socket; bool m_connected; bool m_loggedIn; }; #endif /* __IRCCONNECTION_H */ diff --git a/noncore/net/opieirc/ircmessageparser.cpp b/noncore/net/opieirc/ircmessageparser.cpp index cfad2c1..9c1492c 100644 --- a/noncore/net/opieirc/ircmessageparser.cpp +++ b/noncore/net/opieirc/ircmessageparser.cpp @@ -1,263 +1,272 @@ #include <qtextstream.h> #include <qdatetime.h> #include "ircmessageparser.h" #include "ircversion.h" +#include "ircchannelperson.h" +//#include "transferreceiver.h" /* Lookup table for literal commands */ IRCLiteralMessageParserStruct IRCMessageParser::literalParserProcTable[] = { { "PING", FUNC(parseLiteralPing) }, { "NOTICE", FUNC(parseLiteralNotice) }, { "JOIN", FUNC(parseLiteralJoin) }, { "PRIVMSG", FUNC(parseLiteralPrivMsg) }, { "NICK", FUNC(parseLiteralNick) }, { "PART", FUNC(parseLiteralPart) }, { "QUIT", FUNC(parseLiteralQuit) }, { "ERROR", FUNC(parseLiteralError) }, { "ERROR:", FUNC(parseLiteralError) }, { "MODE", FUNC(parseLiteralMode) }, { "KICK", FUNC(parseLiteralKick) }, { "TOPIC", FUNC(parseLiteralTopic) }, { 0 , 0 } }; /* Lookup table for literal commands */ IRCCTCPMessageParserStruct IRCMessageParser::ctcpParserProcTable[] = { { "PING", FUNC(parseCTCPPing) }, { "VERSION", FUNC(parseCTCPVersion) }, { "ACTION", FUNC(parseCTCPAction) }, + { "DCC", FUNC(parseCTCPDCC) }, { 0 , 0 } }; /* Lookup table for numerical commands * According to: * http://www.faqs.org/rfcs/rfc1459.html * http://www.faqs.org/rfcs/rfc2812.html */ IRCNumericalMessageParserStruct IRCMessageParser::numericalParserProcTable[] = { { 1, "%1", "1", FUNC(parseNumericalServerName) }, // RPL_WELCOME { 2, "%1", "1", 0 }, // RPL_YOURHOST { 3, "%1", "1", 0 }, // RPL_CREATED { 4, QT_TR_NOOP("Server %1 version %2 supports usermodes '%3' and channelmodes '%4'"), "1:4", FUNC(parseNumericalServerFeatures) }, // RPL_MYINFO { 5, 0, 0, FUNC(parseNumericalServerProtocol) }, // RPL_BOUNCE, RPL_PROTOCTL { 250, "%1", "1", 0 }, // RPL_STATSCONN { 251, "%1", "1", 0 }, // RPL_LUSERCLIENT { 252, QT_TR_NOOP("There are %1 operators connected"), "1", 0 }, // RPL_LUSEROP { 253, QT_TR_NOOP("There are %1 unknown connection(s)"), "1", 0 }, // RPL_LUSERUNKNOWN { 254, QT_TR_NOOP("There are %1 channels formed"), "1", 0 }, // RPL_LUSERCHANNELS { 255, "%1", "1", 0 }, // RPL_LUSERME { 263, QT_TR_NOOP("Please wait a while and try again"), 0, 0 }, // RPL_TRYAGAIN { 265, "%1", "1", 0 }, // RPL_LOCALUSERS { 266, "%1", "1", 0 }, // RPL_GLOBALUSERS - { 311, QT_TR_NOOP("Whois %1 (%2@%3)\nReal name: %4"), "1:3,5" }, // RPL_WHOISUSER + { 311, QT_TR_NOOP("Whois %1 (%2@%3)\nReal name: %4"), "1:3,5", 0 }, // RPL_WHOISUSER { 312, QT_TR_NOOP("%1 is using server %2"), "1,2", 0 }, // RPL_WHOISSERVER { 317, 0, 0, FUNC(parseNumericalWhoisIdle) }, // RPL_WHOISIDLE { 318, "%1 :%2", "1,2", 0 }, // RPL_ENDOFWHOIS + { 319, QT_TR_NOOP("%1 is on channels: %2"), "1,2", 0 }, // RPL_WHOISCHANNELS { 320, "%1 %2", "1,2", 0}, // RPL_WHOISVIRT { 332, 0, 0, FUNC(parseNumericalTopic) }, // RPL_TOPIC { 333, 0, 0, FUNC(parseNumericalTopicWhoTime) }, // RPL_TOPICWHOTIME*/ { 353, QT_TR_NOOP("Names for %1: %2"), "2,3", FUNC(parseNumericalNames) }, // RPL_NAMREPLY { 366, "%1 :%2", "1,2", FUNC(parseNumericalEndOfNames) }, // RPL_ENDOFNAMES { 369, "%1 :%2", "1,2", 0 }, // RPL_ENDOFWHOWAS { 372, "%1", "1", 0 }, // RPL_MOTD { 375, "%1", "1", 0 }, // RPL_MOTDSTART { 376, "%1", "1", 0 }, // RPL_ENDOFMOTD { 377, "%1", "1", 0 }, // RPL_MOTD2 { 378, "%1", "1", 0 }, // RPL_MOTD3 { 391, QT_TR_NOOP("Time on server %1 is %2"), "1,2", 0 }, // RPL_TIME { 401, QT_TR_NOOP("Channel or nick %1 doesn't exists"), "1", 0 }, // ERR_NOSUCHNICK - { 406, QT_TR_NOOP("There is no history information for %1"), "1" }, // ERR_WASNOSUCHNICK + { 406, QT_TR_NOOP("There is no history information for %1"), "1", 0 }, // ERR_WASNOSUCHNICK { 409, "%1", "1", 0 }, // ERR_NOORIGIN { 411, "%1", "1", 0 }, // ERR_NORECIPIENT { 412, "%1", "1", 0 }, // ERR_NOTEXTTOSEND { 421, QT_TR_NOOP("Unknown command: %1"), "1", 0 }, // ERR_ERR_UNKNOWNCOMMAND { 422, "%1", "1", 0 }, // ERR_NOMOTD { 433, QT_TR_NOOP("Can't change nick to %1: %2"), "1,2", FUNC(parseNumericalNicknameInUse) }, // ERR_NICKNAMEINUSE { 442, QT_TR_NOOP("You're not on channel %1"), "1", 0}, // ERR_NOTONCHANNEL { 477, "%1", "1", 0 }, // ERR_NOCHANMODES || ERR_NEEDREGGEDNICK { 482, QT_TR_NOOP("[%1] Operation not permitted, you don't have enough channel privileges"), "1", 0 }, //ERR_CHANOPRIVSNEEDED { 0, 0, 0, 0 } }; IRCMessageParser::IRCMessageParser(IRCSession *session) { m_session = session; } void IRCMessageParser::parse(IRCMessage *message) { /* Find out what kind of message we have here and call the appropriate handler using the parser tables. If no handler can be found, print out an error message */ if (message->isNumerical()) { for (int i=0; i<numericalParserProcTable[i].commandNumber; i++) { if (message->commandNumber() == numericalParserProcTable[i].commandNumber) { parseNumerical(message, i); return; } } emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Received unhandled numeric command: %1").arg( QString::number(message->commandNumber()) ))); } else if (message->isCTCP()) { for (int i=0; ctcpParserProcTable[i].commandName; i++) { if (message->ctcpCommand() == ctcpParserProcTable[i].commandName) { - (this->*(ctcpParserProcTable[i].proc))(message); + parseCTCP(message, i); return; } } emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Received unhandled ctcp command: %1").arg( message->ctcpCommand())) ); } else { for (int i=0; literalParserProcTable[i].commandName; i++) { if (message->command() == literalParserProcTable[i].commandName) { (this->*(literalParserProcTable[i].proc))(message); return; } } emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Received unhandled literal command: %1").arg( message->command()) )); } } void IRCMessageParser::parseNumerical(IRCMessage *message, int position) { QString out = tr(numericalParserProcTable[position].message); QString paramString = numericalParserProcTable[position].params; if(!out.isEmpty() && !paramString.isEmpty()) { QStringList params = message->params(numericalParserProcTable[position].params); QStringList::Iterator end = params.end(); for (QStringList::Iterator it = params.begin(); it != end; ++it) { out = out.arg(*it); } emit outputReady(IRCOutput(OUTPUT_SERVERMESSAGE, out)); } if(numericalParserProcTable[position].proc) (this->*(numericalParserProcTable[position].proc))(message); } +void IRCMessageParser::parseCTCP(IRCMessage *message, int position) { + if(ctcpParserProcTable[position].proc) + (this->*(ctcpParserProcTable[position].proc))(message); +} + + + void IRCMessageParser::parseNumericalServerName(IRCMessage *message) { emit outputReady(IRCOutput(OUTPUT_TITLE, tr("Connected to")+" <b>" + message->prefix() + "</b>")); - /* Register EFFECTIVE nickname, some networks (as irc-hispano) uses nick:password + /* Register EFFECTIVE nickname, some networks (as irc-hispano) use nick:password * for authentication and the parser gets confused */ m_session->m_server->setNick(message->param(0)); } void IRCMessageParser::parseNumericalServerFeatures(IRCMessage *message) { m_session->setValidUsermodes(message->param(2)); m_session->setValidChannelmodes(message->param(3)); } void IRCMessageParser::parseNumericalServerProtocol(IRCMessage *message) { /* XXX: Add some usefull features here */ QString out = message->allParameters(); out = out.mid(out.find(' ')+1); emit outputReady(IRCOutput(OUTPUT_SERVERMESSAGE, out)); } void IRCMessageParser::parseNumericalWhoisIdle(IRCMessage *message) { QDateTime dt; QTime t; t = t.addSecs(message->param(2).toInt()); dt.setTime_t(message->param(3).toInt()); emit outputReady(IRCOutput(OUTPUT_SERVERMESSAGE, tr("%1 has been idle for %2").arg(message->param(1)).arg(t.toString()))); emit outputReady(IRCOutput(OUTPUT_SERVERMESSAGE, tr("%1 signed on %2").arg(message->param(1)).arg(dt.toString()))); } void IRCMessageParser::parseLiteralPing(IRCMessage *message) { m_session->m_connection->sendLine("PONG " + message->allParameters()); } void IRCMessageParser::parseLiteralNotice(IRCMessage *message) { emit outputReady(IRCOutput(OUTPUT_SERVERMESSAGE, message->allParameters())); } void IRCMessageParser::parseLiteralJoin(IRCMessage *message) { QString channelName = message->param(0).lower(); IRCPerson mask(message->prefix()); IRCChannel *channel = m_session->getChannel(channelName); if (!channel) { /* We joined */ if (mask.nick() == m_session->m_server->nick()) { channel = new IRCChannel(channelName); m_session->addChannel(channel); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Nonexistant channel join - desynchronized?"))); } } else { /* Someone else joined */ if (mask.nick() != m_session->m_server->nick()) { if (!channel->getPerson(mask.nick())) { - IRCChannelPerson *chanperson = new IRCChannelPerson(); IRCPerson *person = m_session->getPerson(mask.nick()); if (!person) { person = new IRCPerson(message->prefix()); m_session->addPerson(person); } - chanperson->flags = 0; - chanperson->person = person; + IRCChannelPerson *chanperson = new IRCChannelPerson(person); channel->addPerson(chanperson); IRCOutput output(OUTPUT_OTHERJOIN ,tr("%1 joined channel %2").arg( mask.nick() ).arg( channelName )); output.addParam(channel); output.addParam(chanperson); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Person has already joined the channel - desynchronized?"))); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("You already joined the channel - desynchronized?"))); } } } void IRCMessageParser::parseLiteralPart(IRCMessage *message) { QString channelName = message->param(0).lower(); IRCChannel *channel = m_session->getChannel(channelName); IRCPerson mask(message->prefix()); if (channel) { if (mask.nick() == m_session->m_server->nick()) { m_session->removeChannel(channel); IRCOutput output(OUTPUT_SELFPART, tr("You left channel %1").arg( channelName )); output.addParam(channel); emit outputReady(output); delete channel; } else { IRCChannelPerson *person = channel->getPerson(mask.nick()); if (person) { channel->removePerson(person); IRCOutput output(OUTPUT_OTHERPART, tr("%1 left channel %2").arg( mask.nick() ).arg( channelName) ); output.addParam(channel); output.addParam(person); emit outputReady(output); delete person; } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Parting person not found - desynchronized?"))); } } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Channel for part not found - desynchronized?"))); } } void IRCMessageParser::parseLiteralPrivMsg(IRCMessage *message) { if (m_session->m_server->nick().lower() == message->param(0).lower() ) { /* IRC Query message detected, verify sender and display it */ IRCPerson mask(message->prefix()); IRCPerson *person = m_session->getPerson(mask.nick()); if (!person) { /* Person not yet known, create and add to the current session */ person = new IRCPerson(message->prefix()); m_session->addPerson(person); } IRCOutput output(OUTPUT_QUERYPRIVMSG, message->param(1)); output.addParam(person); emit outputReady(output); } else if (message->param(0).at(0) == '#' || message->param(0).at(0) == '+') { /* IRC Channel message detected, verify sender, channel and display it */ IRCChannel *channel = m_session->getChannel(message->param(0).lower()); if (channel) { IRCPerson mask(message->prefix()); IRCChannelPerson *person = channel->getPerson(mask.nick()); @@ -294,332 +303,339 @@ void IRCMessageParser::parseLiteralNick(IRCMessage *message) { RCPerson *person = m_session->getPerson(mask.nick()); if (person) { //IRCOutput output(OUTPUT_NICKCHANGE, tr("%1 is now known as %2").arg( mask.nick() ).arg( message->param(0))); new code starts here -- this removes the person from all channels QList<IRCChannel> channels; m_session->getChannelsByPerson(person, channels); QListIterator<IRCChannel> it(channels); for (;it.current(); ++it) { IRCChannelPerson *chanperson = it.current()->getPerson(mask.nick()); it.current()->removePerson(chanperson); chanperson->person->setNick(message->param(0)); it.current()->addPerson(chanperson); IRCOutput output(OUTPUT_NICKCHANGE, tr("%1 is now known as %2").arg( mask.nick() ).arg( message->param(0))); output.addParam(person); emit outputReady(output); } new code ends here } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Nickname change of an unknown person"))); } }*/ } void IRCMessageParser::parseLiteralQuit(IRCMessage *message) { IRCPerson mask(message->prefix()); IRCPerson *person = m_session->getPerson(mask.nick()); if (person) { QList<IRCChannel> channels; m_session->getChannelsByPerson(person, channels); QListIterator<IRCChannel> it(channels); for (;it.current(); ++it) { IRCChannelPerson *chanperson = it.current()->getPerson(mask.nick()); it.current()->removePerson(chanperson); delete chanperson; } m_session->removePerson(person); IRCOutput output(OUTPUT_QUIT, tr("%1 has quit (%2)" ).arg( mask.nick() ).arg( message->param(0) )); output.addParam(person); emit outputReady(output); delete person; } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Unknown person quit - desynchronized?"))); } } void IRCMessageParser::parseLiteralTopic(IRCMessage *message) { IRCPerson mask(message->prefix()); IRCChannel *channel = m_session->getChannel(message->param(0).lower()); if (channel) { IRCOutput output(OUTPUT_TOPIC, mask.nick() + tr(" changed topic to ") + "\"" + message->param(1) + "\""); output.addParam(channel); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Unknown channel topic - desynchronized?"))); } } void IRCMessageParser::parseLiteralError(IRCMessage *message) { emit outputReady(IRCOutput(OUTPUT_ERROR, message->allParameters())); } void IRCMessageParser::parseCTCPPing(IRCMessage *message) { IRCPerson mask(message->prefix()); - m_session->m_connection->sendCTCP(mask.nick(), "PING " + message->allParameters()); + m_session->m_connection->sendCTCPReply(mask.nick(), "PING", message->allParameters()); emit outputReady(IRCOutput(OUTPUT_CTCP, tr("Received a CTCP PING from ")+mask.nick())); //IRCPerson mask(message->prefix()); QString dest = message->ctcpDestination(); if (dest.startsWith("#")) { IRCChannel *channel = m_session->getChannel(dest.lower()); if (channel) { IRCChannelPerson *person = channel->getPerson(mask.nick()); if (person) { IRCOutput output(OUTPUT_CHANACTION, tr("Received a CTCP PING from ")+ mask.nick()) ; output.addParam(channel); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP PING with unknown person - Desynchronized?"))); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP PING with unknown channel - Desynchronized?"))); } } else { if (message->ctcpDestination() == m_session->m_server->nick()) { IRCPerson *person = m_session->getPerson(mask.nick()); if (!person) { /* Person not yet known, create and add to the current session */ person = new IRCPerson(message->prefix()); m_session->addPerson(person); } IRCOutput output(OUTPUT_QUERYACTION, tr("Received a CTCP PING from ")+ mask.nick() ); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP PING with bad recipient"))); } } } void IRCMessageParser::parseCTCPVersion(IRCMessage *message) { IRCPerson mask(message->prefix()); - m_session->m_connection->sendCTCP(mask.nick(), "VERSION " APP_VERSION " " APP_COPYSTR); - emit outputReady(IRCOutput(OUTPUT_CTCP, tr("Received a CTCP VERSION from ")+mask.nick())); + IRCOutput output(OUTPUT_CTCP); + if(message->isCTCPRequest()) { + m_session->m_connection->sendCTCPReply(mask.nick(), "VERSION", APP_VERSION " " APP_COPYSTR); + output.setMessage(tr("Received a CTCP VERSION request from ") + mask.nick()); + } + + else { + output.setMessage("Received CTCP VERSION reply from " + mask.nick() + ":" + message->param(0)); + } + emit outputReady(output); } void IRCMessageParser::parseCTCPAction(IRCMessage *message) { IRCPerson mask(message->prefix()); QString dest = message->ctcpDestination(); if (dest.startsWith("#")) { IRCChannel *channel = m_session->getChannel(dest.lower()); if (channel) { IRCChannelPerson *person = channel->getPerson(mask.nick()); if (person) { IRCOutput output(OUTPUT_CHANACTION, "*" + mask.nick() + message->param(0)); output.addParam(channel); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP ACTION with unknown person - Desynchronized?"))); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP ACTION with unknown channel - Desynchronized?"))); } } else { if (message->ctcpDestination() == m_session->m_server->nick()) { IRCPerson *person = m_session->getPerson(mask.nick()); if (!person) { /* Person not yet known, create and add to the current session */ person = new IRCPerson(message->prefix()); m_session->addPerson(person); } IRCOutput output(OUTPUT_QUERYACTION, "*" + mask.nick() + message->param(0)); output.addParam(person); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("CTCP ACTION with bad recipient"))); } } } +void IRCMessageParser::parseCTCPDCC(IRCMessage *message) { + QStringList params = QStringList::split(' ', message->param(0).stripWhiteSpace()); + if( params.count() != 5) { + emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Malformed DCC request from ") + IRCPerson(message->prefix()).nick())); + return; + } + + //TransferReceiver *foo = new TransferReceiver(params[2].toUInt(), params[3].toUInt(), params[1], params[4].toUInt()); +} + void IRCMessageParser::parseLiteralMode(IRCMessage *message) { IRCPerson mask(message->prefix()); if (message->param(0).startsWith("#")) { IRCChannel *channel = m_session->getChannel(message->param(0).lower()); if (channel) { QString temp, parameters = message->allParameters().right(message->allParameters().length() - channel->channelname().length() - 1); QTextIStream stream(¶meters); bool set = FALSE; while (!stream.atEnd()) { stream >> temp; if (temp.startsWith("+")) { set = TRUE; temp = temp.right(1); - } else if (temp.startsWith("-")) { + } + else + if (temp.startsWith("-")) { set = FALSE; temp = temp.right(1); - } else { + } + else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change has unknown type"))); return; } if (temp == "o") { stream >> temp; IRCChannelPerson *person = channel->getPerson(temp); if (person) { - if (set) { - person->flags |= PERSON_FLAG_OP; - IRCOutput output(OUTPUT_CHANPERSONMODE, mask.nick() + tr(" gives channel operator status to " + person->person->nick())); - output.addParam(channel); - output.addParam(person); - emit outputReady(output); - } else { - person->flags &= 0xFFFF - PERSON_FLAG_OP; - IRCOutput output(OUTPUT_CHANPERSONMODE, mask.nick() + tr(" removes channel operator status from " + person->person->nick())); + IRCOutput output(OUTPUT_CHANPERSONMODE, person->setOp(mask.nick(), set)); output.addParam(channel); output.addParam(person); emit outputReady(output); } - } else { + else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change with unknown person - Desynchronized?"))); } - } else if (temp == "v") { + } + else + if (temp == "v") { stream >> temp; IRCChannelPerson *person = channel->getPerson(temp); if (person) { - if (set) { - person->flags |= PERSON_FLAG_VOICE; - IRCOutput output(OUTPUT_CHANPERSONMODE, mask.nick() + tr(" gives voice to " + person->person->nick())); - output.addParam(channel); - output.addParam(person); - emit outputReady(output); - } else { - person->flags &= 0xFFFF - PERSON_FLAG_VOICE; - IRCOutput output(OUTPUT_CHANPERSONMODE, mask.nick() + tr(" removes voice from " + person->person->nick())); + IRCOutput output(OUTPUT_CHANPERSONMODE, person->setVoice(mask.nick(), set)); output.addParam(channel); output.addParam(person); emit outputReady(output); } - } else { + else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change with unknown person - Desynchronized?"))); } - } else { + } + else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change with unknown flag"))); } } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Mode change with unknown kannel - Desynchronized?"))); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("User modes not supported yet"))); } } void IRCMessageParser::parseLiteralKick(IRCMessage *message) { IRCPerson mask(message->prefix()); IRCChannel *channel = m_session->getChannel(message->param(0).lower()); if (channel) { IRCChannelPerson *person = channel->getPerson(message->param(1)); if (person) { - if (person->person->nick() == m_session->m_server->nick()) { + if (person->nick() == m_session->m_server->nick()) { m_session->removeChannel(channel); IRCOutput output(OUTPUT_SELFKICK, tr("You were kicked from ") + channel->channelname() + tr(" by ") + mask.nick() + " (" + message->param(2) + ")"); output.addParam(channel); emit outputReady(output); } else { /* someone else got kicked */ channel->removePerson(person); - IRCOutput output(OUTPUT_OTHERKICK, person->person->nick() + tr(" was kicked from ") + channel->channelname() + tr(" by ") + mask.nick()+ " (" + message->param(2) + ")"); + IRCOutput output(OUTPUT_OTHERKICK, person->nick() + tr(" was kicked from ") + channel->channelname() + tr(" by ") + mask.nick()+ " (" + message->param(2) + ")"); output.addParam(channel); output.addParam(person); emit outputReady(output); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Unknown person kick - desynchronized?"))); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Unknown channel kick - desynchronized?"))); } } void IRCMessageParser::parseNumericalNames(IRCMessage *message) { /* Name list sent when joining a channel */ IRCChannel *channel = m_session->getChannel(message->param(2).lower()); if (channel != 0) { QString people = message->param(3); QTextIStream stream(&people); QString temp; while (!stream.atEnd()) { stream >> temp; char flagch = temp.at(0).latin1(); int flag = 0; QString nick; /* Parse person flags */ if (flagch == '@' || flagch == '+' || flagch=='%' || flagch == '*') { nick = temp.right(temp.length()-1); switch (flagch) { - case '@': flag = PERSON_FLAG_OP; break; - case '+': flag = PERSON_FLAG_VOICE; break; - case '%': flag = PERSON_FLAG_HALFOP; break; + case '@': flag = IRCChannelPerson::PERSON_FLAG_OP; break; + case '+': flag = IRCChannelPerson::PERSON_FLAG_VOICE; break; + case '%': flag = IRCChannelPerson::PERSON_FLAG_HALFOP; break; default : flag = 0; break; } } else { nick = temp; } - IRCChannelPerson *chan_person = new IRCChannelPerson(); IRCPerson *person = m_session->getPerson(nick); if (person == 0) { person = new IRCPerson(); person->setNick(nick); m_session->addPerson(person); } - chan_person->person = person; - chan_person->flags = flag; + IRCChannelPerson *chan_person = new IRCChannelPerson(person); + chan_person->setFlags(flag); channel->addPerson(chan_person); } } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Server message with unknown channel"))); } } void IRCMessageParser::parseNumericalEndOfNames(IRCMessage *message) { /* Done syncing to channel */ IRCChannel *channel = m_session->getChannel(message->param(1).lower()); if (channel) { channel->setHasPeople(TRUE); /* Yes, we want the names before anything happens inside the GUI */ IRCOutput output(OUTPUT_SELFJOIN, tr("You joined channel ") + channel->channelname()); output.addParam(channel); emit outputReady(output); } else { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Server message with unknown channel"))); } } void IRCMessageParser::parseNumericalNicknameInUse(IRCMessage *) { /* If we are connnected this error is not critical */ if(m_session->isLoggedIn()) return; emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Nickname is in use, please reconnect with a different nickname"))); m_session->endSession(); } void IRCMessageParser::parseNumericalNoSuchNick(IRCMessage *) { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("No such nickname"))); } void IRCMessageParser::parseNumericalTopic(IRCMessage *message) { IRCChannel *channel = m_session->getChannel(message->param(1).lower()); if (channel) { IRCOutput output(OUTPUT_TOPIC, tr("Topic for channel " + channel->channelname() + " is \"" + message->param(2) + "\"")); output.addParam(channel); emit outputReady(output); } else { IRCOutput output(OUTPUT_TOPIC, tr("Topic for channel " + message->param(1) + " is \"" + message->param(2) + "\"")); output.addParam(0); emit outputReady(output); } } void IRCMessageParser::parseNumericalTopicWhoTime(IRCMessage *) { } diff --git a/noncore/net/opieirc/ircmessageparser.h b/noncore/net/opieirc/ircmessageparser.h index 2fca61e..4ebbddd 100644 --- a/noncore/net/opieirc/ircmessageparser.h +++ b/noncore/net/opieirc/ircmessageparser.h @@ -14,86 +14,88 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IRCMESSAGEPARSER_H #define __IRCMESSAGEPARSER_H #include "ircsession.h" /* Macro to facilitate the parser table's creation */ #define FUNC(__proc) &IRCMessageParser::__proc class IRCMessageParser; /* Typedef representing a parser function */ typedef void (IRCMessageParser::*IRCMessageParseProc)(IRCMessage *); /* Struct representing a literal command handler */ typedef struct IRCLiteralMessageParserStruct { char *commandName; IRCMessageParseProc proc; }; /* Struct representing a ctcp command handler */ typedef struct IRCCTCPMessageParserStruct { char *commandName; IRCMessageParseProc proc; }; /* Struct representing a numerical command handler */ typedef struct IRCNumericalMessageParserStruct { unsigned short commandNumber; char *message; char *params; IRCMessageParseProc proc; }; class IRCMessageParser : public QObject { Q_OBJECT public: /* Create an IRCMessageParser object */ IRCMessageParser(IRCSession *session); /* Parse a server message and take the appropriate actions */ void parse(IRCMessage *message); signals: /* Used to send commands to the UI (such as displaying text etc) */ void outputReady(IRCOutput output); private: /* Parser functions */ void parseLiteralPing(IRCMessage *message); void parseLiteralNotice(IRCMessage *message); void parseLiteralJoin(IRCMessage *message); void parseLiteralPrivMsg(IRCMessage *message); void parseLiteralNick(IRCMessage *message); void parseLiteralPart(IRCMessage *message); void parseLiteralQuit(IRCMessage *message); void parseLiteralError(IRCMessage *message); void parseLiteralMode(IRCMessage *message); void parseLiteralKick(IRCMessage *message); void parseLiteralTopic(IRCMessage *message); void parseNumerical(IRCMessage *message, int position); + void parseCTCP(IRCMessage *message, int position); void parseNumericalServerName(IRCMessage *message); void parseNumericalServerFeatures(IRCMessage *message); void parseNumericalServerProtocol(IRCMessage *message); void parseNumericalWhoisIdle(IRCMessage *message); void parseNumericalNames(IRCMessage *message); void parseNumericalEndOfNames(IRCMessage *message); void parseNumericalNicknameInUse(IRCMessage *message); void parseNumericalNoSuchNick(IRCMessage *message); void parseNumericalTopic(IRCMessage *message); void parseNumericalTopicWhoTime(IRCMessage *message); void parseCTCPPing(IRCMessage *message); void parseCTCPVersion(IRCMessage *message); void parseCTCPAction(IRCMessage *message); + void parseCTCPDCC(IRCMessage *message); protected: IRCSession *m_session; /* Parser tables */ static IRCLiteralMessageParserStruct literalParserProcTable[]; static IRCNumericalMessageParserStruct numericalParserProcTable[]; static IRCCTCPMessageParserStruct ctcpParserProcTable[]; }; #endif /* __IRCMESSAGEPARSER_H */ diff --git a/noncore/net/opieirc/ircservertab.cpp b/noncore/net/opieirc/ircservertab.cpp index 90353f2..bddc37e 100644 --- a/noncore/net/opieirc/ircservertab.cpp +++ b/noncore/net/opieirc/ircservertab.cpp @@ -1,69 +1,70 @@ #include <qtextstream.h> #include <qwhatsthis.h> #include "ircservertab.h" #include "ircmessageparser.h" +#include "ircchannelperson.h" bool IRCServerTab::containsPing( const QString& text, IRCServerTab* tab ) { return (text.contains(IRCMessageParser::tr("Received a CTCP PING from "))) || (text.find("ping") != -1 && text.find( tab->server()->nick() != -1)); } IRCServerTab::IRCServerTab(IRCServer server, MainWindow *mainWindow, QWidget *parent, const char *name, WFlags f) : IRCTab(parent, name, f) { m_server = server; m_session = new IRCSession(&m_server); m_mainWindow = mainWindow; m_close = FALSE; m_lines = 0; m_description->setText(tr("Connecting to")+" <b>" + server.hostname() + ":" + QString::number(server.port()) + "</b>"); m_textview = new QTextView(this); m_textview->setHScrollBarMode(QScrollView::AlwaysOff); m_textview->setVScrollBarMode(QScrollView::AlwaysOn); m_textview->setTextFormat(RichText); QWhatsThis::add(m_textview, tr("Server messages")); m_layout->add(m_textview); m_field = new IRCHistoryLineEdit(this); connect(m_field, SIGNAL(nextTab()), this, SIGNAL(nextTab())); connect(m_field, SIGNAL(prevTab()), this, SIGNAL(prevTab())); connect(m_field, SIGNAL(closeTab()), this, SIGNAL(closeTab())); connect(this, SIGNAL(editFocus()), m_field, SLOT(setEditFocus())); QWhatsThis::add(m_field, tr("Type commands here. A list of available commands can be found inside the OpieIRC help")); m_layout->add(m_field); connect(m_field, SIGNAL(returnPressed()), this, SLOT(processCommand())); connect(m_session, SIGNAL(outputReady(IRCOutput)), this, SLOT(display(IRCOutput))); connect(m_mainWindow, SIGNAL(updateScroll()), this, SLOT(scrolling())); connect(m_session, SIGNAL(updateChannels()), this, SLOT(slotUpdateChannels())); settingsChanged(); m_field->setFocus(); m_field->setActiveWindow(); } void IRCServerTab::scrolling(){ m_textview->ensureVisible(0, m_textview->contentsHeight()); } void IRCServerTab::appendText(QString text) { /* not using append because it creates layout problems */ QString txt = m_textview->text() + IRCTab::appendTimestamp( text ); if (m_maxLines > 0 && m_lines >= m_maxLines) { int firstBreak = txt.find('\n'); if (firstBreak != -1) { txt = "<qt bgcolor=\"" + m_backgroundColor + "\"/>" + txt.right(txt.length() - (firstBreak + 1)); } } else { m_lines++; } m_textview->setText(txt); m_textview->ensureVisible(0, m_textview->contentsHeight()); emit changed(this); } @@ -250,129 +251,129 @@ void IRCServerTab::remove() { /* Session has previously been closed */ m_channelTabs.first(); while (m_channelTabs.current() != 0) { m_mainWindow->killTab(m_channelTabs.current(), true); } m_queryTabs.first(); while (m_queryTabs.current() != 0) { m_mainWindow->killTab(m_queryTabs.current(), true); } m_mainWindow->killTab(this); } } IRCChannelTab *IRCServerTab::getTabForChannel(IRCChannel *channel) { QListIterator<IRCChannelTab> it(m_channelTabs); for (; it.current(); ++it) { if (it.current()->channel() == channel) return it.current(); } return 0; } IRCQueryTab *IRCServerTab::getTabForQuery(IRCPerson *person) { QListIterator<IRCQueryTab> it(m_queryTabs); for (; it.current(); ++it) { if (it.current()->person()->nick() == person->nick()) return it.current(); } return 0; } void IRCServerTab::display(IRCOutput output) { /* All messages to be displayed inside the GUI get here */ switch (output.type()) { case OUTPUT_CONNCLOSE: if (m_close) { m_channelTabs.first(); while (m_channelTabs.current() != 0) { m_mainWindow->killTab(m_channelTabs.current(), true); } m_queryTabs.first(); while (m_queryTabs.current() != 0) { m_mainWindow->killTab(m_queryTabs.current(), true); } m_mainWindow->killTab(this); } else { appendText("<font color=\"" + m_errorColor + "\">" + output.htmlMessage() +"</font><br>"); QListIterator<IRCChannelTab> it(m_channelTabs); for (; it.current(); ++it) { it.current()->appendText("<font color=\"" + m_serverColor + "\">" + output.htmlMessage() +"</font><br>"); } } break; case OUTPUT_SELFJOIN: { IRCChannelTab *channeltab = new IRCChannelTab((IRCChannel *)output.getParam(0), this, m_mainWindow, (QWidget *)parent()); m_channelTabs.append(channeltab); m_mainWindow->addTab(channeltab); } break; case OUTPUT_CHANPRIVMSG: { IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0)); - channelTab->appendText("<font color=\"" + m_textColor + "\"><</font><font color=\"" + m_otherColor + "\">"+IRCOutput::toHTML(((IRCChannelPerson *)output.getParam(1))->person->nick())+"</font><font color=\"" + m_textColor + "\">> " + output.htmlMessage()+"</font><br>"); + channelTab->appendText("<font color=\"" + m_textColor + "\"><</font><font color=\"" + m_otherColor + "\">"+IRCOutput::toHTML(((IRCChannelPerson *)output.getParam(1))->nick())+"</font><font color=\"" + m_textColor + "\">> " + output.htmlMessage()+"</font><br>"); } break; case OUTPUT_QUERYACTION: case OUTPUT_QUERYPRIVMSG: { IRCQueryTab *queryTab = getTabForQuery((IRCPerson *)output.getParam(0)); if (!queryTab) { queryTab = new IRCQueryTab((IRCPerson *)output.getParam(0), this, m_mainWindow, (QWidget *)parent()); m_queryTabs.append(queryTab); m_mainWindow->addTab(queryTab); } queryTab->display(output); } break; case OUTPUT_SELFPART: { IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0)); if (channelTab) m_mainWindow->killTab(channelTab, true); } break; case OUTPUT_SELFKICK: { appendText("<font color=\"" + m_errorColor + "\">" + output.htmlMessage() + "</font><br>"); IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0)); if (channelTab) m_mainWindow->killTab(channelTab, true); } break; case OUTPUT_CHANACTION: { IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0)); channelTab->appendText("<font color=\"" + m_otherColor + "\">"+output.htmlMessage()+"</font><br>"); } break; case OUTPUT_TOPIC: { IRCChannel *channel = (IRCChannel *) output.getParam(0); if (channel) { IRCChannelTab *channelTab = getTabForChannel(channel); if (channelTab) { channelTab->appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); return; } } IRCChannelTab::enqueue(channel->channelname(), "<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); } break; case OUTPUT_QUIT: { QString nick = ((IRCPerson *)output.getParam(0))->nick(); QListIterator<IRCChannelTab> it(m_channelTabs); for (; it.current(); ++it) { if (it.current()->list()->hasPerson(nick)) { it.current()->appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); it.current()->list()->update(); } } } break; case OUTPUT_NICKCHANGE: { QString *nick = static_cast<QString*>(output.getParam(0)); if(!nick) { appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); break; } QListIterator<IRCChannelTab> it(m_channelTabs); for (; it.current(); ++it) { if (it.current()->list()->hasPerson(*nick)) { it.current()->appendText("<font color=\"" + m_notificationColor + "\">"+output.htmlMessage()+"</font><br>"); diff --git a/noncore/net/opieirc/ircsession.cpp b/noncore/net/opieirc/ircsession.cpp index ca0df50..80a327a 100644 --- a/noncore/net/opieirc/ircsession.cpp +++ b/noncore/net/opieirc/ircsession.cpp @@ -1,66 +1,68 @@ + #include "ircsession.h" #include "ircmessageparser.h" +#include "ircchannelperson.h" #include "ircversion.h" IRCSession::IRCSession(IRCServer *server) { m_server = server; m_connection = new IRCConnection(m_server); m_parser = new IRCMessageParser(this); connect(m_connection, SIGNAL(messageArrived(IRCMessage*)), this, SLOT(handleMessage(IRCMessage*))); connect(m_parser, SIGNAL(outputReady(IRCOutput)), this, SIGNAL(outputReady(IRCOutput))); connect(m_connection, SIGNAL(outputReady(IRCOutput)), this, SIGNAL(outputReady(IRCOutput))); } IRCSession::~IRCSession() { /* We want this to get deleted automatically */ m_channels.setAutoDelete(TRUE); m_people.setAutoDelete(TRUE); delete m_parser; delete m_connection; } void IRCSession::beginSession() { m_connection->doConnect(); } void IRCSession::join(QString channelname) { m_connection->sendLine("JOIN " + channelname); } void IRCSession::quit(){ m_connection->sendLine("QUIT :[OI] I'm too good to need a reason"); } void IRCSession::quit(QString message){ m_connection->sendLine("QUIT :" + message); } void IRCSession::topic(IRCChannel *channel, QString message){ m_connection->sendLine("TOPIC :" + channel->channelname() + " " + message); } void IRCSession::mode(IRCChannel *channel, QString message){ m_connection->sendLine("MODE " + channel->channelname() + " " + message); } void IRCSession::mode(IRCPerson *person, QString message){ m_connection->sendLine("MODE " + person->nick() + " " + message); } void IRCSession::mode(QString message){ m_connection->sendLine("MODE " + message); } void IRCSession::raw(QString message){ m_connection->sendLine(message); } void IRCSession::kick(IRCChannel *channel, IRCPerson *person) { m_connection->sendLine("KICK " + channel->channelname() + " " + person->nick() +" :0wn3d - no reason"); } void IRCSession::op(IRCChannel *channel, IRCPerson *person) { m_connection->sendLine("MODE " + channel->channelname() + " +ooo " + person->nick()); } @@ -76,121 +78,137 @@ void IRCSession::sendMessage(IRCChannel *channel, QString message) { m_connection->sendLine("PRIVMSG " + channel->channelname() + " :" + message); } void IRCSession::sendAction(IRCChannel *channel, QString message) { m_connection->sendLine("PRIVMSG " + channel->channelname() + " :\001ACTION " + message + "\001"); } void IRCSession::sendAction(IRCPerson *person, QString message) { m_connection->sendLine("PRIVMSG " + person->nick() + " :\001ACTION " + message + "\001"); } bool IRCSession::isSessionActive() { return m_connection->isConnected(); } bool IRCSession::isLoggedIn() { return m_connection->isLoggedIn(); } void IRCSession::endSession() { if (m_connection->isLoggedIn()) quit(APP_VERSION); else m_connection->close(); } void IRCSession::part(IRCChannel *channel) { m_connection->sendLine("PART " + channel->channelname() + " :" + APP_VERSION); } void IRCSession::setValidUsermodes(const QString &modes) { m_validUsermodes = modes; } void IRCSession::setValidChannelmodes(const QString &modes) { m_validChannelmodes = modes; } void IRCSession::updateNickname(const QString &oldNickname, const QString &newNickname) { QList<IRCChannel> channels; IRCOutput output; if (oldNickname == m_server->nick()) { m_server->setNick(newNickname); output = IRCOutput(OUTPUT_NICKCHANGE, tr("You are now known as %1").arg(newNickname)); channels = m_channels; } else { IRCPerson *person = getPerson(oldNickname); if(!person) { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Nickname change of an unknown person"))); return; } getChannelsByPerson(person, channels); output = IRCOutput(OUTPUT_NICKCHANGE, tr("%1 is now known as %2").arg(oldNickname).arg(newNickname)); } QListIterator<IRCChannel> it(channels); for (;it.current(); ++it) { IRCChannelPerson *chanperson = it.current()->getPerson(oldNickname); it.current()->removePerson(chanperson); - chanperson->person->setNick(newNickname); + chanperson->setNick(newNickname); it.current()->addPerson(chanperson); } emit updateChannels(); output.addParam(new QString(newNickname)); emit outputReady(output); } IRCChannel *IRCSession::getChannel(QString channelname) { QListIterator<IRCChannel> it(m_channels); for (; it.current(); ++it) { if (it.current()->channelname() == channelname) { return it.current(); } } return 0; } IRCPerson *IRCSession::getPerson(QString nickname) { QListIterator<IRCPerson> it(m_people); for (; it.current(); ++it) { if (it.current()->nick() == nickname) { return it.current(); } } return 0; } void IRCSession::getChannelsByPerson(IRCPerson *person, QList<IRCChannel> &channels) { QListIterator<IRCChannel> it(m_channels); for (; it.current(); ++it) { if (it.current()->getPerson(person->nick()) != 0) { channels.append(it.current()); } } } void IRCSession::addPerson(IRCPerson *person) { m_people.append(person); } void IRCSession::addChannel(IRCChannel *channel) { m_channels.append(channel); } void IRCSession::removeChannel(IRCChannel *channel) { m_channels.remove(channel); } void IRCSession::removePerson(IRCPerson *person) { m_people.remove(person); } void IRCSession::handleMessage(IRCMessage *message) { m_parser->parse(message); } + +void IRCSession::whois(const QString &nickname) { + m_connection->whois(nickname); +} + +void IRCSession::sendCTCPPing(const QString &nickname) { + m_connection->sendCTCPPing(nickname); +} + +void IRCSession::sendCTCPRequest(const QString &nickname, const QString &type, const QString &args) { + m_connection->sendCTCPRequest(nickname, type, args); +} + +void IRCSession::sendCTCPReply(const QString &nickname, const QString &type, const QString &args) { + m_connection->sendCTCPReply(nickname, type, args); +} diff --git a/noncore/net/opieirc/ircsession.h b/noncore/net/opieirc/ircsession.h index 96de3e4..3859b68 100644 --- a/noncore/net/opieirc/ircsession.h +++ b/noncore/net/opieirc/ircsession.h @@ -4,88 +4,92 @@ 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IRCSESSION_H #define __IRCSESSION_H #include <qstring.h> #include <qlist.h> #include "ircserver.h" #include "ircconnection.h" #include "ircmessage.h" #include "ircchannel.h" #include "ircoutput.h" class IRCMessageParser; /* The IRCSession stores all information relating to the connection to one IRC server. IRCSession makes it possible to run multiple IRC server connections from within the same program */ class IRCSession : public QObject { friend class IRCMessageParser; Q_OBJECT public: IRCSession(IRCServer *server); ~IRCSession(); void join(QString channel); void quit(QString message); void quit(); void raw(QString message); void topic(IRCChannel *channel, QString message); void mode(IRCChannel *channel, QString message); void mode(IRCPerson *person, QString message); void mode(QString message); void part(IRCChannel *channel); void op(IRCChannel *channel, IRCPerson *person); void kick(IRCChannel *channel, IRCPerson *person); void kick(IRCChannel *channel, IRCPerson *person, QString message); void beginSession(); bool isSessionActive(); void endSession(); bool isLoggedIn(); void sendMessage(IRCPerson *person, QString message); void sendMessage(IRCChannel *channel, QString message); void sendAction(IRCPerson *person, QString message); void sendAction(IRCChannel *channel, QString message); void updateNickname(const QString &oldNickname, const QString &newNickname); void setValidUsermodes(const QString &modes); void setValidChannelmodes(const QString &modes); + void whois(const QString &nickname); + void sendCTCPPing(const QString &nickname); + void sendCTCPRequest(const QString &nickname, const QString &type, const QString &args); + void sendCTCPReply(const QString &nickname, const QString &type, const QString &args); IRCChannel *getChannel(QString channelname); IRCPerson *getPerson(QString nickname); protected: void addPerson(IRCPerson *person); void addChannel(IRCChannel *channel); void removeChannel(IRCChannel *channel); void removePerson(IRCPerson *person); void getChannelsByPerson(IRCPerson *person, QList<IRCChannel> &channels); protected slots: void handleMessage(IRCMessage *message); signals: void outputReady(IRCOutput output); void updateChannels(); protected: IRCServer *m_server; IRCConnection *m_connection; IRCMessageParser *m_parser; QList<IRCChannel> m_channels; QList<IRCPerson> m_people; QString m_validUsermodes; QString m_validChannelmodes; }; #endif /* __IRCSESSION_H */ diff --git a/noncore/net/opieirc/mainwindow.cpp b/noncore/net/opieirc/mainwindow.cpp index 2562f33..1811a0c 100644 --- a/noncore/net/opieirc/mainwindow.cpp +++ b/noncore/net/opieirc/mainwindow.cpp @@ -1,135 +1,139 @@ #include <qmenubar.h> #include <qpe/resource.h> + +#include <opie2/odebug.h> + #include <qwhatsthis.h> #include "mainwindow.h" #include "ircservertab.h" #include "ircserverlist.h" #include "ircsettings.h" QString MainWindow::appCaption() { return QObject::tr("Opie IRC"); } MainWindow::MainWindow(QWidget *parent, const char *name, WFlags) : QMainWindow(parent, name, WStyle_ContextHelp) { setCaption(tr("IRC Client")); m_tabWidget = new IRCTabWidget(this); QWhatsThis::add(m_tabWidget, tr("Server connections, channels, queries and other things will be placed here")); connect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), this, SLOT(selected(QWidget*))); setCentralWidget(m_tabWidget); setToolBarsMovable(FALSE); QMenuBar *menuBar = new QMenuBar(this); QPopupMenu *irc = new QPopupMenu(this); menuBar->insertItem(tr("IRC"), irc); QAction *a = new QAction(tr("New connection"), Resource::loadPixmap("pass"), QString::null, 0, this, 0); connect(a, SIGNAL(activated()), this, SLOT(newConnection())); a->setWhatsThis(tr("Create a new connection to an IRC server")); a->addTo(irc); a = new QAction(tr("Settings"), Resource::loadPixmap("SettingsIcon"), QString::null, 0, this, 0); a->setWhatsThis(tr("Configure OpieIRC's behavior and appearance")); connect(a, SIGNAL(activated()), this, SLOT(settings())); a->addTo(irc); loadSettings(); } /*IRCTabWidget MainWindow::getTabWidget(){ return m_tabWidget; } */ void MainWindow::loadSettings() { Config config("OpieIRC"); config.setGroup("OpieIRC"); IRCTab::m_backgroundColor = config.readEntry("BackgroundColor", "#FFFFFF"); IRCTab::m_textColor = config.readEntry("TextColor", "#000000"); IRCTab::m_errorColor = config.readEntry("ErrorColor", "#FF0000"); IRCTab::m_selfColor = config.readEntry("SelfColor", "#CC0000"); IRCTab::m_otherColor = config.readEntry("OtherColor", "#0000BB"); IRCTab::m_serverColor = config.readEntry("ServerColor", "#0000FF"); IRCTab::m_notificationColor = config.readEntry("NotificationColor", "#AA3300"); IRCTab::m_maxLines = config.readNumEntry("Lines", 100); IRCTab::setUseTimeStamps( config.readBoolEntry("DisplayTime", false ) ); } void MainWindow::selected(QWidget *) { m_tabWidget->setTabColor(m_tabWidget->currentPageIndex(), black); emit updateScroll(); } void MainWindow::addTab(IRCTab *tab) { connect(tab, SIGNAL(changed(IRCTab*)), this, SLOT(changeEvent(IRCTab*))); connect(tab, SIGNAL(ping (const QString&)), this, SLOT(slotPing(const QString&))); connect(tab, SIGNAL(nextTab()), this, SLOT(slotNextTab())); connect(tab, SIGNAL(prevTab()), this, SLOT(slotPrevTab())); m_tabWidget->addTab(tab, tab->title()); m_tabWidget->showPage(tab); tab->setID(m_tabWidget->currentPageIndex()); m_tabs.append(tab); } void MainWindow::changeEvent(IRCTab *tab) { if (tab->id() != m_tabWidget->currentPageIndex()) m_tabWidget->setTabColor(tab->id(), blue); } void MainWindow::killTab(IRCTab *tab, bool imediate) { m_toDelete.append( tab ); if ( imediate ) slotKillTabsLater(); else QTimer::singleShot(0, this, SLOT(slotKillTabsLater()) ); } void MainWindow::slotKillTabsLater() { for ( QListIterator<IRCTab> it(m_toDelete); it.current(); ++it ) { m_tabWidget->removePage( it.current() ); + odebug << it.current() << oendl; m_tabs.remove( it.current() ); } m_toDelete.setAutoDelete( true ); m_toDelete.clear(); m_toDelete.setAutoDelete( false ); } void MainWindow::newConnection() { IRCServerList list(this, "ServerList", TRUE); if (list.exec() == QDialog::Accepted && list.hasServer()) { IRCServerTab *serverTab = new IRCServerTab(list.server(), this, m_tabWidget); addTab(serverTab); serverTab->doConnect(); } } void MainWindow::settings() { IRCSettings settings(this, "Settings", TRUE); if (settings.exec() == QDialog::Accepted) { QListIterator<IRCTab> it(m_tabs); for (; it.current(); ++it) { /* Inform all tabs about the new settings */ it.current()->settingsChanged(); } } } void MainWindow::slotNextTab() { int i = m_tabWidget->currentPageIndex (); m_tabWidget->setCurrentPage ( i+1 ); int j = m_tabWidget->currentPageIndex (); if ( i == j ) m_tabWidget->setCurrentPage ( 1 ); } void MainWindow::slotPrevTab() { int i = m_tabWidget->currentPageIndex (); if ( i > 1 ) m_tabWidget->setCurrentPage ( i-1 ); } void MainWindow::slotPing( const QString& /*channel*/ ) { raise(); } diff --git a/noncore/net/opieirc/opieirc.pro b/noncore/net/opieirc/opieirc.pro index db89fa6..1ef9be2 100644 --- a/noncore/net/opieirc/opieirc.pro +++ b/noncore/net/opieirc/opieirc.pro @@ -1,28 +1,30 @@ CONFIG = qt warn_on quick-app HEADERS = ircchannel.h ircconnection.h \ ircmessage.h \ ircmessageparser.h ircoutput.h \ ircperson.h ircserver.h ircsession.h \ mainwindow.h irctab.h ircservertab.h \ ircchanneltab.h ircchannellist.h \ ircserverlist.h ircservereditor.h \ - ircquerytab.h ircsettings.h ircmisc.h + ircquerytab.h ircsettings.h ircmisc.h \ + ircchannelperson.h SOURCES = ircchannel.cpp ircconnection.cpp \ ircmessage.cpp \ ircmessageparser.cpp ircoutput.cpp \ ircperson.cpp ircserver.cpp \ ircsession.cpp main.cpp mainwindow.cpp \ irctab.cpp ircservertab.cpp \ ircchanneltab.cpp ircchannellist.cpp \ ircserverlist.cpp ircservereditor.cpp \ - ircquerytab.cpp ircsettings.cpp ircmisc.cpp + ircquerytab.cpp ircsettings.cpp ircmisc.cpp \ + ircchannelperson.cpp INCLUDEPATH += $(OPIEDIR)/include DEPENDPATH += $(OPIEDIR)/include PRECOMPILED_HEADER = stable.h LIBS += -lqpe -lopiecore2 -lopieui2 -lqtaux2 TARGET = opieirc include( $(OPIEDIR)/include.pro ) |