Bringing back session save/restore. Old state won't be imported, unfortunately,
authorManuel Nickschas <sputnick@quassel-irc.org>
Sun, 20 Jan 2008 03:21:12 +0000 (03:21 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sun, 20 Jan 2008 03:21:12 +0000 (03:21 +0000)
so you'll have to rejoin your chans once after doing this update... :)

Also made shutting down sessions sane. CoreSession's destructor was never called because of
me not thinking about how Thread::quit() works.

12 files changed:
src/common/network.cpp
src/common/network.h
src/core/core.cpp
src/core/core.h
src/core/coresession.cpp
src/core/coresession.h
src/core/coreusersettings.cpp
src/core/coreusersettings.h
src/core/networkconnection.cpp
src/core/sessionthread.cpp
src/core/sessionthread.h
version.inc

index 1b3ab30..982011b 100644 (file)
@@ -37,6 +37,7 @@ Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(p
     _myNick(QString()),
     _networkName(QString("<not initialized>")),
     _currentServer(QString()),
     _myNick(QString()),
     _networkName(QString("<not initialized>")),
     _currentServer(QString()),
+    _connected(false),
     _prefixes(QString()),
     _prefixModes(QString()),
     _proxy(0),
     _prefixes(QString()),
     _prefixModes(QString()),
     _proxy(0),
@@ -86,6 +87,10 @@ bool Network::isChannelName(const QString &channelname) const {
     return QString("#&!+").contains(channelname[0]);
 }
 
     return QString("#&!+").contains(channelname[0]);
 }
 
+bool Network::isConnected() const {
+  return _connected;
+}
+
 QString Network::prefixToMode(const QString &prefix) {
   if(prefixes().contains(prefix))
     return QString(prefixModes()[prefixes().indexOf(prefix)]);
 QString Network::prefixToMode(const QString &prefix) {
   if(prefixes().contains(prefix))
     return QString(prefixModes()[prefixes().indexOf(prefix)]);
@@ -327,6 +332,11 @@ void Network::setCurrentServer(const QString &currentServer) {
   emit currentServerSet(currentServer);
 }
 
   emit currentServerSet(currentServer);
 }
 
+void Network::setConnected(bool connected) {
+  _connected = connected;
+  emit connectedSet(connected);
+}
+
 void Network::setMyNick(const QString &nickname) {
   _myNick = nickname;
   emit myNickSet(nickname);
 void Network::setMyNick(const QString &nickname) {
   _myNick = nickname;
   emit myNickSet(nickname);
index 6a58d84..80131fa 100644 (file)
@@ -48,7 +48,7 @@ class Network : public SyncableObject {
   Q_PROPERTY(QByteArray codecForEncoding READ codecForEncoding WRITE setCodecForEncoding STORED false)
   Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding STORED false)
   Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity STORED false)
   Q_PROPERTY(QByteArray codecForEncoding READ codecForEncoding WRITE setCodecForEncoding STORED false)
   Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding STORED false)
   Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity STORED false)
-  // Q_PROPERTY(bool isConnected READ isConnected STORED false)
+  Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected STORED false)
 
 public:
   Network(const NetworkId &networkid, QObject *parent = 0);
 
 public:
   Network(const NetworkId &networkid, QObject *parent = 0);
@@ -64,6 +64,8 @@ public:
 
   bool isChannelName(const QString &channelname) const;
 
 
   bool isChannelName(const QString &channelname) const;
 
+  bool isConnected() const;
+
   QString prefixToMode(const QString &prefix);
   QString prefixToMode(const QCharRef &prefix);
   QString modeToPrefix(const QString &mode);
   QString prefixToMode(const QString &prefix);
   QString prefixToMode(const QCharRef &prefix);
   QString modeToPrefix(const QString &mode);
@@ -108,6 +110,7 @@ public:
 public slots:
   void setNetworkName(const QString &networkName);
   void setCurrentServer(const QString &currentServer);
 public slots:
   void setNetworkName(const QString &networkName);
   void setCurrentServer(const QString &currentServer);
+  void setConnected(bool isConnected);
   void setMyNick(const QString &mynick);
   void setIdentity(IdentityId);
 
   void setMyNick(const QString &mynick);
   void setIdentity(IdentityId);
 
@@ -152,6 +155,7 @@ private slots:
 signals:
   void networkNameSet(const QString &networkName);
   void currentServerSet(const QString &currentServer);
 signals:
   void networkNameSet(const QString &networkName);
   void currentServerSet(const QString &currentServer);
