-CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent)
- : QObject(parent),
- user(uid),
- _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
- storage(_storage),
- scriptEngine(new QScriptEngine(this))
-{
-
- SignalProxy *p = signalProxy();
-
- SessionSettings s(user);
- sessionData = s.sessionData(); qDebug() << sessionData;
- /*
- QSettings s; // FIXME don't use QSettings anymore
- mutex.lock();
- s.beginGroup(QString("SessionData/%1").arg(user));
- foreach(QString key, s.allKeys()) { qDebug() << key;
- sessionData[key] = s.value(key);
- }
- s.endGroup();
- mutex.unlock(); // FIXME remove
- */
- /* temporarily disabled
- s.beginGroup(QString("Identities/%1").arg(user));
- foreach(QString id, s.childKeys()) {
- Identity *i = new Identity(s.value(id).value<Identity>(), this);
- if(i->id() < 1) {
- qDebug() << QString("Invalid identity!");
- continue;
- }
- if(_identities.contains(i->id())) {
- qDebug() << "Duplicate identity, ignoring!";
- continue;
- }
- qDebug() << "loaded identity" << id;
- _identities[i->id()] = i;
- }
- s.endGroup();
- mutex.unlock();
- if(!_identities.count()) {
- Identity i(1);
- i.setToDefaults();
- //_identities[i->id()] = i;
- createOrUpdateIdentity(i);
- }
- */
-
- p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(serverStateRequested()));
- p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString)));
- p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromGui(BufferInfo, QString)));
- p->attachSlot(SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)), this, SLOT(sendBacklog(BufferInfo, QVariant, QVariant)));
- p->attachSignal(this, SIGNAL(displayMsg(Message)));
- p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString)));
- p->attachSignal(this, SIGNAL(backlogData(BufferInfo, QVariantList, bool)));
- p->attachSignal(this, SIGNAL(bufferInfoUpdated(BufferInfo)));
- p->attachSignal(storage, SIGNAL(bufferInfoUpdated(BufferInfo)));
- 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 &)));
-
- p->attachSignal(this, SIGNAL(identityCreated(const Identity &)));
- p->attachSignal(this, SIGNAL(identityRemoved(IdentityId)));
- p->attachSlot(SIGNAL(createIdentity(const Identity &)), this, SLOT(createOrUpdateIdentity(const Identity &)));
- p->attachSlot(SIGNAL(updateIdentity(const Identity &)), this, SLOT(createOrUpdateIdentity(const Identity &)));
- p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId)));
-
- initScriptEngine();
-
- foreach(Identity *id, _identities.values()) {
- p->synchronize(id);
- }
-}
-
-CoreSession::~CoreSession() {
-}
-
-UserId CoreSession::userId() const {
- 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;
+class ProcessMessagesEvent : public QEvent
+{
+public:
+ ProcessMessagesEvent() : QEvent(QEvent::User) {}
+};
+
+
+CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent)
+ : QObject(parent),
+ _user(uid),
+ _signalProxy(new SignalProxy(SignalProxy::Server, this)),
+ _aliasManager(this),
+ _bufferSyncer(new CoreBufferSyncer(this)),
+ _backlogManager(new CoreBacklogManager(this)),
+ _bufferViewManager(new CoreBufferViewManager(_signalProxy, this)),
+ _dccConfig(new CoreDccConfig(this)),
+ _ircListHelper(new CoreIrcListHelper(this)),
+ _networkConfig(new CoreNetworkConfig("GlobalNetworkConfig", this)),
+ _coreInfo(this),
+ _transferManager(new CoreTransferManager(this)),
+ _eventManager(new CoreEventManager(this)),
+ _eventStringifier(new EventStringifier(this)),
+ _sessionEventProcessor(new CoreSessionEventProcessor(this)),
+ _ctcpParser(new CtcpParser(this)),
+ _ircParser(new IrcParser(this)),
+ scriptEngine(new QScriptEngine(this)),
+ _processMessages(false),
+ _ignoreListManager(this),
+ _highlightRuleManager(this)
+{
+ SignalProxy *p = signalProxy();
+ p->setHeartBeatInterval(30);
+ p->setMaxHeartBeatCount(60); // 30 mins until we throw a dead socket out
+
+ connect(p, SIGNAL(peerRemoved(Peer*)), SLOT(removeClient(Peer*)));
+
+ connect(p, SIGNAL(connected()), SLOT(clientsConnected()));
+ connect(p, SIGNAL(disconnected()), SLOT(clientsDisconnected()));
+
+ p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString)));
+ p->attachSignal(this, SIGNAL(displayMsg(Message)));
+ p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString)));
+
+ p->attachSignal(this, SIGNAL(identityCreated(const Identity &)));
+ p->attachSignal(this, SIGNAL(identityRemoved(IdentityId)));
+ p->attachSlot(SIGNAL(createIdentity(const Identity &, const QVariantMap &)), this, SLOT(createIdentity(const Identity &, const QVariantMap &)));
+ p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId)));
+
+ p->attachSignal(this, SIGNAL(networkCreated(NetworkId)));
+ p->attachSignal(this, SIGNAL(networkRemoved(NetworkId)));
+ p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &, const QStringList &)), this, SLOT(createNetwork(const NetworkInfo &, const QStringList &)));
+ p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId)));
+
+ p->attachSlot(SIGNAL(changePassword(PeerPtr,QString,QString,QString)), this, SLOT(changePassword(PeerPtr,QString,QString,QString)));
+ p->attachSignal(this, SIGNAL(passwordChanged(PeerPtr,bool)));
+
+ p->attachSlot(SIGNAL(kickClient(int)), this, SLOT(kickClient(int)));
+ p->attachSignal(this, SIGNAL(disconnectFromCore()));
+
+ loadSettings();
+ initScriptEngine();
+
+ eventManager()->registerObject(ircParser(), EventManager::NormalPriority);
+ eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier!
+ eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority);
+ eventManager()->registerObject(eventStringifier(), EventManager::NormalPriority);
+ eventManager()->registerObject(this, EventManager::LowPriority); // for sending MessageEvents to the client
+ // some events need to be handled after msg generation
+ eventManager()->registerObject(sessionEventProcessor(), EventManager::LowPriority, "lateProcess");
+ eventManager()->registerObject(ctcpParser(), EventManager::LowPriority, "send");
+
+ // periodically save our session state
+ connect(&(Core::instance()->syncTimer()), SIGNAL(timeout()), this, SLOT(saveSessionState()));
+
+ p->synchronize(_bufferSyncer);
+ p->synchronize(&aliasManager());
+ p->synchronize(_backlogManager);
+ p->synchronize(dccConfig());
+ p->synchronize(ircListHelper());
+ p->synchronize(networkConfig());
+ p->synchronize(&_coreInfo);
+ p->synchronize(&_ignoreListManager);
+ p->synchronize(&_highlightRuleManager);
+ p->synchronize(transferManager());
+ // Restore session state
+ if (restoreState)
+ restoreSessionState();
+
+ emit initialized();
+}
+
+
+CoreSession::~CoreSession()
+{
+ saveSessionState();
+
+ /* Why partially duplicate CoreNetwork destructor? When each CoreNetwork quits in the
+ * destructor, disconnections are processed in sequence for each object. For many IRC servers
+ * on a slow network, this could significantly delay core shutdown [msecs wait * network count].
+ *
+ * Here, CoreSession first calls disconnect on all networks, letting them all start
+ * disconnecting before beginning to sequentially wait for each network. Ideally, after the
+ * first network is disconnected, the other networks will have already closed. Worst-case may
+ * still wait [msecs wait time * num. of networks], but the risk should be much lower.
+ *
+ * CoreNetwork should still do cleanup in its own destructor in case a network is deleted
+ * outside of deleting the whole CoreSession.
+ *
+ * If this proves to be problematic in the future, there's an alternative Qt signal-based system
+ * implemented in another pull request that guarentees a maximum amount of time to disconnect,
+ * but at the cost of more complex code.
+ *
+ * See https://github.com/quassel/quassel/pull/203
+ */
+
+ foreach(CoreNetwork *net, _networks.values()) {
+ // Request each network properly disconnect, but don't count as user-requested disconnect
+ if (net->socketConnected()) {
+ // Only try if the socket's fully connected (not initializing or disconnecting).
+ // Force an immediate disconnect, jumping the command queue. Ensures the proper QUIT is
+ // shown even if other messages are queued.
+ net->disconnectFromIrc(false, QString(), false, true);
+ }