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)
+IF(BUILD_CORE OR BUILD_GUI)
+ MESSAGE(FATAL_ERROR "\nBuilding of standalone core or GUI not supported at this time. Please check back later.\n")
+ENDIF(BUILD_CORE OR BUILD_GUI)
+
SET(CMAKE_BUILD_TYPE Debug)
# Define files
# KDevelop Custom Project File List
-network/server.h
-network/server.cpp
core/core.cpp
core/CMakeLists.txt
core/core.h
-gui/channelwidget.cpp
-gui/channelwidget.h
gui/CMakeLists.txt
-gui/identitiesdlg.ui
-gui/identitieseditdlg.ui
gui/mainwin.cpp
gui/mainwin.h
-gui/networkeditdlg.ui
-gui/nickeditdlg.ui
gui/serverlist.cpp
gui/serverlist.h
-gui/serverlistdlg.ui
images/iconmap.xml
images/icons.qrc
main/main_core.cpp
main/main_mono.cpp
-network/CMakeLists.txt
CMakeLists.txt
COPYING
Doxyfile
core/coreproxy.h
main/util.cpp
main/util.h
-gui/coreconnectdlg.ui
gui/coreconnectdlg.cpp
gui/coreconnectdlg.h
main/proxy_common.h
images/qirc-icon.png
main/global.cpp
main/global.h
-gui/channelwidget-old.ui
gui/identities.cpp
gui/identities.h
-network/buffer.cpp
-network/buffer.h
gui/channelwidgetinput.h
gui/channelwidgetinput.cpp
plugins/plugin.h
gui/ui/ircwidget.ui
gui/ui/mainwin.ui
gui/ui/networkeditdlg.ui
-gui/ui/networkwidget.ui
gui/ui/nickeditdlg.ui
gui/ui/servereditdlg.ui
gui/ui/serverlistdlg.ui
gui/ui/settingsdlg.ui
gui/ui/bufferview.ui
-gui/bufferview.cpp
-gui/bufferview.h
gui/buffer.cpp
gui/buffer.h
main/message.cpp
gui/chatwidget.h
gui/style.cpp
gui/style.h
+main/logger.cpp
+main/logger.h
+templates/cpp
+templates/h
+gui/bufferwidget.h
+gui/bufferwidget.cpp
+main/settings.cpp
+main/settings.h
+gui/settingsdlg.h
+gui/settingsdlg.cpp
+gui/settingspages.cpp
+gui/settingspages.h
+gui/bufferview.cpp
+gui/bufferview.h
+core/backlog.cpp
+core/backlog.h
+ChangeLog
+core/storage.cpp
+core/storage.h
+core/sqlitestorage.cpp
+dev-notes
+dev-notes/builtin_cmds.obsolete.cpp
+gui
+gui/tabcompleter.cpp
+gui/tabcompleter.h
+core
+core/sqlitestorage.h
/***************************************************************************
- * Copyright (C) 2005/06 by The Quassel Team *
+ * Copyright (C) 2005-07 by The Quassel IRC Development Team *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include <QtSql>
#include <QSettings>
+Core *Core::instanceptr = 0;
+
+Core * Core::instance() {
+ if(instanceptr) return instanceptr;
+ instanceptr = new Core();
+ instanceptr->init();
+ return instanceptr;
+}
+
+void Core::destroy() {
+ delete instanceptr;
+ instanceptr = 0;
+}
+
Core::Core() {
- if(core) qFatal("Trying to instantiate more than one Core object!");
+}
+
+void Core::init() {
if(!SqliteStorage::isAvailable()) {
qFatal("Sqlite is currently required! Please make sure your Qt library has sqlite support enabled.");
}
//SqliteStorage::init();
storage = new SqliteStorage();
- user = storage->validateUser("Default", "password");
- if(!user) user = storage->addUser("Default", "password");
- Q_ASSERT(user);
+ connect(Global::instance(), SIGNAL(dataPutLocally(UserId, QString)), this, SLOT(updateGlobalData(UserId, QString)));
+ connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
+ //startListening(); // FIXME
+ if(Global::runMode == Global::Monolithic) { // TODO Make GUI user configurable
+ guiUser = storage->validateUser("Default", "password");
+ if(!guiUser) guiUser = storage->addUser("Default", "password");
+ Q_ASSERT(guiUser);
+ Global::setGuiUser(guiUser);
+ createSession(guiUser);
+ } else guiUser = 0;
- connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
- connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
- connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGUI(BufferId, QString)));
- connect(coreProxy, SIGNAL(gsImportBacklog()), storage, SLOT(importOldBacklog()));
- connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
- connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
- connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
- connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
- connect(storage, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
- connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
+ // Read global settings from config file
+ QSettings s;
+ s.beginGroup("Global");
+ foreach(QString unum, s.childGroups()) {
+ UserId uid = unum.toUInt();
+ s.beginGroup(unum);
+ foreach(QString key, s.childKeys()) {
+ Global::updateData(uid, key, s.value(key));
+ }
+ s.endGroup();
+ }
+ s.endGroup();
+}
+
+Core::~Core() {
+ foreach(QTcpSocket *sock, validClients.keys()) {
+ delete sock;
+ }
+ qDeleteAll(sessions);
+ delete storage;
+}
+
+CoreSession *Core::session(UserId uid) {
+ Core *core = instance();
+ if(core->sessions.contains(uid)) return core->sessions[uid];
+ else return 0;
+}
+
+CoreSession *Core::guiSession() {
+ Core *core = instance();
+ if(core->guiUser && core->sessions.contains(core->guiUser)) return core->sessions[core->guiUser];
+ else return 0;
+}
+
+CoreSession *Core::createSession(UserId uid) {
+ Core *core = instance();
+ Q_ASSERT(!core->sessions.contains(uid));
+ CoreSession *sess = new CoreSession(uid, core->storage);
+ core->sessions[uid] = sess;
+ connect(sess, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), core, SLOT(recvProxySignal(CoreSignal, QVariant, QVariant, QVariant)));
+ return sess;
+}
+
+
+bool Core::startListening(uint port) {
+ if(!server.listen(QHostAddress::Any, port)) {
+ qWarning(QString(QString("Could not open GUI client port %1: %2").arg(port).arg(server.errorString())).toAscii());
+ return false;
+ }
+ qDebug() << "Listening for GUI clients on port" << server.serverPort();
+ return true;
+}
+
+void Core::stopListening() {
+ server.close();
+ qDebug() << "No longer listening for GUI clients.";
+}
+
+void Core::incomingConnection() {
+ // TODO implement SSL
+ QTcpSocket *socket = server.nextPendingConnection();
+ connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+ connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
+ blockSizes.insert(socket, (quint32)0);
+ qDebug() << "Client connected from " << socket->peerAddress().toString();
+}
+
+void Core::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)) {
+ if(validClients.contains(socket)) {
+ QList<QVariant> sigdata = item.toList();
+ if((GUISignal)sigdata[0].toInt() == GS_UPDATE_GLOBAL_DATA) {
+ processClientUpdate(socket, sigdata[1].toString(), sigdata[2]);
+ } else {
+ sessions[validClients[socket]]->processSignal((GUISignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
+ }
+ } else {
+ // we need to auth the client
+ try {
+ processClientInit(socket, item);
+ } catch(Storage::AuthError) {
+ qWarning() << "Authentification error!"; // FIXME
+ socket->close();
+ return;
+ } catch(Exception e) {
+ qWarning() << "Client init error:" << e.msg();
+ socket->close();
+ return;
+ }
+ }
+ blockSizes[socket] = bsize = 0;
+ }
+ blockSizes[socket] = bsize;
+}
+
+void Core::clientDisconnected() {
+ QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
+ blockSizes.remove(socket);
+ validClients.remove(socket);
+ qDebug() << "Client disconnected.";
+ // TODO remove unneeded sessions - if necessary/possible...
+}
+
+void Core::processClientInit(QTcpSocket *socket, const QVariant &v) {
+ VarMap msg = v.toMap();
+ if(msg["GUIProtocol"].toUInt() != GUI_PROTOCOL) {
+ //qWarning() << "Client version mismatch.";
+ throw Exception("GUI client version mismatch");
+ }
+ // Auth
+ UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed
+
+ // Find or create session for validated user
+ CoreSession *sess;
+ if(sessions.contains(uid)) sess = sessions[uid];
+ else {
+ sess = createSession(uid);
+ validClients[socket] = uid;
+ }
+ VarMap reply;
+ VarMap coreData;
+ // FIXME
+ QStringList dataKeys = Global::keys(uid);
+ QString key;
+ foreach(key, dataKeys) {
+ coreData[key] = Global::data(key);
+ }
+ reply["CoreData"] = coreData;
+ reply["SessionState"] = sess->sessionState();
+ QList<QVariant> sigdata;
+ sigdata.append(CS_CORE_STATE); sigdata.append(QVariant(reply)); sigdata.append(QVariant()); sigdata.append(QVariant());
+ writeDataToDevice(socket, QVariant(sigdata));
+ sess->sendServerStates();
+}
+
+void Core::processClientUpdate(QTcpSocket *socket, QString key, const QVariant &data) {
+ UserId uid = validClients[socket];
+ Global::updateData(uid, key, data);
+ QList<QVariant> sigdata;
+ sigdata.append(CS_UPDATE_GLOBAL_DATA); sigdata.append(key); sigdata.append(data); sigdata.append(QVariant());
+ foreach(QTcpSocket *s, validClients.keys()) {
+ if(validClients[s] == uid && s != socket) writeDataToDevice(s, QVariant(sigdata));
+ }
+}
+
+void Core::updateGlobalData(UserId uid, QString key) {
+ QVariant data = Global::data(uid, key);
+ QList<QVariant> sigdata;
+ sigdata.append(CS_UPDATE_GLOBAL_DATA); sigdata.append(key); sigdata.append(data); sigdata.append(QVariant());
+ foreach(QTcpSocket *socket, validClients.keys()) {
+ if(validClients[socket] == uid) writeDataToDevice(socket, QVariant(sigdata));
+ }
+}
+
+void Core::recvProxySignal(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ CoreSession *sess = qobject_cast<CoreSession*>(sender());
+ Q_ASSERT(sess);
+ UserId uid = sess->userId();
+ QList<QVariant> sigdata;
+ sigdata.append(sig); sigdata.append(arg1); sigdata.append(arg2); sigdata.append(arg3);
+ //qDebug() << "Sending signal: " << sigdata;
+ foreach(QTcpSocket *socket, validClients.keys()) {
+ if(validClients[socket] == uid) writeDataToDevice(socket, QVariant(sigdata));
+ }
+}
+
+/*
// Read global settings from config file
QSettings s;
s.beginGroup("Global");
connect(global, SIGNAL(dataPutLocally(QString)), SLOT(globalDataUpdated(QString)));
}
+ */
+
+CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_storage) {
+ coreProxy = new CoreProxy();
+ connect(coreProxy, SIGNAL(send(CoreSignal, QVariant, QVariant, QVariant)), this, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)));
+
+ connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
+ connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
+ connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGui(BufferId, QString)));
+ connect(coreProxy, SIGNAL(gsImportBacklog()), storage, SLOT(importOldBacklog()));
+ connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
+ connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
+ connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
+ connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
+ connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
+ connect(storage, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
+ connect(Global::instance(), SIGNAL(dataUpdatedRemotely(UserId, QString)), this, SLOT(globalDataUpdated(UserId, QString)));
+ connect(Global::instance(), SIGNAL(dataPutLocally(UserId, QString)), this, SLOT(globalDataUpdated(UserId, QString)));
+
+}
+
+CoreSession::~CoreSession() {
-Core::~Core() {
- //foreach(Server *s, servers) {
- // delete s;
- //}
- delete storage;
}
-void Core::globalDataUpdated(QString key) {
- QVariant data = global->getData(key);
+UserId CoreSession::userId() {
+ return user;
+}
+
+void CoreSession::processSignal(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
+ coreProxy->recv(sig, arg1, arg2, arg3);
+}
+
+void CoreSession::globalDataUpdated(UserId uid, QString key) {
+ Q_ASSERT(uid == userId());
+ QVariant data = Global::data(userId(), key);
QSettings s;
- s.setValue(QString("Global/")+key, data);
+ s.setValue(QString("Global/%1/").arg(userId())+key, data);
}
-void Core::connectToIrc(QStringList networks) {
+void CoreSession::connectToIrc(QStringList networks) {
foreach(QString net, networks) {
if(servers.contains(net)) {
} else {
- Server *server = new Server(net);
+ Server *server = new Server(userId(), net);
connect(this, SIGNAL(serverStateRequested()), server, SLOT(sendState()));
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(this, SIGNAL(msgFromGui(QString, QString, QString)), server, SLOT(userInput(QString, QString, QString)));
connect(server, SIGNAL(serverState(QString, VarMap)), coreProxy, SLOT(csServerState(QString, VarMap)));
//connect(server, SIGNAL(displayMsg(Message)), this, SLOT(recvMessageFromServer(Message)));
connect(server, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)), this, SLOT(recvMessageFromServer(Message::Type, QString, QString, QString, quint8)));
connect(server, SIGNAL(nickUpdated(QString, QString, VarMap)), coreProxy, SLOT(csNickUpdated(QString, QString, VarMap)));
connect(server, SIGNAL(ownNickSet(QString, QString)), coreProxy, SLOT(csOwnNickSet(QString, QString)));
connect(server, SIGNAL(queryRequested(QString, QString)), coreProxy, SLOT(csQueryRequested(QString, QString)));
- // add error handling
+ // TODO add error handling
connect(server, SIGNAL(connected(QString)), coreProxy, SLOT(csServerConnected(QString)));
connect(server, SIGNAL(disconnected(QString)), this, SLOT(serverDisconnected(QString)));
}
}
-void Core::serverDisconnected(QString net) {
+void CoreSession::serverDisconnected(QString net) {
delete servers[net];
servers.remove(net);
coreProxy->csServerDisconnected(net);
}
-void Core::msgFromGUI(BufferId bufid, QString msg) {
- emit msgFromGUI(bufid.network(), bufid.buffer(), msg);
+void CoreSession::msgFromGui(BufferId bufid, QString msg) {
+ emit msgFromGui(bufid.network(), bufid.buffer(), msg);
}
// 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(Message::Type type, QString target, QString text, QString sender, quint8 flags) {
+void CoreSession::recvMessageFromServer(Message::Type type, QString target, QString text, QString sender, quint8 flags) {
Server *s = qobject_cast<Server*>(this->sender());
Q_ASSERT(s);
BufferId buf;
emit displayMsg(msg);
}
-void Core::recvStatusMsgFromServer(QString msg) {
+void CoreSession::recvStatusMsgFromServer(QString msg) {
Server *s = qobject_cast<Server*>(sender());
Q_ASSERT(s);
emit displayStatusMsg(s->getNetwork(), msg);
}
-QList<BufferId> Core::getBuffers() {
+
+QList<BufferId> CoreSession::buffers() const {
return storage->requestBuffers(user);
}
-void Core::sendBacklog(BufferId id, QVariant v1, QVariant v2) {
+
+QVariant CoreSession::sessionState() {
+ VarMap v;
+ QList<QVariant> bufs;
+ foreach(BufferId id, storage->requestBuffers(user)) { bufs.append(QVariant::fromValue(id)); }
+ v["Buffers"] = bufs;
+
+ return v;
+}
+
+void CoreSession::sendServerStates() {
+ emit serverStateRequested();
+}
+
+void CoreSession::sendBacklog(BufferId id, QVariant v1, QVariant v2) {
QList<QVariant> log;
QList<Message> msglist;
if(v1.type() == QVariant::DateTime) {
}
-Core *core = 0;
+//Core *core = 0;
#ifndef _CORE_H_
#define _CORE_H_
-#include <QMap>
#include <QString>
#include <QVariant>
#include <QSqlDatabase>
#include "server.h"
-#include "backlog.h"
#include "storage.h"
#include "global.h"
+#include "coreproxy.h"
+
+class CoreSession;
+class Core : public QObject {
+ Q_OBJECT
+
+ public:
+ static Core * instance();
+ static void destroy();
+
+ static CoreSession * session(UserId);
+ static CoreSession * guiSession();
+ static CoreSession * createSession(UserId);
+
+ private slots:
+ void recvProxySignal(CoreSignal, QVariant, QVariant, QVariant);
+ bool startListening(uint port = 4242);
+ void stopListening();
+ void incomingConnection();
+ void clientHasData();
+ void clientDisconnected();
+ void updateGlobalData(UserId, QString);
+
+ private:
+ Core();
+ ~Core();
+ void init();
+ static Core *instanceptr;
+
+ void processClientInit(QTcpSocket *socket, const QVariant &v);
+ void processClientUpdate(QTcpSocket *socket, QString key, const QVariant &data);
+
+ UserId guiUser;
+ QHash<UserId, CoreSession *> sessions;
+ Storage *storage;
+
+ QTcpServer server; // TODO: implement SSL
+ QHash<QTcpSocket *, UserId> validClients;
+ QHash<QTcpSocket *, quint32> blockSizes;
+};
+
+class CoreSession : public QObject {
+ Q_OBJECT
+
+ public:
+ CoreSession(UserId, Storage *);
+ ~CoreSession();
+
+ QList<BufferId> buffers() const;
+ inline UserId userId();
+ QVariant sessionState();
+ CoreProxy *proxy();
+
+ public slots:
+ void connectToIrc(QStringList);
+ void processSignal(GUISignal, QVariant, QVariant, QVariant);
+ void sendBacklog(BufferId, QVariant, QVariant);
+ void msgFromGui(BufferId, QString message);
+ void sendServerStates();
+
+ signals:
+ void proxySignal(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+
+ void msgFromGui(QString net, QString buf, QString message);
+ void displayMsg(Message message);
+ void displayStatusMsg(QString, QString);
+
+ void connectToIrc(QString net);
+ void disconnectFromIrc(QString net);
+ void serverStateRequested();
+
+ void backlogData(BufferId, QList<QVariant>, bool done);
+
+ void bufferIdUpdated(BufferId);
+
+ private slots:
+ //void recvProxySignal(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+ void globalDataUpdated(UserId, QString);
+ void recvStatusMsgFromServer(QString msg);
+ void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+ void serverDisconnected(QString net);
+
+ private:
+ CoreProxy *coreProxy;
+ Storage *storage;
+ QHash<QString, Server *> servers;
+ UserId user;
+
+};
+
+/*
class Core : public QObject {
Q_OBJECT
};
-extern Core *core;
+*/
+//extern Core *core;
+
#endif
#include "core.h"
CoreProxy::CoreProxy() {
- if(coreProxy) qFatal("Trying to instantiate more than one CoreProxy object!");
- coreProxy = this;
- core = new Core();
-
- 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;
- /*
- VarMap bl;
- QHash<QString, QList<Message> > log = core->getBackLog();
- foreach(QString net, log.keys()) {
- QByteArray buf;
- QDataStream out(&buf, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_2);
- foreach(Message msg, log[net]) { out << msg; }
- bl[net] = buf;
- }
- reply["CoreBackLog"] = bl;
- */
- QList<QVariant> bufs;
- foreach(BufferId id, core->getBuffers()) { bufs.append(QVariant::fromValue(id)); }
- reply["CoreBuffers"] = bufs;
- QList<QVariant> sigdata;
- sigdata.append(CS_CORE_STATE); sigdata.append(QVariant(reply)); sigdata.append(QVariant()); sigdata.append(QVariant());
- writeDataToDevice(socket, QVariant(sigdata));
- emit requestServerStates();
+// connect(global, SIGNAL(dataPutLocally(QString)), this, SLOT(updateGlobalData(QString)));
+// connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
}
+/*
void CoreProxy::processClientUpdate(QTcpSocket *socket, QString key, QVariant data) {
global->updateData(key, data);
QList<QVariant> sigdata;
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;
writeDataToDevice(socket, QVariant(sigdata));
}
}
+*/
void CoreProxy::recv(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
//qDebug() << "[CORE] Received signal" << sig << ":" << arg1<<arg2<<arg3;
}
}
-CoreProxy *coreProxy;
+
+//CoreProxy *coreProxy;
void requestServerStates();
- private:
void send(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+
+ public:
+ //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);
+ private:
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;
};
-extern CoreProxy *coreProxy;
+//extern CoreProxy *coreProxy;
#include <QMetaObject>
#include <QDateTime>
-Server::Server(QString net) : network(net) {
+Server::Server(UserId uid, QString net) : user(uid), network(net) {
QString MQUOTE = QString('\020');
ctcpMDequoteHash[MQUOTE + '0'] = QString('\000');
ctcpMDequoteHash[MQUOTE + 'n'] = QString('\n');
void Server::connectToIrc(QString net) {
if(net != network) return; // not me!
- networkSettings = global->getData("Networks").toMap()[net].toMap();
- identity = global->getData("Identities").toMap()[networkSettings["Identity"].toString()].toMap();
+ networkSettings = Global::data(user, "Networks").toMap()[net].toMap();
+ identity = Global::data(user, "Identities").toMap()[networkSettings["Identity"].toString()].toMap();
QList<QVariant> servers = networkSettings["Servers"].toList();
QString host = servers[0].toMap()["Address"].toString();
quint16 port = servers[0].toMap()["Port"].toUInt();
Q_OBJECT
public:
- Server(QString network);
+ Server(UserId uid, QString network);
~Server();
+ UserId userId() const { return user; }
// serverState state();
- bool isConnected() { return socket.state() == QAbstractSocket::ConnectedState; }
+ bool isConnected() const { return socket.state() == QAbstractSocket::ConnectedState; }
QString getNetwork() { return network; }
QStringList providesUserHandlers();
void defaultCtcpHandler(CtcpType ctcptype, QString prefix, QString cmd, QString target, QString param);
private:
+ UserId user;
QString network;
QTcpSocket socket;
//QHash<QString, Buffer*> buffers;
if(query.first()) {
return query.value(0).toUInt();
} else {
- return 0;
+ throw AuthError();
+ //return 0;
}
}
//! Sent if a new BufferId is created, or an existing one changed somehow.
void bufferIdUpdated(BufferId);
+ public:
+ /* Exceptions */
+ struct AuthError : public Exception {};
protected:
// Old stuff, just for importing old file-based data
};
-#endif
\ No newline at end of file
+#endif
+
ui.progressBar->show();
VarMap initmsg;
initmsg["GUIProtocol"] = GUI_PROTOCOL;
- guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg));
+ // FIXME guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg));
}
void CoreConnectDlg::coreConnectionError(QString err) {
void recvPartialItem(quint32 avail, quint32 size);
- public:
void send(GUISignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+
+ public slots:
void recv(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
private slots:
IdentitiesDlg::IdentitiesDlg(QWidget *parent, QString selected) : QDialog(parent) {
ui.setupUi(this);
- connect(global, SIGNAL(dataUpdatedRemotely(QString)), this, SLOT(globalDataUpdated(QString)));
+ connect(Global::instance(), SIGNAL(dataUpdatedRemotely(UserId, QString)), this, SLOT(globalDataUpdated(UserId, QString)));
connect(ui.enableAutoAway, SIGNAL(stateChanged(int)), this, SLOT(autoAwayChecked()));
- identities = global->getData("Identities").toMap();
+ identities = Global::data("Identities").toMap();
foreach(QString name, identities.keys()) {
nameMapping[name] = name;
}
}
/* this needs more work! mapping? */
-void IdentitiesDlg::globalDataUpdated(QString key) {
+void IdentitiesDlg::globalDataUpdated(UserId, 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?"),
updateIdentity(getCurIdentity());
QString result = checkValidity();
if(result.length() == 0) {
- global->putData("Identities", identities);
+ Global::putData("Identities", identities);
// We have to care about renamed identities and update the network list appropriately...
- VarMap networks = global->getData("Networks").toMap();
+ VarMap networks = Global::data("Networks").toMap();
foreach(QString netname, networks.keys()) {
VarMap net = networks[netname].toMap();
if(nameMapping.contains(net["Identity"].toString())) {
} else net["Identity"] = "Default";
networks[netname] = net;
}
- global->putData("Networks", networks);
+ Global::putData("Networks", networks);
QDialog::accept();
} else {
QMessageBox::warning(this, tr("Invalid Identity!"),
void editIdentities();
- void globalDataUpdated(QString);
+ void globalDataUpdated(UserId, QString);
private:
Ui::IdentitiesDlg ui;
MainWin::MainWin() : QMainWindow() {
ui.setupUi(this);
//widget = 0;
- qDebug() << "Available DB drivers: " << QSqlDatabase::drivers ();
+ //qDebug() << "Available DB drivers: " << QSqlDatabase::drivers ();
setWindowTitle("Quassel IRC");
//setWindowTitle("Κυασελ Εγαρζη");
setWindowIcon(QIcon(":/qirc-icon.png"));
settings.endGroup();
// check if we already have a valid identity
- if(!global->getData("Identities", VarMap()).toMap().contains("Default")) editIdentities(true);
+ if(!Global::data("Identities", VarMap()).toMap().contains("Default")) editIdentities(true);
connect(this, SIGNAL(requestConnect(QStringList)), guiProxy, SLOT(gsRequestConnect(QStringList)));
// Autoconnect
QStringList list;
- VarMap networks = global->getData("Networks").toMap();
+ VarMap networks = Global::data("Networks").toMap();
foreach(QString net, networks.keys()) {
if(networks[net].toMap()["AutoConnect"].toBool()) {
list << net;
}
void ServerListDlg::updateNetworkTree() {
- VarMap networks = global->getData("Networks").toMap();
+ VarMap networks = Global::data("Networks").toMap();
//QStringList headers;
//headers << "Network" << "Autoconnect";
ui.networkTree->clear();
void ServerListDlg::on_addButton_clicked() {
NetworkEditDlg dlg(this, VarMap());
if(dlg.exec() == QDialog::Accepted) {
- VarMap networks = global->getData("Networks").toMap();
+ VarMap networks = Global::data("Networks").toMap();
VarMap net = dlg.getNetwork();
networks[net["Name"].toString()] = net;
- global->putData("Networks", networks);
+ Global::putData("Networks", networks);
updateNetworkTree();
}
}
void ServerListDlg::on_editButton_clicked() {
QString curnet = ui.networkTree->currentItem()->text(0);
- VarMap networks = global->getData("Networks").toMap();
+ VarMap networks = Global::data("Networks").toMap();
NetworkEditDlg dlg(this, networks[curnet].toMap());
if(dlg.exec() == QDialog::Accepted) {
VarMap net = dlg.getNetwork();
networks.remove(curnet);
networks[net["Name"].toString()] = net;
- global->putData("Networks", networks);
+ Global::putData("Networks", networks);
updateNetworkTree();
}
}
void ServerListDlg::on_deleteButton_clicked() {
if(QMessageBox::warning(this, tr("Remove Network?"), tr("Are you sure you want to delete the selected network(s)?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- VarMap networks = global->getData("Networks").toMap();
+ VarMap networks = Global::data("Networks").toMap();
QList<QTreeWidgetItem *> sel = ui.networkTree->selectedItems();
foreach(QTreeWidgetItem *item, sel) {
networks.remove(item->text(0));
}
- global->putData("Networks", networks);
+ Global::putData("Networks", networks);
updateNetworkTree();
}
}
connect(ui.serverList, SIGNAL(itemSelectionChanged()), this, SLOT(updateServerButtons()));
- VarMap identities = global->getData("Identities").toMap();
+ VarMap identities = Global::data("Identities").toMap();
ui.identityList->addItem(tr("Default Identity"));
foreach(QString id, identities.keys()) {
if(id != "Default") ui.identityList->addItem(id);
}
QStringList groups; groups << "";
- VarMap nets = global->getData("Networks").toMap();
+ VarMap nets = Global::data("Networks").toMap();
foreach(QString net, nets.keys()) {
QString gr = nets[net].toMap()["Group"].toString();
if(!groups.contains(gr) && !gr.isEmpty()) {
QString NetworkEditDlg::checkValidity() {
QString r;
- VarMap nets = global->getData("Networks").toMap();
+ VarMap nets = Global::data("Networks").toMap();
if(ui.networkName->text() != oldName && nets.keys().contains(ui.networkName->text())) {
r += tr(" Network name already exists.");
}
else id = "Default";
IdentitiesDlg dlg(this, id);
if(dlg.exec() == QDialog::Accepted) {
- VarMap identities = global->getData("Identities").toMap();
+ VarMap identities = Global::data("Identities").toMap();
ui.identityList->clear();
ui.identityList->addItem(tr("Default Identity"));
foreach(QString i, identities.keys()) {
/***************************************************************************
- * Copyright (C) 2005 by The Quassel Team *
+ * Copyright (C) 2005-07 by The Quassel IRC Development Team *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
extern void messageHandler(QtMsgType type, const char *msg);
+Global *Global::instanceptr = 0;
+
+Global * Global::instance() {
+ if(instanceptr) return instanceptr;
+ return instanceptr = new Global();
+}
+
+void Global::destroy() {
+ delete instanceptr;
+ instanceptr = 0;
+}
+
Global::Global() {
- if(global) qFatal("Trying to instantiate more than one Global object!");
qInstallMsgHandler(messageHandler);
qRegisterMetaType<Message>("Message");
qRegisterMetaTypeStreamOperators<Message>("Message");
qRegisterMetaType<BufferId>("BufferId");
qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
- //initIconMap();
+ guiUser = 0;
}
-/*
-void Global::setLogger(Logger *) {
+Global::~Global() {
-};
-*/
+}
+
+void Global::setGuiUser(UserId uid) {
+ guiUser = uid;
+}
+
+QVariant Global::data(QString key, QVariant defval) {
+ return data(guiUser, key, defval);
+}
-QVariant Global::getData(QString key, QVariant defval) {
+QVariant Global::data(UserId uid, QString key, QVariant defval) {
QVariant d;
mutex.lock();
- if(data.contains(key)) d = data[key];
+ if(instance()->datastore[uid].contains(key)) d = instance()->datastore[uid][key];
else d = defval;
mutex.unlock();
//qDebug() << "getData("<<key<<"): " << d;
return d;
}
-QStringList Global::getKeys() {
+QStringList Global::keys() {
+ return keys(guiUser);
+}
+
+QStringList Global::keys(UserId uid) {
QStringList k;
mutex.lock();
- k = data.keys();
+ k = instance()->datastore[uid].keys();
mutex.unlock();
return k;
}
void Global::putData(QString key, QVariant d) {
+ putData(guiUser, key, d);
+}
+
+void Global::putData(UserId uid, QString key, QVariant d) {
mutex.lock();
- data[key] = d;
+ instance()->datastore[uid][key] = d;
mutex.unlock();
- emit dataPutLocally(key);
+ emit instance()->dataPutLocally(uid, key);
}
void Global::updateData(QString key, QVariant d) {
+ updateData(guiUser, key, d);
+}
+
+void Global::updateData(UserId uid, QString key, QVariant d) {
mutex.lock();
- data[key] = d;
+ instance()->datastore[uid][key] = d;
mutex.unlock();
- emit dataUpdatedRemotely(key);
+ emit instance()->dataUpdatedRemotely(uid, key);
}
/* not done yet */
+/*
void Global::initIconMap() {
// Do not depend on GUI in core!
-/*
QDomDocument doc("IconMap");
QFile file("images/iconmap.xml");
if(!file.open(QIODevice::ReadOnly)) {
file.close();
}
-*/
}
+*/
/**************************************************************************************/
// return 0;
//}
-Global *global = 0;
+QMutex Global::mutex;
Global::RunMode Global::runMode;
+UserId Global::guiUser;
QString Global::quasselDir;
#define _GLOBAL_H_
/** The protocol version we use fo the communication between core and GUI */
-#define GUI_PROTOCOL 1
+#define GUI_PROTOCOL 2
#define BACKLOG_FORMAT 2
#define BACKLOG_STRING "QuasselIRC Backlog File"
/* Some global stuff */
typedef QMap<QString, QVariant> VarMap;
-extern Global *global;
typedef uint UserId;
typedef uint MsgId;
Q_OBJECT
public:
- Global();
//static Logger *getLogger();
//static void setLogger(Logger *);
// static QIcon *getIcon(QString symbol);
- QVariant getData(QString key, QVariant defaultValue = QVariant());
- QStringList getKeys();
+ static Global *instance();
+ static void destroy();
+ static void setGuiUser(UserId);
+
+ static QVariant data(QString key, QVariant defaultValue = QVariant());
+ static QVariant data(UserId, QString key, QVariant defaultValue = QVariant());
+ static QStringList keys();
+ static QStringList keys(UserId);
+
+ static void putData(QString key, QVariant data); ///< Store data changed locally, will be propagated to all other clients and the core
+ static void putData(UserId, QString key, QVariant data);
- public slots:
- 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
+ static void updateData(QString key, QVariant data); ///< Update stored data if requested by the core or other clients
+ static void updateData(UserId, QString key, QVariant data);
signals:
- void dataPutLocally(QString key);
- void dataUpdatedRemotely(QString key); // sent by remote update only!
+ void dataPutLocally(UserId, QString key);
+ void dataUpdatedRemotely(UserId, QString key); // sent by remote update only!
public:
- enum RunMode { Monolithic, GUIOnly, CoreOnly };
+ enum RunMode { Monolithic, GuiOnly, CoreOnly };
static RunMode runMode;
static QString quasselDir;
private:
- static void initIconMap();
+ Global();
+ ~Global();
+ static Global *instanceptr;
+
+ static UserId guiUser;
+ //static void initIconMap();
//static Logger *logger;
// static QString iconPath;
- QHash<QString, QString> iconMap;
- QMutex mutex;
- QHash<QString, QVariant> data;
+ //QHash<QString, QString> iconMap;
+ static QMutex mutex;
+ QHash<UserId, QHash<QString, QVariant> > datastore;
};
-class Exception {
- public:
+struct Exception {
Exception(QString msg = "Unknown Exception") : _msg(msg) {};
virtual inline QString msg() { return _msg; }
int main(int argc, char **argv) {
QApplication app(argc, argv);
- QApplication::setOrganizationDomain("quassel-irc.org");
- QApplication::setApplicationName("Quassel IRC");
- QApplication::setOrganizationName("The Quassel Team");
+ QCoreApplication::setOrganizationDomain("quassel-irc.org");
+ QCoreApplication::setApplicationName("Quassel IRC");
+ QCoreApplication::setOrganizationName("Quassel IRC Development Team");
Global::runMode = Global::Monolithic;
Global::quasselDir = QDir::homePath() + "/.quassel";
//settings = new Settings();
- global = new Global();
+ //global = new Global();
guiProxy = new GUIProxy();
- coreProxy = new CoreProxy();
+ //coreProxy = new CoreProxy();
+ QObject::connect(Core::guiSession(), SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), guiProxy, SLOT(recv(CoreSignal, QVariant, QVariant, QVariant)));
+ QObject::connect(guiProxy, SIGNAL(send(GUISignal, QVariant, QVariant, QVariant)), Core::guiSession(), SLOT(processSignal(GUISignal, QVariant, QVariant, QVariant)));
Settings::init();
Style::init();
mainWin->show();
mainWin->init();
int exitCode = app.exec();
- delete core;
+ //delete core;
+ Core::destroy();
delete guiProxy;
- delete coreProxy;
- delete global;
+ //delete coreProxy;
+ //delete global;
delete mainWin;
//delete settings;
return exitCode;
}
void MainWin::syncToCore() {
- Q_ASSERT(global->getData("CoreReady").toBool());
- coreBuffers = core->getBuffers();
+ //Q_ASSERT(Global::data("CoreReady").toBool());
+ coreBuffers = Core::guiSession()->buffers();
// NOTE: We don't need to request server states, because in the monolithic version there can't be
// any servers connected at this stage...
}
+/*
void CoreProxy::sendToGUI(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
guiProxy->recv(sig, arg1, arg2, arg3);
}
+*/
GUIProxy::GUIProxy() {
if(guiProxy) qFatal("Trying to instantiate more than one GUIProxy object!");
}
+/*
void GUIProxy::send(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
coreProxy->recv(sig, arg1, arg2, arg3);
}
+*/
// Dummy function definitions
// These are not needed, since we don't have a network connection to the core.