More neato stuff. A preliminary TabWidget now allows us to display multiple buffers,
authorManuel Nickschas <sputnick@quassel-irc.org>
Tue, 24 Oct 2006 10:15:10 +0000 (10:15 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Tue, 24 Oct 2006 10:15:10 +0000 (10:15 +0000)
and we already sorta use this feature. Implemented /say, /quote and /join. Made output
prettier. However, this is all still pretty much work in progress and I guess there are
still some Q_ASSERTs triggering where they shouldn't.

21 files changed:
core/core.cpp
core/core.h
core/coreproxy.cpp
core/coreproxy.h
gui/CMakeLists.txt
gui/channelwidget.cpp
gui/channelwidget.h
gui/channelwidget.ui
gui/guiproxy.cpp
gui/guiproxy.h
gui/ircwidget.ui [new file with mode: 0644]
gui/mainwin.cpp
main/global.cpp
main/proxy_common.h
network/CMakeLists.txt
network/buffer.cpp
network/buffer.h
network/message.cpp
network/message.h
network/server.cpp
network/server.h

index f7fedd1..6270527 100644 (file)
@@ -29,8 +29,8 @@ Core::Core() {
   if(core) qFatal("Trying to instantiate more than one Core object!");
 
   connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
-  connect(coreProxy, SIGNAL(gsUserInput(QString)), this, SLOT(inputLine(QString)));
-  connect(this, SIGNAL(sendMessage(QString, QString, QString)), coreProxy, SLOT(csSendMessage(QString, QString, QString)));
+  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)));
 
   // Read global settings from config file
@@ -54,12 +54,6 @@ void Core::globalDataUpdated(QString key) {
   s.setValue(QString("Global/")+key, data);
 }
 
