So rather than using /quote, you might now use standard IRC commands for most tasks.
Also, work has been done for further prettifiying the output.
gui/identities.h
network/buffer.cpp
network/buffer.h
+gui/channelwidgetinput.h
+gui/channelwidgetinput.cpp
+plugins/plugin.h
-SET(gui_SRCS channelwidget.cpp mainwin.cpp serverlist.cpp identities.cpp coreconnectdlg.cpp guiproxy.cpp)
+SET(gui_SRCS channelwidget.cpp channelwidgetinput.cpp mainwin.cpp serverlist.cpp
+ identities.cpp coreconnectdlg.cpp guiproxy.cpp)
SET(gui_HDRS )
-SET(gui_MOCS channelwidget.h mainwin.h serverlist.h identities.h coreconnectdlg.h guiproxy.h)
+SET(gui_MOCS channelwidget.h channelwidgetinput.h mainwin.h serverlist.h identities.h coreconnectdlg.h guiproxy.h)
SET(gui_UICS channelwidget.ui identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui
nickeditdlg.ui serverlistdlg.ui servereditdlg.ui coreconnectdlg.ui ircwidget.ui)
ui.topicEdit->hide();
ui.chanSettingsButton->hide();
}
+ connect(ui.nickTree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*)));
+ connect(ui.nickTree, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*)));
connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed()));
- //ui.inputEdit->setFocus();
+ connect(this, SIGNAL(nickListChanged(QStringList)), ui.inputEdit, SLOT(updateNickList(QStringList)));
+ ui.inputEdit->setFocus();
+
+ opsExpanded = voicedExpanded = usersExpanded = true;
// Define standard colors
stdCol = "black";
kickCol = "firebrick";
nickCol = "magenta";
+ completer = 0;
}
void ChannelWidget::enterPressed() {
- emit sendInput(networkName(), bufferName(), ui.inputEdit->text());
+ QStringList lines = ui.inputEdit->text().split('\n', QString::SkipEmptyParts);
+ foreach(QString msg, lines) {
+ if(msg.isEmpty()) continue;
+ emit sendInput(networkName(), bufferName(), msg);
+ }
ui.inputEdit->clear();
}
break;
case Message::Join:
c = joinCol;
- s = QString(tr("--> %1 (%2@%3) has joined %4")).arg(nick).arg(user).arg(host).arg(bufferName());
+ s = QString(tr("--> %1 (%2@%3) has joined %4")).arg(nick).arg(user).arg(host).arg(bufferName());
break;
case Message::Part:
c = partCol;
- s = QString(tr("<-- %1 (%2@%3) has left %4")).arg(nick).arg(user).arg(host).arg(bufferName());
+ s = QString(tr("<-- %1 (%2@%3) has left %4")).arg(nick).arg(user).arg(host).arg(bufferName());
if(!msg.msg.isEmpty()) s = QString("%1 (%2)").arg(s).arg(msg.msg);
break;
case Message::Kick:
{ c = kickCol;
QString victim = msg.msg.section(" ", 0, 0);
+ if(victim == ui.ownNick->currentText()) victim = tr("you");
QString kickmsg = msg.msg.section(" ", 1);
- s = QString(tr("--> %1 has kicked %2 from %3")).arg(nick).arg(victim).arg(bufferName());
+ s = QString(tr("--> %1 has kicked %2 from %3")).arg(nick).arg(victim).arg(bufferName());
if(!kickmsg.isEmpty()) s = QString("%1 (%2)").arg(s).arg(kickmsg);
}
break;
case Message::Quit:
c = quitCol;
- s = QString(tr("<-- %1 (%2@%3) has quit")).arg(nick).arg(user).arg(host);
+ s = QString(tr("<-- %1 (%2@%3) has quit")).arg(nick).arg(user).arg(host);
if(!msg.msg.isEmpty()) s = QString("%1 (%2)").arg(s).arg(msg.msg);
break;
case Message::Nick:
c = nickCol;
- if(nick == msg.msg) s = QString(tr("<-> You are now known as %1")).arg(msg.msg);
- else s = QString(tr("<-> %1 is now known as %2")).arg(nick).arg(msg.msg);
+ if(nick == msg.msg) s = QString(tr("<-> You are now known as %1")).arg(msg.msg);
+ else s = QString(tr("<-> %1 is now known as %2")).arg(nick).arg(msg.msg);
+ break;
+ case Message::Mode:
+ c = serverCol;
+ if(nick.isEmpty()) s = tr("* User mode: %1").arg(msg.msg);
+ else s = tr("* Mode %1 by %2").arg(msg.msg).arg(nick);
break;
default:
c = stdCol; n = QString("[%1]").arg(msg.sender); s = msg.msg;
break;
}
+ s.replace('&', "&"); s.replace('<', "<"); s.replace('>', ">");
QString html = QString("<table cellspacing=0 cellpadding=0><tr>"
"<td width=50><div style=\"color:%2;\">[%1]</div></td>")
.arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")).arg("darkblue");
if(!n.isEmpty())
html += QString("<td width=150><div align=right style=\"white-space:pre;margin-left:6px;color:%2;\">%1</div></td>")
- .arg(n).arg("mediumseagreen");
- html += QString("<td><div style=\"margin-left:6px;color:%2;\">%1</div></td>""</tr></table>")
- .arg(s).arg(c);
+ .arg(n).arg("royalblue");
+ html += QString("<td><div style=\"margin-left:6px;color:%2;\">%1</div></td>""</tr></table>").arg(s).arg(c);
ui.chatWidget->append(html);
//ui.chatWidget->append(QString("<table border=1 cellspacing=0 cellpadding=0><tr><td>%1</td><td width=100 style=border-right-width:1px;><div style=margin-left:8px; margin-right:8px;>%2</div></td><td style=color:firebrick> %3</td></tr></table>")
//.arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")).arg(nick).arg(s));
- //ui.chatWidget->setTextColor(stdCol);
- //ui.chatWidget->append(QString("[%1] ").arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")));
- //ui.chatWidget->setTextColor(c);
- //ui.chatWidget->append(s + "\n");
- //ui.chatWidget->insertHtml(QString("<table><tr><td>[12:13]</td><td width=20><div align=right>[nickname]</div></td><td>This is the Message!</td></tr>"
- // "<tr><td>[12:13]</td><td><div align=right>[nick]</div></td><td>This is the Message!</td></tr>"
- // "<tr><td>[12:13]</td><td><div align=right>[looongnickname]</div></td><td>This is the Message!</td></tr>"
- // "<tr><td>[12:13]</td><td><div align=right>[nickname]</div></td><td>This is the Message!</td></tr></table>"
- // ));
ui.chatWidget->ensureCursorVisible();
}
void ChannelWidget::addNick(QString nick, VarMap props) {
nicks[nick] = props;
updateNickList();
+ if(completer) delete completer;
+ completer = new QCompleter(nicks.keys());
+ ui.inputEdit->setCompleter(completer);
}
void ChannelWidget::updateNick(QString nick, VarMap props) {
if(ops->childCount()) {
ops->setText(0, tr("%1 Operators").arg(ops->childCount()));
ui.nickTree->addTopLevelItem(ops);
- ops->setExpanded(true);
+ ops->setExpanded(opsExpanded);
} else delete ops;
if(voiced->childCount()) {
voiced->setText(0, tr("%1 Voiced").arg(voiced->childCount()));
ui.nickTree->addTopLevelItem(voiced);
- voiced->setExpanded(true);
+ voiced->setExpanded(voicedExpanded);
} else delete voiced;
if(users->childCount()) {
users->setText(0, tr("%1 Users").arg(users->childCount()));
ui.nickTree->addTopLevelItem(users);
- users->setExpanded(true);
+ users->setExpanded(usersExpanded);
} else delete users;
}
+
+void ChannelWidget::itemExpansionChanged(QTreeWidgetItem *item) {
+ if(item->child(0)->text(0).startsWith('@')) opsExpanded = item->isExpanded();
+ else if(item->child(0)->text(0).startsWith('+')) voicedExpanded = item->isExpanded();
+ else usersExpanded = item->isExpanded();
+}
+
/**********************************************************************************************/
connect(cw, SIGNAL(sendInput(QString, QString, QString)), this, SLOT(userInput(QString, QString, QString)));
ui.tabWidget->addTab(cw, net+buf);
ui.tabWidget->setCurrentWidget(cw);
- //cw->setFocus();
+ cw->setFocus();
buffers[key] = cw;
}
return buffers[key];
void IrcWidget::removeNick(QString net, QString nick) {
VarMap chans = nicks[net].toMap()[nick].toMap()["Channels"].toMap();
- qDebug() << "REMOVE" << nick;
foreach(QString bufname, chans.keys()) {
- qDebug() << "remove from"<<bufname;
getBuffer(net, bufname)->removeNick(nick);
}
VarMap netnicks = nicks[net].toMap();
QString bufferName() { return _bufferName; }
QString networkName() { return _networkName; }
+
signals:
void sendInput(QString, QString, QString);
+ void nickListChanged(QStringList);
public slots:
void recvMessage(Message);
void enterPressed();
void updateNickList();
+ void itemExpansionChanged(QTreeWidgetItem *);
+
private:
Ui::ChannelWidget ui;
QString _networkName;
QString _bufferName;
VarMap nicks;
+
+ QCompleter *completer;
+
+ bool opsExpanded, voicedExpanded, usersExpanded;
};
/** Temporary widget for displaying a set of ChannelWidgets. */
</widget>
</item>
<item>
- <widget class="QLineEdit" name="inputEdit" >
+ <widget class="ChannelWidgetInput" name="inputEdit" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>3</hsizetype>
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>ChannelWidgetInput</class>
+ <extends>QLineEdit</extends>
+ <header>channelwidgetinput.h</header>
+ </customwidget>
+ </customwidgets>
<tabstops>
<tabstop>inputEdit</tabstop>
<tabstop>ownNick</tabstop>
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 by The Quassel Team *
+ * devel@quassel-irc.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. *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#include "channelwidgetinput.h"
+
+ChannelWidgetInput::ChannelWidgetInput(QWidget *parent) : QLineEdit(parent) {
+ idx = 0;
+ connect(this, SIGNAL(returnPressed()), this, SLOT(enter()));
+}
+
+void ChannelWidgetInput::keyPressEvent(QKeyEvent * event) {
+ if(event->key() == Qt::Key_Up) {
+ if(idx > 0) { idx--; setText(history[idx]); }
+ event->accept();
+ } else if(event->key() == Qt::Key_Down) {
+ if(idx < history.count()) idx++;
+ if(idx < history.count()) setText(history[idx]);
+ else setText("");
+ event->accept();
+ } else if(event->key() == Qt::Key_Tab) {
+ // Tabcomplete
+ if(cursorPosition() == text().length()) {
+
+
+ }
+ event->accept();
+ } else {
+ QLineEdit::keyPressEvent(event);
+ }
+}
+
+bool ChannelWidgetInput::event(QEvent *e) {
+ if(e->type() == QEvent::KeyPress) {
+ keyPressEvent(dynamic_cast<QKeyEvent*>(e));
+ return true;
+ }
+ return QLineEdit::event(e);
+}
+
+void ChannelWidgetInput::enter() {
+ history << text();
+ idx = history.count();
+}
+
+void ChannelWidgetInput::updateNickList(QStringList l) {
+ nickList = l;
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 by The Quassel Team *
+ * devel@quassel-irc.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. *
+ * *
+ * 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 _CHANNELWIDGETINPUT_H_
+#define _CHANNELWIDGETINPUT_H_
+
+#include <QtCore>
+#include <QtGui>
+
+class ChannelWidgetInput : public QLineEdit {
+ Q_OBJECT
+
+ public:
+ ChannelWidgetInput(QWidget *parent = 0);
+
+ public slots:
+ void updateNickList(QStringList);
+
+ protected:
+ virtual bool event(QEvent *);
+ virtual void keyPressEvent(QKeyEvent * event);
+
+ private slots:
+ void enter();
+
+ private:
+ qint32 idx;
+ QStringList history;
+ QStringList nickList;
+
+};
+
+#endif
#include <QDataStream>
QDataStream &operator<<(QDataStream &out, const Message &msg) {
- out << (quint8)msg.type << (quint8)msg.flags << msg.sender << msg.msg << (quint32)msg.timeStamp.toTime_t();
+ out << (quint32)msg.timeStamp.toTime_t() << (quint8)msg.type << (quint8)msg.flags << msg.sender << msg.msg;
return out;
}
QDataStream &operator>>(QDataStream &in, Message &msg) {
quint8 t, f;
quint32 ts;
- in >> t >> f >> msg.sender >> msg.msg >> ts;
+ in >> ts >> t >> f >> msg.sender >> msg.msg;
msg.type = (Message::Type)t;
msg.flags = (Message::Flags)f;
msg.timeStamp = QDateTime::fromTime_t(ts);
return userhost.section('@', 1);
}
+bool isChannelName(QString str) {
+ return QString("#&!+").contains(str[0]);
+}
+
void writeDataToDevice(QIODevice *dev, const QVariant &item) {
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
QString userFromMask(QString mask);
QString hostFromMask(QString mask);
+bool isChannelName(QString str);
+
/**
* Writes a QVariant to a device. The data item is prefixed with the resulting blocksize,
* so the corresponding function readDataFromDevice() can check if enough data is available
if(!msg.startsWith('/')) {
msg = QString("/SAY ") + msg;
}
- handleUserMsg(buf, msg);
+ handleUserInput(buf, msg);
}
void Server::putRawLine(QString s) {
}
cmd = msg.section(' ', 0, 0).toUpper();
msg = msg.section(' ', 1);
- QString left = msg.section(':', 0, 0);
- QString trailing = msg.section(':', 1);
+ QString left, trailing;
+ // RPL_ISUPPORT (005) can contain colons, so don't treat it like the rest of the commands
+ if(cmd.toUInt() == 5) {
+ left = msg.remove(QString(":are supported by this server"));
+ } else {
+ left = msg.section(':', 0, 0);
+ trailing = msg.section(':', 1);
+ }
if(!left.isEmpty()) {
params << left.split(' ', QString::SkipEmptyParts);
}
case 2: case 3: case 4: case 5: case 251: case 252: case 253: case 254: case 255: case 372: case 375:
emit displayMsg("", Message(Message::Server, params.join(" "), prefix));
break;
+ // Server error messages, display them in red. First param will be appended.
+ case 401: case 402: case 403: case 404:
+ { QString p = params.takeFirst();
+ emit displayMsg("", Message(Message::Error, params.join(" ") + " " + p, prefix));
+ break;
+ }
// Ignore these commands.
case 366: case 376:
break;
}
}
-void Server::handleUserMsg(QString bufname, QString usrMsg) {
+void Server::handleUserInput(QString bufname, QString usrMsg) {
try {
+ /* Looks like we don't need core-side buffers...
Buffer *buffer = 0;
if(!bufname.isEmpty()) {
Q_ASSERT(buffers.contains(bufname));
buffer = buffers[bufname];
}
+ */
QString cmd = usrMsg.section(' ', 0, 0).remove(0, 1).toUpper();
QString msg = usrMsg.section(' ', 1).trimmed();
QString hname = cmd.toLower();
hname[0] = hname[0].toUpper();
hname = "handleUser" + hname;
- if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(QString, msg), Q_ARG(Buffer*, buffer))) {
+ if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(QString, bufname), Q_ARG(QString, msg))) {
// Ok. Default handler it is.
- defaultUserHandler(cmd, msg, buffer);
+ defaultUserHandler(bufname, cmd, msg);
}
} catch(Exception e) {
emit displayMsg("", Message(Message::Error, e.msg()));
}
}
-void Server::defaultUserHandler(QString cmd, QString msg, Buffer *buf) {
+void Server::defaultUserHandler(QString bufname, QString cmd, QString msg) {
emit displayMsg("", Message(Message::Error, QString("Error: %1 %2").arg(cmd).arg(msg)));
}
/**********************************************************************************/
/*
-void Server::handleUser(QString msg, Buffer *buf) {
+void Server::handleUser(QString bufname, QString msg) {
}
*/
-void Server::handleUserJoin(QString msg, Buffer *buf) {
+void Server::handleUserAway(QString bufname, QString msg) {
+ putCmd("AWAY", QStringList(msg));
+}
+
+void Server::handleUserDeop(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'o';
+ QStringList params;
+ params << bufname << m << nicks;
+ putCmd("MODE", params);
+}
+
+void Server::handleUserDevoice(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'v';
+ QStringList params;
+ params << bufname << m << nicks;
+ putCmd("MODE", params);
+}
+
+void Server::handleUserInvite(QString bufname, QString msg) {
+ QStringList params;
+ params << msg << bufname;
+ putCmd("INVITE", params);
+}
+
+void Server::handleUserJoin(QString bufname, QString msg) {
putCmd("JOIN", QStringList(msg));
+}
+
+void Server::handleUserKick(QString bufname, QString msg) {
+ QStringList params;
+ params << bufname << msg.split(' ', QString::SkipEmptyParts);
+ putCmd("KICK", params);
+}
+
+void Server::handleUserList(QString bufname, QString msg) {
+ putCmd("LIST", msg.split(' ', QString::SkipEmptyParts));
+}
+
+void Server::handleUserMode(QString bufname, QString msg) {
+ putCmd("MODE", msg.split(' ', QString::SkipEmptyParts));
+}
+
+void Server::handleUserMsg(QString bufname, QString msg) {
+ QString nick = msg.section(" ", 0, 0);
+ msg = msg.section(" ", 1).trimmed();
+ if(nick.isEmpty() || msg.isEmpty()) return;
+ QStringList params;
+ params << nick << msg;
+ putCmd("PRIVMSG", params);
+}
+
+void Server::handleUserNick(QString bufname, QString msg) {
+ QString nick = msg.section(' ', 0, 0);
+ putCmd("NICK", QStringList(nick));
+}
+
+void Server::handleUserOp(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'o';
+ QStringList params;
+ params << bufname << m << nicks;
+ putCmd("MODE", params);
+}
+
+void Server::handleUserPart(QString bufname, QString msg) {
+ QStringList params;
+ params << bufname << msg;
+ putCmd("PART", params);
+}
+void Server::handleUserQuit(QString bufname, QString msg) {
+ putCmd("QUIT", QStringList(msg));
}
-void Server::handleUserQuote(QString msg, Buffer *buf) {
+void Server::handleUserQuote(QString bufname, QString msg) {
putRawLine(msg);
}
-void Server::handleUserSay(QString msg, Buffer *buf) {
- if(!buf) return; // server buffer
+void Server::handleUserSay(QString bufname, QString msg) {
+ if(bufname.isEmpty()) return; // server buffer
QStringList params;
- params << buf->name() << msg;
+ params << bufname << msg;
putCmd("PRIVMSG", params);
emit displayMsg(params[0], Message(Message::Msg, msg, currentNick, Message::Self));
}
+void Server::handleUserVoice(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'v';
+ QStringList params;
+ params << bufname << m << nicks;
+ putCmd("MODE", params);
+}
+
/**********************************************************************************/
void Server::handleServerJoin(QString prefix, QStringList params) {
Q_ASSERT(params.count() == 1);
QString nick = updateNickFromMask(prefix);
if(nick == currentNick) {
- Q_ASSERT(!buffers.contains(params[0])); // cannot join a buffer twice!
- Buffer *buf = new Buffer(params[0]);
- buffers[params[0]] = buf;
+ // Q_ASSERT(!buffers.contains(params[0])); // cannot join a buffer twice!
+ // Buffer *buf = new Buffer(params[0]);
+ // buffers[params[0]] = buf;
} else {
VarMap n;
if(nicks.contains(nick)) {
}
}
+void Server::handleServerMode(QString prefix, QStringList params) {
+ if(isChannelName(params[0])) {
+ // TODO only channel-user modes supported by now
+ QString prefixes = serverSupports["PrefixModes"].toString();
+ QString modes = params[1];
+ int p = 2;
+ int m = 0;
+ bool add = true;
+ while(m < modes.length()) {
+ if(modes[m] == '+') { add = true; m++; continue; }
+ if(modes[m] == '-') { add = false; m++; continue; }
+ if(prefixes.contains(modes[m])) { // it's a user channel mode
+ Q_ASSERT(params.count() > m && nicks.contains(params[p]));
+ QString nick = params[p++];
+ VarMap n = nicks[nick].toMap(); VarMap clist = n["Channels"].toMap(); VarMap chan = clist[params[0]].toMap();
+ QString mstr = chan["Mode"].toString();
+ add ? mstr += modes[m] : mstr.remove(modes[m]);
+ chan["Mode"] = mstr; clist[params[0]] = chan; n["Channels"] = clist; nicks[nick] = n;
+ emit nickUpdated(network, nick, n);
+ m++;
+ } else {
+ // TODO add more modes
+ m++;
+ }
+ }
+ emit displayMsg(params[0], Message(Message::Mode, params.join(" "), prefix));
+ } else {
+ //Q_ASSERT(nicks.contains(params[0]));
+ //VarMap n = nicks[params[0]].toMap();
+ //QString mode = n["Mode"].toString();
+ emit displayMsg("", Message(Message::Mode, params.join(" ")));
+ }
+}
+
void Server::handleServerNick(QString prefix, QStringList params) {
QString oldnick = updateNickFromMask(prefix);
QString newnick = params[0];
emit displayMsg("", Message(Message::Server, params[1], prefix));
}
+/* RPL_ISUPPORT */
+void Server::handleServer005(QString prefix, QStringList params) {
+ foreach(QString p, params) {
+ QString key = p.section("=", 0, 0);
+ QString val = p.section("=", 1);
+ serverSupports[key] = val;
+ // handle some special cases
+ if(key == "PREFIX") {
+ VarMap foo; QString modes, prefixes;
+ Q_ASSERT(val.contains(')') && val.startsWith('('));
+ int m = 1, p;
+ for(p = 2; p < val.length(); p++) if(val[p] == ')') break;
+ p++;
+ for(; val[m] != ')'; m++, p++) {
+ Q_ASSERT(p < val.length());
+ foo[QString(val[m])] = QString(val[p]);
+ modes += val[m]; prefixes += val[p];
+ }
+ serverSupports["PrefixModes"] = modes; serverSupports["Prefixes"] = prefixes;
+ serverSupports["ModePrefixMap"] = foo;
+ }
+ }
+}
+
+
/* RPL_NOTOPIC */
void Server::handleServer331(QString prefix, QStringList params) {
emit topicSet(network, params[0], "");
void Server::handleServer353(QString prefix, QStringList params) {
params.removeFirst(); // = or *
QString buf = params.takeFirst();
+ QString prefixes = serverSupports["Prefixes"].toString();
foreach(QString nick, params[0].split(' ')) {
- // TODO: parse more prefix characters! use 005?
- QString mode = "";
- if(nick.startsWith('@')) { mode = "o"; nick.remove(0,1); }
- else if(nick.startsWith('+')) { mode = "v"; nick.remove(0,1); }
- VarMap c; c["Mode"] = mode;
+ QString mode = "", pfx = "";
+ if(prefixes.contains(nick[0])) {
+ pfx = nick[0];
+ for(int i = 0;; i++)
+ if(prefixes[i] == nick[0]) { mode = serverSupports["PrefixModes"].toString()[i]; break; }
+ nick.remove(0,1);
+ }
+ VarMap c; c["Mode"] = mode; c["Prefix"] = pfx;
if(nicks.contains(nick)) {
VarMap n = nicks[nick].toMap();
VarMap chans = n["Channels"].toMap();
/* Message Handlers */
- /* void handleUser(QString, Buffer *) */
- void handleUserJoin(QString, Buffer *);
- void handleUserQuote(QString, Buffer *);
- void handleUserSay(QString, Buffer *);
-
+ /* void handleUser(QString, QString); */
+ void handleUserAway(QString, QString);
+ void handleUserDeop(QString, QString);
+ void handleUserDevoice(QString, QString);
+ void handleUserInvite(QString, QString);
+ void handleUserJoin(QString, QString);
+ void handleUserKick(QString, QString);
+ void handleUserList(QString, QString);
+ void handleUserMode(QString, QString);
+ void handleUserMsg(QString, QString);
+ void handleUserNick(QString, QString);
+ void handleUserOp(QString, QString);
+ void handleUserPart(QString, QString);
+ void handleUserQuit(QString, QString);
+ void handleUserQuote(QString, QString);
+ void handleUserSay(QString, QString);
+ void handleUserVoice(QString, QString);
/* void handleServer(QString, QStringList); */
void handleServerJoin(QString, QStringList);
void handleServerKick(QString, QStringList);
+ void handleServerMode(QString, QStringList);
void handleServerNick(QString, QStringList);
void handleServerNotice(QString, QStringList);
void handleServerPart(QString, QStringList);
void handleServerQuit(QString, QStringList);
void handleServer001(QString, QStringList); // RPL_WELCOME
+ void handleServer005(QString, QStringList); // RPL_ISUPPORT
void handleServer331(QString, QStringList); // RPL_NOTOPIC
void handleServer332(QString, QStringList); // RPL_TOPIC
void handleServer333(QString, QStringList); // Topic set by...
void handleServer353(QString, QStringList); // RPL_NAMREPLY
void defaultServerHandler(QString cmd, QString prefix, QStringList params);
- void defaultUserHandler(QString cmd, QString msg, Buffer *buf);
+ void defaultUserHandler(QString buf, QString cmd, QString msg);
private:
QString network;
QTcpSocket socket;
- QHash<QString, Buffer*> buffers;
+ //QHash<QString, Buffer*> buffers;
QString currentNick;
QString currentServer;
VarMap networkSettings;
VarMap identity;
VarMap nicks; // stores all known nicks for the server
+ VarMap serverSupports; // stores results from RPL_ISUPPORT
void handleServerMsg(QString rawMsg);
- void handleUserMsg(QString buffer, QString usrMsg);
+ void handleUserInput(QString buffer, QString usrMsg);
QString updateNickFromMask(QString mask);