From: Manuel Nickschas Date: Wed, 25 Oct 2006 01:14:22 +0000 (+0000) Subject: Lots of additions again. Working on implementing commands and prettifying the output. X-Git-Tag: 0.1.0~261 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=057883f768f86257c9dbefeb5ef12403b207b773 Lots of additions again. Working on implementing commands and prettifying the output. Still work in progress, of course. At least we have a sorta working nick list now, even though only joins are handled by now. Oh, and timestamps and stuff. --- diff --git a/core/core.cpp b/core/core.cpp index 6270527f..44c925a0 100644 --- a/core/core.cpp +++ b/core/core.cpp @@ -30,8 +30,8 @@ Core::Core() { connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList))); connect(coreProxy, SIGNAL(gsUserInput(QString, QString, QString)), this, SIGNAL(msgFromGUI(QString, QString, QString))); - connect(this, SIGNAL(sendMessage(QString, QString, Message)), coreProxy, SLOT(csSendMessage(QString, QString, Message))); - connect(this, SIGNAL(sendStatusMsg(QString, QString)), coreProxy, SLOT(csSendStatusMsg(QString, QString))); + connect(this, SIGNAL(displayMsg(QString, QString, Message)), coreProxy, SLOT(csDisplayMsg(QString, QString, Message))); + connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString))); // Read global settings from config file QSettings s; @@ -63,10 +63,15 @@ void Core::connectToIrc(QStringList networks) { connect(this, SIGNAL(connectToIrc(QString)), server, SLOT(connectToIrc(QString))); connect(this, SIGNAL(disconnectFromIrc(QString)), server, SLOT(disconnectFromIrc(QString))); connect(this, SIGNAL(msgFromGUI(QString, QString, QString)), server, SLOT(userInput(QString, QString, QString))); - connect(server, SIGNAL(sendMessage(QString, Message)), this, SLOT(recvMessageFromServer(QString, Message))); - connect(server, SIGNAL(sendStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString))); - connect(server, SIGNAL(setTopic(QString, QString, QString)), coreProxy, SLOT(csSetTopic(QString, QString, QString))); + connect(server, SIGNAL(displayMsg(QString, Message)), this, SLOT(recvMessageFromServer(QString, Message))); + connect(server, SIGNAL(displayStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString))); + connect(server, SIGNAL(modeSet(QString, QString, QString)), coreProxy, SLOT(csModeSet(QString, QString, QString))); + connect(server, SIGNAL(topicSet(QString, QString, QString)), coreProxy, SLOT(csTopicSet(QString, QString, QString))); connect(server, SIGNAL(setNicks(QString, QString, QStringList)), coreProxy, SLOT(csSetNicks(QString, QString, QStringList))); + connect(server, SIGNAL(nickAdded(QString, QString, VarMap)), coreProxy, SLOT(csNickAdded(QString, QString, VarMap))); + connect(server, SIGNAL(nickRemoved(QString, QString)), coreProxy, SLOT(csNickRemoved(QString, QString))); + connect(server, SIGNAL(nickUpdated(QString, QString, VarMap)), coreProxy, SLOT(csNickUpdated(QString, QString, VarMap))); + connect(server, SIGNAL(ownNickSet(QString, QString)), coreProxy, SLOT(csOwnNickSet(QString, QString))); // add error handling server->start(); @@ -76,16 +81,18 @@ void Core::connectToIrc(QStringList networks) { } } +// ALL messages coming pass through these functions before going to the GUI. +// So this is the perfect place for storing the backlog and log stuff. void Core::recvMessageFromServer(QString buf, Message msg) { Q_ASSERT(sender()); QString net = qobject_cast(sender())->getNetwork(); - emit sendMessage(net, buf, msg); + emit displayMsg(net, buf, msg); } void Core::recvStatusMsgFromServer(QString msg) { Q_ASSERT(sender()); QString net = qobject_cast(sender())->getNetwork(); - emit sendStatusMsg(net, msg); + emit displayStatusMsg(net, msg); } diff --git a/core/core.h b/core/core.h index b87bc233..6b7a0aec 100644 --- a/core/core.h +++ b/core/core.h @@ -40,8 +40,8 @@ class Core : public QObject { signals: void msgFromGUI(QString network, QString channel, QString message); - void sendMessage(QString network, QString channel, Message message); - void sendStatusMsg(QString, QString); + void displayMsg(QString network, QString channel, Message message); + void displayStatusMsg(QString, QString); void connectToIrc(QString net); void disconnectFromIrc(QString net); diff --git a/core/coreproxy.h b/core/coreproxy.h index d1fd9c74..8cdea831 100644 --- a/core/coreproxy.h +++ b/core/coreproxy.h @@ -23,6 +23,7 @@ #include "proxy_common.h" #include "message.h" +#include "global.h" #include #include @@ -40,10 +41,15 @@ class CoreProxy : public QObject { public slots: inline void csUpdateGlobalData(QString key, QVariant data) { send(CS_UPDATE_GLOBAL_DATA, key, data); } - inline void csSendMessage(QString net, QString buf, Message msg) { send(CS_SEND_MESSAGE, net, buf, QVariant::fromValue(msg)); } - inline void csSendStatusMsg(QString net, QString msg) { send(CS_SEND_STATUS_MSG, net, msg); } - inline void csSetTopic(QString net, QString buf, QString topic) { send(CS_SET_TOPIC, net, buf, topic); } + inline void csDisplayMsg(QString net, QString buf, Message msg) { send(CS_DISPLAY_MSG, net, buf, QVariant::fromValue(msg)); } + inline void csDisplayStatusMsg(QString net, QString msg) { send(CS_DISPLAY_STATUS_MSG, net, msg); } + inline void csModeSet(QString net, QString target, QString mode) { send(CS_MODE_SET, net, target, mode); } + inline void csTopicSet(QString net, QString buf, QString topic) { send(CS_TOPIC_SET, net, buf, topic); } inline void csSetNicks(QString net, QString buf, QStringList nicks) { send(CS_SET_NICKS, net, buf, nicks); } + inline void csNickAdded(QString net, QString nick, VarMap props) { send(CS_NICK_ADDED, net, nick, props); } + inline void csNickRemoved(QString net, QString nick) { send(CS_NICK_REMOVED, net, nick); } + inline void csNickUpdated(QString net, QString nick, VarMap props) { send(CS_NICK_UPDATED, net, nick, props); } + inline void csOwnNickSet(QString net, QString nick) { send(CS_OWN_NICK_SET, net, nick); } signals: void gsPutGlobalData(QString, QVariant); diff --git a/gui/channelwidget.cpp b/gui/channelwidget.cpp index f5024b23..5053654b 100644 --- a/gui/channelwidget.cpp +++ b/gui/channelwidget.cpp @@ -24,10 +24,18 @@ #include #include -ChannelWidget::ChannelWidget(QString netname, QString bufname, QWidget *parent) : QWidget(parent) { +ChannelWidget::ChannelWidget(QString netname, QString bufname, QString own, QWidget *parent) : QWidget(parent) { ui.setupUi(this); _networkName = netname; _bufferName = bufname; + ui.ownNick->clear(); + ui.ownNick->addItem(own); + if(bufname.isEmpty()) { + // Server Buffer + ui.nickTree->hide(); + ui.topicEdit->hide(); + ui.chanSettingsButton->hide(); + } connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed())); //ui.inputEdit->setFocus(); @@ -43,7 +51,7 @@ ChannelWidget::ChannelWidget(QString netname, QString bufname, QWidget *parent) } void ChannelWidget::enterPressed() { - emit sendMessage(networkName(), bufferName(), ui.inputEdit->text()); + emit sendInput(networkName(), bufferName(), ui.inputEdit->text()); ui.inputEdit->clear(); } @@ -51,18 +59,29 @@ void ChannelWidget::recvMessage(Message msg) { QString s; QColor c = stdCol; switch(msg.type) { + case Message::Msg: + c = stdCol; s = QString("<%1> %2").arg(msg.sender).arg(msg.msg); + break; case Message::Server: c = serverCol; s = msg.msg; break; case Message::Error: c = errorCol; s = msg.msg; break; + case Message::Join: + c = joinCol; s = msg.msg; + break; default: c = stdCol; s = QString("[%1] %2").arg(msg.sender).arg(msg.msg); break; } ui.chatWidget->setTextColor(c); - ui.chatWidget->insertPlainText(QString("%1\n").arg(s)); + ui.chatWidget->insertPlainText(QString("[%2] %1\n").arg(s).arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss"))); + //ui.chatWidget->insertHtml(QString("" + // "" + // "" + // "
[12:13]
[nickname]
This is the Message!
[12:13]
[nick]
This is the Message!
[12:13]
[looongnickname]
This is the Message!
[12:13]
[nickname]
This is the Message!
" + // )); ui.chatWidget->ensureCursorVisible(); } @@ -80,6 +99,59 @@ void ChannelWidget::setNicks(QStringList nicks) { } +void ChannelWidget::addNick(QString nick, VarMap props) { + nicks[nick] = props; + updateNickList(); +} + +void ChannelWidget::updateNick(QString nick, VarMap props) { + nicks[nick] = props; + updateNickList(); +} + +void ChannelWidget::removeNick(QString nick) { + nicks[nick].toMap().remove(nick); + updateNickList(); +} + +void ChannelWidget::setOwnNick(QString nick) { + ui.ownNick->clear(); + ui.ownNick->addItem(nick); +} + +void ChannelWidget::updateNickList() { + ui.nickTree->clear(); + if(nicks.count() != 1) ui.nickTree->setHeaderLabel(tr("%1 Users").arg(nicks.count())); + else ui.nickTree->setHeaderLabel(tr("1 User")); + QTreeWidgetItem *ops = new QTreeWidgetItem(); + QTreeWidgetItem *voiced = new QTreeWidgetItem(); + QTreeWidgetItem *users = new QTreeWidgetItem(); + // To sort case-insensitive, we have to put all nicks in a map which is sorted by (lowercase) key... + QMap sorted; + foreach(QString n, nicks.keys()) { sorted[n.toLower()] = n; } + foreach(QString n, sorted.keys()) { + QString nick = sorted[n]; + QString mode = nicks[nick].toMap()["Channels"].toMap()[bufferName()].toMap()["Mode"].toString(); + if(mode.contains('o')) { new QTreeWidgetItem(ops, QStringList(QString("@%1").arg(nick))); } + else if(mode.contains('v')) { new QTreeWidgetItem(voiced, QStringList(QString("+%1").arg(nick))); } + else new QTreeWidgetItem(users, QStringList(nick)); + } + if(ops->childCount()) { + ops->setText(0, tr("%1 Operators").arg(ops->childCount())); + ui.nickTree->addTopLevelItem(ops); + ops->setExpanded(true); + } else delete ops; + if(voiced->childCount()) { + voiced->setText(0, tr("%1 Voiced").arg(voiced->childCount())); + ui.nickTree->addTopLevelItem(voiced); + voiced->setExpanded(true); + } else delete voiced; + if(users->childCount()) { + users->setText(0, tr("%1 Users").arg(users->childCount())); + ui.nickTree->addTopLevelItem(users); + users->setExpanded(true); + } else delete users; +} /**********************************************************************************************/ @@ -87,18 +159,22 @@ IrcWidget::IrcWidget(QWidget *parent) : QWidget(parent) { ui.setupUi(this); ui.tabWidget->removeTab(0); - connect(guiProxy, SIGNAL(csSendMessage(QString, QString, Message)), this, SLOT(recvMessage(QString, QString, Message))); - connect(guiProxy, SIGNAL(csSendStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); - connect(guiProxy, SIGNAL(csSetTopic(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString))); + connect(guiProxy, SIGNAL(csDisplayMsg(QString, QString, Message)), this, SLOT(recvMessage(QString, QString, Message))); + connect(guiProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); + connect(guiProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString))); connect(guiProxy, SIGNAL(csSetNicks(QString, QString, QStringList)), this, SLOT(setNicks(QString, QString, QStringList))); - connect(this, SIGNAL(sendMessage( QString, QString, QString )), guiProxy, SLOT(gsUserInput(QString, QString, QString))); + connect(guiProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap))); + connect(guiProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString))); + connect(guiProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap))); + connect(guiProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString))); + connect(this, SIGNAL(sendInput( QString, QString, QString )), guiProxy, SLOT(gsUserInput(QString, QString, QString))); } ChannelWidget * IrcWidget::getBuffer(QString net, QString buf) { QString key = net + buf; if(!buffers.contains(key)) { - ChannelWidget *cw = new ChannelWidget(net, buf); - connect(cw, SIGNAL(sendMessage(QString, QString, QString)), this, SLOT(userInput(QString, QString, QString))); + ChannelWidget *cw = new ChannelWidget(net, buf, ownNick); + 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(); @@ -119,7 +195,7 @@ void IrcWidget::recvStatusMsg(QString net, QString msg) { } void IrcWidget::userInput(QString net, QString buf, QString msg) { - emit sendMessage(net, buf, msg); + emit sendInput(net, buf, msg); } void IrcWidget::setTopic(QString net, QString buf, QString topic) { @@ -132,3 +208,42 @@ void IrcWidget::setNicks(QString net, QString buf, QStringList nicks) { cw->setNicks(nicks); } +void IrcWidget::addNick(QString net, QString nick, VarMap props) { + nicks[net].toMap()[nick] = props; + VarMap chans = props["Channels"].toMap(); + QStringList c = chans.keys(); + foreach(QString bufname, c) { + getBuffer(net, bufname)->addNick(nick, props); + } +} + +void IrcWidget::updateNick(QString net, QString nick, VarMap props) { + QStringList oldchans = nicks[net].toMap()[nick].toMap()["Channels"].toMap().keys(); + QStringList newchans = props["Channels"].toMap().keys(); + foreach(QString c, newchans) { + if(oldchans.contains(c)) getBuffer(net, c)->updateNick(nick, props); + else getBuffer(net, c)->addNick(nick, props); + } + foreach(QString c, oldchans) { + if(!newchans.contains(c)) getBuffer(net, c)->removeNick(nick); + } + nicks[net].toMap()[nick] = props; +} + +void IrcWidget::removeNick(QString net, QString nick) { + VarMap chans = nicks[net].toMap()[nick].toMap()["Channels"].toMap(); + foreach(QString bufname, chans.keys()) { + getBuffer(net, bufname)->removeNick(nick); + } + qDebug() << nicks; + nicks[net].toMap().remove(nick); + qDebug() << nicks; +} + +void IrcWidget::setOwnNick(QString net, QString nick) { + ownNick = nick; + foreach(ChannelWidget *cw, buffers.values()) { + if(cw->networkName() == net) cw->setOwnNick(nick); + } +} + diff --git a/gui/channelwidget.h b/gui/channelwidget.h index 7338ecdc..e1d2f2e2 100644 --- a/gui/channelwidget.h +++ b/gui/channelwidget.h @@ -24,27 +24,34 @@ #include "ui_channelwidget.h" #include "ui_ircwidget.h" +#include "global.h" #include "message.h" class ChannelWidget : public QWidget { Q_OBJECT public: - ChannelWidget(QString netname, QString bufname, QWidget *parent = 0); + ChannelWidget(QString netname, QString bufname, QString ownNick, QWidget *parent = 0); QString bufferName() { return _bufferName; } QString networkName() { return _networkName; } signals: - void sendMessage(QString, QString, QString); + void sendInput(QString, QString, QString); public slots: void recvMessage(Message); void recvStatusMsg(QString msg); void setTopic(QString); void setNicks(QStringList); + void addNick(QString nick, VarMap props); + void removeNick(QString nick); + void updateNick(QString nick, VarMap props); + void setOwnNick(QString nick); + private slots: void enterPressed(); + void updateNickList(); private: Ui::ChannelWidget ui; @@ -52,6 +59,7 @@ class ChannelWidget : public QWidget { QColor stdCol, errorCol, noticeCol, joinCol, quitCol, partCol, serverCol; QString _networkName; QString _bufferName; + VarMap nicks; }; /** Temporary widget for displaying a set of ChannelWidgets. */ @@ -66,9 +74,13 @@ class IrcWidget : public QWidget { void recvStatusMsg(QString network, QString message); void setTopic(QString, QString, QString); void setNicks(QString, QString, QStringList); + void addNick(QString net, QString nick, VarMap props); + void removeNick(QString net, QString nick); + void updateNick(QString net, QString nick, VarMap props); + void setOwnNick(QString net, QString nick); signals: - void sendMessage(QString network, QString buffer, QString message); + void sendInput(QString network, QString buffer, QString message); private slots: void userInput(QString, QString, QString); @@ -76,6 +88,8 @@ class IrcWidget : public QWidget { private: Ui::IrcWidget ui; QHash buffers; + VarMap nicks; + QString ownNick; ChannelWidget * getBuffer(QString net, QString buf); }; diff --git a/gui/channelwidget.ui b/gui/channelwidget.ui index a821979f..3bc85eb0 100644 --- a/gui/channelwidget.ui +++ b/gui/channelwidget.ui @@ -126,6 +126,9 @@ Qt::ElideRight + + true + false @@ -218,16 +221,9 @@ - - - mainNick - - - - - altNick - - + + QComboBox::AdjustToContents + diff --git a/gui/guiproxy.cpp b/gui/guiproxy.cpp index e9da5b01..9848ff3b 100644 --- a/gui/guiproxy.cpp +++ b/gui/guiproxy.cpp @@ -30,10 +30,15 @@ void GUIProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) case CS_CORE_STATE: emit csCoreState(arg1); break; case CS_UPDATE_GLOBAL_DATA: emit csUpdateGlobalData(arg1.toString(), arg2); break; //case CS_GLOBAL_DATA_CHANGED: emit csGlobalDataChanged(arg1.toString()); break; - case CS_SEND_MESSAGE: emit csSendMessage(arg1.toString(), arg2.toString(), arg3.value()); break; - case CS_SEND_STATUS_MSG: emit csSendStatusMsg(arg1.toString(), arg2.toString()); break; - case CS_SET_TOPIC: emit csSetTopic(arg1.toString(), arg2.toString(), arg3.toString()); break; + case CS_DISPLAY_MSG: emit csDisplayMsg(arg1.toString(), arg2.toString(), arg3.value()); break; + case CS_DISPLAY_STATUS_MSG: emit csDisplayStatusMsg(arg1.toString(), arg2.toString()); break; + case CS_MODE_SET: emit csModeSet(arg1.toString(), arg2.toString(), arg3.toString()); break; + case CS_TOPIC_SET: emit csTopicSet(arg1.toString(), arg2.toString(), arg3.toString()); break; case CS_SET_NICKS: emit csSetNicks(arg1.toString(), arg2.toString(), arg3.toStringList()); break; + case CS_NICK_ADDED: emit csNickAdded(arg1.toString(), arg2.toString(), arg3.toMap()); break; + case CS_NICK_REMOVED: emit csNickRemoved(arg1.toString(), arg2.toString()); break; + case CS_NICK_UPDATED: emit csNickUpdated(arg1.toString(), arg2.toString(), arg3.toMap()); break; + case CS_OWN_NICK_SET: emit csOwnNickSet(arg1.toString(), arg2.toString()); break; default: qWarning() << "Unknown signal in GUIProxy::recv: " << sig; } diff --git a/gui/guiproxy.h b/gui/guiproxy.h index df788d72..a068b6d1 100644 --- a/gui/guiproxy.h +++ b/gui/guiproxy.h @@ -23,6 +23,7 @@ #include "proxy_common.h" #include "message.h" +#include "global.h" #include #include @@ -48,12 +49,17 @@ class GUIProxy : public QObject { signals: void csCoreState(QVariant); - void csSendMessage(QString, QString, Message); - void csSendStatusMsg(QString, QString); + void csDisplayMsg(QString, QString, Message); + void csDisplayStatusMsg(QString, QString); void csUpdateGlobalData(QString key, QVariant data); void csGlobalDataChanged(QString key); - void csSetTopic(QString, QString, QString); + void csModeSet(QString, QString, QString); + void csTopicSet(QString, QString, QString); void csSetNicks(QString, QString, QStringList); + void csNickAdded(QString, QString, VarMap); + void csNickRemoved(QString, QString); + void csNickUpdated(QString, QString, VarMap); + void csOwnNickSet(QString, QString); void coreConnected(); void coreDisconnected(); diff --git a/main/message.cpp b/main/message.cpp index 37398225..e89d1a1c 100644 --- a/main/message.cpp +++ b/main/message.cpp @@ -22,14 +22,16 @@ #include QDataStream &operator<<(QDataStream &out, const Message &msg) { - out << (quint8)msg.type << (quint8)msg.flags << msg.sender << msg.msg; + out << (quint8)msg.type << (quint8)msg.flags << msg.sender << msg.msg << (quint32)msg.timeStamp.toTime_t(); return out; } QDataStream &operator>>(QDataStream &in, Message &msg) { quint8 t, f; - in >> t >> f >> msg.sender >> msg.msg; + quint32 ts; + in >> t >> f >> msg.sender >> msg.msg >> ts; msg.type = (Message::Type)t; msg.flags = (Message::Flags)f; + msg.timeStamp = QDateTime::fromTime_t(ts); return in; } diff --git a/main/message.h b/main/message.h index 9eb182a7..c1954f56 100644 --- a/main/message.h +++ b/main/message.h @@ -33,9 +33,10 @@ struct Message { Flags flags; QString sender; QString msg; + QDateTime timeStamp; Message(QString _msg = "", QString _sender = "", Type _type = Msg, Flags _flags = None) - : msg(_msg), sender(_sender), type(_type), flags(_flags) {}; + : msg(_msg), sender(_sender), type(_type), flags(_flags) { timeStamp = QDateTime::currentDateTime().toUTC(); }; }; diff --git a/main/proxy_common.h b/main/proxy_common.h index f7b55945..64dd228b 100644 --- a/main/proxy_common.h +++ b/main/proxy_common.h @@ -25,8 +25,9 @@ enum GUISignal { GS_CLIENT_INIT, GS_USER_INPUT, GS_REQUEST_CONNECT, GS_UPDATE_GL }; -enum CoreSignal { CS_CORE_STATE, CS_SEND_MESSAGE, CS_SEND_STATUS_MSG, CS_UPDATE_GLOBAL_DATA, - CS_SET_TOPIC, CS_SET_NICKS, +enum CoreSignal { CS_CORE_STATE, CS_DISPLAY_MSG, CS_DISPLAY_STATUS_MSG, CS_UPDATE_GLOBAL_DATA, + CS_MODE_SET, CS_TOPIC_SET, CS_SET_NICKS, CS_NICK_ADDED, CS_NICK_REMOVED, CS_NICK_UPDATED, + CS_OWN_NICK_SET, }; diff --git a/network/builtin_cmds.cpp b/network/builtin_cmds.cpp index 2e72c9de..59274692 100644 --- a/network/builtin_cmds.cpp +++ b/network/builtin_cmds.cpp @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +/* THIS CODE IS OBSOLETE! */ + #include //#include "message.h" #include "cmdcodes.h" diff --git a/network/cmdcodes.h b/network/cmdcodes.h index 787a6735..7f9625f3 100644 --- a/network/cmdcodes.h +++ b/network/cmdcodes.h @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +/* THIS CODE IS OBSOLETE! */ + #ifndef _CMDCODES_H_ #define _CMDCODES_H_ diff --git a/network/server.cpp b/network/server.cpp index d9e0a5b9..e4d37a6a 100644 --- a/network/server.cpp +++ b/network/server.cpp @@ -24,6 +24,7 @@ #include "message.h" #include +#include Server::Server(QString net) : network(net) { @@ -45,11 +46,12 @@ void Server::run() { void Server::connectToIrc(QString net) { if(net != network) return; // not me! - QList servers = global->getData("Networks").toMap()[net].toMap()["Servers"].toList(); - qDebug() << "Connecting to"<< servers[0].toMap(); + networkSettings = global->getData("Networks").toMap()[net].toMap(); + identity = global->getData("Identities").toMap()[networkSettings["Identity"].toString()].toMap(); + QList servers = networkSettings["Servers"].toList(); QString host = servers[0].toMap()["Address"].toString(); quint16 port = servers[0].toMap()["Port"].toUInt(); - sendStatusMsg(QString("Connecting to %1:%2...").arg(host).arg(port)); + displayStatusMsg(QString("Connecting to %1:%2...").arg(host).arg(port)); socket.connectToHost(host, port); } @@ -74,9 +76,8 @@ void Server::socketError( QAbstractSocket::SocketError err ) { } void Server::socketConnected( ) { - qDebug() << "Socket connected!"; - putRawLine("NICK :QuasselDev"); - putRawLine("USER Sputnick 8 * :Using Quassel IRC (WiP Version)"); + putRawLine(QString("NICK :%1").arg(identity["NickList"].toStringList()[0])); + putRawLine(QString("USER %1 8 * :%2").arg(identity["Ident"].toString()).arg(identity["RealName"].toString())); } void Server::socketDisconnected( ) { @@ -88,6 +89,22 @@ void Server::socketStateChanged(QAbstractSocket::SocketState state) { //qDebug() << "Socket state changed: " << state; } +QString Server::nickFromMask(QString mask) { + return mask.section('!', 0, 0); +} + +QString Server::userFromMask(QString mask) { + QString userhost = mask.section('!', 1); + if(userhost.isEmpty()) return QString(); + return userhost.section('@', 0, 0); +} + +QString Server::hostFromMask(QString mask) { + QString userhost = mask.section('!', 1); + if(userhost.isEmpty()) return QString(); + return userhost.section('@', 1); +} + void Server::userInput(QString net, QString buf, QString msg) { if(net != network) return; // not me! msg = msg.trimmed(); // remove whitespace from start and end @@ -143,6 +160,13 @@ void Server::handleServerMsg(QString msg) { if(!trailing.isEmpty()) { params << trailing; } + // numeric replies usually have our own nick as first param. Remove this! + // BTW, this behavior is not in the RFC. + uint num = cmd.toUInt(); + if(num > 1 && params.count() > 0) { // 001 sets our nick, so we shouldn't remove anything + if(params[0] == currentNick) params.removeFirst(); + else qWarning((QString("First param NOT nick: %1:%2 %3").arg(prefix).arg(cmd).arg(params.join(" "))).toAscii()); + } // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-) QString hname = cmd.toLower(); hname[0] = hname[0].toUpper(); @@ -152,35 +176,31 @@ void Server::handleServerMsg(QString msg) { defaultServerHandler(cmd, prefix, params); } } catch(Exception e) { - emit sendMessage("", Message(e.msg(), "", Message::Error)); + emit displayMsg("", Message(e.msg(), "", Message::Error)); } } void Server::defaultServerHandler(QString cmd, QString prefix, QStringList params) { uint num = cmd.toUInt(); if(num) { - if(params.count() > 0) { - if(params[0] == currentNick) params.removeFirst(); // remove nick if it is first arg - else qWarning((QString("First param NOT nick: %1:%2 %3").arg(prefix).arg(cmd).arg(params.join(" "))).toAscii()); - } // A lot of server messages don't really need their own handler because they don't do much. // Catch and handle these here. switch(num) { // Welcome, status, info messages. Just display these. case 2: case 3: case 4: case 5: case 251: case 252: case 253: case 254: case 255: case 372: case 375: - emit sendMessage("", Message(params.join(" "), prefix, Message::Server)); + emit displayMsg("", Message(params.join(" "), prefix, Message::Server)); break; // Ignore these commands. - case 376: + case 366: case 376: break; // Everything else will be marked in red, so we can add them somewhere. default: - emit sendMessage("", Message(cmd + " " + params.join(" "), prefix, Message::Error)); + emit displayMsg("", Message(cmd + " " + params.join(" "), prefix, Message::Error)); } //qDebug() << prefix <<":"<name() << msg; putCmd("PRIVMSG", params); + emit displayMsg(params[0], Message(msg, currentNick, Message::Msg, Message::Self)); } /**********************************************************************************/ void Server::handleServerJoin(QString prefix, QStringList params) { Q_ASSERT(params.count() == 1); - QString bufname = params[0]; - if(!buffers.contains(bufname)) { - Buffer *buf = new Buffer(bufname); - buffers[bufname] = buf; + QString nick = nickFromMask(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; + } else { + VarMap n; + if(nicks.contains(nick)) { + n = nicks[nick].toMap(); + VarMap chans = n["Channels"].toMap(); + // Q_ASSERT(!chans.keys().contains(params[0])); TODO uncomment + chans[params[0]] = VarMap(); + n["Channels"] = chans; + nicks[nick] = n; + emit nickUpdated(network, nick, n); + } else { + VarMap chans; + chans[params[0]] = VarMap(); + n["Channels"] = chans; + n["Nick"] = nick; + n["User"] = userFromMask(prefix); + n["Host"] = hostFromMask(prefix); + nicks[nick] = n; + emit nickAdded(network, nick, n); + } + QString user = n["User"].toString(); QString host = n["Host"].toString(); + if(user.isEmpty() || host.isEmpty()) emit displayMsg(params[0], Message(tr("%1 has joined %2").arg(nick).arg(params[0]), "", Message::Join)); + else emit displayMsg(params[0], Message(tr("%1 (%2@%3) has joined %4").arg(nick).arg(user).arg(host).arg(params[0]), "", Message::Join)); } - // handle user joins! } + + void Server::handleServerNotice(QString prefix, QStringList params) { Message msg(params[1], prefix, Message::Notice); - if(prefix == currentServer) emit sendMessage("", Message(params[1], prefix, Message::Server)); - else emit sendMessage("", Message(params[1], prefix, Message::Notice)); + if(prefix == currentServer) emit displayMsg("", Message(params[1], prefix, Message::Server)); + else emit displayMsg("", Message(params[1], prefix, Message::Notice)); } void Server::handleServerPing(QString prefix, QStringList params) { @@ -259,7 +305,7 @@ void Server::handleServerPing(QString prefix, QStringList params) { } void Server::handleServerPrivmsg(QString prefix, QStringList params) { - emit sendMessage(params[0], Message(params[1], prefix, Message::Msg)); + emit displayMsg(params[0], Message(params[1], nickFromMask(prefix), Message::Msg)); } @@ -267,21 +313,54 @@ void Server::handleServerPrivmsg(QString prefix, QStringList params) { void Server::handleServer001(QString prefix, QStringList params) { currentServer = prefix; currentNick = params[0]; - emit sendMessage("", Message(params[1], prefix, Message::Server)); + emit ownNickSet(network, currentNick); + emit displayMsg("", Message(params[1], prefix, Message::Server)); } /* RPL_NOTOPIC */ void Server::handleServer331(QString prefix, QStringList params) { - if(params[0] == currentNick) params.removeFirst(); - emit setTopic(network, params[0], ""); + emit topicSet(network, params[0], ""); } /* RPL_TOPIC */ void Server::handleServer332(QString prefix, QStringList params) { - if(params[0] == currentNick) params.removeFirst(); - emit setTopic(network, params[0], params[1]); + emit topicSet(network, params[0], params[1]); + emit displayMsg(params[0], Message(tr("Topic for %1 is \"%2\"").arg(params[0]).arg(params[1]), "", Message::Server)); } +/* Topic set by... */ +void Server::handleServer333(QString prefix, QStringList params) { + emit displayMsg(params[0], Message(tr("Topic set by %1 on %2").arg(params[1]).arg(QDateTime::fromTime_t(params[2].toUInt()).toString()), "", Message::Server)); +} + +/* RPL_NAMREPLY */ +void Server::handleServer353(QString prefix, QStringList params) { + params.removeFirst(); // = or * + QString buf = params.takeFirst(); + 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; + if(nicks.contains(nick)) { + VarMap n = nicks[nick].toMap(); + VarMap chans = n["Channels"].toMap(); + chans[buf] = c; + n["Channels"] = chans; + nicks[nick] = n; + emit nickUpdated(network, nick, n); + } else { + VarMap n; VarMap c; VarMap chans; + c["Mode"] = mode; + chans[buf] = c; + n["Channels"] = chans; + n["Nick"] = nick; + nicks[nick] = n; + emit nickAdded(network, nick, n); + } + } +} /***********************************************************************************/ /* Exception classes for message handling */ diff --git a/network/server.h b/network/server.h index 6fde53f8..c5a3daa5 100644 --- a/network/server.h +++ b/network/server.h @@ -62,12 +62,17 @@ class Server : public QThread { signals: void recvRawServerMsg(QString); - void sendStatusMsg(QString); - void sendMessage(QString buffer, Message msg); + void displayStatusMsg(QString); + void displayMsg(QString buffer, Message msg); void disconnected(); - void setTopic(QString network, QString buffer, QString topic); + void nickAdded(QString network, QString nick, VarMap props); + void nickRemoved(QString network, QString nick); + void nickUpdated(QString network, QString nick, VarMap props); + void modeSet(QString network, QString target, QString mode); + void topicSet(QString network, QString buffer, QString topic); void setNicks(QString network, QString buffer, QStringList nicks); + void ownNickSet(QString network, QString newNick); private slots: @@ -95,6 +100,8 @@ class Server : public QThread { void handleServer001(QString, QStringList); // RPL_WELCOME 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); @@ -106,10 +113,17 @@ class Server : public QThread { QString currentNick; QString currentServer; + VarMap networkSettings; + VarMap identity; + VarMap nicks; // stores all known nicks for the server void handleServerMsg(QString rawMsg); void handleUserMsg(QString buffer, QString usrMsg); + QString nickFromMask(QString mask); + QString userFromMask(QString mask); + QString hostFromMask(QString mask); + class ParseError : public Exception { public: ParseError(QString cmd, QString prefix, QStringList params);