Still working on the authentification stuff. Technically, now even in the monolithic...
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 27 Jun 2007 21:48:19 +0000 (21:48 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 27 Jun 2007 21:48:19 +0000 (21:48 +0000)
to the internal core (still using the possible shortcuts, of course). It should also be able to disconnect, although
not all is cleaned up yet in the process. After this is done, one will be able to disconnect the client from the internal
core and connect to a remote core, and vice versa.
This made a lot of changes to the init process necessary, so I have changed quite a bit of stuff around.

You should refrain from building core and client separately now, even though it probably compiles. It is not tested yet,
and the GUI stuff is still missing anyways.

18 files changed:
src/CMakeLists.txt
src/client/client.cpp
src/client/client.h
src/client/clientproxy.h
src/common/CMakeLists.txt
src/common/main.cpp
src/common/proxy_common.h
src/common/quasselui.h
src/core/core.cpp
src/core/core.h
src/core/coreproxy.cpp
src/core/coreproxy.h
src/core/sqlitestorage.cpp
src/qtgui/coreconnectdlg.cpp
src/qtgui/mainwin.cpp
src/qtgui/mainwin.h
src/qtgui/ui/coreconnectdlg.ui
src/qtgui/ui/mainwin.ui

index 9fc218e..7e0244f 100644 (file)
@@ -20,13 +20,13 @@ IF(BUILD MATCHES "mono" OR BUILD MATCHES "all")
   SET(BUILD_MONO true)
   MESSAGE("Building monolithic Quassel.")
 ENDIF(BUILD MATCHES "mono" OR BUILD MATCHES "all")
-IF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI)
+IF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_QTGUI)
   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)
+ENDIF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_QTGUI)
 
-IF(BUILD_CORE OR BUILD_QTGUI)
-  MESSAGE(FATAL_ERROR "\nBuilding of standalone core or GUI not supported at this time. Please check back later.\n")
-ENDIF(BUILD_CORE OR BUILD_QTGUI)
+#IF(BUILD_CORE OR BUILD_QTGUI)
+#  MESSAGE(FATAL_ERROR "\nBuilding of standalone core or GUI not supported at this time. Please check back later.\n")
+#ENDIF(BUILD_CORE OR BUILD_QTGUI)
 
 SET(CMAKE_BUILD_TYPE Debug)
 
@@ -96,7 +96,7 @@ IF(BUILD_QTGUI OR BUILD_MONO)  # OK, now we need QtGui!
   ENDIF(BUILD_MONO)
 
   IF(BUILD_QTGUI)
-    ADD_EXECUTABLE(quasselclient ${quassel_gui_SRCS} ${_RCCS})
+    ADD_EXECUTABLE(quasselclient ${quassel_qtgui_SRCS} ${_RCCS})
     TARGET_LINK_LIBRARIES(quasselclient common client qtgui ${QT_LIBRARIES})
     SET(TARGET_LIST ${TARGET_LIST} quasselclient)
   ENDIF(BUILD_QTGUI)
index 8b954d3..30eeb51 100644 (file)
 
 Client * Client::instanceptr = 0;
 
+bool Client::connectedToCore = false;
 Client::ClientMode Client::clientMode;
 QHash<BufferId, Buffer *> Client::buffers;
 QHash<uint, BufferId> Client::bufferIds;
 QHash<QString, QHash<QString, VarMap> > Client::nicks;
-QHash<QString, bool> Client::connected;
+QHash<QString, bool> Client::netConnected;
 QHash<QString, QString> Client::ownNick;
-QList<BufferId> Client::coreBuffers;
+//QList<BufferId> Client::coreBuffers;
 
 
 Client *Client::instance() {
@@ -58,6 +59,7 @@ Client::Client() {
     // TODO: make this configurable (allow monolithic client to connect to remote cores)
   if(Global::runMode == Global::Monolithic) clientMode = LocalCore;
   else clientMode = RemoteCore;
+  connectedToCore = false;
 }
 
 void Client::init(AbstractUi *ui) {
@@ -92,20 +94,18 @@ void Client::init() {
   connect(clientProxy, SIGNAL(csUpdateBufferId(BufferId)), this, SLOT(updateBufferId(BufferId)));
   connect(this, SIGNAL(sendInput(BufferId, QString)), clientProxy, SLOT(gsUserInput(BufferId, QString)));
   connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), clientProxy, SLOT(gsRequestBacklog(BufferId, QVariant, QVariant)));
+  connect(this, SIGNAL(requestNetworkStates()), clientProxy, SLOT(gsRequestNetworkStates()));
 
-  syncToCore();
+  connect(mainUi, SIGNAL(connectToCore(const VarMap &)), this, SLOT(connectToCore(const VarMap &)));
+  connect(mainUi, SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore()));
+  connect(this, SIGNAL(connected()), mainUi, SLOT(connectedToCore()));
+  connect(this, SIGNAL(disconnected()), mainUi, SLOT(disconnectedFromCore()));
 
   layoutTimer = new QTimer(this);
   layoutTimer->setInterval(0);
   layoutTimer->setSingleShot(false);
   connect(layoutTimer, SIGNAL(timeout()), this, SLOT(layoutMsg()));
 
-  /* make lookups by id faster */
-  foreach(BufferId id, coreBuffers) {
-    bufferIds[id.uid()] = id;  // make lookups by id faster
-    buffer(id);                // create all buffers, so we see them in the network views
-    emit requestBacklog(id, -1, -1);  // TODO: use custom settings for backlog request
-  }
 }
 
 Client::~Client() {
@@ -120,12 +120,71 @@ BufferTreeModel *Client::bufferModel() {
   return instance()->_bufferModel;
 }
 
+bool Client::isConnected() { return connectedToCore; }
+
+void Client::connectToCore(const VarMap &conn) {
+  // TODO implement SSL
+  if(isConnected()) {
+    qDebug() << "Already connected to core!";
+    return;
+  }
+  if(conn["Host"].toString().isEmpty()) {
+    clientMode = LocalCore;
+    syncToCore();  // TODO send user and pw from conn info
+  } else {
+    clientMode = RemoteCore;
+    socket.connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
+  }
+}
+
+void Client::disconnectFromCore() {
+  if(clientMode == RemoteCore) {
+    socket.close();
+  } else {
+    disconnectFromLocalCore();
+    coreDisconnected();
+  }
+  // TODO clear internal data
+}
+
 void Client::coreConnected() {
+  syncToCore();
 
 }
 
 void Client::coreDisconnected() {
+  connectedToCore = false;
+  emit disconnected();
+}
+
+void Client::syncToCore() {
+  VarMap state;
+  if(clientMode == LocalCore) {
+    state = connectToLocalCore("Default", "password").toMap(); // TODO make this configurable
+  } else {
 
+  }
+
+  VarMap data = state["CoreData"].toMap();
+  foreach(QString key, data.keys()) {
+    Global::updateData(key, data[key]);
+  }
+  //if(!Global::data("CoreReady").toBool()) {
+  //  qFatal("Something is wrong, getting invalid data from core!");
+  //}
+
+  VarMap sessionState = state["SessionState"].toMap();
+  QList<QVariant> coreBuffers = sessionState["Buffers"].toList();
+  /* make lookups by id faster */
+  foreach(QVariant vid, coreBuffers) {
+    BufferId id = vid.value<BufferId>();
+    bufferIds[id.uid()] = id;  // make lookups by id faster
+    buffer(id);                // create all buffers, so we see them in the network views
+    //emit requestBacklog(id, -1, -1);  // TODO: use custom settings for backlog request
+  }
+  connectedToCore = true;
+  emit connected();
+  emit requestNetworkStates();
 }
 
 void Client::updateCoreData(UserId, QString key) {
@@ -146,15 +205,6 @@ void Client::recvProxySignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVa
   writeDataToDevice(&socket, QVariant(sigdata));
 }
 
-void Client::connectToCore(QString host, quint16 port) {
-  // TODO implement SSL
-  socket.connectToHost(host, port);
-}
-
-void Client::disconnectFromCore() {
-  socket.close();
-}
-
 void Client::serverError(QAbstractSocket::SocketError) {
   emit coreConnectionError(socket.errorString());
 }
@@ -174,7 +224,7 @@ void Client::serverHasData() {
 }
 
 void Client::networkConnected(QString net) {
-  connected[net] = true;
+  netConnected[net] = true;
   BufferId id = statusBufferId(net);
   Buffer *b = buffer(id);
   b->setActive(true);
@@ -189,7 +239,7 @@ void Client::networkDisconnected(QString net) {
     //b->displayMsg(Message(id, Message::Server, tr("Server disconnected."))); FIXME
     b->setActive(false);
   }
-  connected[net] = false;
+  netConnected[net] = false;
 }
 
 void Client::updateBufferId(BufferId id) {
@@ -224,8 +274,12 @@ Buffer * Client::buffer(BufferId id) {
   return buffers[id];
 }
 
+QList<BufferId> Client::allBufferIds() {
+  return buffers.keys();
+}
+
 void Client::recvNetworkState(QString net, QVariant state) {
-  connected[net] = true;
+  netConnected[net] = true;
   setOwnNick(net, state.toMap()["OwnNick"].toString());
   buffer(statusBufferId(net))->setActive(true);
   VarMap t = state.toMap()["Topics"].toMap();
@@ -289,7 +343,7 @@ void Client::userInput(BufferId id, QString msg) {
 
 void Client::setTopic(QString net, QString buf, QString topic) {
   BufferId id = bufferId(net, buf);
-  if(!connected[id.network()]) return;
+  if(!netConnected[id.network()]) return;
   Buffer *b = buffer(id);
   b->setTopic(topic);
   //if(!b->isActive()) {
@@ -299,7 +353,7 @@ void Client::setTopic(QString net, QString buf, QString topic) {
 }
 
 void Client::addNick(QString net, QString nick, VarMap props) {
-  if(!connected[net]) return;
+  if(!netConnected[net]) return;
   nicks[net][nick] = props;
   VarMap chans = props["Channels"].toMap();
   QStringList c = chans.keys();
@@ -309,7 +363,7 @@ void Client::addNick(QString net, QString nick, VarMap props) {
 }
 
 void Client::renameNick(QString net, QString oldnick, QString newnick) {
-  if(!connected[net]) return;
+  if(!netConnected[net]) return;
   QStringList chans = nicks[net][oldnick]["Channels"].toMap().keys();
   foreach(QString c, chans) {
     buffer(bufferId(net, c))->renameNick(oldnick, newnick);
@@ -318,7 +372,7 @@ void Client::renameNick(QString net, QString oldnick, QString newnick) {
 }
 
 void Client::updateNick(QString net, QString nick, VarMap props) {
-  if(!connected[net]) return;
+  if(!netConnected[net]) return;
   QStringList oldchans = nicks[net][nick]["Channels"].toMap().keys();
   QStringList newchans = props["Channels"].toMap().keys();
   foreach(QString c, newchans) {
@@ -332,7 +386,7 @@ void Client::updateNick(QString net, QString nick, VarMap props) {
 }
 
 void Client::removeNick(QString net, QString nick) {
-  if(!connected[net]) return;
+  if(!netConnected[net]) return;
   VarMap chans = nicks[net][nick]["Channels"].toMap();
   foreach(QString bufname, chans.keys()) {
     buffer(bufferId(net, bufname))->removeNick(nick);
@@ -341,7 +395,7 @@ void Client::removeNick(QString net, QString nick) {
 }
 
 void Client::setOwnNick(QString net, QString nick) {
-  if(!connected[net]) return;
+  if(!netConnected[net]) return;
   ownNick[net] = nick;
   foreach(BufferId id, buffers.keys()) {
     if(id.network() == net) {
index eee57fd..9bc4034 100644 (file)
@@ -40,6 +40,7 @@ class Client : public QObject {
     static void init(AbstractUi *);
     static void destroy();
 
+    static QList<BufferId> allBufferIds();
     static Buffer *buffer(BufferId);
     static BufferId statusBufferId(QString net);
     static BufferId bufferId(QString net, QString buf);
@@ -48,6 +49,8 @@ class Client : public QObject {
 
     static AbstractUiMsg *layoutMsg(const Message &);
 
+    static bool isConnected();
+
   signals:
     void sendInput(BufferId, QString message);
     void showBuffer(Buffer *);
@@ -57,13 +60,18 @@ class Client : public QObject {
     void bufferDestroyed(Buffer *);
     void backlogReceived(Buffer *, QList<Message>);
     void requestBacklog(BufferId, QVariant, QVariant);
+    void requestNetworkStates();
 
     void recvPartialItem(quint32 avail, quint32 size);
     void coreConnectionError(QString errorMsg);
 
+    void connected();
+    void disconnected();
+
   public slots:
     //void selectBuffer(Buffer *);
-    void connectToCore(QString host, quint16 port);
+    //void connectToLocalCore();
+    void connectToCore(const VarMap &);
     void disconnectFromCore();
 
   private slots:
@@ -100,6 +108,8 @@ class Client : public QObject {
     static Client *instanceptr;
 
     void syncToCore();
+    QVariant connectToLocalCore(QString user, QString passwd);  // defined in main.cpp
+    void disconnectFromLocalCore();                             // defined in main.cpp
 
     enum ClientMode { LocalCore, RemoteCore };
     static ClientMode clientMode;
@@ -111,12 +121,13 @@ class Client : public QObject {
     QTcpSocket socket;
     quint32 blockSize;
 
+    static bool connectedToCore;
     static QHash<BufferId, Buffer *> buffers;
     static QHash<uint, BufferId> bufferIds;
     static QHash<QString, QHash<QString, VarMap> > nicks;
-    static QHash<QString, bool> connected;
+    static QHash<QString, bool> netConnected;
     static QHash<QString, QString> ownNick;
-    static QList<BufferId> coreBuffers;
+    //static QList<BufferId> coreBuffers;
 
     QTimer *layoutTimer;
     QList<Buffer *> layoutQueue;
index 28fbfff..abe7ca4 100644 (file)
@@ -42,6 +42,7 @@ class ClientProxy : public QObject {
     inline void gsRequestConnect(QStringList networks)                { send(GS_REQUEST_CONNECT, networks); }
     inline void gsImportBacklog()                                     { send(GS_IMPORT_BACKLOG); }
     inline void gsRequestBacklog(BufferId id, QVariant v1, QVariant v2) { send(GS_REQUEST_BACKLOG, QVariant::fromValue(id), v1, v2); }
+    inline void gsRequestNetworkStates()                              { send(GS_REQUEST_NETWORK_STATES); }
 
     inline void gsGeneric(ClientSignal sig, QVariant v1 = QVariant(), QVariant v2 = QVariant(), QVariant v3 = QVariant()) { send(sig, v1, v2, v3); }
 
index 7f46552..55457d2 100644 (file)
@@ -1,6 +1,6 @@
 SET(common_SRCS global.cpp logger.cpp util.cpp message.cpp settings.cpp)
-SET(common_HDRS util.h message.h settings.h quasselui.h)
-SET(common_MOCS global.h logger.h)
+SET(common_HDRS util.h message.h settings.h)
+SET(common_MOCS global.h logger.h quasselui.h)
 
 QT4_WRAP_CPP(_MOC ${common_MOCS})
 ADD_LIBRARY(common ${_MOC} ${common_SRCS} ${common_HDRS})
index 48760d2..a35ab4c 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "global.h"
 #include "settings.h"
+#include "quasselui.h"
 
 #if defined BUILD_CORE
 #include <QCoreApplication>
@@ -58,27 +59,28 @@ int main(int argc, char **argv) {
   Global::runMode = Global::Monolithic;
   QApplication app(argc, argv);
 #endif
-
+  //AbstractUi *foo = new AbstractUi();
+  //foo->init();
   QCoreApplication::setOrganizationDomain("quassel-irc.org");
   QCoreApplication::setApplicationName("Quassel IRC");
   QCoreApplication::setOrganizationName("Quassel IRC Development Team");
 
   Global::quasselDir = QDir::homePath() + "/.quassel";
-  Core::instance();
-#ifdef BUILD_MONO
-  QObject::connect(Core::localSession(), SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), ClientProxy::instance(), SLOT(recv(CoreSignal, QVariant, QVariant, QVariant)));
-  QObject::connect(ClientProxy::instance(), SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), Core::localSession(), SLOT(processSignal(ClientSignal, QVariant, QVariant, QVariant)));
+#ifndef BUILD_QTGUI
+  Core::instance();  // create and init the core
 #endif
 
   Settings::init();
 
 #ifndef BUILD_CORE
   Style::init();
-  MainWin *mainWin = new MainWin();
-  Client::init(mainWin);
-  mainWin->init();
-#else
-  Core::instance(); // create and init the core object
+  AbstractUi foo;  // This avoids an annoying linker error (bug?) where AbstractUi's vtable is not found.
+                   // Yes, it's fugly. Yes, I'd like an alternative.
+  QtGui *gui = new QtGui();
+  Client::init(gui);
+  gui->init();
+//#else
+//  Core::instance(); // create and init the core object
 #endif
 
   int exitCode = app.exec();
@@ -87,7 +89,7 @@ int main(int argc, char **argv) {
   // the mainWin has to be deleted before the Core
   // if not Quassel will crash on exit under certain conditions since the gui
   // still wants to access clientdata
-  delete mainWin;
+  delete gui;
   Client::destroy();
 #endif
 #ifndef BUILD_QTGUI
@@ -97,11 +99,23 @@ int main(int argc, char **argv) {
   return exitCode;
 }
 
-#ifndef BUILD_CORE
-void Client::syncToCore() {
-  //Q_ASSERT(Global::data("CoreReady").toBool());
-  coreBuffers = Core::localSession()->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...
+#ifdef BUILD_QTGUI
+QVariant Client::connectToLocalCore(QString, QString) { return QVariant(); }
+void Client::disconnectFromLocalCore() {}
+#elif defined BUILD_MONO
+
+QVariant Client::connectToLocalCore(QString user, QString passwd) {
+  // TODO catch exceptions
+  QVariant reply = Core::connectLocalClient(user, passwd);
+  QObject::connect(Core::localSession(), SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), ClientProxy::instance(), SLOT(recv(CoreSignal, QVariant, QVariant, QVariant)));
+  QObject::connect(ClientProxy::instance(), SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), Core::localSession(), SLOT(processSignal(ClientSignal, QVariant, QVariant, QVariant)));
+  return reply;
 }
+
+void Client::disconnectFromLocalCore() {
+  disconnect(Core::localSession(), 0, ClientProxy::instance(), 0);
+  disconnect(ClientProxy::instance(), 0, Core::localSession(), 0);
+  Core::disconnectLocalClient();
+}
+
 #endif
index 30421e7..2eacb0d 100644 (file)
@@ -22,7 +22,7 @@
 #define _PROXY_COMMON_H_
 
 enum ClientSignal { GS_CLIENT_INIT, GS_USER_INPUT, GS_REQUEST_CONNECT, GS_UPDATE_GLOBAL_DATA, GS_IMPORT_BACKLOG,
-  GS_REQUEST_BACKLOG
+  GS_REQUEST_BACKLOG, GS_REQUEST_NETWORK_STATES
 
 };
 
index 1b8c7a0..0925b2e 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _QUASSELUI_H_
 #define _QUASSELUI_H_
 
+#include <QObject>
 #include "message.h"
 
 class AbstractUiMsg {
@@ -36,13 +37,22 @@ class AbstractUiMsg {
 };
 
 
-class AbstractUi {
+class AbstractUi : public QObject {
+  Q_OBJECT
 
   public:
+    static void foo() {};
     virtual ~AbstractUi() {};
-    virtual AbstractUiMsg *layoutMsg(const Message &) = 0;
+    virtual void init() {};  // called after the client is initialized
+    virtual AbstractUiMsg *layoutMsg(const Message &) { return 0; }
 
+  protected slots:
+    virtual void connectedToCore() {}
+    virtual void disconnectedFromCore() {}
 
+  signals:
+    void connectToCore(const VarMap &connInfo);
+    void disconnectFromCore();
 
 };
 
index 1df55da..f9bc84f 100644 (file)
@@ -43,7 +43,7 @@ void Core::destroy() {
 }
 
 Core::Core() {
-  qDebug() << "core";
+
 }
 
 void Core::init() {
@@ -55,6 +55,8 @@ void Core::init() {
   connect(Global::instance(), SIGNAL(dataPutLocally(UserId, QString)), this, SLOT(updateGlobalData(UserId, QString)));
   connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
   //startListening(); // FIXME
+  guiUser = 0;
+  /*
   if(Global::runMode == Global::Monolithic) {  // TODO Make GUI user configurable
     try {
       guiUser = storage->validateUser("Default", "password");
@@ -65,7 +67,7 @@ void Core::init() {
     Global::setGuiUser(guiUser);
     createSession(guiUser);
   } else guiUser = 0;
-
+  */
   // Read global settings from config file
   QSettings s;
   s.beginGroup("Global");
@@ -173,36 +175,53 @@ void Core::clientDisconnected() {
   // TODO remove unneeded sessions - if necessary/possible...
 }
 
+QVariant Core::connectLocalClient(QString user, QString passwd) {
+  UserId uid = instance()->storage->validateUser(user, passwd);
+  QVariant reply = instance()->initSession(uid);
+  instance()->guiUser = uid;
+  Global::setGuiUser(uid);
+  qDebug() << "Local client connected.";
+  return reply;
+}
+
+QVariant Core::disconnectLocalClient() {
+  qDebug() << "Local client disconnected.";
+  instance()->guiUser = 0;
+  Global::setGuiUser(0);
+}
+
 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
+    // Auth
   UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString());  // throws exception if this failed
+  VarMap reply = initSession(uid).toMap();
+  validClients[socket] = uid;
+  QList<QVariant> sigdata;
+  sigdata.append(CS_CORE_STATE); sigdata.append(QVariant(reply)); sigdata.append(QVariant()); sigdata.append(QVariant());
+  writeDataToDevice(socket, QVariant(sigdata));
+}
 
+QVariant Core::initSession(UserId uid) {
   // Find or create session for validated user
   CoreSession *sess;
   if(sessions.contains(uid)) sess = sessions[uid];
   else {
     sess = createSession(uid);
-    validClients[socket] = uid;
+    //validClients[socket] = uid;
   }
   VarMap reply;
   VarMap coreData;
-  // FIXME
   QStringList dataKeys = Global::keys(uid);
-  QString key;
-  foreach(key, dataKeys) {
-    coreData[key] = Global::data(key);
+  foreach(QString key, dataKeys) {
+    coreData[key] = Global::data(uid, 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();
+  return reply;
 }
 
 void Core::processClientUpdate(QTcpSocket *socket, QString key, const QVariant &data) {
@@ -263,6 +282,7 @@ CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_st
   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(coreProxy, SIGNAL(gsRequestNetworkStates()), this, SLOT(sendServerStates()));
   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)));
index 126e3a5..aec0469 100644 (file)
@@ -43,6 +43,9 @@ class Core : public QObject {
     static CoreSession * localSession();
     static CoreSession * createSession(UserId);
 
+    static QVariant connectLocalClient(QString user, QString passwd);
+    static QVariant disconnectLocalClient();
+
   private slots:
     void recvProxySignal(CoreSignal, QVariant, QVariant, QVariant);
     bool startListening(uint port = 4242);
@@ -58,6 +61,13 @@ class Core : public QObject {
     void init();
     static Core *instanceptr;
 
+    //! Initiate a session for the user with the given credentials if one does not already exist.
+    /** This function is called during the init process for a new client. If there is no session for the
+     *  given user, one is created.
+     * \param userId The user
+     * \return A QVariant containing the session data, e.g. global data and buffers
+     */
+    QVariant initSession(UserId userId);
     void processClientInit(QTcpSocket *socket, const QVariant &v);
     void processClientUpdate(QTcpSocket *socket, QString key, const QVariant &data);
 
index ee9ea2d..84c427c 100644 (file)
@@ -68,6 +68,7 @@ void CoreProxy::recv(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant ar
     case GS_REQUEST_CONNECT: emit gsRequestConnect(arg1.toStringList()); break;
     case GS_IMPORT_BACKLOG: emit gsImportBacklog(); break;
     case GS_REQUEST_BACKLOG: emit gsRequestBacklog(arg1.value<BufferId>(), arg2, arg3); break;
+    case GS_REQUEST_NETWORK_STATES: emit gsRequestNetworkStates(); break;
     //default: qWarning() << "Unknown signal in CoreProxy::recv: " << sig;
     default: emit gsGeneric(sig, arg1, arg2, arg3);
   }
index 071f651..737d061 100644 (file)
@@ -65,6 +65,7 @@ class CoreProxy : public QObject {
     void gsRequestConnect(QStringList networks);
     void gsImportBacklog();
     void gsRequestBacklog(BufferId, QVariant, QVariant);
+    void gsRequestNetworkStates();
 
     void gsGeneric(ClientSignal, QVariant, QVariant, QVariant);
 
index af5767d..00dc4c0 100644 (file)
@@ -386,7 +386,6 @@ QList<Message> SqliteStorage::requestMsgs(BufferId buffer, int lastmsgs, int off
     msg.msgId = requestMsgsQuery->value(0).toUInt();
     messagelist << msg;
   }
-
   return messagelist;
 }
 
index d51bb5d..102c3cc 100644 (file)
@@ -29,6 +29,7 @@ CoreConnectDlg::CoreConnectDlg(QWidget *parent) : QDialog(parent) {
   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()));
 
@@ -39,31 +40,32 @@ CoreConnectDlg::CoreConnectDlg(QWidget *parent) : QDialog(parent) {
   if(s.value("GUI/CoreAutoConnect").toBool()) {
     hostSelected();
   }
+  */
 }
 
-void CoreConnectDlg::setStartState() {
+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());
+  ui.hostName->setSelection(0, ui.hostName->text().length()); */
 }
 
 void CoreConnectDlg::hostEditChanged(QString txt) {
   ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(txt.length());
 }
 
-void CoreConnectDlg::hostSelected() {
+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(ClientProxy::instance(), SIGNAL(coreConnected()), this, SLOT(coreConnected()));
   connect(ClientProxy::instance(), SIGNAL(coreConnectionError(QString)), this, SLOT(coreConnectionError(QString)));
   Client::instance()->connectToCore(ui.hostName->text(), ui.hostPort->value());
-
+*/
 }
 
-void CoreConnectDlg::coreConnected() {
+void CoreConnectDlg::coreConnected() { /*
   ui.hostLabel->hide(); ui.hostName->hide(); ui.portLabel->hide(); ui.hostPort->hide();
   ui.statusText->setText(tr("Synchronizing..."));
   QSettings s;
@@ -75,7 +77,7 @@ void CoreConnectDlg::coreConnected() {
   ui.progressBar->show();
   VarMap initmsg;
   initmsg["GUIProtocol"] = GUI_PROTOCOL;
-  // FIXME guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg));
+  // FIXME guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg)); */
 }
 
 void CoreConnectDlg::coreConnectionError(QString err) {
index 772acab..bb193cf 100644 (file)
 #include "settingsdlg.h"
 #include "settingspages.h"
 
-MainWin::MainWin() : QMainWindow() {
-  ui.setupUi(this);
+QtGui::QtGui() : AbstractUi() {
+  mainWin = new MainWin(this);
+  connect(mainWin, SIGNAL(connectToCore(const VarMap &)), this, SIGNAL(connectToCore(const VarMap &)));
+  connect(mainWin, SIGNAL(disconnectFromCore()), this, SIGNAL(disconnectFromCore()));
   
-  //widget = 0;
-  //qDebug() << "Available DB drivers: " << QSqlDatabase::drivers ();
+}
+
+QtGui::~QtGui() {
+  delete mainWin;
+}
+
+void QtGui::init() {
+  mainWin->init();
+}
+
+AbstractUiMsg *QtGui::layoutMsg(const Message &msg) {
+  return mainWin->layoutMsg(msg);
+}
+
+void QtGui::connectedToCore() {
+  mainWin->connectedToCore();
+}
+
+void QtGui::disconnectedFromCore() {
+  mainWin->disconnectedFromCore();
+}
+
+MainWin::MainWin(QtGui *_gui, QWidget *parent) : QMainWindow(parent), gui(_gui) {
+  ui.setupUi(this);
   setWindowTitle("Quassel IRC");
   //setWindowTitle("Κυασελ Εγαρζη");
   setWindowIcon(QIcon(":/qirc-icon.png"));
   setWindowIconText("Quassel IRC");
 
-  //workspace = new QWorkspace(this);
-  //setCentralWidget(workspace);
   statusBar()->showMessage(tr("Waiting for core..."));
   
 }
 
 void MainWin::init() {
+  connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), ClientProxy::instance(), SLOT(gsRequestBacklog(BufferId, QVariant, QVariant)));
   ui.bufferWidget->init();
 
   show();
-  //syncToCore();
+
+  VarMap connInfo;
+  connInfo["User"] = "Default";
+  connInfo["Password"] = "password";
+  connectToCore(connInfo);
+
   statusBar()->showMessage(tr("Ready."));
   systray = new QSystemTrayIcon(this);
   systray->setIcon(QIcon(":/qirc-icon.png"));
@@ -92,6 +120,7 @@ void MainWin::init() {
     }
   }
   */
+
 }
 
 MainWin::~MainWin() {
@@ -124,7 +153,7 @@ void MainWin::setupMenus() {
 
 void MainWin::setupViews() {
   
-  BufferTreeModel *model = Client::bufferModel(); // FIXME Where is the delete for that? :p
+  BufferTreeModel *model = Client::bufferModel();
   connect(model, SIGNAL(bufferSelected(Buffer *)), this, SLOT(showBuffer(Buffer *)));
   
   addBufferView(tr("All Buffers"), model, BufferViewFilter::AllNets, QStringList());
@@ -153,6 +182,16 @@ void MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model,
   netViews.append(dock);
 }
 
+void MainWin::connectedToCore() {
+  foreach(BufferId id, Client::allBufferIds()) {
+    emit requestBacklog(id, 100, -1);
+  }
+}
+
+void MainWin::disconnectedFromCore() {
+
+}
+
 AbstractUiMsg *MainWin::layoutMsg(const Message &msg) {
   return new ChatLine(msg);
 }
index e46e233..eed60f7 100644 (file)
@@ -24,7 +24,6 @@
 #include <QtGui>
 #include "ui_mainwin.h"
 
-#include "quasselui.h"
 //#include "global.h"
 #include "message.h"
 #include "chatwidget.h"
@@ -35,17 +34,32 @@ class ServerListDlg;
 class CoreConnectDlg;
 class Buffer;
 class SettingsDlg;
+class MainWin;
 
-//!\brief The main window and central object of Quassel GUI.
-/** In addition to displaying the main window including standard stuff like a menubar,
- * dockwidgets and of course the chat window, this class also stores all data it
- * receives from the core, and it maintains a list of all known nicks.
- */
-class MainWin : public QMainWindow, public AbstractUi {
+class QtGui : public AbstractUi {
   Q_OBJECT
 
   public:
-    MainWin();
+    QtGui();
+    ~QtGui();
+    void init();
+    AbstractUiMsg *layoutMsg(const Message &);
+
+  protected slots:
+    void connectedToCore();
+    void disconnectedFromCore();
+
+  private:
+    MainWin *mainWin;
+};
+
+
+//!\brief The main window of Quassel's QtGui.
+class MainWin : public QMainWindow {
+  Q_OBJECT
+
+  public:
+    MainWin(QtGui *gui, QWidget *parent = 0);
     virtual ~MainWin();
 
     void init();
@@ -56,7 +70,9 @@ class MainWin : public QMainWindow, public AbstractUi {
   protected:
     void closeEvent(QCloseEvent *event);
 
-    //void importOldBacklog();
+  protected slots:
+    void connectedToCore();
+    void disconnectedFromCore();
 
   private slots:
 
@@ -69,15 +85,21 @@ class MainWin : public QMainWindow, public AbstractUi {
     void importBacklog();
 
   signals:
+    void connectToCore(const VarMap &connInfo);
+    void disconnectFromCore();
+    void requestBacklog(BufferId, QVariant, QVariant);
     void importOldBacklog();
 
   private:
     Ui::MainWin ui;
+    QtGui *gui;
 
     void setupMenus();
     void setupViews();
     void setupSettingsDlg();
 
+    void enableMenus();
+
     QSystemTrayIcon *systray;
 
     ServerListDlg *serverListDlg;
@@ -88,6 +110,7 @@ class MainWin : public QMainWindow, public AbstractUi {
 
     QList<QDockWidget *> netViews;
 
+    friend class QtGui;
 };
 
 #endif
index 12b0be0..1311565 100644 (file)
@@ -5,14 +5,12 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>499</width>
-    <height>144</height>
+    <width>498</width>
+    <height>270</height>
    </rect>
   </property>
   <property name="sizePolicy" >
-   <sizepolicy>
-    <hsizetype>5</hsizetype>
-    <vsizetype>3</vsizetype>
+   <sizepolicy vsizetype="MinimumExpanding" hsizetype="Preferred" >
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
    <string>Connect to Quassel Core</string>
   </property>
   <property name="windowIcon" >
-   <iconset resource="../images/icons.qrc" >:/default/server.png</iconset>
+   <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>
+    <widget class="QGroupBox" name="groupBox" >
+     <property name="title" >
+      <string>Core Connection Settings</string>
      </property>
+     <layout class="QHBoxLayout" >
+      <item>
+       <layout class="QGridLayout" >
+        <item row="0" column="0" colspan="2" >
+         <widget class="QComboBox" name="connectProfileName" />
+        </item>
+        <item row="1" column="0" >
+         <widget class="QLabel" name="label_2" >
+          <property name="text" >
+           <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
+&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;span style=" font-weight:600;">Host:&lt;/span>&lt;/p>&lt;/body>&lt;/html></string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1" >
+         <widget class="QLabel" name="hostName" >
+          <property name="text" >
+           <string>quassel.mindpool.net:4242</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="0" >
+         <widget class="QLabel" name="label_3" >
+          <property name="text" >
+           <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
+&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;span style=" font-weight:600;">User:&lt;/span>&lt;/p>&lt;/body>&lt;/html></string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1" >
+         <widget class="QLabel" name="user" >
+          <property name="text" >
+           <string>quasseluser</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="0" >
+         <widget class="QLabel" name="label_4" >
+          <property name="text" >
+           <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
+&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;span style=" font-weight:600;">Password:&lt;/span>&lt;/p>&lt;/body>&lt;/html></string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="1" >
+         <widget class="QLineEdit" name="passwdEdit" >
+          <property name="echoMode" >
+           <enum>QLineEdit::Password</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="2" >
+         <widget class="QPushButton" name="editConnectProfile" >
+          <property name="text" >
+           <string>Edit...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="2" >
+         <widget class="QPushButton" name="newConnectProfile" >
+          <property name="text" >
+           <string>New...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="2" >
+         <widget class="QCheckBox" name="rememberPasswd" >
+          <property name="text" >
+           <string>Remember</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
     </widget>
    </item>
    <item>
-    <layout class="QHBoxLayout" >
-     <property name="margin" >
-      <number>0</number>
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
      </property>
-     <property name="spacing" >
-      <number>6</number>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
      </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>
+    </spacer>
    </item>
    <item>
     <widget class="QProgressBar" name="progressBar" >
     </widget>
    </item>
    <item>
-    <spacer>
-     <property name="orientation" >
-      <enum>Qt::Vertical</enum>
+    <layout class="QHBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
      </property>
-     <property name="sizeHint" >
-      <size>
-       <width>20</width>
-       <height>53</height>
-      </size>
+     <property name="leftMargin" >
+      <number>0</number>
      </property>
-    </spacer>
-   </item>
-   <item>
-    <layout class="QHBoxLayout" >
-     <property name="margin" >
+     <property name="topMargin" >
       <number>0</number>
      </property>
-     <property name="spacing" >
-      <number>6</number>
+     <property name="rightMargin" >
+      <number>0</number>
+     </property>
+     <property name="bottomMargin" >
+      <number>0</number>
      </property>
      <item>
       <widget class="QCheckBox" name="autoConnect" >
    </item>
   </layout>
  </widget>
+ <includes/>
  <resources>
-  <include location="../images/icons.qrc" />
+  <include location="../../images/icons.qrc" />
  </resources>
  <connections>
   <connection>
index ea93b30..82c7e6e 100644 (file)
     <property name="title" >
      <string>Connection</string>
     </property>
+    <widget class="QMenu" name="menuConnectCore" >
+     <property name="title" >
+      <string>Connect to Core</string>
+     </property>
+     <addaction name="actionInternal" />
+    </widget>
+    <addaction name="menuConnectCore" />
+    <addaction name="actionDisconnectCore" />
+    <addaction name="separator" />
     <addaction name="actionNetworkList" />
     <addaction name="actionQuickConnect" />
     <addaction name="separator" />
     </property>
     <addaction name="actionImportBacklog" />
    </widget>
+   <widget class="QMenu" name="menuCore" >
+    <property name="title" >
+     <string>Core</string>
+    </property>
+   </widget>
    <addaction name="menuConnection" />
    <addaction name="menuViews" />
+   <addaction name="menuCore" />
    <addaction name="menuSettings" />
    <addaction name="menuHelp" />
    <addaction name="menuDebug" />
     <string>Import Backlog</string>
    </property>
   </action>
+  <action name="actionConnect_to_Core" >
+   <property name="text" >
+    <string>Connect</string>
+   </property>
+  </action>
+  <action name="actionDisconnect_2" >
+   <property name="text" >
+    <string>Disconnect</string>
+   </property>
+  </action>
+  <action name="actionInternal" >
+   <property name="text" >
+    <string>Internal</string>
+   </property>
+  </action>
+  <action name="actionDisconnectCore" >
+   <property name="text" >
+    <string>Disconnect from Core</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>