Disconnect when same SSID selected (#1)
[dhcpcd-ui] / src / dhcpcd-qt / dhcpcd-wi.cpp
index 16767c3f0874ea54f3456e921b2a613f8f47a239..4e4d86a8a5fbeaa2a11a77f28d95a4cd0376c802 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * dhcpcd-qt
- * Copyright 2014 Roy Marples <roy@marples.name>
+ * Copyright 2014-2017 Roy Marples <roy@marples.name>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -40,6 +40,7 @@
 #include "dhcpcd-wi.h"
 #include "dhcpcd-qt.h"
 #include "dhcpcd-ifmenu.h"
+#include "dhcpcd-ssid.h"
 #include "dhcpcd-ssidmenu.h"
 
 DhcpcdWi::DhcpcdWi(DhcpcdQt *parent, DHCPCD_WPA *wpa)
@@ -49,34 +50,42 @@ DhcpcdWi::DhcpcdWi(DhcpcdQt *parent, DHCPCD_WPA *wpa)
        this->wpa = wpa;
        menu = NULL;
        scans = NULL;
+       ssid = NULL;
 
        notifier = NULL;
        pingTimer = NULL;
+       scanTimer = NULL;
 }
 
 DhcpcdWi::~DhcpcdWi()
 {
 
+       close();
        if (menu) {
                dhcpcdQt->menuDeleted(menu);
-               menu->setVisible(false);
                menu->deleteLater();
                menu = NULL;
        }
 
        if (notifier) {
-               notifier->setEnabled(false);
                notifier->deleteLater();
                notifier = NULL;
        }
 
        if (pingTimer) {
-               pingTimer->stop();
                pingTimer->deleteLater();
                pingTimer = NULL;
        }
 
-       dhcpcd_wi_scans_free(scans);
+       if (ssid) {
+               ssid->deleteLater();
+               ssid = NULL;
+       }
+
+       if (scanTimer) {
+               scanTimer->deleteLater();
+               scanTimer = NULL;
+       }
 }
 
 DHCPCD_WPA *DhcpcdWi::getWpa()
