* Separation of GUI and Core finished, including synchronized global data in Global *global
* Speaking of which, the Quassel class has been renamed to Global, way cooler!
* TCP/IP between GUI and Core works, though the server port is still hardcoded to 4242
* The build system now handles any combination of "mono", "core" and "gui" for cmake's -DBUILD
* A lot of fixes and stuff
* More to come, but the basic framework should be stabilizing now.
PROJECT(Quassel)
-# CMAKE_MINIMUM_REQUIRED(VERSION 2.4.2)
+# 2.4.2 had a bug with out-of-source builds and UIC dependencies.
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4.3 FATAL_ERROR)
# Select if Quassel should be built in client, server or monolithic mode
-SET(BUILD "mono" CACHE STRING "Defines which Quassel parts are to be built. Can contain 'core', 'gui' and/or 'monolithic' (which is the default).")
+SET(BUILD "mono" CACHE STRING "Defines which Quassel parts are to be built. Can contain 'core', 'gui' and/or 'monolithic' (which is the default), or 'all' to build everything.")
SET(BUILD_CORE )
SET(BUILD_GUI )
SET(BUILD_MONO )
-IF(BUILD MATCHES "core")
+IF(BUILD MATCHES "core" OR BUILD MATCHES "all")
SET(BUILD_CORE true)
- MESSAGE(STATUS "Building Quassel core.")
-ENDIF(BUILD MATCHES "core")
-IF(BUILD MATCHES "gui")
+ MESSAGE("Building Quassel core.")
+ENDIF(BUILD MATCHES "core" OR BUILD MATCHES "all")
+IF(BUILD MATCHES "gui" OR BUILD MATCHES "all")
SET(BUILD_GUI true)
- MESSAGE(STATUS "Building Quassel GUI.")
-ENDIF(BUILD MATCHES "gui")
-IF(BUILD MATCHES "mono")
+ MESSAGE("Building Quassel GUI.")
+ENDIF(BUILD MATCHES "gui" OR BUILD MATCHES "all")
+IF(BUILD MATCHES "mono" OR BUILD MATCHES "all")
SET(BUILD_MONO true)
- MESSAGE(STATUS "Building monolithic Quassel.")
-ENDIF(BUILD MATCHES "mono")
+ MESSAGE("Building monolithic Quassel.")
+ENDIF(BUILD MATCHES "mono" OR BUILD MATCHES "all")
IF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI)
- MESSAGE(FATAL_ERROR "You have not selected which parts of Quassel I should build. Aborting.\nRun 'cmake -DBUILD=<part>', where <part> contains one or more of 'core', 'gui' or 'monolithic'.")
+ MESSAGE(FATAL_ERROR "\nYou have not selected which parts of Quassel I should build. Aborting.\nRun 'cmake <path> -DBUILD=<part>', where <part> contains one or more of 'core', 'gui' or 'monolithic', or 'all' to build everything.\n")
ENDIF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI)
# Define files
SET(quassel_mono_SRCS main/main_mono.cpp)
SET(quassel_core_SRCS main/main_core.cpp)
-#SET(quassel_gui_SRCS main/main_gui.cpp ${common_SRCS})
+SET(quassel_gui_SRCS main/main_gui.cpp ${common_SRCS})
SET(quassel_RCCS images/icons.qrc)
SET(quassel_DIRS main gui core network)
SET(QT_DONT_USE_QTGUI true) # This is added later if GUI is requested
INCLUDE(${QT_USE_FILE})
+# Define subdirs. CMake complains if a directory is added twice, so make sure this
+# does not happen in any combination of the requested targets.
+
ADD_SUBDIRECTORY(main)
+IF(BUILD_CORE)
+ ADD_SUBDIRECTORY(core)
+ ADD_SUBDIRECTORY(network)
+ENDIF(BUILD_CORE)
+IF(BUILD_MONO AND NOT BUILD_CORE)
+ ADD_SUBDIRECTORY(core)
+ ADD_SUBDIRECTORY(network)
+ENDIF(BUILD_MONO AND NOT BUILD_CORE)
+
QT4_ADD_RESOURCES(_RCCS ${quassel_RCCS})
IF(BUILD_CORE)
ADD_DEFINITIONS(-DBUILD_CORE)
- ADD_SUBDIRECTORY(network)
- ADD_SUBDIRECTORY(core)
ADD_EXECUTABLE(quasselcore ${quassel_core_SRCS} ${_RCCS})
TARGET_LINK_LIBRARIES(quasselcore core network main ${QT_LIBRARIES})
ENDIF(BUILD_CORE)
SET(QT_INCLUDE_DIR "")
SET(QT_LIBRARIES "")
INCLUDE(${QT_USE_FILE})
+ ADD_SUBDIRECTORY(gui)
IF(BUILD_MONO)
ADD_DEFINITIONS(-DBUILD_MONO)
- ADD_SUBDIRECTORY(gui)
- ADD_SUBDIRECTORY(network)
- ADD_SUBDIRECTORY(core)
ADD_EXECUTABLE(quassel ${quassel_mono_SRCS} ${_RCCS})
TARGET_LINK_LIBRARIES(quassel gui core network main ${QT_LIBRARIES})
ENDIF(BUILD_MONO)
IF(BUILD_GUI)
ADD_DEFINITIONS(-DBUILD_GUI)
- ADD_SUBDIRECTORY(gui)
ADD_EXECUTABLE(quasselgui ${quassel_gui_SRCS} ${_RCCS})
TARGET_LINK_LIBRARIES(quasselgui gui main ${QT_LIBRARIES})
ENDIF(BUILD_GUI)
-# Doxyfile 1.4.1-KDevelop
+# Doxyfile 1.4.7
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-PROJECT_NAME = quassel.kdevelop
+PROJECT_NAME = "Quassel IRC"
PROJECT_NUMBER = 0.1
-OUTPUT_DIRECTORY =
+OUTPUT_DIRECTORY = doc
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
the
ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = YES
-FULL_PATH_NAMES = YES
+FULL_PATH_NAMES = NO
STRIP_FROM_PATH = /
STRIP_FROM_INC_PATH =
SHORT_NAMES = YES
-JAVADOC_AUTOBRIEF = YES
+JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
-DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
-OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
-SUBGROUPING = NO
+BUILTIN_STL_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
-EXTRACT_LOCAL_CLASSES = YES
-EXTRACT_LOCAL_METHODS = YES
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
-SHOW_USED_FILES = NO
+SHOW_USED_FILES = YES
SHOW_DIRECTORIES = YES
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
-INPUT = /home/sputnick/devel/quassel
+INPUT = /home/sputnick/shared/Development/quassel/
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.moc \
*.xpm \
*.dox
-RECURSIVE = yes
+RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
-STRIP_CODE_COMMENTS = NO
-REFERENCED_BY_RELATION = NO
-REFERENCES_RELATION = NO
-VERBATIM_HEADERS = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
-GENERATE_XML = yes
+GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING = YES
+ENABLE_PREPROCESSING = NO
MACRO_EXPANSION = NO
-EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = quassel.tag
-ALLEXTERNALS = NO
+ALLEXTERNALS = YES
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
-UML_LOOK = NO
+UML_LOOK = YES
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
+CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
main/main_gui.cpp
core/coreproxy.cpp
core/coreproxy.h
+main/util.cpp
+main/util.h
+gui/coreconnectdlg.ui
+gui/coreconnectdlg.cpp
+gui/coreconnectdlg.h
connect(&server, SIGNAL(recvLine(QString)), coreProxy, SLOT(csCoreMessage(QString)));
+ // Read global settings from config file
QSettings s;
- VarMap identities = s.value("Network/Identities").toMap();
- //VarMap networks = s.value("Network/
- quassel->putData("Identities", identities);
+ s.beginGroup("Global");
+ QString key;
+ foreach(key, s.childKeys()) {
+ global->updateData(key, s.value(key));
+ }
+ global->updateData("CoreReady", true);
+ // Now that we are in sync, we can connect signals to automatically store further updates.
+ // I don't think we care if global data changed locally or if it was updated by a client.
+ connect(global, SIGNAL(dataUpdatedRemotely(QString)), SLOT(globalDataUpdated(QString)));
+ connect(global, SIGNAL(dataPutLocally(QString)), SLOT(globalDataUpdated(QString)));
server.start();
}
-void Core::init() {
-
-
-}
-
-/*
-void Core::run() {
-
- connect(&server, SIGNAL(recvLine(const QString &)), this, SIGNAL(outputLine(const QString &)));
- //connect(
- server.start();
- exec();
-}
-*/
-
void Core::connectToIrc(const QString &h, quint16 port) {
+ if(server.isConnected()) return;
qDebug() << "Core: Connecting to " << h << ":" << port;
server.connectToIrc(h, port);
}
}
-VarMap Core::loadIdentities() {
- QSettings s;
- return s.value("Network/Identities").toMap();
-}
-
-void Core::storeIdentities(VarMap identities) {
+void Core::globalDataUpdated(QString key) {
+ QVariant data = global->getData(key);
QSettings s;
- s.setValue("Network/Identities", identities);
+ s.setValue(QString("Global/")+key, data);
}
-Core *core;
+Core *core = 0;
signals:
void outputLine(const QString &); // temp
+ private slots:
+ void globalDataUpdated(QString);
+
private:
//void run();
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#include "coreproxy.h"
#include <QDebug>
+#include "coreproxy.h"
+#include "quassel.h"
+#include "util.h"
+
CoreProxy::CoreProxy() {
if(coreProxy) qFatal("Trying to instantiate more than one CoreProxy object!");
+ connect(global, SIGNAL(dataPutLocally(QString)), this, SLOT(updateGlobalData(QString)));
+ connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
+ if(!server.listen(QHostAddress::Any, 4242)) {
+ qFatal(QString(QString("Could not open GUI client port %1: %2").arg(4242).arg(server.errorString())).toAscii());
+ }
+ qDebug() << "Listening for GUI clients on port" << server.serverPort() << ".";
+}
+
+void CoreProxy::incomingConnection() {
+ QTcpSocket *socket = server.nextPendingConnection();
+ connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
+ clients.append(socket);
+ blockSizes.insert(socket, (quint32)0);
+ qDebug() << "Client connected from " << socket->peerAddress().toString();
+}
+
+void CoreProxy::clientHasData() {
+ QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
+ Q_ASSERT(socket && blockSizes.contains(socket));
+ quint32 bsize = blockSizes.value(socket);
+ QVariant item;
+ while(readDataFromDevice(socket, bsize, item)) {
+ QList<QVariant> sigdata = item.toList();
+ Q_ASSERT(sigdata.size() == 4);
+ switch((GUISignal)sigdata[0].toInt()) {
+ case GS_CLIENT_INIT: processClientInit(socket, sigdata[1]); break;
+ case GS_UPDATE_GLOBAL_DATA: processClientUpdate(socket, sigdata[1].toString(), sigdata[2]); break;
+ //case GS_CLIENT_READY: processClientReady(sigdata[1], sigdata[2], sigdata[3]); break;
+ default: recv((GUISignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]); break;
+ }
+ blockSizes[socket] = bsize = 0;
+ }
+ blockSizes[socket] = bsize;
+}
+
+void CoreProxy::clientDisconnected() {
+ QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
+ blockSizes.remove(socket);
+ clients.removeAll(socket);
+ qDebug() << "Client disconnected.";
+}
+
+void CoreProxy::processClientInit(QTcpSocket *socket, const QVariant &v) {
+ VarMap msg = v.toMap();
+ if(msg["GUIProtocol"].toUInt() != GUI_PROTOCOL) {
+ qDebug() << "Client version mismatch. Disconnecting.";
+ socket->close();
+ return;
+ }
+ VarMap reply;
+ VarMap coreData;
+ QStringList dataKeys = global->getKeys();
+ QString key;
+ foreach(key, dataKeys) {
+ coreData[key] = global->getData(key);
+ }
+ reply["CoreData"] = coreData;
+ //QVariant payload = QByteArray(1000000, 'a');
+ //reply["payload"] = payload;
+ QList<QVariant> sigdata;
+ sigdata.append(CS_CORE_STATE); sigdata.append(QVariant(reply)); sigdata.append(QVariant()); sigdata.append(QVariant());
+ writeDataToDevice(socket, QVariant(sigdata));
+}
+
+void CoreProxy::processClientUpdate(QTcpSocket *socket, QString key, QVariant data) {
+ global->updateData(key, data);
+ QList<QVariant> sigdata;
+ sigdata.append(CS_UPDATE_GLOBAL_DATA); sigdata.append(key); sigdata.append(data); sigdata.append(QVariant());
+ QTcpSocket *s;
+ foreach(s, clients) {
+ if(s != socket) writeDataToDevice(s, QVariant(sigdata));
+ }
+}
+
+void CoreProxy::updateGlobalData(QString key) {
+ QVariant data = global->getData(key);
+ emit csUpdateGlobalData(key, data);
+}
+
+void CoreProxy::send(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ sendToGUI(sig, arg1, arg2, arg3);
+ QList<QVariant> sigdata;
+ sigdata.append(sig); sigdata.append(arg1); sigdata.append(arg2); sigdata.append(arg3);
+ //qDebug() << "Sending signal: " << sigdata;
+ QTcpSocket *socket;
+ foreach(socket, clients) {
+ writeDataToDevice(socket, QVariant(sigdata));
+ }
}
-void CoreProxy::csCoreMessage(QString s) {
- send(CS_CORE_MESSAGE, s);
+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_REQUEST_CONNECT: emit gsRequestConnect(arg1.toString(), arg2.toUInt()); break;
+ default: qWarning() << "Unknown signal in CoreProxy::recv: " << sig;
+ }
}
CoreProxy *coreProxy;
#include "proxy_common.h"
-#include <QObject>
-#include <QVariant>
+#include <QtCore>
+#include <QTcpSocket>
+#include <QTcpServer>
/** This class is the Core side of the proxy. The Core connects its signals and slots to it,
* and the calls are marshalled and sent to (or received and unmarshalled from) the GUIProxy.
class CoreProxy : public QObject {
Q_OBJECT
- private:
- void send(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
- void recv(GUISignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
-
public:
CoreProxy();
public slots:
- void csCoreMessage(QString);
-
+ inline void csCoreMessage(QString s) { send(CS_CORE_MESSAGE, s); }
+ inline void csUpdateGlobalData(QString key, QVariant data) { send(CS_UPDATE_GLOBAL_DATA, key, data); }
signals:
+ void gsPutGlobalData(QString, QVariant);
void gsUserInput(QString);
void gsRequestConnect(QString, quint16);
+ private:
+ void send(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+ void recv(GUISignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+ void sendToGUI(CoreSignal, QVariant arg1, QVariant arg2, QVariant arg3);
+
+ void processClientInit(QTcpSocket *socket, const QVariant &v);
+ void processClientUpdate(QTcpSocket *, QString key, QVariant data);
+
+ private slots:
+ void incomingConnection();
+ void clientHasData();
+ void clientDisconnected();
+ void updateGlobalData(QString key);
+
+ private:
+ QTcpServer server;
+ QList<QTcpSocket *> clients;
+ QHash<QTcpSocket *, quint32> blockSizes;
+
friend class GUIProxy;
};
-SET(gui_SRCS channelwidget.cpp mainwin.cpp serverlist.cpp guiproxy.cpp)
+SET(gui_SRCS channelwidget.cpp mainwin.cpp serverlist.cpp coreconnectdlg.cpp guiproxy.cpp)
SET(gui_HDRS )
-SET(gui_MOCS channelwidget.h mainwin.h serverlist.h guiproxy.h)
-SET(gui_UICS channelwidget.ui identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui nickeditdlg.ui serverlistdlg.ui)
+SET(gui_MOCS channelwidget.h mainwin.h serverlist.h coreconnectdlg.h guiproxy.h)
+SET(gui_UICS channelwidget.ui identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui nickeditdlg.ui serverlistdlg.ui coreconnectdlg.ui)
QT4_WRAP_UI(_UIC ${gui_UICS})
QT4_WRAP_CPP(_MOC ${gui_MOCS})
# We need to work around a dependency bug with out-of-source builds...
-SET_SOURCE_FILES_PROPERTIES(${gui_SRCS} PROPERTIES OBJECT_DEPENDS "${_UIC}")
+# Seems to be fixed!
+#SET_SOURCE_FILES_PROPERTIES(${gui_SRCS} PROPERTIES OBJECT_DEPENDS "${_UIC}")
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_LIBRARY(gui ${gui_HDRS} ${gui_SRCS} ${_MOC} ${_UIC})
--- /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 <QtGui>
+#include "coreconnectdlg.h"
+#include "guiproxy.h"
+#include "quassel.h"
+
+CoreConnectDlg::CoreConnectDlg(QWidget *parent) : QDialog(parent) {
+ ui.setupUi(this);
+ ui.progressBar->hide();
+ coreState = 0;
+ QSettings s;
+ connect(ui.hostName, SIGNAL(textChanged(QString)), this, SLOT(hostEditChanged(QString)));
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(hostSelected()));
+
+ ui.hostName->setText(s.value("GUI/CoreHost", "localhost").toString());
+ ui.hostName->setSelection(0, ui.hostName->text().length());
+ ui.hostPort->setValue(s.value("GUI/CorePort", 4242).toInt());
+ ui.autoConnect->setChecked(s.value("GUI/CoreAutoConnect", true).toBool());
+ if(s.value("GUI/CoreAutoConnect").toBool()) {
+ hostSelected();
+ }
+}
+
+void CoreConnectDlg::setStartState() {
+ ui.hostName->show(); ui.hostPort->show(); ui.hostLabel->show(); ui.portLabel->show();
+ ui.statusText->setText(tr("Connect to Quassel Core running on:"));
+ ui.buttonBox->button(QDialogButtonBox::Ok)->show();
+ ui.hostName->setEnabled(true); ui.hostPort->setEnabled(true);
+ ui.hostName->setSelection(0, ui.hostName->text().length());
+}
+
+void CoreConnectDlg::hostEditChanged(QString txt) {
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(txt.length());
+}
+
+void CoreConnectDlg::hostSelected() {
+ ui.hostName->hide(); ui.hostPort->hide(); ui.hostLabel->hide(); ui.portLabel->hide();
+ ui.statusText->setText(tr("Connecting to %1:%2" ).arg(ui.hostName->text()).arg(ui.hostPort->value()));
+ ui.buttonBox->button(QDialogButtonBox::Ok)->hide();
+ connect(guiProxy, SIGNAL(coreConnected()), this, SLOT(coreConnected()));
+ connect(guiProxy, SIGNAL(coreConnectionError(QString)), this, SLOT(coreConnectionError(QString)));
+ guiProxy->connectToCore(ui.hostName->text(), ui.hostPort->value());
+
+}
+
+void CoreConnectDlg::coreConnected() {
+ ui.hostLabel->hide(); ui.hostName->hide(); ui.portLabel->hide(); ui.hostPort->hide();
+ ui.statusText->setText(tr("Synchronizing..."));
+ QSettings s;
+ s.setValue("GUI/CoreHost", ui.hostName->text());
+ s.setValue("GUI/CorePort", ui.hostPort->value());
+ s.setValue("GUI/CoreAutoConnect", ui.autoConnect->isChecked());
+ connect(guiProxy, SIGNAL(recvPartialItem(quint32, quint32)), this, SLOT(updateProgressBar(quint32, quint32)));
+ connect(guiProxy, SIGNAL(csCoreState(QVariant)), this, SLOT(recvCoreState(QVariant)));
+ ui.progressBar->show();
+ VarMap initmsg;
+ initmsg["GUIProtocol"] = GUI_PROTOCOL;
+ guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg));
+}
+
+void CoreConnectDlg::coreConnectionError(QString err) {
+ QMessageBox::warning(this, tr("Connection Error"), tr("<b>Could not connect to Quassel Core!</b><br>\n") + err, QMessageBox::Retry);
+ disconnect(guiProxy, 0, this, 0);
+ ui.autoConnect->setChecked(false);
+ setStartState();
+}
+
+void CoreConnectDlg::updateProgressBar(quint32 recv, quint32 avail) {
+ ui.progressBar->setMaximum(avail);
+ ui.progressBar->setValue(recv);
+}
+
+void CoreConnectDlg::recvCoreState(QVariant state) {
+ ui.progressBar->hide();
+ coreState = state;
+ accept();
+}
+
+QVariant CoreConnectDlg::getCoreState() {
+ return coreState;
+}
--- /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 _CORECONNECTDLG_H
+#define _CORECONNECTDLG_H
+
+#include "coreconnectdlg.h"
+#include "ui_coreconnectdlg.h"
+
+class CoreConnectDlg: public QDialog {
+ Q_OBJECT
+
+ public:
+ CoreConnectDlg(QWidget *);
+ QVariant getCoreState();
+
+ private slots:
+ void hostEditChanged(QString);
+ void hostSelected();
+
+ void coreConnected();
+ void coreConnectionError(QString);
+ void updateProgressBar(quint32 bytes, quint32 avail);
+ void recvCoreState(QVariant);
+
+ private:
+ Ui::CoreConnectDlg ui;
+ QVariant coreState;
+
+ void setStartState();
+};
+
+#endif
--- /dev/null
+<ui version="4.0" >
+ <class>CoreConnectDlg</class>
+ <widget class="QDialog" name="CoreConnectDlg" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>499</width>
+ <height>144</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle" >
+ <string>Connect to Quassel Core</string>
+ </property>
+ <property name="windowIcon" >
+ <iconset resource="../images/icons.qrc" >:/default/server.png</iconset>
+ </property>
+ <property name="modal" >
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="statusText" >
+ <property name="text" >
+ <string>Connect to Quassel Core running on:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="hostLabel" >
+ <property name="text" >
+ <string>Host</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="hostName" />
+ </item>
+ <item>
+ <widget class="QLabel" name="portLabel" >
+ <property name="text" >
+ <string>Port</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="hostPort" >
+ <property name="maximum" >
+ <number>65535</number>
+ </property>
+ <property name="minimum" >
+ <number>1024</number>
+ </property>
+ <property name="value" >
+ <number>4242</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar" >
+ <property name="value" >
+ <number>0</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>53</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="autoConnect" >
+ <property name="text" >
+ <string>Connect automatically</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>101</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../images/icons.qrc" />
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>CoreConnectDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>507</x>
+ <y>273</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>297</x>
+ <y>151</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#include "guiproxy.h"
-
-GUIProxy::GUIProxy() {
- if(guiProxy) qFatal("Trying to instantiate more than one CoreProxy object!");
-
-}
+#include <QtDebug>
-void GUIProxy::gsUserInput(QString s) {
- send(GS_USER_INPUT, s);
-}
+#include "guiproxy.h"
+#include "util.h"
-void GUIProxy::gsRequestConnect(QString h, quint16 p) {
- send(GS_REQUEST_CONNECT, h, p);
+void GUIProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ //qDebug() << "[GUI] Received signal:" << sig <<arg1<<arg2<<arg3;
+ switch(sig) {
+ 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_CORE_MESSAGE: emit csCoreMessage(arg1.toString()); break;
+ default: qWarning() << "Unknown signal in GUIProxy::recv: " << sig;
+ }
}
GUIProxy *guiProxy;
#include <QObject>
#include <QVariant>
+#include <QTcpSocket>
/** This class is the GUI side of the proxy. The GUI connects its signals and slots to it,
* and the calls are marshalled and sent to (or received and unmarshalled from) the CoreProxy.
class GUIProxy : public QObject {
Q_OBJECT
- private:
- void send(GUISignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
- void recv(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
-
public:
GUIProxy();
public slots:
- void gsUserInput(QString);
- void gsRequestConnect(QString, quint16);
+ inline void gsUserInput(QString s) { send(GS_USER_INPUT, s); }
+ inline void gsRequestConnect(QString host, quint16 port) { send(GS_REQUEST_CONNECT, host, port); }
+ //inline void gsPutQuasselData(QString key, QVariant data) { send(GS_PUT_QUASSEL_DATA, key, data); }
+ void connectToCore(QString host, quint16 port);
+ void disconnectFromCore();
signals:
+ void csCoreState(QVariant);
void csCoreMessage(QString);
+ void csUpdateGlobalData(QString key, QVariant data);
+ void csGlobalDataChanged(QString key);
+
+ void coreConnected();
+ void coreDisconnected();
+ void coreConnectionError(QString errorMsg);
+
+ void recvPartialItem(quint32 avail, quint32 size);
+
+ public:
+ void send(GUISignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+ void recv(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+
+ private slots:
+ void updateCoreData(QString);
+
+ void serverError(QAbstractSocket::SocketError);
+ void serverHasData();
+
+ private:
+ QTcpSocket socket;
+ quint32 blockSize;
friend class CoreProxy;
#include <QtGui>
+#include "quassel.h"
+
#include "mainwin.h"
#include "channelwidget.h"
#include "serverlist.h"
-
-#include "core.h"
-#include "server.h"
+#include "coreconnectdlg.h"
MainWin::MainWin() : QMainWindow() {
setWindowTitle("Quassel IRC");
- setWindowIcon(QIcon(":/default/tux.png"));
+ setWindowIcon(QIcon(":/qirc-icon.png"));
setWindowIconText("Quassel IRC");
//workspace = new QWorkspace(this);
//setCentralWidget(workspace);
- ChannelWidget *cw = new ChannelWidget(this);
+ //ChannelWidget *cw = new ChannelWidget(this);
//workspace->addWindow(cw);
- setCentralWidget(cw);
+ //setCentralWidget(cw);
+ statusBar()->showMessage(tr("Waiting for core..."));
+ setEnabled(false);
+ show();
+ syncToCore();
+ setEnabled(true);
serverListDlg = new ServerListDlg(this);
serverListDlg->setVisible(serverListDlg->showOnStartup());
- //showServerList();
-
setupMenus();
- statusBar()->showMessage(tr("Ready"));
+ //identitiesAct = settingsMenu->addAction(QIcon(":/default/identity.png"), tr("&Identities..."), serverListDlg, SLOT(editIdentities()));
+ //showServerList();
+ ChannelWidget *cw = new ChannelWidget(this);
+ setCentralWidget(cw);
+ //setEnabled(true);
+ statusBar()->showMessage(tr("Ready."));
+}
+void MainWin::syncToCore() {
+ if(global->getData("CoreReady").toBool()) return;
+ // ok, apparently we are running as standalone GUI
+ coreConnectDlg = new CoreConnectDlg(this);
+ if(coreConnectDlg->exec() != QDialog::Accepted) {
+ //qApp->quit();
+ exit(1);
+ }
+ VarMap state = coreConnectDlg->getCoreState().toMap()["CoreData"].toMap();
+ delete coreConnectDlg;
+ QString key;
+ foreach(key, state.keys()) {
+ global->updateData(key, state[key]);
+ }
+ if(!global->getData("CoreReady").toBool()) {
+ QMessageBox::critical(this, tr("Fatal Error"), tr("<b>Could not synchronize with Quassel Core!</b><br>Quassel GUI will be aborted."), QMessageBox::Abort);
+ //qApp->quit();
+ exit(1);
+ }
}
void MainWin::setupMenus() {
aboutAct->setEnabled(0);
aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
-
//toolBar = new QToolBar("Test", this);
//toolBar->addAction(identitiesAct);
//addToolBar(Qt::TopToolBarArea, toolBar);
class QWorkspace;
class ServerListDlg;
+class CoreConnectDlg;
class MainWin : public QMainWindow {
Q_OBJECT
private slots:
void showServerList();
-
+
private:
void setupMenus();
-
+ void syncToCore();
+
QWorkspace *workspace;
QToolBar *toolBar;
QMenu *fileMenu, *editMenu, *ircMenu, *serverMenu, *windowMenu, *helpMenu, *settingsMenu;
QAction *identitiesAct, *configAct;
ServerListDlg *serverListDlg;
+ CoreConnectDlg *coreConnectDlg;
};
#endif
/* NOTE: This dialog holds not only the server list, but also the identities.
* This makes perfect sense given the fact that connections are initiated from
* this dialog, and that the dialog exists during the lifetime of the program.
- * This data is also only used from within the GUI, which means it shouldn't be
- * part of the global Quassel class (me thinks).
*/
ServerListDlg::ServerListDlg(QWidget *parent) : QDialog(parent) {
ui.setupUi(this);
QSettings settings;
- settings.beginGroup("Network");
+ settings.beginGroup("GUI");
ui.showOnStartup->setChecked(settings.value("ShowServerListOnStartup", true).toBool());
// create some default entries
VarMap s1, s2, s3, s4;
}
void ServerListDlg::loadIdentities() {
- //QSettings s;
- //s.beginGroup("Identities");
- //identities = s.value("Network/Identities").toMap();
- //identities = GuiProxy::loadIdentities();
- identities = quassel->getData("Identities").toMap();
+ identities = global->getData("Identities", VarMap()).toMap();
while(!identities.contains("Default")) {
- identities = VarMap();
editIdentities();
}
}
void ServerListDlg::storeIdentities() {
- //QSettings s;
- //s.setValue("Network/Identities", identities);
- //GuiProxy::storeIdentities(identities);
- quassel->putData("Identities", identities);
+ global->putData("Identities", identities);
}
void ServerListDlg::editIdentities() {
if(dlg.exec() == QDialog::Accepted) {
identities = dlg.getIdentities();
QMap<QString, QString> mapping = dlg.getNameMapping();
- // add mapping here
+ // add mapping here <-- well, I don't fucking know anymore what I meant by this back in 2005...
//
storeIdentities();
void ServerListDlg::on_showOnStartup_stateChanged(int) {
QSettings s;
- s.setValue("Network/ShowServerListOnStartup", ui.showOnStartup->isChecked());
+ s.setValue("GUI/ShowServerListOnStartup", ui.showOnStartup->isChecked());
}
/***************************************************************************/
IdentitiesDlg::IdentitiesDlg(QWidget *parent, VarMap _identities) : QDialog(parent) {
ui.setupUi(this);
+ connect(global, SIGNAL(dataUpdatedRemotely(QString)), this, SLOT(globalDataUpdated(QString)));
+
connect(ui.enableAutoAway, SIGNAL(stateChanged(int)), this, SLOT(autoAwayChecked()));
identities = _identities;
connect(ui.downNickButton, SIGNAL(clicked()), this, SLOT(downNick()));
}
+void IdentitiesDlg::globalDataUpdated(QString key) {
+ if(key == "Identities") {
+ if(QMessageBox::warning(this, tr("Data changed remotely!"), tr("<b>Some other GUI client changed the identities data!</b><br>"
+ "Apply updated settings, losing all changes done locally?"),
+ QMessageBox::Apply|QMessageBox::Discard) == QMessageBox::Apply) {
+ identities = global->getData(key).toMap();
+ updateWidgets();
+ }
+ }
+}
+
VarMap IdentitiesDlg::createDefaultIdentity() {
VarMap id;
id["RealName"] = "foo";
void editIdentities();
+ void globalDataUpdated(QString);
+
private:
Ui::IdentitiesDlg ui;
VarMap identities;
<file>default/view_split.png</file>
<file>default/view_top_bottom.png</file>
<file>default/wizard.png</file>
+ <file>qirc-icon.png</file>
</qresource>
</RCC>
-SET(main_SRCS quassel.cpp logger.cpp)
-SET(main_HDRS )
+SET(main_SRCS quassel.cpp logger.cpp util.cpp)
+SET(main_HDRS util.h)
SET(main_MOCS quassel.h logger.h)
QT4_WRAP_CPP(_MOC ${main_MOCS})
#include <iostream>
#include <QCoreApplication>
+#include <QtNetwork>
+#include <QtCore>
+#include <QtDebug>
#include "quassel.h"
#include "core.h"
#include "coreproxy.h"
+#include "util.h"
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName("Quassel IRC");
QCoreApplication::setOrganizationName("The Quassel Team");
- Quassel::runMode = Quassel::CoreOnly;
- quassel = new Quassel();
+ Global::runMode = Global::CoreOnly;
+ global = new Global();
coreProxy = new CoreProxy();
core = new Core();
//Logger *logger = new Logger();
//Quassel::setLogger(logger);
- core->init();
-
int exitCode = app.exec();
delete core;
delete coreProxy;
- delete quassel;
+ delete global;
return exitCode;
}
-Core *core = 0;
-
-//GUIProxy::send(uint func, QVariant arg) {
- /*
- switch(func) {
- case LOAD_IDENTITIES: return (QVariant) CoreProxy::loadIdentities();
- case STORE_IDENTITIES: CoreProxy::storeIdentities(arg.toMap()); return 0;
-
- }
- */
+void CoreProxy::sendToGUI(CoreSignal, QVariant, QVariant, QVariant) {
+ // dummy function, no GUI available!
+}
-//}
#include "quassel.h"
#include "guiproxy.h"
+#include "util.h"
#include "mainwin.h"
QApplication::setApplicationName("Quassel IRC");
QApplication::setOrganizationName("The Quassel Team");
- Quassel::runMode = Quassel::GUIOnly;
- quassel = new Quassel();
+ Global::runMode = Global::GUIOnly;
+ global = new Global();
guiProxy = new GUIProxy();
MainWin mainWin;
- mainWin.show();
int exitCode = app.exec();
delete guiProxy;
- delete quassel;
+ delete global;
}
-void GUIProxy::send(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+GUIProxy::GUIProxy() {
+ if(guiProxy) qFatal("Trying to instantiate more than one CoreProxy object!");
+
+ blockSize = 0;
+
+ connect(&socket, SIGNAL(readyRead()), this, SLOT(serverHasData()));
+ connect(&socket, SIGNAL(connected()), this, SIGNAL(coreConnected()));
+ connect(&socket, SIGNAL(disconnected()), this, SIGNAL(coreDisconnected()));
+ connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(serverError(QAbstractSocket::SocketError)));
+ connect(global, SIGNAL(dataPutLocally(QString)), this, SLOT(updateCoreData(QString)));
+ connect(this, SIGNAL(csUpdateGlobalData(QString, QVariant)), global, SLOT(updateData(QString, QVariant)));
+
+}
+void GUIProxy::connectToCore(QString host, quint16 port) {
+ socket.connectToHost(host, port);
+ //VarMap initmsg;
+ //initmsg["GUIProtocol"] = GUI_PROTOCOL;
+ //send(GS_CLIENT_INIT, QVariant(initmsg));
+}
+void GUIProxy::disconnectFromCore() {
+ socket.close();
}
-void GUIProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+void GUIProxy::serverError(QAbstractSocket::SocketError) {
+ emit coreConnectionError(socket.errorString());
+}
+void GUIProxy::serverHasData() {
+ QVariant item;
+ while(readDataFromDevice(&socket, blockSize, item)) {
+ emit recvPartialItem(1,1);
+ QList<QVariant> sigdata = item.toList();
+ Q_ASSERT(sigdata.size() == 4);
+ recv((CoreSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
+ blockSize = 0;
+ }
+ if(blockSize > 0) {
+ emit recvPartialItem(socket.bytesAvailable(), blockSize);
+ }
+}
+void GUIProxy::send(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ QList<QVariant> sigdata;
+ sigdata.append(sig); sigdata.append(arg1); sigdata.append(arg2); sigdata.append(arg3);
+ //qDebug() << "Sending signal: " << sigdata;
+ writeDataToDevice(&socket, QVariant(sigdata));
+}
+void GUIProxy::updateCoreData(QString key) {
+ QVariant data = global->getData(key);
+ send(GS_UPDATE_GLOBAL_DATA, key, data);
}
QApplication::setApplicationName("Quassel IRC");
QApplication::setOrganizationName("The Quassel Team");
- Quassel::runMode = Quassel::Monolithic;
- quassel = new Quassel();
+ Global::runMode = Global::Monolithic;
+ global = new Global();
guiProxy = new GUIProxy();
coreProxy = new CoreProxy();
core = new Core();
- core->init();
-
MainWin mainWin;
mainWin.show();
int exitCode = app.exec();
delete core;
delete guiProxy;
delete coreProxy;
- delete quassel;
+ delete global;
return exitCode;
}
-void GUIProxy::send(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
- coreProxy->recv(sig, arg1, arg2, arg3);
+void CoreProxy::sendToGUI(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ guiProxy->recv(sig, arg1, arg2, arg3);
}
-void CoreProxy::recv(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
- switch(sig) {
- case GS_USER_INPUT: emit gsUserInput(arg1.toString()); break;
- case GS_REQUEST_CONNECT: emit gsRequestConnect(arg1.toString(), arg2.toUInt()); break;
- default: qWarning() << "Unknown signal in CoreProxy::recv: " << sig;
- }
+GUIProxy::GUIProxy() {
+ if(guiProxy) qFatal("Trying to instantiate more than one CoreProxy object!");
}
-void CoreProxy::send(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
- guiProxy->recv(sig, arg1, arg2, arg3);
+void GUIProxy::send(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ coreProxy->recv(sig, arg1, arg2, arg3);
}
-void GUIProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
- switch(sig) {
- case CS_CORE_MESSAGE: emit csCoreMessage(arg1.toString()); break;
- default: qWarning() << "Unknown signal in GUIProxy::recv: " << sig;
- }
-}
+// Dummy function definitions
+// These are not needed, since we don't have a network connection to the core.
+void GUIProxy::serverHasData() {}
+void GUIProxy::connectToCore(QString, quint16) {}
+void GUIProxy::disconnectFromCore() {}
+void GUIProxy::updateCoreData(QString) {}
+void GUIProxy::serverError(QAbstractSocket::SocketError) {}
+
#ifndef _PROXY_COMMON_H_
#define _PROXY_COMMON_H_
-enum GUISignal { GS_USER_INPUT, GS_REQUEST_CONNECT,
+enum GUISignal { GS_CLIENT_INIT, GS_USER_INPUT, GS_REQUEST_CONNECT, GS_UPDATE_GLOBAL_DATA,
};
-enum CoreSignal { CS_CORE_MESSAGE
+enum CoreSignal { CS_CORE_STATE, CS_CORE_MESSAGE, CS_UPDATE_GLOBAL_DATA,
};
#include "quassel.h"
#include "logger.h"
-//#include "proxy.h"
#include "core.h"
#include <QString>
+#include <QStringList>
#include <QDomDocument>
extern void messageHandler(QtMsgType type, const char *msg);
-Quassel::Quassel() {
- if(quassel) qFatal("Trying to instantiate more than one Quassel object!");
+Global::Global() {
+ if(global) qFatal("Trying to instantiate more than one Global object!");
qInstallMsgHandler(messageHandler);
//initIconMap();
}
/*
-void Quassel::setLogger(Logger *) {
+void Global::setLogger(Logger *) {
};
*/
-QVariant Quassel::getData(QString key) {
+QVariant Global::getData(QString key, QVariant defval) {
+ QVariant d;
mutex.lock();
- QVariant d = data[key];
+ if(data.contains(key)) d = data[key];
+ else d = defval;
mutex.unlock();
- qDebug() << "getData("<<key<<"): " << d;
+ //qDebug() << "getData("<<key<<"): " << d;
return d;
}
-void Quassel::putData(QString key, const QVariant &d) {
+QStringList Global::getKeys() {
+ QStringList k;
+ mutex.lock();
+ k = data.keys();
+ mutex.unlock();
+ return k;
+}
+
+void Global::putData(QString key, QVariant d) {
+ mutex.lock();
+ data[key] = d;
+ mutex.unlock();
+ emit dataPutLocally(key);
+}
+
+void Global::updateData(QString key, QVariant d) {
mutex.lock();
data[key] = d;
mutex.unlock();
- emit dataChanged(key, d);
- qDebug() << "putData("<<key<<"): " << d;
- qDebug() << "data: " << data;
+ emit dataUpdatedRemotely(key);
}
/* not done yet */
-void Quassel::initIconMap() {
+void Global::initIconMap() {
// Do not depend on GUI in core!
/*
QDomDocument doc("IconMap");
* @return Pointer to a newly created QIcon
*/
//
-//QIcon *Quassel::getIcon(QString /*symbol*/) {
+//QIcon *Global::getIcon(QString /*symbol*/) {
//if(symbol == "connect"
// return 0;
//}
-Quassel *quassel = 0;
-Quassel::RunMode Quassel::runMode;
+Global *global = 0;
+Global::RunMode Global::runMode;
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#ifndef _QUASSEL_H_
-#define _QUASSEL_H_
+#ifndef _GLOBAL_H_
+#define _GLOBAL_H_
-class Quassel;
+/** The protocol version we use fo the communication between core and GUI */
+#define GUI_PROTOCOL 1
+
+class Global;
#include <QtCore>
//#include <QMutex>
/* Some global stuff */
typedef QMap<QString, QVariant> VarMap;
-extern Quassel *quassel;
+extern Global *global;
/**
- * A static class containing global data.
- * This is used in both core and GUI modules. Where appropriate, accessors are thread-safe
- * to account for that fact.
- */
-class Quassel : public QObject {
+ * This class is mostly a globally synchronized data store, meant for storing systemwide settings such
+ * as identities or network lists. This class is a singleton, but not static as we'd like to use signals and
+ * slots with it.
+ * The global object is used in both Core and GUI clients. Storing and retrieving data is thread-safe.
+ * \note While updated data is propagated to all the remote parts of Quassel quite quickly, the synchronization
+ * protocol is in no way designed to guarantee strict consistency at all times. In other words, it may
+ * well happen that different instances of global data differ from one another for a little while until
+ * all update messages have been processed. You should never rely on all global data stores being consistent.
+*/
+class Global : public QObject {
Q_OBJECT
public:
- Quassel();
+ Global();
//static Logger *getLogger();
//static void setLogger(Logger *);
// static QIcon *getIcon(QString symbol);
- QVariant getData(QString key);
+ QVariant getData(QString key, QVariant defaultValue = QVariant());
+ QStringList getKeys();
public slots:
- void putData(QString key, const QVariant &data);
+ void putData(QString key, QVariant data); ///< Store data changed locally, will be propagated to all other clients and the core
+ void updateData(QString key, QVariant data); ///< Update stored data if requested by the core or other clients
signals:
- void dataChanged(QString key, const QVariant &data);
+ void dataPutLocally(QString key);
+ void dataUpdatedRemotely(QString key); // sent by remote update only!
public:
enum RunMode { Monolithic, GUIOnly, CoreOnly };
private:
static void initIconMap();
-
+
//static Logger *logger;
// static QString iconPath;
--- /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 "util.h"
+
+#include <QtCore>
+
+void writeDataToDevice(QIODevice *dev, const QVariant &item) {
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_1);
+ out << (quint32)0 << item;
+ out.device()->seek(0);
+ out << (quint32)(block.size() - sizeof(quint32));
+ dev->write(block);
+}
+
+bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item) {
+ QDataStream in(dev);
+ in.setVersion(QDataStream::Qt_4_1);
+
+ if(blockSize == 0) {
+ if(dev->bytesAvailable() < (int)sizeof(quint32)) return false;
+ in >> blockSize;
+ }
+ if(dev->bytesAvailable() < blockSize) return false;
+ in >> item;
+ return true;
+}
--- /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 _UTIL_H_
+#define _UTIL_H_
+
+#include <QIODevice>
+#include <QVariant>
+
+/**
+ * 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
+ * at the device to reread the item.
+ */
+void writeDataToDevice(QIODevice *, const QVariant &);
+
+/** Reads a data item from a device that has previously been written by writeDataToDevice().
+ * If not enough data bytes are available, the function returns false and the QVariant reference
+ * remains untouched.
+ */
+bool readDataFromDevice(QIODevice *, quint32 &, QVariant &);
+
+
+
+
+
+#endif
#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 run 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...
void run();
// serverState state();
+ bool isConnected() { return socket.state() == QAbstractSocket::ConnectedState; }
public slots:
// void setServerOptions();