Add Qt-based connection detection
[quassel.git] / src / client / coreconnection.cpp
index d077e24..735fab4 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2013 by the Quassel Project                        *
+ *   Copyright (C) 2005-2015 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -43,7 +43,8 @@ CoreConnection::CoreConnection(QObject *parent)
     _progressMinimum(0),
     _progressMaximum(-1),
     _progressValue(-1),
-    _resetting(false)
+    _resetting(false),
+    _qNetworkConfigurationManager(0)
 {
     qRegisterMetaType<ConnectionState>("CoreConnection::ConnectionState");
 }
@@ -57,10 +58,12 @@ void CoreConnection::init()
     _reconnectTimer.setSingleShot(true);
     connect(&_reconnectTimer, SIGNAL(timeout()), SLOT(reconnectTimeout()));
 
-#ifdef HAVE_KDE
+#ifdef HAVE_KDE4
     connect(Solid::Networking::notifier(), SIGNAL(statusChanged(Solid::Networking::Status)),
         SLOT(solidNetworkStatusChanged(Solid::Networking::Status)));
 #endif
+    _qNetworkConfigurationManager = new QNetworkConfigurationManager(this);
+    connect(_qNetworkConfigurationManager, SIGNAL(onlineStateChanged(bool)), SLOT(onlineStateChanged(bool)));
 
     CoreConnectionSettings s;
     s.initAndNotify("PingTimeoutInterval", this, SLOT(pingTimeoutIntervalChanged(QVariant)), 60);
@@ -127,7 +130,7 @@ void CoreConnection::reconnectTimeout()
     if (!_peer) {
         CoreConnectionSettings s;
         if (_wantReconnect && s.autoReconnect()) {
-#ifdef HAVE_KDE
+#ifdef HAVE_KDE4
             // If using Solid, we don't want to reconnect if we're offline
             if (s.networkDetectionMode() == CoreConnectionSettings::UseSolid) {
                 if (Solid::Networking::status() != Solid::Networking::Connected
@@ -135,7 +138,13 @@ void CoreConnection::reconnectTimeout()
                     return;
                 }
             }
-#endif /* HAVE_KDE */
+#endif /* HAVE_KDE4 */
+            // If using QNetworkConfigurationManager, ditto
+            if (s.networkDetectionMode() == CoreConnectionSettings::UseQNetworkConfigurationManager) {
+               if (!_qNetworkConfigurationManager->isOnline()) {
+                    return;
+               }
+            }
 
             reconnectToCore();
         }
@@ -169,7 +178,7 @@ void CoreConnection::reconnectIntervalChanged(const QVariant &interval)
 }
 
 
-#ifdef HAVE_KDE
+#ifdef HAVE_KDE4
 
 void CoreConnection::solidNetworkStatusChanged(Solid::Networking::Status status)
 {
@@ -199,6 +208,26 @@ void CoreConnection::solidNetworkStatusChanged(Solid::Networking::Status status)
 
 #endif
 
+void CoreConnection::onlineStateChanged(bool isOnline)
+{
+    CoreConnectionSettings s;
+    if (s.networkDetectionMode() != CoreConnectionSettings::UseQNetworkConfigurationManager)
+        return;
+
+    if(isOnline) {
+        // qDebug() << "QNetworkConfigurationManager reports Online";
+        if (state() == Disconnected) {
+            if (_wantReconnect && s.autoReconnect()) {
+                reconnectToCore();
+            }
+        }
+    } else {
+        // qDebug() << "QNetworkConfigurationManager reports Offline";
+        if (state() != Disconnected && !isLocalConnection())
+            disconnectFromCore(tr("Network is down"), true);
+    }
+}
+
 bool CoreConnection::isEncrypted() const
 {
     return _peer && _peer->isSecure();
@@ -211,65 +240,15 @@ bool CoreConnection::isLocalConnection() const
         return false;
     if (currentAccount().isInternal())
         return true;
-    if (_peer->isLocal())
-        return true;
+    if (_authHandler)
+        return _authHandler->isLocal();
+    if (_peer)
+        return _peer->isLocal();
 
     return false;
 }
 
 
-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::onConnectionReady()
 {
     setState(Connected);
@@ -297,9 +276,9 @@ void CoreConnection::coreSocketError(QAbstractSocket::SocketError error, const Q
 
 void CoreConnection::coreSocketDisconnected()
 {
+    setState(Disconnected);
     _wasReconnect = false;
     resetConnection(_wantReconnect);
-    // FIXME handle disconnects gracefully
 }
 
 
@@ -362,6 +341,7 @@ void CoreConnection::resetConnection(bool wantReconnect)
 
     emit connectionMsg(tr("Disconnected from core."));
     emit encrypted(false);
+    setState(Disconnected);
 
     // initiate if a reconnect if appropriate
     CoreConnectionSettings s;
@@ -429,8 +409,6 @@ void CoreConnection::connectToCurrentAccount()
         return;
     }
 
-    resetConnection(false);
-
     if (currentAccount().isInternal()) {
         if (Quassel::runMode() != Quassel::Monolithic) {
             qWarning() << "Cannot connect to internal core in client-only mode!";
@@ -442,6 +420,7 @@ void CoreConnection::connectToCurrentAccount()
         _peer = peer;
         Client::instance()->signalProxy()->addPeer(peer); // sigproxy will take ownership
         emit connectToInternalCore(peer);
+        setState(Connected);
 
         return;
     }
@@ -450,7 +429,6 @@ void CoreConnection::connectToCurrentAccount()
 
     connect(_authHandler, SIGNAL(disconnected()), SLOT(coreSocketDisconnected()));
     connect(_authHandler, SIGNAL(connectionReady()), SLOT(onConnectionReady()));
-    connect(_authHandler, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState)));
     connect(_authHandler, SIGNAL(socketError(QAbstractSocket::SocketError,QString)), SLOT(coreSocketError(QAbstractSocket::SocketError,QString)));
     connect(_authHandler, SIGNAL(transferProgress(int,int)), SLOT(updateProgress(int,int)));
     connect(_authHandler, SIGNAL(requestDisconnect(QString,bool)), SLOT(disconnectFromCore(QString,bool)));
@@ -472,6 +450,7 @@ void CoreConnection::connectToCurrentAccount()
     connect(_authHandler, SIGNAL(loginSuccessful(CoreAccount)), SLOT(onLoginSuccessful(CoreAccount)));
     connect(_authHandler, SIGNAL(handshakeComplete(RemotePeer*,Protocol::SessionState)), SLOT(onHandshakeComplete(RemotePeer*,Protocol::SessionState)));
 
+    setState(Connecting);
     _authHandler->connectToCore();
 }
 
@@ -514,7 +493,7 @@ void CoreConnection::onHandshakeComplete(RemotePeer *peer, const Protocol::Sessi
 
     _peer = peer;
     connect(peer, SIGNAL(disconnected()), SLOT(coreSocketDisconnected()));
-    connect(peer, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState)));
+    connect(peer, SIGNAL(statusMessage(QString)), SIGNAL(connectionMsg(QString)));
     connect(peer, SIGNAL(socketError(QAbstractSocket::SocketError,QString)), SLOT(coreSocketError(QAbstractSocket::SocketError,QString)));
 
     Client::signalProxy()->addPeer(_peer);  // sigproxy takes ownership of the peer!