+  void connectedSet(bool isConnected);
   void myNickSet(const QString &mynick);
   void identitySet(IdentityId);
 
   void myNickSet(const QString &mynick);
   void identitySet(IdentityId);
 
@@ -186,6 +190,7 @@ private:
   QString _myNick;
   QString _networkName;
   QString _currentServer;
   QString _myNick;
   QString _networkName;
   QString _currentServer;
+  bool _connected;
 
   QString _prefixes;
   QString _prefixModes;
 
   QString _prefixes;
   QString _prefixModes;
index 298d7e3..e222a13 100644 (file)
@@ -95,37 +95,35 @@ Core::~Core() {
 }
 
 void Core::restoreState() {
 }
 
 void Core::restoreState() {
-  return;
-  /*
-  Q_ASSERT(!instance()->sessions.count());
+  if(instance()->sessions.count()) {
+    qWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
+    return;
+  }
   CoreSettings s;
   CoreSettings s;
-  QList<QVariant> users = s.coreState().toList();
-  if(users.count() > 0) {
+  uint build = s.coreState().toMap()["CoreBuild"].toUInt();
+  if(build < 362) {
+    qWarning() << qPrintable(tr("Core state too old, ignoring..."));
+    return;
+  }
+  QVariantList activeSessions = s.coreState().toMap()["ActiveSessions"].toList();
+  if(activeSessions.count() > 0) {
     qDebug() << "Restoring previous core state...";
     qDebug() << "Restoring previous core state...";
-    foreach(QVariant v, users) {
-      QVariantMap m = v.toMap();
-      if(m.contains("UserId")) {
-        CoreSession *sess = createSession(m["UserId"].toUInt());
-        sess->restoreState(m["State"]);  // FIXME multithreading
-      }
+    foreach(QVariant v, activeSessions) {
+      UserId user = v.value<UserId>();
+      instance()->createSession(user, true);
     }
     qDebug() << "...done.";
   }
     }
     qDebug() << "...done.";
   }
-  */
 }
 
 void Core::saveState() {
 }
 
 void Core::saveState() {
-  /*
   CoreSettings s;
   CoreSettings s;
-  QList<QVariant> users;
-  foreach(CoreSession *sess, instance()->sessions.values()) {
-    QVariantMap m;
-    m["UserId"] = sess->user();  // FIXME multithreading
-    m["State"] = sess->state();
-    users << m;
-  }
-  s.setCoreState(users);
-  */
+  QVariantMap state;
+  QVariantList activeSessions;
+  foreach(UserId user, instance()->sessions.keys()) activeSessions << QVariant::fromValue<UserId>(user);
+  state["CoreBuild"] = Global::quasselBuild;
+  state["ActiveSessions"] = activeSessions;
+  s.setCoreState(state);
 }
 
 /*** Storage Access ***/
 }
 
 /*** Storage Access ***/
@@ -308,15 +306,6 @@ void Core::clientDisconnected() {
   // Suggestion: kill sessions if they are not connected to any network and client.
 }
 
   // Suggestion: kill sessions if they are not connected to any network and client.
 }
 
