From 6f2f1723f5bb3d26908f6dd297890f6fba43793b Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Sun, 20 Jan 2008 03:21:12 +0000 Subject: [PATCH] Bringing back session save/restore. Old state won't be imported, unfortunately, 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. --- src/common/network.cpp | 10 ++++++ src/common/network.h | 7 +++- src/core/core.cpp | 55 ++++++++++++----------------- src/core/core.h | 2 +- src/core/coresession.cpp | 63 ++++++++++++++++++---------------- src/core/coresession.h | 10 +++--- src/core/coreusersettings.cpp | 8 +++++ src/core/coreusersettings.h | 3 ++ src/core/networkconnection.cpp | 2 ++ src/core/sessionthread.cpp | 9 ++--- src/core/sessionthread.h | 4 ++- version.inc | 4 +-- 12 files changed, 101 insertions(+), 76 deletions(-) diff --git a/src/common/network.cpp b/src/common/network.cpp index 1b3ab308..982011be 100644 --- a/src/common/network.cpp +++ b/src/common/network.cpp @@ -37,6 +37,7 @@ Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(p _myNick(QString()), _networkName(QString("")), _currentServer(QString()), + _connected(false), _prefixes(QString()), _prefixModes(QString()), _proxy(0), @@ -86,6 +87,10 @@ bool Network::isChannelName(const QString &channelname) const { 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)]); @@ -327,6 +332,11 @@ void Network::setCurrentServer(const QString ¤tServer) { emit currentServerSet(currentServer); } +void Network::setConnected(bool connected) { + _connected = connected; + emit connectedSet(connected); +} + void Network::setMyNick(const QString &nickname) { _myNick = nickname; emit myNickSet(nickname); diff --git a/src/common/network.h b/src/common/network.h index 6a58d841..80131fac 100644 --- a/src/common/network.h +++ b/src/common/network.h @@ -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(bool isConnected READ isConnected STORED false) + Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected STORED false) public: Network(const NetworkId &networkid, QObject *parent = 0); @@ -64,6 +64,8 @@ public: bool isChannelName(const QString &channelname) const; + bool isConnected() const; + 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 ¤tServer); + void setConnected(bool isConnected); void setMyNick(const QString &mynick); void setIdentity(IdentityId); @@ -152,6 +155,7 @@ private slots: signals: void networkNameSet(const QString &networkName); void currentServerSet(const QString ¤tServer); + void connectedSet(bool isConnected); void myNickSet(const QString &mynick); void identitySet(IdentityId); @@ -186,6 +190,7 @@ private: QString _myNick; QString _networkName; QString _currentServer; + bool _connected; QString _prefixes; QString _prefixModes; diff --git a/src/core/core.cpp b/src/core/core.cpp index 298d7e35..e222a137 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -95,37 +95,35 @@ Core::~Core() { } 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; - QList 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..."; - 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(); + instance()->createSession(user, true); } qDebug() << "...done."; } - */ } void Core::saveState() { - /* CoreSettings s; - QList 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(user); + state["CoreBuild"] = Global::quasselBuild; + state["ActiveSessions"] = activeSessions; + s.setCoreState(state); } /*** Storage Access ***/ @@ -308,15 +306,6 @@ void Core::clientDisconnected() { // 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; @@ -366,12 +355,12 @@ void Core::setupClientSession(QTcpSocket *socket, UserId uid) { 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; } - SessionThread *sess = new SessionThread(uid, this); + SessionThread *sess = new SessionThread(uid, restore, this); sessions[uid] = sess; sess->start(); return sess; diff --git a/src/core/core.h b/src/core/core.h index 76693176..67f6dec8 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -139,7 +139,7 @@ class Core : public QObject { 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); diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index c34e8988..910bca14 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -35,7 +35,7 @@ #include -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)) @@ -113,10 +113,14 @@ CoreSession::CoreSession(UserId uid, QObject *parent) : QObject(parent), p->synchronize(net); } + // Restore session state + if(restoreState) restoreSessionState(); + emit initialized(); } CoreSession::~CoreSession() { + saveSessionState(); } UserId CoreSession::user() const { @@ -138,35 +142,33 @@ Identity *CoreSession::identity(IdentityId id) const { return 0; } -QVariant CoreSession::state() const { // FIXME +void CoreSession::saveSessionState() const { QVariantMap res; - /* - QList 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(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(); + 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(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))); @@ -256,13 +258,16 @@ SignalProxy *CoreSession::signalProxy() const { 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 } -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 + network(networkid)->setConnected(false); + Q_ASSERT(_connections.contains(networkid)); _connections.take(networkid)->deleteLater(); Q_ASSERT(!_connections.contains(networkid)); diff --git a/src/core/coresession.h b/src/core/coresession.h index 1c8924ab..01ffd8e8 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -37,7 +37,7 @@ class CoreSession : public QObject { Q_OBJECT public: - CoreSession(UserId, QObject *parent = 0); + CoreSession(UserId, bool restoreState, QObject *parent = 0); ~CoreSession(); QList buffers() const; @@ -56,8 +56,8 @@ public: 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. @@ -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); - 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. diff --git a/src/core/coreusersettings.cpp b/src/core/coreusersettings.cpp index a858d570..d83d75f2 100644 --- a/src/core/coreusersettings.cpp +++ b/src/core/coreusersettings.cpp @@ -49,6 +49,14 @@ QList CoreUserSettings::identityIds() { 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"))) { diff --git a/src/core/coreusersettings.h b/src/core/coreusersettings.h index eee2e573..3a8c6b39 100644 --- a/src/core/coreusersettings.h +++ b/src/core/coreusersettings.h @@ -38,6 +38,9 @@ class CoreUserSettings : public CoreSettings { Identity identity(IdentityId id); QList identityIds(); + void setSessionState(const QVariant &data); + QVariant sessionState(const QVariant &def = QVariant()); + private: // this stuff should only be accessed by CoreSession! QVariantMap sessionData(); diff --git a/src/core/networkconnection.cpp b/src/core/networkconnection.cpp index 803564b6..0369c213 100644 --- a/src/core/networkconnection.cpp +++ b/src/core/networkconnection.cpp @@ -183,6 +183,7 @@ void NetworkConnection::socketHasData() { } void NetworkConnection::socketError( QAbstractSocket::SocketError err ) { + Q_UNUSED(err); qDebug() << "Socket Error!"; } @@ -199,6 +200,7 @@ void NetworkConnection::socketConnected() { } void NetworkConnection::socketStateChanged(QAbstractSocket::SocketState state) { + Q_UNUSED(state); //qDebug() << "Socket state changed: " << state; } diff --git a/src/core/sessionthread.cpp b/src/core/sessionthread.cpp index d5070955..d178c2bb 100644 --- a/src/core/sessionthread.cpp +++ b/src/core/sessionthread.cpp @@ -24,18 +24,18 @@ #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; + _restoreState = restoreState, connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized())); } SessionThread::~SessionThread() { - // FIXME + // shut down thread gracefully quit(); wait(); - if(session()) _session->deleteLater(); } CoreSession *SessionThread::session() { @@ -76,8 +76,9 @@ void SessionThread::addClientToSession(QIODevice *socket) { } void SessionThread::run() { - _session = new CoreSession(user()); + _session = new CoreSession(user(), _restoreState); emit initialized(); exec(); + delete _session; } diff --git a/src/core/sessionthread.h b/src/core/sessionthread.h index ee29d2e3..b6c340a3 100644 --- a/src/core/sessionthread.h +++ b/src/core/sessionthread.h @@ -33,7 +33,7 @@ class SessionThread : public QThread { Q_OBJECT public: - SessionThread(UserId user, QObject *parent = 0); + SessionThread(UserId user, bool restoreState, QObject *parent = 0); ~SessionThread(); void run(); @@ -49,12 +49,14 @@ class SessionThread : public QThread { signals: void initialized(); + void shutdown(); private: CoreSession *_session; UserId _user; QList clientQueue; bool _sessionInitialized; + bool _restoreState; bool isSessionInitialized(); void addClientToSession(QIODevice *socket); diff --git a/version.inc b/version.inc index 4a88192d..f5426b06 100644 --- a/version.inc +++ b/version.inc @@ -4,8 +4,8 @@ { 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; -- 2.20.1