@@ -95,7 +104,7 @@ bool DhcpcdWi::setScans(DHCPCD_WI_SCAN *scans)
 {
        bool changed = false;
 
-       if (menu && menu->isVisible()) {
+       if (menu) {
                QList<DhcpcdSsidMenu*> lst;
                DHCPCD_WI_SCAN *scan;
                DHCPCD_IF *i;
@@ -160,7 +169,7 @@ bool DhcpcdWi::setScans(DHCPCD_WI_SCAN *scans)
        dhcpcd_wi_scans_free(this->scans);
        this->scans = scans;
 
-       return changed;
+       return (changed && menu && menu->isVisible());
 }
 
 void DhcpcdWi::createMenuItem(QMenu *menu, DHCPCD_WI_SCAN *scan,
@@ -178,6 +187,9 @@ void DhcpcdWi::createMenu1(QMenu *menu)
        DHCPCD_WI_SCAN *scan;
        QAction *before;
 
+       connect(menu, SIGNAL(aboutToShow()), this, SLOT(menuShown()));
+       connect(menu, SIGNAL(aboutToHide()), this, SLOT(menuHidden()));
+
        i = dhcpcd_wpa_if(wpa);
        for (scan = scans; scan; scan = scan->next) {
                before = NULL;
@@ -233,9 +245,40 @@ bool DhcpcdWi::open()
        pingTimer = new QTimer(this);
        connect(pingTimer, SIGNAL(timeout()), this, SLOT(ping()));
        pingTimer->start(DHCPCD_WPA_PING);
+       scanTimer = new QTimer(this);
+       connect(scanTimer, SIGNAL(timeout()), this, SLOT(scan()));
+       scanTimer->start(DHCPCD_WPA_SCAN_LONG);
        return true;
 }
 
+void DhcpcdWi::close()
+{
+
+       if (menu)
+               menu->setVisible(false);
+
+       if (notifier)
+               notifier->setEnabled(false);
+
+       if (pingTimer)
+               pingTimer->stop();
+
+       if (ssid)
+               ssid->reject();
+
+       if (scanTimer)
+               scanTimer->stop();
+
+       if (scans) {
+               dhcpcd_wi_scans_free(scans);
+               scans = NULL;
+       }
+       if (wpa) {
+               dhcpcd_wpa_close(wpa);
+               wpa = NULL;
+       }
+}
+
 void DhcpcdWi::dispatch()
 {
 
@@ -252,35 +295,51 @@ void DhcpcdWi::ping()
 void DhcpcdWi::connectSsid(DHCPCD_WI_SCAN *scan)
 {
        DHCPCD_WI_SCAN s;
+       DHCPCD_IF *i;
        int err;
 
        /* Take a copy of scan incase it's destroyed by a scan update */
        memcpy(&s, scan, sizeof(s));
        s.next = NULL;
 
-       if (s.flags & WSF_PSK) {
+       i = dhcpcd_wpa_if(wpa);
+       if (i == NULL)
+               err = DHCPCD_WPA_ERR;
+       else if (dhcpcd_wi_associated(i, &s)) {
+               /* Disconnect if same interface selected */
+               if (!dhcpcd_wpa_disconnect(wpa))
+                       err = DHCPCD_WPA_ERR_DISCONN;
+               else
+                       err = DHCPCD_WPA_SUCCESS;
+       } else if (s.flags & WSF_PSK) {
                bool ok;
-               QString pwd = QInputDialog::getText(dhcpcdQt, s.ssid,
-                   tr("Pre Shared key"), QLineEdit::Normal, NULL, &ok);
+               QString pwd;
+
+               ssid = new DhcpcdSsid(this, &s);
+               pwd = ssid->getPsk(&ok);
+               ssid->deleteLater();
+               ssid = NULL;
                if (!ok)
                        return;
                if (pwd.isNull() || pwd.isEmpty())
                        err = dhcpcd_wpa_select(wpa, &s);
                else
-                       err = dhcpcd_wpa_configure(wpa, &s, pwd.toAscii());
+                       err = dhcpcd_wpa_configure(wpa, &s, pwd.toLatin1());
        } else
                err = dhcpcd_wpa_configure(wpa, &s, NULL);
 
        QString errt;
-
        switch (err) {
        case DHCPCD_WPA_SUCCESS:
                return;
+       case DHCPCD_WPA_ERR:
+               errt = tr("Failed.");
+               break;
        case DHCPCD_WPA_ERR_DISCONN:
                errt = tr("Failed to disconnect.");
                break;
        case DHCPCD_WPA_ERR_RECONF:
-               errt = tr("Faile to reconfigure.");
+               errt = tr("Failed to reconfigure.");
                break;
        case DHCPCD_WPA_ERR_SET:
                errt = tr("Failed to set key management.");
@@ -308,3 +367,30 @@ void DhcpcdWi::connectSsid(DHCPCD_WI_SCAN *scan)
        QMessageBox::critical(dhcpcdQt, tr("Error setting wireless properties"),
            errt);
 }
+
+void DhcpcdWi::scan()
+{
+       DHCPCD_IF *i;
+
+       i = dhcpcd_wpa_if(wpa);
+       if (!i->up || dhcpcd_wpa_can_background_scan(wpa))
+               dhcpcd_wpa_scan(wpa);
+}
+
+void DhcpcdWi::menuHidden()
+{
+
+       if (scanTimer) {
+               scanTimer->stop();
+               scanTimer->start(DHCPCD_WPA_SCAN_LONG);
+       }
+}
+
+void DhcpcdWi::menuShown()
+{
+
+       if (scanTimer) {
+               scanTimer->stop();
+               scanTimer->start(DHCPCD_WPA_SCAN_SHORT);
+       }
+}