-  
-  //disconnect(socket, 0, this, 0);
-  /*
-  sessions[uid]->addClient(socket);  // FIXME multithreading
-  qDebug() << "Client initialized successfully.";
-  SignalProxy::writeDataToDevice(socket, reply);
-  */
-
-
 void Core::processCoreSetup(QTcpSocket *socket, QVariantMap &msg) {
   if(msg["HasSettings"].toBool()) {
     QVariantMap auth;
 void Core::processCoreSetup(QTcpSocket *socket, QVariantMap &msg) {
   if(msg["HasSettings"].toBool()) {
     QVariantMap auth;
@@ -366,12 +355,12 @@ void Core::setupClientSession(QTcpSocket *socket, UserId uid) {
   sess->addClient(socket);
 }
 
   sess->addClient(socket);
 }
 
-SessionThread *Core::createSession(UserId uid) {
+SessionThread *Core::createSession(UserId uid, bool restore) {
   if(sessions.contains(uid)) {
     qWarning() << "Calling createSession() when a session for the user already exists!";
     return 0;
   }
   if(sessions.contains(uid)) {
     qWarning() << "Calling createSession() when a session for the user already exists!";
     return 0;
   }
-  SessionThread *sess = new SessionThread(uid, this);
+  SessionThread *sess = new SessionThread(uid, restore, this);
   sessions[uid] = sess;
   sess->start();
   return sess;
   sessions[uid] = sess;
   sess->start();
   return sess;
index 7669317..67f6dec 100644 (file)
@@ -139,7 +139,7 @@ class Core : public QObject {
     void init();
     static Core *instanceptr;
 
     void init();
     static Core *instanceptr;
 
-    SessionThread *createSession(UserId userId);
+    SessionThread *createSession(UserId userId, bool restoreState = false);
     void setupClientSession(QTcpSocket *socket, UserId uid);
     void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
 
     void setupClientSession(QTcpSocket *socket, UserId uid);
     void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
 
index c34e898..910bca1 100644 (file)
@@ -35,7 +35,7 @@
 
 #include <QtScript>
 
 
 #include <QtScript>
 
-CoreSession::CoreSession(UserId uid, QObject *parent) : QObject(parent),
+CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObject(parent),
     _user(uid),
     _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
     scriptEngine(new QScriptEngine(this))
     _user(uid),
     _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
     scriptEngine(new QScriptEngine(this))
@@ -113,10 +113,14 @@ CoreSession::CoreSession(UserId uid, QObject *parent) : QObject(parent),
     p->synchronize(net);
   }
 
     p->synchronize(net);
   }
 
+  // Restore session state
+  if(restoreState) restoreSessionState();
+
   emit initialized();
 }
 
 CoreSession::~CoreSession() {
   emit initialized();
 }
 
 CoreSession::~CoreSession() {
+  saveSessionState();
 }
 
 UserId CoreSession::user() const {
 }
 
 UserId CoreSession::user() const {
@@ -138,35 +142,33 @@ Identity *CoreSession::identity(IdentityId id) const {
   return 0;
 }
 
   return 0;
 }
 
-QVariant CoreSession::state() const { // FIXME
+void CoreSession::saveSessionState() const {
   QVariantMap res;
   QVariantMap res;
-  /*
-  QList<QVariant> conn;
-  foreach(NetworkConnection *net, connections.values()) {
-    if(net->isConnected()) {
-      QVariantMap m;
-      m["Network"] = net->networkName();
-      m["State"] = net->state();
-      conn << m;
-    }
+  QVariantList conn;
+  foreach(NetworkConnection *net, _connections.values()) {
+    QVariantMap m;
+    m["NetworkId"] = QVariant::fromValue<NetworkId>(net->networkId());
+    m["State"] = net->state();
+    conn << m;
   }
   }
-  res["ConnectedServers"] = conn;
-  */
-  return res;
+  res["CoreBuild"] = Global::quasselBuild;
+  res["ConnectedNetworks"] = conn;
+  CoreUserSettings s(user());
+  s.setSessionState(res);
 }
 
 }
 
-void CoreSession::restoreState(const QVariant &previousState) { // FIXME
-  // Session restore
-  /*
-  QVariantMap state = previousState.toMap();
-  if(state.contains("ConnectedServers")) {
-    foreach(QVariant v, state["ConnectedServers"].toList()) {
-      QVariantMap m = v.toMap();
-      QString net = m["Network"].toString();
-      if(!net.isEmpty()) connectToNetwork(net, m["State"]);
-    }
+void CoreSession::restoreSessionState() {
+  CoreUserSettings s(user());
+  uint build = s.sessionState().toMap()["CoreBuild"].toUInt();
+  if(build < 362) {
+    qWarning() << qPrintable(tr("Session state does not exist or is too old!"));
+    return;
+  }
+  QVariantList conn = s.sessionState().toMap()["ConnectedNetworks"].toList();
+  foreach(QVariant v, conn) {
+    NetworkId id = v.toMap()["NetworkId"].value<NetworkId>();
+    if(_networks.keys().contains(id)) connectToNetwork(id, v.toMap()["State"]);
   }
   }
-  */
 }
 
 
 }
 
 
@@ -225,8 +227,8 @@ void CoreSession::attachNetworkConnection(NetworkConnection *conn) {
   //connect(this, SIGNAL(disconnectFromIrc(QString)), network, SLOT(disconnectFromIrc(QString)));
   //connect(this, SIGNAL(msgFromGui(uint, QString, QString)), network, SLOT(userInput(uint, QString, QString)));
 
   //connect(this, SIGNAL(disconnectFromIrc(QString)), network, SLOT(disconnectFromIrc(QString)));
   //connect(this, SIGNAL(msgFromGui(uint, QString, QString)), network, SLOT(userInput(uint, QString, QString)));
 
-  //connect(conn, SIGNAL(connected(NetworkId)), this, SLOT(networkConnected(NetworkId)));
-  //connect(conn, SIGNAL(disconnected(NetworkId)), this, SLOT(networkDisconnected(NetworkId)));
+  connect(conn, SIGNAL(connected(NetworkId)), this, SLOT(networkConnected(NetworkId)));
+  connect(conn, SIGNAL(disconnected(NetworkId)), this, SLOT(networkDisconnected(NetworkId)));
   signalProxy()->attachSignal(conn, SIGNAL(connected(NetworkId)), SIGNAL(networkConnected(NetworkId)));
   signalProxy()->attachSignal(conn, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId)));
 
   signalProxy()->attachSignal(conn, SIGNAL(connected(NetworkId)), SIGNAL(networkConnected(NetworkId)));
   signalProxy()->attachSignal(conn, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId)));
 
