everybody has joined, and restores this information upon restart (so all networks will
automagically connected and the appropriate channels rejoined).
Has not been tested with more than one active CoreSessions.
You can start the core without session restore by using --norestore as parameter.
Closes BR #63.
src/uisupport/nickview.cpp
src/uisupport/nickview.h
src/uisupport/settingspage.cpp
+src/uisupport/settingspage.h
src/uisupport/tabcompleter.cpp
src/uisupport/tabcompleter.h
+src/uisupport/uisettings.cpp
+src/uisupport/uisettings.h
src/uisupport/uistyle.cpp
src/uisupport/uistyle.h
src/uisupport/uisupport.pri
gui->init();
#endif
+#ifndef BUILD_QTUI
+ if(!QCoreApplication::arguments().contains("--norestore")) {
+ Core::restoreState();
+ }
+#endif
+
int exitCode = app.exec();
+#ifndef BUILD_QTUI
+ Core::saveState();
+#endif
+
#ifndef BUILD_CORE
// the mainWin has to be deleted before the Core
// if not Quassel will crash on exit under certain conditions since the gui
}
bool NetworkInfo::isMyNick(IrcUser *ircuser) const {
- return (ircuser->nick().toLower() == myNick());
+ return (ircuser->nick().toLower() == myNick().toLower());
}
bool NetworkInfo::isChannelName(const QString &channelname) const {
#include <QVariantMap>
#include <QPointer>
+#include "types.h"
+
class SignalProxy;
class IrcUser;
class IrcChannel;
NetworkInfo(const uint &networkid, QObject *parent = 0);
//virtual ~NetworkInfo();
- uint networkId() const;
+ NetworkId networkId() const;
bool initialized() const;
SignalProxy *proxy() const;
connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
startListening(s.port());
guiUser = 0;
+
}
bool Core::initStorageSqlite(QVariantMap dbSettings, bool setup) {
}
}
+void Core::restoreState() {
+ Q_ASSERT(!instance()->sessions.count());
+ CoreSettings s;
+ QList<QVariant> users = s.coreState().toList();
+ if(users.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"]);
+ }
+ }
+ }
+}
+
+void Core::saveState() {
+ CoreSettings s;
+ QList<QVariant> users;
+ foreach(CoreSession *sess, instance()->sessions.values()) {
+ QVariantMap m;
+ m["UserId"] = sess->userId();
+ m["State"] = sess->state();
+ users << m;
+ }
+ s.setCoreState(users);
+}
+
CoreSession *Core::session(UserId uid) {
Core *core = instance();
if(core->sessions.contains(uid)) return core->sessions[uid];
static QVariant connectLocalClient(QString user, QString passwd);
static void disconnectLocalClient();
+ static void saveState();
+ static void restoreState();
+
private slots:
bool startListening(uint port = DEFAULT_PORT);
void stopListening();
p->attachSignal(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)));
p->attachSlot(SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &)));
/* Autoconnect. (When) do we actually do this?
+ --> session restore should be enough!
QStringList list;
QVariantMap networks = retrieveSessionData("Networks").toMap();
foreach(QString net, networks.keys()) {
} qDebug() << list;
if(list.count()) connectToIrc(list);
*/
+
}
CoreSession::~CoreSession() {
return user;
}
+QVariant CoreSession::state() const {
+ QVariantMap res;
+ QList<QVariant> conn;
+ foreach(Server *server, servers.values()) {
+ if(server->isConnected()) {
+ QVariantMap m;
+ m["Network"] = server->networkName();
+ m["State"] = server->state();
+ conn << m;
+ }
+ }
+ res["ConnectedServers"] = conn;
+ return res;
+}
+
+void CoreSession::restoreState(const QVariant &previousState) {
+ // 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::storeSessionData(const QString &key, const QVariant &data) {
QSettings s;
s.beginGroup(QString("SessionData/%1").arg(user));
}
// FIXME switch to NetworkIDs
-void CoreSession::connectToNetwork(QString network) {
+void CoreSession::connectToNetwork(QString network, const QVariant &previousState) {
uint networkid = getNetworkId(network);
if(networkid == 0) {
qWarning() << "unable to connect to Network" << network << "(User:" << userId() << "): unable to determine NetworkId";
return;
}
if(!servers.contains(networkid)) {
- Server *server = new Server(userId(), networkid, network);
+ Server *server = new Server(userId(), networkid, network, previousState);
servers[networkid] = server;
attachServer(server);
server->start();
CoreSession(UserId, Storage *, QObject *parent = 0);
virtual ~CoreSession();
- uint getNetworkId(const QString &network) const;
+ NetworkId getNetworkId(const QString &network) const;
QList<BufferInfo> buffers() const;
UserId userId() const;
QVariant sessionState();
//! Retrieve a piece of session-wide data.
QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
-
+
SignalProxy *signalProxy() const;
-
+
void attachServer(Server *server);
-
+
+ //! Return necessary data for restoring the session after restarting the core
+ QVariant state() const;
+ void restoreState(const QVariant &previousState);
+
public slots:
//! Store a piece session-wide data and distribute it to connected clients.
void storeSessionData(const QString &key, const QVariant &data);
void serverStateRequested();
void addClient(QIODevice *connection);
-
- void connectToNetwork(QString);
-
+
+ void connectToNetwork(QString, const QVariant &previousState = QVariant());
+ //void connectToNetwork(NetworkId);
+
//void processSignal(ClientSignal, QVariant, QVariant, QVariant);
void sendBacklog(BufferInfo, QVariant, QVariant);
void msgFromGui(BufferInfo, QString message);
-
+
signals:
void msgFromGui(uint netid, QString buf, QString message);
void displayMsg(Message message);
void displayStatusMsg(QString, QString);
-
+
void connectToIrc(QString net);
void disconnectFromIrc(QString net);
SignalProxy *_signalProxy;
Storage *storage;
- QHash<uint, Server *> servers;
+ QHash<NetworkId, Server *> servers;
QVariantMap sessionData;
QMutex mutex;
return localValue("Port", def).toUInt();
}
+void CoreSettings::setCoreState(const QVariant &data) {
+ setLocalValue("CoreState", data);
+}
+
+QVariant CoreSettings::coreState(const QVariant &def) {
+ return localValue("CoreState", def);
+}
+
QStringList CoreSettings::sessionKeys() {
Q_ASSERT(false);
return QStringList();
#include "settings.h"
class CoreSettings : public Settings {
-
+
public:
virtual ~CoreSettings();
CoreSettings();
-
+
void setDatabaseSettings(const QVariant &data);
QVariant databaseSettings(const QVariant &def = QVariant());
-
+
void setPort(const uint &port);
uint port(const uint &def = DEFAULT_PORT);
-
+
+ void setCoreState(const QVariant &data);
+ QVariant coreState(const QVariant &def = QVariant());
+
private:
//virtual QStringList allSessionKeys() = 0;
virtual QStringList sessionKeys();
-
+
virtual void setSessionValue(const QString &key, const QVariant &data);
virtual QVariant sessionValue(const QString &key, const QVariant &def = QVariant());
};
networkInfo()->setMyNick(nickFromMask(myhostmask));
emit displayMsg(Message::Server, "", params[0], prefix);
+
// TODO: reimplement perform List!
//// send performlist
#include "core.h"
#include "coresession.h"
+#include "ircuser.h"
#include "networkinfo.h"
#include "ircserverhandler.h"
#include "userinputhandler.h"
#include "ctcphandler.h"
-Server::Server(UserId uid, uint networkId, QString net)
+Server::Server(UserId uid, NetworkId networkId, QString net, const QVariant &state)
: _userId(uid),
_networkId(networkId),
_ircServerHandler(new IrcServerHandler(this)),
_userInputHandler(new UserInputHandler(this)),
_ctcpHandler(new CtcpHandler(this)),
- _networkInfo(new NetworkInfo(networkId, this))
+ _networkInfo(new NetworkInfo(networkId, this)),
+ _previousState(state)
{
+ connect(networkInfo(), SIGNAL(currentServerSet(const QString &)), this, SLOT(sendPerform()));
networkInfo()->setNetworkName(net);
networkInfo()->setProxy(coreSession()->signalProxy());
}
socket.connectToHost(host, port);
}
+void Server::sendPerform() {
+ // TODO: reimplement perform List!
+ //// send performlist
+ //QStringList performList = networkSettings["Perform"].toString().split( "\n" );
+ //int count = performList.count();
+ //for(int a = 0; a < count; a++) {
+ // if(!performList[a].isEmpty() ) {
+ // userInput(network, "", performList[a]);
+ // }
+ //}
+
+ // rejoin channels we've been in
+ QStringList chans = _previousState.toStringList();
+ if(chans.count() > 0) {
+ qDebug() << "autojoining" << chans;
+ QString list = chans.join(",");
+ putCmd("join", QStringList(list));
+ }
+ // delete _previousState, we won't need it again
+ _previousState = QVariant();
+}
+
+QVariant Server::state() {
+ IrcUser *me = networkInfo()->ircUser(networkInfo()->myNick());
+ if(!me) return QVariant(); // this shouldn't really happen, I guess
+ return me->channels();
+}
+
void Server::disconnectFromIrc(QString net) {
if(net != networkName())
return; // not me!
return _networkId;
}
-QString Server::networkName() {
+QString Server::networkName() const {
return networkInfo()->networkName();
}
Q_OBJECT
public:
- Server(UserId uid, uint networkId, QString network);
+ Server(UserId uid, NetworkId networkId, QString network, const QVariant &previousState = QVariant());
~Server();
UserId userId() const { return _userId; }
// serverState state();
bool isConnected() const { return socket.state() == QAbstractSocket::ConnectedState; }
- uint networkId() const;
- QString networkName(); // hasbeen getNetwork()
+ NetworkId networkId() const;
+ QString networkName() const; // hasbeen getNetwork()
- NetworkInfo *networkInfo() { return _networkInfo; }
- IrcServerHandler *ircServerHandler() {return _ircServerHandler; }
- UserInputHandler *userInputHandler() {return _userInputHandler; }
- CtcpHandler *ctcpHandler() {return _ctcpHandler; }
+ NetworkInfo *networkInfo() const { return _networkInfo; }
+ IrcServerHandler *ircServerHandler() const { return _ircServerHandler; }
+ UserInputHandler *userInputHandler() const { return _userInputHandler; }
+ CtcpHandler *ctcpHandler() const { return _ctcpHandler; }
+
+ QVariant state(); ///< Return data necessary to restore the server's state upon core restart
public slots:
// void setServerOptions();
private slots:
void threadFinished();
+ void sendPerform();
signals:
void serverState(QString net, QVariantMap data);
void connected(uint networkId);
void disconnected(uint networkId);
+ void connectionInitialized(); ///< Emitted after receipt of 001 to indicate that we can now send data to the IRC server
+
void synchronizeClients();
void queryRequested(QString network, QString nick);
private:
UserId _userId;
- uint _networkId;
+ NetworkId _networkId;
QTcpSocket socket;
QVariantMap networkSettings;
QVariantMap identity;
+ QVariant _previousState;
+
CoreSession *coreSession() const;
class ParseError : public Exception {
connect(ui.actionNetworkList, SIGNAL(triggered()), this, SLOT(showServerList()));
connect(ui.actionEditIdentities, SIGNAL(triggered()), serverListDlg, SLOT(editIdentities()));
connect(ui.actionSettingsDlg, SIGNAL(triggered()), this, SLOT(showSettingsDlg()));
- ui.actionSettingsDlg->setEnabled(false);
+ //ui.actionSettingsDlg->setEnabled(false);
connect(ui.actionAboutQt, SIGNAL(triggered()), QApplication::instance(), SLOT(aboutQt()));
}
<item>
<widget class="QStackedWidget" name="settingsStack" >
<property name="sizePolicy" >
- <sizepolicy vsizetype="Preferred" hsizetype="MinimumExpanding" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>