Unnecessary includes removed.
[jenirok] / src / common / connectionmanager.cpp
index 07f277e..d6bddff 100644 (file)
  *
  */
 
-#include <QDebug>
-#include <QApplication>
+#include <QtCore/QDebug>
 #include <QtCore/QTimerEvent>
 #include <QtCore/QVariant>
+#include <QtCore/QStringList>
+#include <QtGui/QApplication>
+#include <QtDBus/QDBusArgument>
+#include <QtDBus/QDBusConnection>
 #include <icd/dbus_api.h>
 #include "connectionmanager.h"
 
 
 ConnectionManager::ConnectionManager(QObject* parent): QObject(parent),
-ready_(false), connected_(false), timeout_(false), ignoreStateChanges_(false),
-timer_(0)
+blocking_(true), stateReady_(false), connectionReady_(false), scanReady_(false),
+connected_(false), timeout_(false), numberOfConnections_(0),
+scannedConnections_(0), timer_(0), error_(NO_ERROR), connections_(0)
 {
     QDBusConnection systemBus = QDBusConnection::systemBus();
 
@@ -42,6 +46,9 @@ timer_(0)
                       ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
                       this, SLOT(connectionChange(const QDBusMessage&)));
 
+    systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+                      ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
+                      this, SLOT(scanResult(const QDBusMessage&)));
 
 }
 
@@ -56,28 +63,162 @@ ConnectionManager::~ConnectionManager()
     systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
                          ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
                          this, SLOT(connectionChange(const QDBusMessage&)));
+
+    systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+                         ICD_DBUS_API_INTERFACE, ICD_DBUS_API_SCAN_SIG,
+                         this, SLOT(scanResult(const QDBusMessage&)));
+}
+
+void ConnectionManager::setBlocking(bool value)
+{
+    blocking_ = value;
 }
 
 bool ConnectionManager::connect()
 {
-    ready_ = false;
-    ignoreStateChanges_ = true;
+    connectionReady_ = false;
     unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
     icd2interface_->call(ICD_DBUS_API_CONNECT_REQ, QVariant(flags));
-    waitSignal();
-    return connected_;
+
+    if(blocking_)
+    {
+        waitSignal(&connectionReady_);
+        return connected_;
+    }
+
+    return true;
+}
+
+bool ConnectionManager::connect(ConnectionManager::Connection const& connection)
+{
+    return connect(connection.id);
 }
 
-bool ConnectionManager::disconnect()
+bool ConnectionManager::connect(QString const& id)
 {
-    if(!connected_)
+    QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.icd",
+                                                      "/com/nokia/icd",
+                                                      "com.nokia.icd",
+                                                      "connect");
+    QList<QVariant> arguments;
+
+    arguments.append(QVariant(id));
+
+    unsigned int val = 0;
+
+    arguments.append(QVariant(val));
+
+    msg.setArguments(arguments);
+
+    QDBusMessage rep = QDBusConnection::systemBus().call(msg);
+
+    if(rep.type() == QDBusMessage::ErrorMessage)
     {
+        if(rep.errorName() == "com.nokia.icd.error.invalid_iap")
+        {
+            error_ = INVALID_IAP;
+        }
+        else
+        {
+            error_ = UNKNOWN_ERROR;
+        }
+
         return false;
     }
 
-    ready_ = false;
-    ignoreStateChanges_ = false;
-    unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
+    return true;
+}
+
+bool ConnectionManager::getBestConnection(Connection& connection, ConnectionType type)
+{
+    bool blockingValue = blocking_;
+
+    blocking_ = true;
+
+    QList<Connection> connections;
+
+    if(!scanConnections(connections))
+    {
+        return false;
+    }
+
+    blocking_ = blockingValue;
+
+    if(connections.size() == 0)
+    {
+        error_ = NO_AVAILABLE_CONNECTIONS;
+        return false;
+    }
+
+    int biggestWlan = -1;
+    int biggestGprs = -1;
+    int bestWlan = -1;
+    int bestGprs = -1;
+
+    for(int i = 0; i < connections.size(); i++)
+    {
+       switch(connections.at(i).type)
+       {
+       case WLAN:
+           if(type != GPRS && connections.at(i).strength > biggestWlan)
+           {
+               biggestWlan = connections.at(i).strength;
+               bestWlan = i;
+           }
+           break;
+
+       case GPRS:
+           if(type != WLAN && connections.at(i).strength > biggestGprs)
+           {
+               biggestGprs = connections.at(i).strength;
+               bestGprs = i;
+           }
+           break;
+
+       default:
+           qDebug() << "Unknown connection type";
+       }
+    }
+
+    if(bestWlan >= 0)
+    {
+        connection = connections.at(bestWlan);
+        return true;
+    }
+    else if(bestGprs >= 0)
+    {
+        connection = connections.at(bestGprs);
+        return true;
+    }
+    else
+    {
+        error_ = NO_AVAILABLE_CONNECTIONS;
+        return false;
+    }
+
+}
+
+bool ConnectionManager::disconnect(bool force)
+{
+    // Forced disconnect is not allowed if connection
+    // was not initialized by this class
+    if(!connected_ && force)
+    {
+        return false;
+    }
+
+    connectionReady_ = false;
+    unsigned int flags;
+
+    if(force)
+    {
+        flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_UI_EVENT);
+    }
+    else
+    {
+        flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
+    }
+
     icd2interface_->call(ICD_DBUS_API_DISCONNECT_REQ, QVariant(flags));
     connected_ = false;
     return true;
@@ -85,28 +226,78 @@ bool ConnectionManager::disconnect()
 
 bool ConnectionManager::isConnected()
 {
-    ready_ = false;
-    ignoreStateChanges_ = false;
+    stateReady_ = false;
     QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_STATE_REQ);
 
     unsigned int numOfReplies = rep.arguments().value(0).value<unsigned int>();
 
     if(numOfReplies == 0)
     {
+        emit isConnectedReply(false);
         return false;
     }
 
-    waitSignal();
-    return connected_;
+    if(blocking_)
+    {
+        waitSignal(&stateReady_);
+        return connected_;
+    }
+
+    return true;
 }
 
-void ConnectionManager::stateChange(const QDBusMessage& rep)
+bool ConnectionManager::scanConnections(QList<ConnectionManager::Connection>& connections,
+                                        ConnectionManager::ConnectionType type)
 {
-    if(ignoreStateChanges_)
+    unsigned int flags = static_cast<unsigned int>(ICD_SCAN_REQUEST_ACTIVE_SAVED);
+    scanReady_ = false;
+    scannedConnections_ = 0;
+    connections_ = &connections;
+
+    QStringList networks;
+
+    switch(type)
     {
-        return;
+    case WLAN:
+        networks << "WLAN_INFRA" << "WLAN_ADHOC";
+        break;
+    case GPRS:
+        networks << "GPRS";
+        break;
+    default:
+        break;
+    }
+
+    QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_SCAN_REQ,
+                                            QVariant(flags),
+                                            QVariant(networks));
+
+    numberOfConnections_ = rep.arguments().value(0).toList().size();
+
+    if(numberOfConnections_ == 0)
+    {
+        connections_ = 0;
+        qDebug() << "No connections";
+        return false;
     }
 
+    if(blocking_)
+    {
+        bool ret = waitSignal(&scanReady_);
+        connections_ = 0;
+        return ret;
+    }
+
+    return true;
+}
+
+ConnectionManager::Error ConnectionManager::error() const
+{
+    return error_;
+}
+
+void ConnectionManager::stateChange(const QDBusMessage& rep)
+{
     unsigned int status = rep.arguments().value(7).value<unsigned int>();
 
     switch(status)
@@ -115,21 +306,21 @@ void ConnectionManager::stateChange(const QDBusMessage& rep)
         break;
     case ICD_STATE_CONNECTED:
         connected_ = true;
-        ready_ = true;
+        stateReady_ = true;
         break;
     case ICD_STATE_DISCONNECTING:
         break;
     case ICD_STATE_DISCONNECTED:
         connected_ = false;
-        ready_ = true;
+        stateReady_ = true;
         break;
     case ICD_STATE_LIMITED_CONN_ENABLED:
         connected_ = true;
-        ready_ = true;
+        stateReady_ = true;
         break;
     case ICD_STATE_LIMITED_CONN_DISABLED:
         connected_ = false;
-        ready_ = true;
+        stateReady_ = true;
         break;
     case ICD_STATE_SEARCH_START:
         break;
@@ -142,6 +333,11 @@ void ConnectionManager::stateChange(const QDBusMessage& rep)
         break;
     }
 
+    if(stateReady_)
+    {
+        emit isConnectedReply(connected_);
+    }
+
 }
 
 void ConnectionManager::connectionChange(const QDBusMessage& rep)
@@ -152,35 +348,95 @@ void ConnectionManager::connectionChange(const QDBusMessage& rep)
     {
     case ICD_CONNECTION_SUCCESSFUL:
         connected_ = true;
-        ready_ = true;
+        connectionReady_ = true;
         break;
     case ICD_CONNECTION_NOT_CONNECTED:
         connected_ = false;
-        ready_ = true;
+        connectionReady_ = true;
         break;
     case ICD_CONNECTION_DISCONNECTED:
         connected_ = false;
-        ready_ = true;
+        connectionReady_ = true;
         break;
     default:
         qDebug() << "Unknown connection status";
         break;
     }
+
+    if(connectionReady_)
+    {
+        emit connectReply(connected_);
+    }
+}
+
+void ConnectionManager::scanResult(const QDBusMessage& rep)
+{
+    if(!connections_)
+    {
+        return;
+    }
+
+    QList<QVariant> args = rep.arguments();
+
+    unsigned int status = args.value(0).value<unsigned int>();
+
+    if(status == ICD_SCAN_COMPLETE)
+    {
+        scannedConnections_++;
+    }
+
+    if(scannedConnections_ >= numberOfConnections_)
+    {
+        scanReady_ = true;
+        connections_ = 0;
+        emit scanReady();
+        return;
+    }
+
+    if(status != ICD_SCAN_NEW)
+    {
+        return;
+    }
+
+    Connection connection;
+    connection.id = QString(args.value(10).toByteArray());
+    connection.name = args.value(8).toString();
+    connection.strength = args.value(11).toInt();
+
+    QString type = args.value(7).toString();
+
+    if(type == "GPRS")
+    {
+        connection.type = GPRS;
+    }
+    else if(type == "WLAN_INFRA" || type == "WLAN_ADHOC")
+    {
+        connection.type = WLAN;
+    }
+    else
+    {
+        qDebug() << "Unknown connection type: " << type;
+        return;
+    }
+
+    emit newConnection(connection);
+
+    connections_->push_back(connection);
 }
 
-bool ConnectionManager::waitSignal()
+bool ConnectionManager::waitSignal(bool* ready)
 {
     timeout_ = false;
     timer_ = startTimer(TIMEOUT);
 
-    while(!ready_ && !timeout_)
+    while(!*ready && !timeout_)
     {
         QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
     }
 
     killTimer(timer_);
 
-    return ready_ || !timeout_;
+    return *ready || !timeout_;
 }
 
 void ConnectionManager::timerEvent(QTimerEvent* event)