-// temp
-void Core::inputLine(QString s) {
-  emit msgFromGUI("", "", s);
-
-}
-
 void Core::connectToIrc(QStringList networks) {
   foreach(QString net, networks) {
     if(servers.contains(net)) {
@@ -69,8 +63,10 @@ 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, QString)), this, SLOT(recvMessageFromServer(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(setNicks(QString, QString, QStringList)), coreProxy, SLOT(csSetNicks(QString, QString, QStringList)));
       // add error handling
 
       server->start();
@@ -80,7 +76,7 @@ void Core::connectToIrc(QStringList networks) {
   }
 }
 
-void Core::recvMessageFromServer(QString buf, QString msg) {
+void Core::recvMessageFromServer(QString buf, Message msg) {
   Q_ASSERT(sender());
   QString net = qobject_cast<Server*>(sender())->getNetwork();
   emit sendMessage(net, buf, msg);
@@ -89,7 +85,6 @@ void Core::recvMessageFromServer(QString buf, QString msg) {
 void Core::recvStatusMsgFromServer(QString msg) {
   Q_ASSERT(sender());
   QString net = qobject_cast<Server*>(sender())->getNetwork();
-  qDebug() << "sent status:"<<msg;
   emit sendStatusMsg(net, msg);
 }
 
index 23ba3c6..b87bc23 100644 (file)
@@ -36,13 +36,11 @@ class Core : public QObject {
     //~Core();
 
   public slots:
-    void inputLine(QString);   // temp
     void connectToIrc(QStringList);
 
   signals:
-    void outputLine(const QString &);  // temp
     void msgFromGUI(QString network, QString channel, QString message);
-    void sendMessage(QString network, QString channel, QString message);
+    void sendMessage(QString network, QString channel, Message message);
     void sendStatusMsg(QString, QString);
 
     void connectToIrc(QString net);
@@ -51,7 +49,7 @@ class Core : public QObject {
   private slots:
     void globalDataUpdated(QString);
     void recvStatusMsgFromServer(QString msg);
-    void recvMessageFromServer(QString buffer, QString msg);
+    void recvMessageFromServer(QString buffer, Message msg);
 
   private:
     QHash<QString, Server *> servers;
index 3db3f15..9138047 100644 (file)
@@ -122,7 +122,7 @@ void CoreProxy::recv(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3)
   //qDebug() << "[CORE] Received signal" << sig << ":" << arg1<<arg2<<arg3;
   switch(sig) {
     case GS_UPDATE_GLOBAL_DATA: emit gsPutGlobalData(arg1.toString(), arg2); break;
-    case GS_USER_INPUT: emit gsUserInput(arg1.toString()); break;
+    case GS_USER_INPUT: emit gsUserInput(arg1.toString(), arg2.toString(), arg3.toString()); break;
     case GS_REQUEST_CONNECT: emit gsRequestConnect(arg1.toStringList()); break;
     default: qWarning() << "Unknown signal in CoreProxy::recv: " << sig;
   }
index 3272a34..d1fd9c7 100644 (file)
@@ -22,6 +22,7 @@
 #define _COREPROXY_H_
 
 #include "proxy_common.h"
+#include "message.h"
 
 #include <QtCore>
 #include <QTcpSocket>
@@ -39,12 +40,14 @@ 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 chan, QString msg)   { send(CS_SEND_MESSAGE, net, chan, msg); }
+    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 csSetNicks(QString net, QString buf, QStringList nicks) { send(CS_SET_NICKS, net, buf, nicks); }
 
   signals:
     void gsPutGlobalData(QString, QVariant);
-    void gsUserInput(QString);
+    void gsUserInput(QString, QString, QString);
     void gsRequestConnect(QStringList networks);
 
   private:
index 3467e3f..d83476c 100644 (file)
@@ -1,7 +1,8 @@
 SET(gui_SRCS channelwidget.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_UICS channelwidget.ui identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui nickeditdlg.ui serverlistdlg.ui servereditdlg.ui coreconnectdlg.ui)
+SET(gui_UICS channelwidget.ui identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui
+             nickeditdlg.ui serverlistdlg.ui servereditdlg.ui coreconnectdlg.ui ircwidget.ui)
 
 QT4_WRAP_UI(_UIC ${gui_UICS})
 QT4_WRAP_CPP(_MOC ${gui_MOCS})
index 70066dc..f5024b2 100644 (file)
 #include <QtGui>
 #include <iostream>
 
-ChannelWidget::ChannelWidget(QWidget *parent) : QWidget(parent) {
+ChannelWidget::ChannelWidget(QString netname, QString bufname, QWidget *parent) : QWidget(parent) {
   ui.setupUi(this);
-  //ui.inputEdit->grabKeyboard();
-
-/*  //ui.splitter->
-  ui.textBrowser->setHtml("[17:21] <em>--> Dante has joined #quassel (~hurz@p1af2242.dip.t-dialin.net)</em><br>"
-                          "[17:21] <em>--> Sput has joined #quassel (~Sput42@vincent.mindpool.net)</em><br>"
-                          "[17:23] &lt;<b>Dante</b>&gt; Das sieht ja soweit schonmal Klasse aus!<br>"
-                          "[17:23] &lt;<b>Sput</b>&gt; Find ich auch... schade dass es noch nix tut :p<br>"
-                          "[17:24] &lt;<b>Dante</b>&gt; Das wird sich ja gottseidank bald √§ndern.<br>"
-                          "[17:24] &lt;<b>Sput</b>&gt; Wollen wir's hoffen :D"
-                          );
- ui.listWidget->addItem("@Dante");
- ui.listWidget->addItem("@Sput");
-  */
-  //connect(&core, SIGNAL(outputLine( const QString& )), ui.textBrowser, SLOT(insertPlainText(const QString &)));
-  //connect(ui.lineEdit, SIGNAL(
-  //connect(&core, SIGNAL(outputLine( const QString& )), this, SLOT(lineReceived(const QString &)));
+  _networkName = netname;
+  _bufferName = bufname;
   connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed()));
-  //connect(this, SIGNAL(inputLine( const QString& )), &core, SLOT(inputLine( const QString& )));
+  //ui.inputEdit->setFocus();
 
-  connect(this, SIGNAL(inputLine(QString)), guiProxy, SLOT(gsUserInput(QString)));
-  connect(guiProxy, SIGNAL(csSendMessage(QString, QString, QString)), this, SLOT(msgReceived(QString, QString, QString)));
-  connect(guiProxy, SIGNAL(csSendStatusMsg(QString, QString)), this, SLOT(statusMsgReceived(QString, QString)));
-  ui.inputEdit->setFocus();
+  // Define standard colors
+  stdCol = QColor("black");
+  noticeCol = QColor("darkblue");
+  serverCol = QColor("darkblue");
+  errorCol = QColor("red");
+  joinCol = QColor("green");
+  quitCol = QColor("firebrick");
+  partCol = QColor("firebrick");
+  
 }
 
 void ChannelWidget::enterPressed() {
-  emit inputLine(ui.inputEdit->text());
+  emit sendMessage(networkName(), bufferName(), ui.inputEdit->text());
   ui.inputEdit->clear();
 }
 
-void ChannelWidget::msgReceived(QString net, QString chan, QString msg) {
-  ui.chatWidget->insertPlainText(QString("[%1:%2] %3\n").arg(net).arg(chan).arg(msg));
+void ChannelWidget::recvMessage(Message msg) {
+  QString s;
+  QColor c = stdCol;
+  switch(msg.type) {
+    case Message::Server:
+      c = serverCol; s = msg.msg;
+      break;
+    case Message::Error:
+      c = errorCol; 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->ensureCursorVisible();
 }
 
-void ChannelWidget::statusMsgReceived(QString net, QString msg) {
-  msgReceived(net, "STATUS", msg);
+void ChannelWidget::recvStatusMsg(QString msg) {
+  ui.chatWidget->insertPlainText(QString("[STATUS] %1").arg(msg));
+  ui.chatWidget->ensureCursorVisible();
+}
+
+void ChannelWidget::setTopic(QString topic) {
+  ui.topicEdit->setText(topic);
+}
+
+void ChannelWidget::setNicks(QStringList nicks) {
+
+
+}
+
+/**********************************************************************************************/
+
+
+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(csSetNicks(QString, QString, QStringList)), this, SLOT(setNicks(QString, QString, QStringList)));
+  connect(this, SIGNAL(sendMessage( 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)));
+    ui.tabWidget->addTab(cw, net+buf);
+    ui.tabWidget->setCurrentWidget(cw);
+    //cw->setFocus();
+    buffers[key] = cw;
+  }
+  return buffers[key];
+}
+
+
+void IrcWidget::recvMessage(QString net, QString buf, Message msg) {
+  ChannelWidget *cw = getBuffer(net, buf);
+  cw->recvMessage(msg);
+}
+
+void IrcWidget::recvStatusMsg(QString net, QString msg) {
+  recvMessage(net, "", QString("[STATUS] %1").arg(msg));
+
 }
+
+void IrcWidget::userInput(QString net, QString buf, QString msg) {
+  emit sendMessage(net, buf, msg);
+}
+
+void IrcWidget::setTopic(QString net, QString buf, QString topic) {
+  ChannelWidget *cw = getBuffer(net, buf);
+  cw->setTopic(topic);
+}
+
+void IrcWidget::setNicks(QString net, QString buf, QStringList nicks) {
+  ChannelWidget *cw = getBuffer(net, buf);
+  cw->setNicks(nicks);
+}
+
index 853d8a9..7338ecd 100644 (file)
 #define _CHANNELWIDGET_H_
 
 #include "ui_channelwidget.h"
+#include "ui_ircwidget.h"
+
+#include "message.h"
 
 class ChannelWidget : public QWidget {
   Q_OBJECT
 
   public:
-    ChannelWidget(QWidget *parent = 0);
+    ChannelWidget(QString netname, QString bufname, QWidget *parent = 0);
 
+    QString bufferName() { return _bufferName; }
+    QString networkName() { return _networkName; }
   signals:
-    void requestConnect(QString, quint16);
-    void inputLine(QString);
+    void sendMessage(QString, QString, QString);
+
+  public slots:
+    void recvMessage(Message);
+    void recvStatusMsg(QString msg);
+    void setTopic(QString);
+    void setNicks(QStringList);
 
   private slots:
     void enterPressed();
-    void msgReceived(QString, QString, QString);
-    void statusMsgReceived(QString net, QString msg);
 
   private:
     Ui::ChannelWidget ui;
 
+    QColor stdCol, errorCol, noticeCol, joinCol, quitCol, partCol, serverCol;
+    QString _networkName;
+    QString _bufferName;
 };
 
+/** Temporary widget for displaying a set of ChannelWidgets. */
+class IrcWidget : public QWidget {
+  Q_OBJECT
+
+  public:
+    IrcWidget(QWidget *parent = 0);
+
+  public slots:
+    void recvMessage(QString network, QString buffer, Message message);
+    void recvStatusMsg(QString network, QString message);
+    void setTopic(QString, QString, QString);
+    void setNicks(QString, QString, QStringList);
+
+  signals:
+    void sendMessage(QString network, QString buffer, QString message);
+
+  private slots:
+    void userInput(QString, QString, QString);
+
+  private:
+    Ui::IrcWidget ui;
+    QHash<QString, ChannelWidget *> buffers;
+
+    ChannelWidget * getBuffer(QString net, QString buf);
+};
 
 #endif
index 82fad18..ffea438 100644 (file)
@@ -1,6 +1,14 @@
 <ui version="4.0" >
  <class>ChannelWidget</class>
  <widget class="QWidget" name="ChannelWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>713</width>
+    <height>519</height>
+   </rect>
+  </property>
   <property name="sizePolicy" >
    <sizepolicy>
     <hsizetype>3</hsizetype>
       <number>6</number>
      </property>
      <item>
-      <widget class="QLineEdit" name="topicEdit" />
+      <widget class="QLineEdit" name="topicEdit" >
+       <property name="focusPolicy" >
+        <enum>Qt::ClickFocus</enum>
+       </property>
+       <property name="readOnly" >
+        <bool>true</bool>
+       </property>
+      </widget>
      </item>
      <item>
       <widget class="QToolButton" name="chanSettingsButton" >
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
+      <property name="font" >
+       <font>
+        <family>Monospace</family>
+       </font>
+      </property>
      </widget>
      <widget class="QTreeWidget" name="nickTree" >
       <property name="sizePolicy" >
   </layout>
  </widget>
  <tabstops>
+  <tabstop>inputEdit</tabstop>
+  <tabstop>ownNick</tabstop>
+  <tabstop>nickTree</tabstop>
   <tabstop>topicEdit</tabstop>
   <tabstop>chanSettingsButton</tabstop>
+  <tabstop>chatWidget</tabstop>
  </tabstops>
  <resources/>
  <connections/>
index a6bd707..e9da5b0 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "guiproxy.h"
 #include "util.h"
+#include "message.h"
 
 void GUIProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
   //qDebug() << "[GUI] Received signal:" << sig <<arg1<<arg2<<arg3;
@@ -29,8 +30,10 @@ 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.toString()); break;
+    case CS_SEND_MESSAGE: emit csSendMessage(arg1.toString(), arg2.toString(), arg3.value<Message>()); 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_SET_NICKS: emit csSetNicks(arg1.toString(), arg2.toString(), arg3.toStringList()); break;
 
     default: qWarning() << "Unknown signal in GUIProxy::recv: " << sig;
   }
index 0c01379..df788d7 100644 (file)
@@ -22,6 +22,7 @@
 #define _GUIPROXY_H_
 
 #include "proxy_common.h"
+#include "message.h"
 
 #include <QObject>
 #include <QVariant>
@@ -39,18 +40,20 @@ class GUIProxy : public QObject {
     GUIProxy();
 
   public slots:
-    inline void gsUserInput(QString s)                             { send(GS_USER_INPUT, s); }
-    inline void gsRequestConnect(QStringList networks)             { send(GS_REQUEST_CONNECT, networks); }
+    inline void gsUserInput(QString net, QString buf, QString msg)    { send(GS_USER_INPUT, net, buf, msg); }
+    inline void gsRequestConnect(QStringList networks)                { send(GS_REQUEST_CONNECT, networks); }
 
     void connectToCore(QString host, quint16 port);
     void disconnectFromCore();
 
   signals:
     void csCoreState(QVariant);
-    void csSendMessage(QString, QString, QString);
+    void csSendMessage(QString, QString, Message);
     void csSendStatusMsg(QString, QString);
     void csUpdateGlobalData(QString key, QVariant data);
     void csGlobalDataChanged(QString key);
+    void csSetTopic(QString, QString, QString);
+    void csSetNicks(QString, QString, QStringList);
 
     void coreConnected();
     void coreDisconnected();
diff --git a/gui/ircwidget.ui b/gui/ircwidget.ui
new file mode 100644 (file)
index 0000000..5ddc795
--- /dev/null
@@ -0,0 +1,44 @@
+<ui version="4.0" >
+ <class>IrcWidget</class>
+ <widget class="QWidget" name="IrcWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>733</width>
+    <height>531</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <property name="margin" >
+    <number>9</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QTabWidget" name="tabWidget" >
+     <property name="tabPosition" >
+      <enum>QTabWidget::South</enum>
+     </property>
+     <property name="tabShape" >
+      <enum>QTabWidget::Rounded</enum>
+     </property>
+     <property name="currentIndex" >
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab" >
+      <attribute name="title" >
+       <string>No connection</string>
+      </attribute>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
index 3faaf10..3fefe4d 100644 (file)
@@ -40,11 +40,8 @@ MainWin::MainWin() : QMainWindow() {
   move(s.value("MainWinPos", QPoint(50, 50)).toPoint());
   s.endGroup();
 
-  workspace = new QWorkspace(this);
-  setCentralWidget(workspace);
-  //ChannelWidget *cw = new ChannelWidget(this);
-  //workspace->addWindow(cw);
-  //setCentralWidget(cw);
+  //workspace = new QWorkspace(this);
+  //setCentralWidget(workspace);
   statusBar()->showMessage(tr("Waiting for core..."));
   setEnabled(false);
   show();
@@ -55,14 +52,12 @@ MainWin::MainWin() : QMainWindow() {
   setupMenus();
   //identitiesAct = settingsMenu->addAction(QIcon(":/default/identity.png"), tr("&Identities..."), serverListDlg, SLOT(editIdentities()));
   //showServerList();
-  ChannelWidget *cw = new ChannelWidget(this);
-  //setCentralWidget(cw);
-  workspace->addWindow(cw);
-  cw->showMaximized();
-  //setEnabled(true);
+  IrcWidget *cw = new IrcWidget(this);
+  setCentralWidget(cw);
+  //workspace->addWindow(cw);
+  //cw->showMaximized();
   statusBar()->showMessage(tr("Ready."));
-  //QSystemTrayIcon *systray = new QSystemTrayIcon(QIcon(":/qirc-icon.png"));
-  //systray->showMessage("Quassel", "Started!");
+  cw->setFocus();
 }
 
 void MainWin::syncToCore() {
index 7a47771..25eba7e 100644 (file)
@@ -21,9 +21,9 @@
 #include "global.h"
 #include "logger.h"
 #include "core.h"
+#include "message.h"
 
-#include <QString>
-#include <QStringList>
+#include <QtCore>
 #include <QDomDocument>
 
 extern void messageHandler(QtMsgType type, const char *msg);
@@ -31,6 +31,7 @@ extern void messageHandler(QtMsgType type, const char *msg);
 Global::Global() {
   if(global) qFatal("Trying to instantiate more than one Global object!");
   qInstallMsgHandler(messageHandler);
+  qRegisterMetaType<Message>("Message");
   //initIconMap();
 }
 
index 53f24a9..f7b5594 100644 (file)
@@ -26,6 +26,7 @@ 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,
 
 };
 
index 2a79cc8..20b0c90 100644 (file)
@@ -1,5 +1,5 @@
-SET(network_SRCS server.cpp buffer.cpp)
-SET(network_HDRS )
+SET(network_SRCS server.cpp buffer.cpp message.cpp)
+SET(network_HDRS message.h)
 SET(network_MOCS server.h buffer.h)
 
 QT4_WRAP_CPP(_MOC ${network_MOCS})
index e204ef8..61cd6b3 100644 (file)
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
+
+#include "buffer.h"
+
+Buffer::Buffer(QString n) {
+  _name = n;
+
+
+
+}
+
index e937f72..cb77fff 100644 (file)
 class Buffer : public QObject {
   Q_OBJECT
 
+  public:
+    Buffer(QString name);
 
+    QString name() { return _name; }
+    QString topic() { return _topic; }
 
+  public slots:
+    //void setNicks(QStringList nicks);
+    //void addNick(QString nick);
+    //void removeNick(QString nick);
+
+  signals:
+
+  private:
+    QString _name;
+    QString _topic;
+    QStringList nicks;
 
 };
 
index b2e6f88..3739822 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-/* OBSOLETE CODE! */
-
 #include "message.h"
-#include <QtDebug>
-
-extern BuiltinCmd builtins[];
-
-recvHandlerType Message::defaultRecvHandler;
-sendHandlerType Message::defaultSendHandler;
-QHash<QString, CmdType> Message::cmdTypes;
-
-Message::Message(Server *srv, Buffer *buf, QString _cmd, QString _prefix, QStringList _params)
-  : server(srv), buffer(buf), cmd(_cmd), prefix(_prefix), params(_params) {
-
-  // Check if it's a registered cmd (or a numeric reply with a custom entry)
-  if(cmdTypes.contains(cmd)) {
-    CmdType c = cmdTypes[cmd];
-    recvHandler = ( c.recvHandler ? c.recvHandler : defaultRecvHandler);
-    sendHandler = ( c.sendHandler ? c.sendHandler : defaultSendHandler);
-    cmdCode = - c.cmdCode; // named commands have a _negative_ code!
-  } else {
-    int t = cmd.toInt();
-    if(t) {
-      cmdCode = t;
-      recvHandler = defaultRecvHandler;
-      sendHandler = defaultSendHandler;
-    } else {
-      // Unknown cmd!
-      qWarning() << "Unknown command: " << cmd;
-      cmdCode = 0;
-    }
-  }
-}
-
-void Message::init(recvHandlerType _r, sendHandlerType _s) {
-  defaultRecvHandler = _r;
-  defaultSendHandler = _s;
-
-  // Register builtin commands
-  for(int i = 0; ; i++) {
-    if(builtins[i].cmd.isEmpty()) break;
-    CmdType c;
-    c.cmdCode = builtins[i].cmdCode;
-    c.cmd = builtins[i].cmd.toUpper();
-    c.cmdDescr = builtins[i].cmdDescr;
-    c.args = builtins[i].args;
-    c.argsDescr = builtins[i].argsDescr;
-    c.recvHandler = ( builtins[i].recvHandler ? builtins[i].recvHandler : defaultRecvHandler);
-    c.sendHandler = ( builtins[i].sendHandler ? builtins[i].sendHandler : defaultSendHandler);
-    cmdTypes.insert(c.cmd, c);
-  }
-
-}
-
-recvHandlerType Message::getRecvHandler() {
-  CmdType c = cmdTypes[cmd];
-  if(c.recvHandler) return c.recvHandler;
-  qDebug() << "No recvHandler defined for " << cmd << "!";
-  return 0;
-}
+#include <QDataStream>
 
-sendHandlerType Message::getSendHandler() {
-  CmdType c = cmdTypes[cmd];
-  if(c.sendHandler) return c.sendHandler;
-  qDebug() << "No sendHandler defined for " << cmd << "!";
-  return 0;
+QDataStream &operator<<(QDataStream &out, const Message &msg) {
+  out << (quint8)msg.type << (quint8)msg.flags << msg.sender << msg.msg;
+  return out;
 }
 
-/** This parses a raw string as sent by the server and constructs a message object which is then returned.
- */
-Message * Message::createFromServerString(Server *srv, QString msg) {
-  if(msg.isEmpty()) {
-    qWarning() << "Received empty message from server!";
-    return 0;
-  }
-  QString prefix;
-  QString cmd;
-  QStringList params;
-  if(msg[0] == ':') {
-    msg.remove(0,1);
-    prefix = msg.section(' ', 0, 0);
-    msg = msg.section(' ', 1);
-  }
-  cmd = msg.section(' ', 0, 0).toUpper();
-  msg = msg.section(' ', 1);
-  QString left = msg.section(':', 0, 0);
-  QString trailing = msg.section(':', 1);
-  if(!left.isEmpty()) {
-    params << left.split(' ', QString::SkipEmptyParts);
-  }
-  if(!trailing.isEmpty()) {
-    params << trailing;
-  }
-  return new Message(srv, 0, cmd, prefix, params);
-  //qDebug() << "prefix: " << prefix << " cmd: " << cmd << " params: " << params;
+QDataStream &operator>>(QDataStream &in, Message &msg) {
+  quint8 t, f;
+  in >> t >> f >> msg.sender >> msg.msg;
+  msg.type = (Message::Type)t;
+  msg.flags = (Message::Flags)f;
+  return in;
 }
index 83c24b3..c9f55a4 100644 (file)
 #ifndef _MESSAGE_H_
 #define _MESSAGE_H_
 
-#include <QHash>
-#include <QString>
-#include <QStringList>
+#include <QtCore>
 
-class Server;
-class Buffer;
-class Message;
+struct Message {
 
-typedef void (*sendHandlerType)(Message *);        // handler for commands sent by the user
-typedef void (*recvHandlerType)(Message *);              // handler for incoming messages
+  /** The different types a message can have for display */
+  enum Type { Msg, Notice, Action, Nick, Mode, Join, Part, Quit, Kick, Kill, Server, Info, Error };
+  enum Flags { None = 0, Self = 1, Highlight = 2 };
 
-/**
- * This contains information that depends (solely) on the message type, such as the handler function and help texts.
- * Most of these are defined at compile time, but more may be added at runtime.
- */
-struct CmdType {
-  int cmdCode;
-  QString cmd;
-  QString cmdDescr;
-  QString args;
-  QString argsDescr;
-  recvHandlerType recvHandler;
-  sendHandlerType sendHandler;
+  Type type;
+  Flags flags;
+  QString sender;
+  QString msg;
 
-};
-
-/**
- *
-*/
-class Message {
-  public:
-    Message(Server *server, Buffer *buffer, QString cmd, QString prefix, QStringList args = QStringList());
-
-    virtual ~Message() {};
-
-    static void init(recvHandlerType defaultRevcHandler, sendHandlerType defaultSendHandler);
-    static Message * createFromServerString(Server *server, QString srvMsg);
-    //static Message * createFromUserString(Server *server, Buffer *buffer, QString usrMsg);
-    //static registerCmd();
-    //static unregisterCmd();
+  Message(QString _msg = "", QString _sender = "", Type _type = Msg, Flags _flags = None)
+  : msg(_msg), sender(_sender), type(_type), flags(_flags) {};
 
-    inline Server * getServer() { return server; }
-    inline Buffer * getBuffer() { return buffer; }
-    inline int getCmdCode() { return cmdCode; }
-    inline QString getPrefix() { return prefix; }
-    inline QString getCmd() { return cmd; }
-    inline QStringList getParams() { return params; }
-    inline recvHandlerType getRecvHandler();
-    inline sendHandlerType getSendHandler();
-
-  protected:
-    Server *server;
-    Buffer *buffer;
-    int cmdCode;
-    QString prefix;
-    QString cmd;
-    QStringList params;
-    recvHandlerType recvHandler;
-    sendHandlerType sendHandler;
-    static recvHandlerType defaultRecvHandler;
-    static sendHandlerType defaultSendHandler;
-
-    static QHash<QString, CmdType> cmdTypes;
 };
 
-
-/** This is only used to have a nice way for defining builtin commands.
- *  We create an array of these in builtin_cmds.cpp and read this to fill our
- *  command hash.
- */
-struct BuiltinCmd {
-  int cmdCode;
-  QString cmd;
-  QString cmdDescr;
-  QString args;
-  QString argsDescr;
-  recvHandlerType recvHandler;
-  sendHandlerType sendHandler;
-};
+Q_DECLARE_METATYPE(Message)
 
 #endif
index 4d00c2c..d9e0a5b 100644 (file)
@@ -21,6 +21,7 @@
 #include "global.h"
 #include "server.h"
 #include "cmdcodes.h"
+#include "message.h"
 
 #include <QMetaObject>
 
@@ -60,7 +61,7 @@ void Server::disconnectFromIrc(QString net) {
 void Server::socketHasData() {
   while(socket.canReadLine()) {
     QString s = socket.readLine().trimmed();
-    //qDebug() << "Read: " << s;
+    qDebug() << "Read: " << s;
     emit recvRawServerMsg(s);
     //Message *msg = Message::createFromServerString(this, s);
     handleServerMsg(s);
@@ -68,7 +69,7 @@ void Server::socketHasData() {
 }
 
 void Server::socketError( QAbstractSocket::SocketError err ) {
-  qDebug() << "Socket Error!";
+  //qDebug() << "Socket Error!";
   //emit error(err);
 }
 
@@ -79,16 +80,22 @@ void Server::socketConnected( ) {
 }
 
 void Server::socketDisconnected( ) {
-  qDebug() << "Socket disconnected!";
-  //emit disconnected();
+  //qDebug() << "Socket disconnected!";
+  emit disconnected();
 }
 
 void Server::socketStateChanged(QAbstractSocket::SocketState state) {
-  qDebug() << "Socket state changed: " << state;
+  //qDebug() << "Socket state changed: " << state;
 }
 
 void Server::userInput(QString net, QString buf, QString msg) {
-  putRawLine(msg);
+  if(net != network) return; // not me!
+  msg = msg.trimmed(); // remove whitespace from start and end
+  if(msg.isEmpty()) return;
+  if(!msg.startsWith('/')) {
+    msg = QString("/SAY ") + msg;
+  }
+  handleUserMsg(buf, msg);
 }
 
 void Server::putRawLine(QString s) {
@@ -139,39 +146,144 @@ void Server::handleServerMsg(QString msg) {
     // 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();
-    hname = "handle" + hname + "FromServer";
+    hname = "handleServer" + hname;
     if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(QString, prefix), Q_ARG(QStringList, params))) {
       // Ok. Default handler it is.
-      defaultHandlerForServer(cmd, prefix, params);
+      defaultServerHandler(cmd, prefix, params);
     }
   } catch(Exception e) {
-    emit sendStatusMsg(e.msg());
+    emit sendMessage("", Message(e.msg(), "", Message::Error));
   }
 }
 
-void Server::defaultHandlerForServer(QString cmd, QString prefix, QStringList params) {
+void Server::defaultServerHandler(QString cmd, QString prefix, QStringList params) {
   uint num = cmd.toUInt();
   if(num) {
-    emit sendMessage("", cmd + " " + params.join(" "));
+    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));
+        break;
+      // Ignore these commands.
+      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));
+    }
+    //qDebug() << prefix <<":"<<cmd<<params;
   } else {
-    emit sendMessage("", QString("Unknown: ") + cmd + " " + params.join(" "));
+    emit sendMessage("", Message(QString("Unknown: ") + cmd + " " + params.join(" "), prefix, Message::Error));
+    //qDebug() << prefix <<":"<<cmd<<params;
+  }
+}
+
+void Server::handleUserMsg(QString bufname, QString usrMsg) {
+  try {
+    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))) {
+        // Ok. Default handler it is.
+      defaultUserHandler(cmd, msg, buffer);
+    }
+  } catch(Exception e) {
+    emit sendMessage("", Message(e.msg(), "", Message::Error));
   }
 }
 
-void Server::handleUserMsg(QString usrMsg) {
+void Server::defaultUserHandler(QString cmd, QString msg, Buffer *buf) {
+  emit sendMessage("", Message(QString("Error: %1 %2").arg(cmd).arg(msg), "", Message::Error));
+
+}
+
+/**********************************************************************************/
+
+/*
+void Server::handleUser(QString msg, Buffer *buf) {
+
+
+}
+*/
+
+void Server::handleUserJoin(QString msg, Buffer *buf) {
+  putCmd("JOIN", QStringList(msg));
+
+}
+
+void Server::handleUserQuote(QString msg, Buffer *buf) {
+  putRawLine(msg);
+}
 
+void Server::handleUserSay(QString msg, Buffer *buf) {
+  if(!buf) return;  // server buffer
+  QStringList params;
+  params << buf->name() << msg;
+  putCmd("PRIVMSG", params);
 }
 
-void Server::handleNoticeFromServer(QString prefix, QStringList params) {
-  sendMessage("", params.join(" "));
+/**********************************************************************************/
 
+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;
+  }
+  // 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));
 }
 
-void Server::handlePingFromServer(QString prefix, QStringList params) {
+void Server::handleServerPing(QString prefix, QStringList params) {
   putCmd("PONG", params);
 }
 
+void Server::handleServerPrivmsg(QString prefix, QStringList params) {
+  emit sendMessage(params[0], Message(params[1], prefix, Message::Msg));
+
+}
+
+/* RPL_WELCOME */
+void Server::handleServer001(QString prefix, QStringList params) {
+  currentServer = prefix;
+  currentNick = params[0];
+  emit sendMessage("", 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], "");
+}
+
+/* RPL_TOPIC */
+void Server::handleServer332(QString prefix, QStringList params) {
+  if(params[0] == currentNick) params.removeFirst();
+  emit setTopic(network, params[0], params[1]);
+}
+
+/***********************************************************************************/
+
 /* Exception classes for message handling */
 Server::ParseError::ParseError(QString cmd, QString prefix, QStringList params) {
   _msg = QString("Command Parse Error: ") + cmd + params.join(" ");
index dff974b..6fde53f 100644 (file)
 
 #include "global.h"
 #include "buffer.h"
+#include "message.h"
 
 #define DEFAULT_PORT 6667
 
-/*! \file */
 
-/*! \class Server
+/*!
  * This is a server object, managing a single connection to an IRC server, handling the associated channels and so on.
  * We have this running in its own thread mainly to not block other server objects or the core if something goes wrong,
  * e.g. if some scripts starts running wild...
@@ -63,9 +63,13 @@ class Server : public QThread {
   signals:
     void recvRawServerMsg(QString);
     void sendStatusMsg(QString);
-    void sendMessage(QString buffer, QString msg);
+    void sendMessage(QString buffer, Message msg);
     void disconnected();
 
+    void setTopic(QString network, QString buffer, QString topic);
+    void setNicks(QString network, QString buffer, QStringList nicks);
+
+
   private slots:
     void run();
     void socketHasData();
@@ -75,19 +79,36 @@ class Server : public QThread {
     void socketStateChanged(QAbstractSocket::SocketState);
 
     /* Message Handlers */
-    /* handleXxxxFromServer(QString prefix, QStringList params); */
-    void handleNoticeFromServer(QString, QStringList);
-    void handlePingFromServer(QString, QStringList);
 
-    void defaultHandlerForServer(QString cmd, QString prefix, QStringList params);
+    /* handleUser(QString, Buffer *) */
+    void handleUserJoin(QString, Buffer *);
+    void handleUserQuote(QString, Buffer *);
+    void handleUserSay(QString, Buffer *);
+
+
+    /* handleServer(QString, QStringList); */
+    void handleServerJoin(QString, QStringList);
+    void handleServerNotice(QString, QStringList);
+    void handleServerPing(QString, QStringList);
+    void handleServerPrivmsg(QString, QStringList);
+
+    void handleServer001(QString, QStringList);   // RPL_WELCOME
+    void handleServer331(QString, QStringList);   // RPL_NOTOPIC
+    void handleServer332(QString, QStringList);   // RPL_TOPIC
+
+    void defaultServerHandler(QString cmd, QString prefix, QStringList params);
+    void defaultUserHandler(QString cmd, QString msg, Buffer *buf);
 
   private:
     QString network;
     QTcpSocket socket;
     QHash<QString, Buffer*> buffers;
 
+    QString currentNick;
+    QString currentServer;
+
     void handleServerMsg(QString rawMsg);
-    void handleUserMsg(QString usrMsg);
+    void handleUserMsg(QString buffer, QString usrMsg);
 
     class ParseError : public Exception {
       public: