I am starting to clean up the mess that is Global right now, and to implement a clean...
authorManuel Nickschas <sputnick@quassel-irc.org>
Sun, 8 Jul 2007 14:36:08 +0000 (14:36 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sun, 8 Jul 2007 14:36:08 +0000 (14:36 +0000)
for storing settings (session-wide and local). First step: Instead of putting synchronization stuff into
Global and doing special treatment for signals in Core, we have now a clear interface for handling
session-wide data in both Client and CoreSession:

Client::storeSessionData(key, data) [static]
Client::retrieveSessionData(key, defdata) [static]
CoreSession::storeSessionData(key, data)
CoreSession::retrieveSessionData(key, defdata)

CoreSession also cares for persistent storage using QSettings. It should be noted that the client-side store function
just sends a signal to the core, and the client-side data is actually updated upon receipt of the sync signal from core.
IOW, stuff is not stored immediately, and you should thus not rely on it being available right after your call to
storeSessionData(). If this is a bad idea, we might change this behavior at some point.

Note: The code has not yet been tested thoroughly, and it's only the first step anyway.

src/client/client.cpp
src/client/client.h
src/client/clientproxy.cpp
src/client/clientproxy.h
src/common/proxy_common.h
src/common/util.cpp
src/core/coreproxy.cpp
src/core/coreproxy.h
src/core/coresession.cpp
src/core/coresession.h

index 6be7e07..9a74119 100644 (file)
@@ -77,6 +77,8 @@ void Client::init() {
 
   connect(Global::instance(), SIGNAL(dataPutLocally(UserId, QString)), this, SLOT(updateCoreData(UserId, QString)));
   connect(clientProxy, SIGNAL(csUpdateGlobalData(QString, QVariant)), this, SLOT(updateLocalData(QString, QVariant)));
 
   connect(Global::instance(), SIGNAL(dataPutLocally(UserId, QString)), this, SLOT(updateCoreData(UserId, QString)));
   connect(clientProxy, SIGNAL(csUpdateGlobalData(QString, QVariant)), this, SLOT(updateLocalData(QString, QVariant)));
+  connect(this, SIGNAL(sendSessionData(const QString &, const QVariant &)), clientProxy, SLOT(gsSessionDataChanged(const QString &, const QVariant &)));
+  connect(clientProxy, SIGNAL(csSessionDataChanged(const QString &, const QVariant &)), this, SLOT(recvSessionData(const QString &, const QVariant &)));
 
   connect(clientProxy, SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), this, SLOT(recvProxySignal(ClientSignal, QVariant, QVariant, QVariant)));
   connect(clientProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant)));
 
   connect(clientProxy, SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), this, SLOT(recvProxySignal(ClientSignal, QVariant, QVariant, QVariant)));
   connect(clientProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant)));
@@ -196,6 +198,25 @@ void Client::updateLocalData(QString key, QVariant data) {
   Global::updateData(key, data);
 }
 
   Global::updateData(key, data);
 }
 
+void Client::recvSessionData(const QString &key, const QVariant &data) {
+  sessionData[key] = data;
+  emit sessionDataChanged(key, data);
+  emit sessionDataChanged(key);
+  qDebug() << "stored data in client:" << key;
+}
+
+void Client::storeSessionData(const QString &key, const QVariant &data) {
+  // Not sure if this is a good idea, but we'll try it anyway:
+  // Calling this function only sends a signal to core. Data is stored upon reception of the update signal,
+  // rather than immediately.
+  emit instance()->sendSessionData(key, data);
+}
+
+QVariant Client::retrieveSessionData(const QString &key, const QVariant &def) {
+  if(instance()->sessionData.contains(key)) return instance()->sessionData[key];
+  else return def;
+}
+
 void Client::recvProxySignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
   if(clientMode == LocalCore) return;
   QList<QVariant> sigdata;
 void Client::recvProxySignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
   if(clientMode == LocalCore) return;
   QList<QVariant> sigdata;
index 452bed0..1b3a4e8 100644 (file)
@@ -55,6 +55,9 @@ class Client : public QObject {
 
     static bool isConnected();
 
 
     static bool isConnected();
 
+    static void storeSessionData(const QString &key, const QVariant &data);
+    static QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
+
   signals:
     void sendInput(BufferId, QString message);
     void showBuffer(Buffer *);
   signals:
     void sendInput(BufferId, QString message);
     void showBuffer(Buffer *);
@@ -72,6 +75,10 @@ class Client : public QObject {
     void connected();
     void disconnected();
 
     void connected();
     void disconnected();
 
+    void sessionDataChanged(const QString &key);
+    void sessionDataChanged(const QString &key, const QVariant &data);
+    void sendSessionData(const QString &key, const QVariant &data);
+
   public slots:
     //void selectBuffer(Buffer *);
     //void connectToLocalCore();
   public slots:
     //void selectBuffer(Buffer *);
     //void connectToLocalCore();
@@ -81,6 +88,7 @@ class Client : public QObject {
   private slots:
     void updateCoreData(UserId, QString);
     void updateLocalData(QString, QVariant);
   private slots:
     void updateCoreData(UserId, QString);
     void updateLocalData(QString, QVariant);
+    void recvSessionData(const QString &key, const QVariant &data);
     void recvProxySignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3);
 
     void serverError(QAbstractSocket::SocketError);
     void recvProxySignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3);
 
     void serverError(QAbstractSocket::SocketError);
@@ -134,6 +142,8 @@ class Client : public QObject {
 
     QTimer *layoutTimer;
     QList<Buffer *> layoutQueue;
 
     QTimer *layoutTimer;
     QList<Buffer *> layoutQueue;
+
+    VarMap sessionData;
 };
 
 #endif
 };
 
 #endif
index 3614aa2..6118ff1 100644 (file)
@@ -48,6 +48,7 @@ void ClientProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant ar
     case CS_SERVER_DISCONNECTED: emit csServerDisconnected(arg1.toString()); break;
     case CS_UPDATE_GLOBAL_DATA: emit csUpdateGlobalData(arg1.toString(), arg2); break;
     //case CS_GLOBAL_DATA_CHANGED: emit csGlobalDataChanged(arg1.toString()); break;
     case CS_SERVER_DISCONNECTED: emit csServerDisconnected(arg1.toString()); break;
     case CS_UPDATE_GLOBAL_DATA: emit csUpdateGlobalData(arg1.toString(), arg2); break;
     //case CS_GLOBAL_DATA_CHANGED: emit csGlobalDataChanged(arg1.toString()); break;
+    case CS_SESSION_DATA_CHANGED: emit csSessionDataChanged(arg1.toString(), arg2); break;
     case CS_DISPLAY_MSG: emit csDisplayMsg(arg1.value<Message>()); break;
     case CS_DISPLAY_STATUS_MSG: emit csDisplayStatusMsg(arg1.toString(), arg2.toString()); break;
     case CS_MODE_SET: emit csModeSet(arg1.toString(), arg2.toString(), arg3.toString()); break;
     case CS_DISPLAY_MSG: emit csDisplayMsg(arg1.value<Message>()); break;
     case CS_DISPLAY_STATUS_MSG: emit csDisplayStatusMsg(arg1.toString(), arg2.toString()); break;
     case CS_MODE_SET: emit csModeSet(arg1.toString(), arg2.toString(), arg3.toString()); break;
index e66aa65..33b3403 100644 (file)
@@ -22,6 +22,7 @@
 #define _CLIENTPROXY_H_
 
 #include <QStringList>
 #define _CLIENTPROXY_H_
 
 #include <QStringList>
+#include <QtDebug>
 
 #include "proxy_common.h"
 #include "message.h"
 
 #include "proxy_common.h"
 #include "message.h"
