+void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState)
+{
+ QString text;
+
+ switch (socketState) {
+ case QAbstractSocket::UnconnectedState:
+ text = tr("Disconnected");
+ break;
+ case QAbstractSocket::HostLookupState:
+ text = tr("Looking up %1...").arg(currentAccount().hostName());
+ break;
+ case QAbstractSocket::ConnectingState:
+ text = tr("Connecting to %1...").arg(currentAccount().hostName());
+ break;
+ case QAbstractSocket::ConnectedState:
+ text = tr("Connected to %1").arg(currentAccount().hostName());
+ break;
+ case QAbstractSocket::ClosingState:
+ text = tr("Disconnecting from %1...").arg(currentAccount().hostName());
+ break;
+ default:
+ break;
+ }
+
+ if (!text.isEmpty())
+ emit progressTextChanged(text);
+
+ setState(socketState);
+}
+
+
+void CoreConnection::setState(QAbstractSocket::SocketState socketState)
+{
+ ConnectionState state;
+
+ switch (socketState) {
+ case QAbstractSocket::UnconnectedState:
+ state = Disconnected;
+ break;
+ case QAbstractSocket::HostLookupState:
+ case QAbstractSocket::ConnectingState:
+ case QAbstractSocket::ConnectedState: // we'll set it to Connected in connectionReady()
+ state = Connecting;
+ break;
+ default:
+ state = Disconnected;
+ }
+
+ setState(state);
+}
+
+
+void CoreConnection::setState(ConnectionState state)
+{
+ if (state != _state) {
+ _state = state;
+ emit stateChanged(state);
+ if (state == Disconnected)
+ emit disconnected();
+ }
+}
+
+
+void CoreConnection::coreSocketError(QAbstractSocket::SocketError)
+{
+ disconnectFromCore(_socket->errorString(), true);
+}
+
+
+void CoreConnection::coreSocketDisconnected()
+{
+ _wasReconnect = !_requestedDisconnect;
+ resetConnection(true);
+ // FIXME handle disconnects gracefully
+}
+
+
+// note: this still expects the legacy protocol
+// noteĀ²: after cleaning this up, we can probably get rid of _socket altogether
+void CoreConnection::coreHasData(const QVariant &item)
+{
+ QVariantMap msg = item.toMap();
+ if (!msg.contains("MsgType")) {
+ // This core is way too old and does not even speak our init protocol...
+ emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
+ disconnectFromCore(QString(), false);
+ return;
+ }
+ if (msg["MsgType"] == "ClientInitAck") {
+ clientInitAck(msg);
+ }
+ else if (msg["MsgType"] == "ClientInitReject") {
+ emit connectionErrorPopup(msg["Error"].toString());
+ disconnectFromCore(QString(), false);
+ return;
+ }
+ else if (msg["MsgType"] == "CoreSetupAck") {
+ emit coreSetupSuccess();
+ }
+ else if (msg["MsgType"] == "CoreSetupReject") {
+ emit coreSetupFailed(msg["Error"].toString());
+ }
+ else if (msg["MsgType"] == "ClientLoginReject") {
+ loginFailed(msg["Error"].toString());
+ }
+ else if (msg["MsgType"] == "ClientLoginAck") {
+ loginSuccess();
+ }
+ else if (msg["MsgType"] == "SessionInit") {
+ // that's it, let's hand over to the signal proxy
+ // if the connection is an orphan, the signalProxy adopts it.
+ // -> we don't need to care about it anymore
+
+ disconnect(_peer, 0, this, 0);
+
+ _peer->setParent(0);
+ Client::signalProxy()->addPeer(_peer);
+
+ sessionStateReceived(msg["SessionState"].toMap());
+ }
+ else {
+ disconnectFromCore(tr("Invalid data received from core"), false);
+ return;
+ }
+}
+
+
+void CoreConnection::disconnectFromCore()
+{
+ if (_socket) {
+ _requestedDisconnect = true;
+ disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect
+ }
+}
+
+
+void CoreConnection::disconnectFromCore(const QString &errorString, bool wantReconnect)
+{
+ if (!wantReconnect)
+ _reconnectTimer.stop();
+
+ _wasReconnect = wantReconnect; // store if disconnect was requested
+
+ resetConnection(wantReconnect);
+
+ if (errorString.isEmpty())
+ emit connectionError(tr("Disconnected"));
+ else
+ emit connectionError(errorString);
+}
+
+
+void CoreConnection::resetConnection(bool wantReconnect)
+{
+ if (_resetting)
+ return;
+ _resetting = true;
+
+ _wantReconnect = wantReconnect;
+
+ if (_peer) {
+ disconnect(_socket, 0, this, 0);
+ disconnect(_peer, 0, this, 0);
+ _peer->close();
+
+ if (_peer->parent() == this)
+ _peer->deleteLater(); // if it's not us, it belongs to the sigproxy which will delete it
+ _socket = 0; // socket is owned and will be deleted by RemoteConnection
+ _peer = 0;