@@ -256,13 +258,16 @@ SignalProxy *CoreSession::signalProxy() const {
   return _signalProxy;
 }
 
   return _signalProxy;
 }
 
-void CoreSession::networkConnected(uint networkid) {
+void CoreSession::networkConnected(NetworkId networkid) {
+  network(networkid)->setConnected(true);
   Core::bufferInfo(user(), networkConnection(networkid)->networkName()); // create status buffer
 }
 
   Core::bufferInfo(user(), networkConnection(networkid)->networkName()); // create status buffer
 }
 
-void CoreSession::networkDisconnected(uint networkid) {
+void CoreSession::networkDisconnected(NetworkId networkid) {
   // FIXME
   // connection should only go away on explicit /part, and handle reconnections etcpp internally otherwise
   // FIXME
   // connection should only go away on explicit /part, and handle reconnections etcpp internally otherwise
+  network(networkid)->setConnected(false);
+
   Q_ASSERT(_connections.contains(networkid));
   _connections.take(networkid)->deleteLater();
   Q_ASSERT(!_connections.contains(networkid));
   Q_ASSERT(_connections.contains(networkid));
   _connections.take(networkid)->deleteLater();
   Q_ASSERT(!_connections.contains(networkid));
index 1c8924a..01ffd8e 100644 (file)
@@ -37,7 +37,7 @@ class CoreSession : public QObject {
   Q_OBJECT
 
 public:
   Q_OBJECT
 
 public:
-  CoreSession(UserId, QObject *parent = 0);
+  CoreSession(UserId, bool restoreState, QObject *parent = 0);
   ~CoreSession();
 
   QList<BufferInfo> buffers() const;
   ~CoreSession();
 
   QList<BufferInfo> buffers() const;
@@ -56,8 +56,8 @@ public:
   void attachNetworkConnection(NetworkConnection *conn);
 
   //! Return necessary data for restoring the session after restarting the core
   void attachNetworkConnection(NetworkConnection *conn);
 
   //! Return necessary data for restoring the session after restarting the core
-  QVariant state() const;
-  void restoreState(const QVariant &previousState);
+  void saveSessionState() const;
+  void restoreSessionState();
 
 public slots:
   //! Store a piece session-wide data and distribute it to connected clients.
 
 public slots:
   //! Store a piece session-wide data and distribute it to connected clients.
@@ -122,8 +122,8 @@ signals:
 private slots:
   void recvStatusMsgFromServer(QString msg);
   void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
 private slots:
   void recvStatusMsgFromServer(QString msg);
   void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
-  void networkConnected(uint networkid);
-  void networkDisconnected(uint networkid);
+  void networkConnected(NetworkId networkid);
+  void networkDisconnected(NetworkId networkid);
 
   //! Called when storage updated a BufferInfo.
   /** This emits bufferInfoUpdated() via SignalProxy, iff it's one of our buffers.
 
   //! Called when storage updated a BufferInfo.
   /** This emits bufferInfoUpdated() via SignalProxy, iff it's one of our buffers.
index a858d57..d83d75f 100644 (file)
@@ -49,6 +49,14 @@ QList<IdentityId> CoreUserSettings::identityIds() {
   return res;
 }
 
   return res;
 }
 
+void CoreUserSettings::setSessionState(const QVariant &data) {
+  setLocalValue("SessionState", data);
+}
+
+QVariant CoreUserSettings::sessionState(const QVariant &def) {
+  return localValue("SessionState", def);
+}
+
 QVariantMap CoreUserSettings::sessionData() {
   QVariantMap res;
   foreach(QString key, localChildKeys(QString("SessionData"))) {
 QVariantMap CoreUserSettings::sessionData() {
   QVariantMap res;
   foreach(QString key, localChildKeys(QString("SessionData"))) {
index eee2e57..3a8c6b3 100644 (file)
@@ -38,6 +38,9 @@ class CoreUserSettings : public CoreSettings {
     Identity identity(IdentityId id);
     QList<IdentityId> identityIds();
 
     Identity identity(IdentityId id);
     QList<IdentityId> identityIds();
 
+    void setSessionState(const QVariant &data);
+    QVariant sessionState(const QVariant &def = QVariant());
+
   private:
     // this stuff should only be accessed by CoreSession!
     QVariantMap sessionData();
   private:
     // this stuff should only be accessed by CoreSession!
     QVariantMap sessionData();
index 803564b..0369c21 100644 (file)
@@ -183,6 +183,7 @@ void NetworkConnection::socketHasData() {
 }
 
 void NetworkConnection::socketError( QAbstractSocket::SocketError err ) {
 }
 
 void NetworkConnection::socketError( QAbstractSocket::SocketError err ) {
+  Q_UNUSED(err);
   qDebug() << "Socket Error!";
 }
 
   qDebug() << "Socket Error!";
 }
 
@@ -199,6 +200,7 @@ void NetworkConnection::socketConnected() {
 }
 
 void NetworkConnection::socketStateChanged(QAbstractSocket::SocketState state) {
 }
 
 void NetworkConnection::socketStateChanged(QAbstractSocket::SocketState state) {
+  Q_UNUSED(state);
   //qDebug() << "Socket state changed: " << state;
 }
 
   //qDebug() << "Socket state changed: " << state;
 }
 
index d507095..d178c2b 100644 (file)
 
 #include "coresession.h"
 
 
 #include "coresession.h"
 
-SessionThread::SessionThread(UserId uid, QObject *parent) : QThread(parent) {
+SessionThread::SessionThread(UserId uid, bool restoreState, QObject *parent) : QThread(parent) {
     _user = uid;
     _session = 0;
     _sessionInitialized = false;
     _user = uid;
     _session = 0;
     _sessionInitialized = false;
+    _restoreState = restoreState,
     connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized()));
 }
 
 SessionThread::~SessionThread() {
     connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized()));
 }
 
 SessionThread::~SessionThread() {
-  // FIXME
+  // shut down thread gracefully
   quit();
   wait();
   quit();
   wait();
-  if(session()) _session->deleteLater();
 }
 
 CoreSession *SessionThread::session() {
 }
 
 CoreSession *SessionThread::session() {
@@ -76,8 +76,9 @@ void SessionThread::addClientToSession(QIODevice *socket) {
 }
 
 void SessionThread::run() {
 }
 
 void SessionThread::run() {
-  _session = new CoreSession(user());
+  _session = new CoreSession(user(), _restoreState);
   emit initialized();
   exec();
   emit initialized();
   exec();
+  delete _session;
 }
 
 }
 
index ee29d2e..b6c340a 100644 (file)
@@ -33,7 +33,7 @@ class SessionThread : public QThread {
   Q_OBJECT
 
   public:
   Q_OBJECT
 
   public:
-    SessionThread(UserId user, QObject *parent = 0);
+    SessionThread(UserId user, bool restoreState, QObject *parent = 0);
     ~SessionThread();
 
     void run();
     ~SessionThread();
 
     void run();
@@ -49,12 +49,14 @@ class SessionThread : public QThread {
 
   signals:
     void initialized();
 
   signals:
     void initialized();
+    void shutdown();
 
   private:
     CoreSession *_session;
     UserId _user;
     QList<QIODevice *> clientQueue;
     bool _sessionInitialized;
 
   private:
     CoreSession *_session;
     UserId _user;
     QList<QIODevice *> clientQueue;
     bool _sessionInitialized;
+    bool _restoreState;
 
     bool isSessionInitialized();
     void addClientToSession(QIODevice *socket);
 
     bool isSessionInitialized();
     void addClientToSession(QIODevice *socket);
index 4a88192..f5426b0 100644 (file)
@@ -4,8 +4,8 @@
 { using namespace Global;
 
   quasselVersion = "0.2.0-pre";
 { using namespace Global;
 
   quasselVersion = "0.2.0-pre";
-  quasselDate = "2008-01-19";
-  quasselBuild = 360;
+  quasselDate = "2008-01-20";
+  quasselBuild = 362;
 
   //! Minimum client build number the core needs
   clientBuildNeeded = 358;
 
   //! Minimum client build number the core needs
   clientBuildNeeded = 358;