@@ -35,6 +36,7 @@ class ClientProxy : public QObject {
     static void destroy();
 
   public slots:
     static void destroy();
 
   public slots:
+    inline void gsSessionDataChanged(const QString &key, const QVariant &data) { send(GS_SESSION_DATA_CHANGED, key, data); }
     inline void gsUserInput(BufferId id, QString msg)                 { send(GS_USER_INPUT, QVariant::fromValue(id), msg); }
     inline void gsRequestConnect(QStringList networks)                { send(GS_REQUEST_CONNECT, networks); }
     inline void gsImportBacklog()                                     { send(GS_IMPORT_BACKLOG); }
     inline void gsUserInput(BufferId id, QString msg)                 { send(GS_USER_INPUT, QVariant::fromValue(id), msg); }
     inline void gsRequestConnect(QStringList networks)                { send(GS_REQUEST_CONNECT, networks); }
     inline void gsImportBacklog()                                     { send(GS_IMPORT_BACKLOG); }
@@ -52,6 +54,7 @@ class ClientProxy : public QObject {
     void csDisplayStatusMsg(QString, QString);
     void csUpdateGlobalData(QString key, QVariant data);
     void csGlobalDataChanged(QString key);
     void csDisplayStatusMsg(QString, QString);
     void csUpdateGlobalData(QString key, QVariant data);
     void csGlobalDataChanged(QString key);
+    void csSessionDataChanged(const QString &key, const QVariant &data);
     void csModeSet(QString, QString, QString);
     void csTopicSet(QString, QString, QString);
     void csNickAdded(QString, QString, VarMap);
     void csModeSet(QString, QString, QString);
     void csTopicSet(QString, QString, QString);
     void csNickAdded(QString, QString, VarMap);
index 609b593..0540574 100644 (file)
 #define _PROXY_COMMON_H_
 
 enum ClientSignal { GS_CLIENT_INIT, GS_USER_INPUT, GS_REQUEST_CONNECT, GS_UPDATE_GLOBAL_DATA, GS_IMPORT_BACKLOG,
 #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_NETWORK_STATES
+  GS_REQUEST_BACKLOG, GS_REQUEST_NETWORK_STATES, GS_SESSION_DATA_CHANGED
 
 };
 
 enum CoreSignal { CS_CORE_STATE, CS_SERVER_CONNECTED, CS_SERVER_DISCONNECTED, CS_SERVER_STATE,
 
 };
 
 enum CoreSignal { CS_CORE_STATE, CS_SERVER_CONNECTED, CS_SERVER_DISCONNECTED, CS_SERVER_STATE,
-  CS_DISPLAY_MSG, CS_DISPLAY_STATUS_MSG, CS_UPDATE_GLOBAL_DATA,
+  CS_DISPLAY_MSG, CS_DISPLAY_STATUS_MSG, CS_UPDATE_GLOBAL_DATA, CS_SESSION_DATA_CHANGED,
   CS_MODE_SET, CS_TOPIC_SET, CS_SET_NICKS, CS_NICK_ADDED, CS_NICK_REMOVED, CS_NICK_RENAMED, CS_NICK_UPDATED,
   CS_OWN_NICK_SET, CS_QUERY_REQUESTED, CS_BACKLOG_DATA, CS_UPDATE_BUFFERID
 
   CS_MODE_SET, CS_TOPIC_SET, CS_SET_NICKS, CS_NICK_ADDED, CS_NICK_REMOVED, CS_NICK_RENAMED, CS_NICK_UPDATED,
   CS_OWN_NICK_SET, CS_QUERY_REQUESTED, CS_BACKLOG_DATA, CS_UPDATE_BUFFERID
 
index b5095d9..1c3d905 100644 (file)
@@ -56,7 +56,7 @@ QString decodeString(QByteArray input, QString encoding) {
       cnt--;
       continue;
     }
       cnt--;
       continue;
     }
-    if(!(input[i] & 0x80)) continue; // 7 bit is always ok
+    if((input[i] & 0x80) == 0x00) continue; // 7 bit is always ok
     if((input[i] & 0xf8) == 0xf0) { cnt = 3; continue; }  // 4-byte char 11110xxx 10yyyyyy 10zzzzzz 10vvvvvv
     if((input[i] & 0xf0) == 0xe0) { cnt = 2; continue; }  // 3-byte char 1110xxxx 10yyyyyy 10zzzzzz
     if((input[i] & 0xe0) == 0xc0) { cnt = 1; continue; }  // 2-byte char 110xxxxx 10yyyyyy
     if((input[i] & 0xf8) == 0xf0) { cnt = 3; continue; }  // 4-byte char 11110xxx 10yyyyyy 10zzzzzz 10vvvvvv
     if((input[i] & 0xf0) == 0xe0) { cnt = 2; continue; }  // 3-byte char 1110xxxx 10yyyyyy 10zzzzzz
     if((input[i] & 0xe0) == 0xc0) { cnt = 1; continue; }  // 2-byte char 110xxxxx 10yyyyyy
index f10af41..e6b9b49 100644 (file)
@@ -19,6 +19,7 @@
  ***************************************************************************/
 
 #include "coreproxy.h"
  ***************************************************************************/
 
 #include "coreproxy.h"
+#include <QtDebug>
 
 CoreProxy::CoreProxy() {
 
 
 CoreProxy::CoreProxy() {
 
@@ -28,6 +29,7 @@ void CoreProxy::recv(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant ar
   //qDebug() << "[CORE] Received signal" << sig << ":" << arg1<<arg2<<arg3;
   switch(sig) {
     case GS_UPDATE_GLOBAL_DATA: emit gsPutGlobalData(arg1.toString(), arg2); break;
   //qDebug() << "[CORE] Received signal" << sig << ":" << arg1<<arg2<<arg3;
   switch(sig) {
     case GS_UPDATE_GLOBAL_DATA: emit gsPutGlobalData(arg1.toString(), arg2); break;
+    case GS_SESSION_DATA_CHANGED: emit gsSessionDataChanged(arg1.toString(), arg2); break;
     case GS_USER_INPUT: emit gsUserInput(arg1.value<BufferId>(), arg2.toString()); break;
     case GS_REQUEST_CONNECT: emit gsRequestConnect(arg1.toStringList()); break;
     case GS_IMPORT_BACKLOG: emit gsImportBacklog(); break;
     case GS_USER_INPUT: emit gsUserInput(arg1.value<BufferId>(), arg2.toString()); break;
     case GS_REQUEST_CONNECT: emit gsRequestConnect(arg1.toStringList()); break;
     case GS_IMPORT_BACKLOG: emit gsImportBacklog(); break;
index fbb34b6..12f5d84 100644 (file)
@@ -42,6 +42,7 @@ class CoreProxy : public QObject {
 
   public slots:
     inline void csUpdateGlobalData(QString key, QVariant data)          { send(CS_UPDATE_GLOBAL_DATA, key, data); }
 
   public slots:
     inline void csUpdateGlobalData(QString key, QVariant data)          { send(CS_UPDATE_GLOBAL_DATA, key, data); }
+    inline void csSessionDataChanged(const QString &key, const QVariant &data) { send(CS_SESSION_DATA_CHANGED, key, data); }
     inline void csServerConnected(QString net)                          { send(CS_SERVER_CONNECTED, net); }
     inline void csServerDisconnected(QString net)                       { send(CS_SERVER_DISCONNECTED, net); }
     inline void csServerState(QString net, VarMap data)                 { send(CS_SERVER_STATE, net, data); }
     inline void csServerConnected(QString net)                          { send(CS_SERVER_CONNECTED, net); }
     inline void csServerDisconnected(QString net)                       { send(CS_SERVER_DISCONNECTED, net); }
     inline void csServerState(QString net, VarMap data)                 { send(CS_SERVER_STATE, net, data); }
@@ -62,6 +63,7 @@ class CoreProxy : public QObject {
 
   signals:
     void gsPutGlobalData(QString, QVariant);
 
   signals:
     void gsPutGlobalData(QString, QVariant);
+    void gsSessionDataChanged(const QString &, const QVariant &);
     void gsUserInput(BufferId, QString);
     void gsRequestConnect(QStringList networks);
     void gsImportBacklog();
     void gsUserInput(BufferId, QString);
     void gsRequestConnect(QStringList networks);
     void gsImportBacklog();
index ae0bdb2..4946711 100644 (file)
 CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_storage) {
   coreProxy = new CoreProxy();
 
 CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_storage) {
   coreProxy = new CoreProxy();
 
+  QSettings s;
+  s.beginGroup(QString("SessionData/%1").arg(user));
+  mutex.lock();
+  foreach(QString key, s.allKeys()) {
+    sessionData[key] = s.value(key);
+  }
+  mutex.unlock();
+
   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(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)));
@@ -40,6 +48,8 @@ CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_st
   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)));
   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)));
+  connect(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), coreProxy, SLOT(csSessionDataChanged(const QString &, const QVariant &)));
+  connect(coreProxy, SIGNAL(gsSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &)));
 }
 
 CoreSession::~CoreSession() {
 }
 
 CoreSession::~CoreSession() {
@@ -61,6 +71,27 @@ void CoreSession::globalDataUpdated(UserId uid, QString key) {
   s.setValue(QString("Global/%1/").arg(userId())+key, data);
 }
 
   s.setValue(QString("Global/%1/").arg(userId())+key, data);
 }
 
+void CoreSession::storeSessionData(const QString &key, const QVariant &data) {
+  QSettings s;
+  s.beginGroup(QString("SessionData/%1").arg(user));
+  mutex.lock();
+  sessionData[key] = data;
+  s.setValue(key, data);
+  mutex.unlock();
+  s.endGroup();
+  emit sessionDataChanged(key, data);
+  emit sessionDataChanged(key);
+}
+
+QVariant CoreSession::retrieveSessionData(const QString &key, const QVariant &def) {
+  QVariant data;
+  mutex.lock();
+  if(!sessionData.contains(key)) data = def;
+  else data = sessionData[key];
+  mutex.unlock();
+  return data;
+}
+
 void CoreSession::connectToIrc(QStringList networks) {
   foreach(QString net, networks) {
     if(servers.contains(net)) {
 void CoreSession::connectToIrc(QStringList networks) {
   foreach(QString net, networks) {
     if(servers.contains(net)) {
@@ -147,6 +178,9 @@ QVariant CoreSession::sessionState() {
   QList<QVariant> bufs;
   foreach(BufferId id, storage->requestBuffers(user)) { bufs.append(QVariant::fromValue(id)); }
   v["Buffers"] = bufs;
   QList<QVariant> bufs;
   foreach(BufferId id, storage->requestBuffers(user)) { bufs.append(QVariant::fromValue(id)); }
   v["Buffers"] = bufs;
+  mutex.lock();
+  v["SessionData"] = sessionData;
+  mutex.unlock();
 
   return v;
 }
 
   return v;
 }
index 24d3d8d..f9336b2 100644 (file)
@@ -40,6 +40,15 @@ class CoreSession : public QObject {
     QList<BufferId> buffers() const;
     UserId userId() const;
     QVariant sessionState();
     QList<BufferId> buffers() const;
     UserId userId() const;
     QVariant sessionState();
+
+  public slots:
+    //! Store a piece session-wide data and distribute it to connected clients.
+    void storeSessionData(const QString &key, const QVariant &data);
+
+  public:
+    //! Retrieve a piece of session-wide data.
+    QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
+
     CoreProxy *proxy();
 
   public slots:
     CoreProxy *proxy();
 
   public slots:
@@ -63,6 +72,8 @@ class CoreSession : public QObject {
     void backlogData(BufferId, QList<QVariant>, bool done);
 
     void bufferIdUpdated(BufferId);
     void backlogData(BufferId, QList<QVariant>, bool done);
 
     void bufferIdUpdated(BufferId);
+    void sessionDataChanged(const QString &key);
+    void sessionDataChanged(const QString &key, const QVariant &data);
 
   private slots:
     //void recvProxySignal(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
 
   private slots:
     //void recvProxySignal(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
@@ -78,6 +89,9 @@ class CoreSession : public QObject {
     QHash<QString, Server *> servers;
     UserId user;
 
     QHash<QString, Server *> servers;
     UserId user;
 
+    VarMap sessionData;
+    QMutex mutex;
+
 };
 
 #endif
 };
 
 #endif