Fix preferences dialog.
authorRoy Marples <roy@marples.name>
Mon, 15 Sep 2014 20:09:25 +0000 (20:09 +0000)
committerRoy Marples <roy@marples.name>
Mon, 15 Sep 2014 20:09:25 +0000 (20:09 +0000)
src/dhcpcd-qt/dhcpcd-about.cpp
src/dhcpcd-qt/dhcpcd-ipv4validator.cpp [new file with mode: 0644]
src/dhcpcd-qt/dhcpcd-ipv4validator.h [new file with mode: 0644]
src/dhcpcd-qt/dhcpcd-preferences.cpp
src/dhcpcd-qt/dhcpcd-preferences.h
src/dhcpcd-qt/dhcpcd-qt.pro
src/dhcpcd-qt/dhcpcd-ssidmenu.cpp
src/libdhcpcd/config.c
src/libdhcpcd/dhcpcd.c
src/libdhcpcd/dhcpcd.h

index 14cfa9365d6228da1f6e20d5f473a06ad814b65a..a25d4c34a36c4eb4964039ee9268f2655753f4f3 100644 (file)
 #include "dhcpcd-qt.h"
 
 DhcpcdAbout::DhcpcdAbout(DhcpcdQt *parent)
-    : QDialog(NULL)
+    : QDialog(parent)
 {
        QVBoxLayout *layout;
 
        this->parent = parent;
        resize(300, 200);
+       setWindowIcon(DhcpcdQt::getIcon("status", "network-transmit-receive"));
        setWindowTitle(tr("About Network Configurator"));
        layout = new QVBoxLayout(this);
 
diff --git a/src/dhcpcd-qt/dhcpcd-ipv4validator.cpp b/src/dhcpcd-qt/dhcpcd-ipv4validator.cpp
new file mode 100644 (file)
index 0000000..a59765f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * dhcpcd-qt
+ * Copyright 2014 Roy Marples <roy@marples.name>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <QStringList>
+
+#include "dhcpcd-ipv4validator.h"
+
+DhcpcdIPv4Validator::DhcpcdIPv4Validator(Flags flags, QObject *parent)
+{
+       this->flags = flags;
+       this->setParent(parent);
+}
+
+QValidator::State DhcpcdIPv4Validator::validate1(QString &input) const
+{
+       if (input.isEmpty())
+               return Acceptable;
+
+       QStringList slist = input.split('.');
+       int sl = slist.size();
+       if (sl > 4)
+               return Invalid;
+
+       bool ok, empty;
+       int cidr, val;
+       cidr = -1;
+       empty = false;
+       QValidator::State CIDRstate = Acceptable;
+       for (int i = 0; i < sl; i++) {
+               QString s = slist[i];
+               if (i == sl - 1 && flags.testFlag(DhcpcdIPv4Validator::CIDR)) {
+                       QStringList ssplit = s.split('/');
+                       s = ssplit[0];
+                       val = ssplit.size();
+                       if (val == 2) {
+                               if (ssplit[1].isEmpty())
+                                       CIDRstate = Intermediate;
+                               else {
+                                       cidr = ssplit[1].toInt(&ok);
+                                       if (!ok || cidr < 0 || cidr > 32)
+                                               return Invalid;
+                               }
+                       } else if (val != 1)
+                               return Invalid;
+               }
+               if (s.isEmpty()) {
+                       if (empty)
+                               return Invalid;
+                       empty = true;
+               } else {
+                       val = s.toInt(&ok);
+                       if (!ok || val < 0 || val > 255)
+                               return Invalid;
+               }
+       }
+       if (sl < 4 && cidr == -1)
+               return Intermediate;
+       return CIDRstate;
+}
+
+QValidator::State DhcpcdIPv4Validator::validate(QString &input, int &) const
+{
+       if (input.isEmpty())
+               return Acceptable;
+
+       QStringList slist = input.split(' ');
+       int sl  = slist.size();
+       if (sl > 1 && !flags.testFlag(DhcpcdIPv4Validator::Spaced))
+               return Invalid;
+
+       QValidator::State state = Acceptable;
+       for (int i = 0; i < sl; i++) {
+               state = validate1(slist[i]);
+               if (state == Invalid)
+                       return Invalid;
+               if (state == Intermediate && i + 1 < sl)
+                       return Invalid;
+       }
+       return state;
+}
diff --git a/src/dhcpcd-qt/dhcpcd-ipv4validator.h b/src/dhcpcd-qt/dhcpcd-ipv4validator.h
new file mode 100644 (file)
index 0000000..ee2c314
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * dhcpcd-qt
+ * Copyright 2014 Roy Marples <roy@marples.name>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DHCPCD_IPV4VALIDATOR_H
+#define DHCPCD_IPV4VALIDATOR_H
+
+#include <QValidator>
+
+class DhcpcdIPv4Validator : public QValidator
+{
+       Q_OBJECT
+
+public:
+       enum Flag {
+               Plain = 0x0,
+               CIDR = 0x01,
+               Spaced = 0x02
+       };
+       Q_DECLARE_FLAGS(Flags, Flag)
+       explicit DhcpcdIPv4Validator(DhcpcdIPv4Validator::Flags flag = Plain, QObject *parent = 0);
+       QValidator::State validate(QString &input, int &pos) const;
+
+private:
+       DhcpcdIPv4Validator::Flags flags;
+       QValidator::State validate1(QString &input) const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(DhcpcdIPv4Validator::Flags)
+#endif
index 2edcbf80a43216bdf9fe5dbed5198dc382d74202..339eddccfa0af6283b2911d896a6deb21394e0f0 100644 (file)
  */
 
 #include <QDialog>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QFormLayout>
+#include <QFrame>
+#include <QGridLayout>
+#include <QHBoxLayout>
 #include <QIcon>
 #include <QLabel>
+#include <QLineEdit>
+#include <QMessageBox>
 #include <QPixmap>
 #include <QPushButton>
+#include <QStandardItemModel>
 #include <QVBoxLayout>
 
 #include "config.h"
 #include "dhcpcd-preferences.h"
+#include "dhcpcd-ipv4validator.h"
 #include "dhcpcd-qt.h"
+#include "dhcpcd-wi.h"
 
 DhcpcdPreferences::DhcpcdPreferences(DhcpcdQt *parent)
-    : QDialog(NULL)
+    : QDialog(parent)
 {
-       QVBoxLayout *layout;
-
        this->parent = parent;
-       resize(300, 200);
-       setWindowTitle("dhcpcd-qt prefs");
-       layout = new QVBoxLayout(this);
+       resize(400, 200);
+       setWindowIcon(DhcpcdQt::getIcon("status", "network-transmit-receive"));
+       setWindowTitle(tr("Network Preferences"));
+
+       name = NULL;
+       config = NULL;
+       eWhat = eBlock = NULL;
+       iface = NULL;
+
+       QVBoxLayout *layout = new QVBoxLayout();
+
+       QGridLayout *topLayout = new QGridLayout();
+       QLabel *conf = new QLabel(tr("Configure:"));
+       topLayout->addWidget(conf, 0, 0);
+
+       what = new QComboBox();
+       connect(what, SIGNAL(currentIndexChanged(const QString &)),
+           this, SLOT(listBlocks(const QString &)));
+       topLayout->addWidget(what, 0, 1);
+       blocks = new QComboBox();
+       connect(blocks, SIGNAL(currentIndexChanged(const QString &)),
+           this, SLOT(showBlock(const QString &)));
+       topLayout->addWidget(blocks, 0, 2);
+
+       topLayout->setColumnStretch(2, 10);
+
+       QWidget *topBox = new QWidget();
+       topBox->setLayout(topLayout);
+       layout->addWidget(topBox);
+       QFrame *topSep = new QFrame();
+       topSep->setFrameShape(QFrame::HLine);
+       topSep->setFrameShadow(QFrame::Sunken);
+       layout->addWidget(topSep);
+
+       autoConf = new QCheckBox(tr("Automatically configure empty options"));
+       autoConf->setChecked(true);
+       layout->addWidget(autoConf);
+
+       DhcpcdIPv4Validator *v =
+           new DhcpcdIPv4Validator(DhcpcdIPv4Validator::Plain, this);
+       DhcpcdIPv4Validator *vc =
+           new DhcpcdIPv4Validator(DhcpcdIPv4Validator::CIDR, this);
+       DhcpcdIPv4Validator *vs =
+           new DhcpcdIPv4Validator(DhcpcdIPv4Validator::Spaced, this);
+       ip = new QLineEdit();
+       ip->setValidator(vc);
+       router = new QLineEdit();
+       router->setValidator(v);
+       rdnss = new QLineEdit();
+       rdnss->setValidator(vs);
+       dnssl = new QLineEdit();
+#if defined(__NetBSD__) || (__OpenBSD__)
+       dnssl->setMaxLength(1024);
+else
+       dnssl->setMaxLength(256);
+#endif
+       QFormLayout *ipLayout = new QFormLayout();
+       ipLayout->addRow(tr("IP Address:"), ip);
+       ipLayout->addRow(tr("Router:"), router);
+       ipLayout->addRow(tr("DNS Servers:"), rdnss);
+       ipLayout->addRow(tr("DNS Search:"), dnssl);
+       ipSetup = new QWidget();
+       ipSetup->setLayout(ipLayout);
+       layout->addWidget(ipSetup);
+
+       QHBoxLayout *buttonLayout = new QHBoxLayout();
+       clear = new QPushButton(tr("&Clear"));
+       clear->setIcon(QIcon::fromTheme("edit-clear"));
+       buttonLayout->addWidget(clear);
+       QPushButton *rebind = new QPushButton(tr("&Rebind"));
+       rebind->setIcon(QIcon::fromTheme("application-x-executable"));
+       buttonLayout->addWidget(rebind);
+       QPushButton *close = new QPushButton(tr("&Close"));
+       close->setIcon(QIcon::fromTheme("window-close"));
+       buttonLayout->addWidget(close);
+       QWidget *buttons = new QWidget();
+       buttons->setLayout(buttonLayout);
+       layout->addWidget(buttons);
+
+       QIcon wired = DhcpcdQt::getIcon("devices", "network-wired");
+       what->addItem(wired, tr("Interface"));
+       QIcon wireless = DhcpcdQt::getIcon("devices", "network-wireless");
+       what->addItem(wireless, tr("SSID"));
 
-       notLabel = new QLabel("<h1>Not implemented yet</h1>", this);
-       notLabel->setAlignment(Qt::AlignCenter);
-       layout->addWidget(notLabel);
+       connect(clear, SIGNAL(clicked()), this, SLOT(clearConfig()));
+       connect(rebind, SIGNAL(clicked()), this, SLOT(rebind()));
+       connect(close, SIGNAL(clicked()), this, SLOT(tryClose()));
+
+       setLayout(layout);
+
+       autoConf->setEnabled(false);
+       ipSetup->setEnabled(false);
+       clear->setEnabled(false);
+
+       DHCPCD_CONNECTION *con = parent->getConnection();
+       if (!dhcpcd_config_writeable(con))
+               QMessageBox::warning(this, tr("Not writeable"),
+                   tr("The dhcpcd configuration file is not writeable\n\n%1")
+                   .arg(dhcpcd_cffile(con)));
+}
+
+DhcpcdPreferences::~DhcpcdPreferences()
+{
+
+       free(eWhat);
+       eWhat = NULL;
+       free(eBlock);
+       eBlock = NULL;
 }
 
 void DhcpcdPreferences::closeEvent(QCloseEvent *e)
@@ -56,3 +166,318 @@ void DhcpcdPreferences::closeEvent(QCloseEvent *e)
        parent->dialogClosed(this);
        QDialog::closeEvent(e);
 }
+
+void DhcpcdPreferences::listBlocks(const QString &txt)
+{
+
+       /* clear and then disconnect so we trigger a save */
+       blocks->clear();
+       blocks->disconnect(this);
+       
+       free(eWhat);
+       eWhat = strdup(txt.toLower().toAscii());
+
+       if (txt == "Interface") {
+               DHCPCD_IF *i;
+
+               blocks->addItem(tr("Select an interface"));
+               for (i = dhcpcd_interfaces(parent->getConnection());
+                   i; i = i->next)
+               {
+                       if (strcmp(i->type, "link") == 0) {
+                               QIcon icon = DhcpcdQt::getIcon("devices",
+                                   i->wireless ?
+                                   "network-wireless" : "network-wired");
+                               blocks->addItem(icon, i->ifname);
+                       }
+               }
+       } else {
+               QList<DhcpcdWi *> *wis = parent->getWis();
+
+               blocks->addItem(tr("Select a SSID"));
+               for (int i = 0; i < wis->size(); i++) {
+                       DHCPCD_WI_SCAN *scan;
+                       DhcpcdWi *wi = wis->at(i);
+
+                       for (scan = wi->getScans(); scan; scan = scan->next) {
+                               QIcon icon;
+
+                               icon = DhcpcdQt::getIcon(
+                                   scan->flags[0] == '\0' ?"devices" :"status",
+                                   scan->flags[0] == '\0' ?"network-wireless" :
+                                       "network-wireless-encrypted");
+                               blocks->addItem(icon, scan->ssid);
+                       }
+               }
+       }
+
+       /* Now make the 1st item unselectable and reconnect */
+       qobject_cast<QStandardItemModel *>(blocks->model())->item(0)->setEnabled(false);
+       connect(blocks, SIGNAL(currentIndexChanged(const QString &)),
+           this, SLOT(showBlock(const QString &)));
+
+}
+
+void DhcpcdPreferences::clearConfig()
+{
+
+       autoConf->setChecked(true);
+       ip->setText("");
+       router->setText("");
+       rdnss->setText("");
+       dnssl->setText("");
+}
+
+void DhcpcdPreferences::showConfig()
+{
+       const char *val;
+       bool a;
+
+       if ((val = dhcpcd_config_get_static(config, "ip_address=")) != NULL)
+                a = false;
+        else
+                a = !((val = dhcpcd_config_get(config, "inform")) == NULL &&
+                    (iface && iface->flags & IFF_POINTOPOINT));
+       autoConf->setChecked(a);
+       ip->setText(val);
+       router->setText(dhcpcd_config_get_static(config, "routers="));
+       rdnss->setText(dhcpcd_config_get_static(config,"domain_name_servers="));
+       dnssl->setText(dhcpcd_config_get_static(config, "domain_search="));
+}
+
+bool DhcpcdPreferences::changedConfig()
+{
+       const char *val;
+       bool a;
+
+       if ((val = dhcpcd_config_get_static(config, "ip_address=")) != NULL)
+                a = false;
+        else
+                a = !((val = dhcpcd_config_get(config, "inform")) == NULL &&
+                    (iface && iface->flags & IFF_POINTOPOINT));
+       if (autoConf->isChecked() != a)
+               return true;
+       if (ip->text().compare(val))
+               return true;
+       val = dhcpcd_config_get_static(config, "routers=");
+       if (router->text().compare(val))
+               return true;
+       val = dhcpcd_config_get_static(config, "domain_name_servers=");
+       if (rdnss->text().compare(val))
+               return true;
+       val = dhcpcd_config_get_static(config, "domain_search=");
+       if (rdnss->text().compare(val))
+               return true;
+       return false;
+}
+
+
+const char *DhcpcdPreferences::getString(QLineEdit *le)
+{
+       if (le->text().isEmpty())
+               return NULL;
+       return le->text().trimmed().toAscii();
+}
+
+bool DhcpcdPreferences::setOption(const char *opt, const char *val, bool *ret)
+{
+        if (opt[strlen(opt) - 1] == '=') {
+                if (!dhcpcd_config_set_static(&config, opt, val))
+                        qCritical("dhcpcd_config_set_static: %s",
+                            strerror(errno));
+                else
+                        return true;
+        } else {
+                if (!dhcpcd_config_set(&config, opt, val))
+                        qCritical("dhcpcd_config_set: %s",
+                            strerror(errno));
+                else
+                        return true;
+        }
+
+        if (ret)
+                *ret = false;
+        return false;
+}
+
+
+bool DhcpcdPreferences::makeConfig()
+{
+       const char ns[] = "", *val;
+       bool a, ret;
+
+       a = autoConf->isChecked();
+       ret = true;
+       if (iface && iface->flags & IFF_POINTOPOINT)
+               setOption("ip_address=", a ? NULL : ns, &ret);
+        else {
+               val = getString(ip);
+                setOption("inform", a ? val : NULL, &ret);
+                setOption("ip_address=", a ? NULL : val, &ret);
+        }
+
+        val = getString(router);
+        setOption("routers=", val, &ret);
+
+       val = getString(rdnss);
+        setOption("domain_name_servers=", val, &ret);
+
+       val = getString(dnssl);
+        setOption("domain_search=", val, &ret);
+
+        return ret;
+}
+
+bool DhcpcdPreferences::writeConfig(bool *cancel)
+{
+
+       switch (QMessageBox::question(this, tr("Save Configuration"),
+           tr("Do you want to save your changes?"),
+           QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) {
+       case QMessageBox::Cancel:
+               *cancel = true;
+               return false;
+       case QMessageBox::Discard:
+               return true;
+       default:
+               break;
+       }
+       *cancel = false;
+
+       DHCPCD_CONNECTION *con = parent->getConnection();
+       if (!makeConfig()) {
+               qCritical("failed to make config");
+               goto err;
+       }
+       if (!dhcpcd_config_write(con, eWhat, eBlock, config)) {
+               qCritical("dhcpcd_config_write: %s", strerror(errno));
+               QMessageBox::critical(parent,
+                   tr("Failed to write configuration"),
+                   tr("Failed to write configuration:\n\n%1: %2")
+                   .arg(dhcpcd_cffile(con))
+                   .arg(strerror(errno)));
+               goto err;
+       }
+       return true;
+
+err:
+       /* Reload our config if there is a problem */
+       config = dhcpcd_config_read(con, eWhat, eBlock);
+       return false;
+}
+
+void DhcpcdPreferences::showBlock(const QString &txt)
+{
+
+       if (eBlock) {
+               if (changedConfig()) {
+                       bool cancel;
+                       if (!writeConfig(&cancel))
+                               return;
+               }
+               free(eBlock);
+       }
+       if (txt.isEmpty())
+               eBlock = NULL;
+       else
+               eBlock = strdup(txt.toAscii());
+
+       dhcpcd_config_free(config);
+       iface = NULL;
+       DHCPCD_CONNECTION *con = parent->getConnection();
+
+       if (eBlock && eWhat) {
+               if (strcmp(eWhat, "interface") == 0)
+                       iface = dhcpcd_get_if(con, eBlock, "link");
+               ip->setEnabled(iface == NULL ||
+                   !(iface->flags & IFF_POINTOPOINT));
+               errno = 0;
+               config = dhcpcd_config_read(con, eWhat, eBlock);
+               if (config == NULL && errno) {
+                       const char *s;
+
+                       s = strerror(errno);
+                       qCritical("dhcpcd_config_read: %s", s);
+                       QMessageBox::critical(this,
+                           tr("Error reading configuration"),
+                           tr("Error reading: ") + dhcpcd_cffile(con) +
+                           "\n\n" + s);
+               }
+       } else
+               config = NULL;
+
+       showConfig();
+       bool enabled = dhcpcd_config_writeable(con) && eBlock != NULL;
+       autoConf->setEnabled(enabled);
+       ipSetup->setEnabled(enabled);
+       clear->setEnabled(enabled);
+}
+
+bool DhcpcdPreferences::tryRebind(const char *ifname)
+{
+
+       if (dhcpcd_rebind(parent->getConnection(), ifname) == 0)
+               return true;
+       
+       qCritical("dhcpcd_rebind: %s", strerror(errno));
+       QMessageBox::critical(this,
+           tr("Rebind failed"),
+           ifname ? tr("Failed to rebind interface %1: %2")
+           .arg(ifname).arg(strerror(errno)) :
+           tr("Failed to rebind: %1")
+           .arg(strerror(errno)));
+       return false; 
+}
+
+void DhcpcdPreferences::rebind()
+{
+
+       if (changedConfig()) {
+               bool cancel;
+               writeConfig(&cancel);
+               if (cancel)
+                       return;
+       }
+
+       DHCPCD_CONNECTION *con = parent->getConnection();
+       DHCPCD_IF *i;
+       bool found = false;
+       bool worked;
+       if (strcmp(eWhat, "interface") == 0) {
+               worked = tryRebind(iface ? iface->ifname : NULL);
+               goto done;
+       }
+       
+       worked = true;
+       for (i = dhcpcd_interfaces(con); i; i = i->next) {
+               if (strcmp(i->ssid, eBlock) == 0) {
+                       found = true;
+                       if (!tryRebind(i->ifname))
+                               worked = false;
+               }
+       }
+       if (!found) {
+               QMessageBox::information(this,
+                   tr("No matching interface"),
+                   tr("No interface is bound to this SSID to rebind"));
+               return;
+       }
+
+done:          
+       if (worked)
+               QMessageBox::information(this,
+                   tr("Rebind sent"),
+                   tr("The rebind signal has been sent to dhcpcd"));
+}
+
+void DhcpcdPreferences::tryClose()
+{
+
+       if (changedConfig()) {
+               bool cancel;
+               writeConfig(&cancel);
+               if (cancel)
+                       return;
+       }
+       close();
+}
index 55dd2d27a10d0b3e0eebaef7d324faf6de06e20a..c90e92dc6efec8c4a91173c4bdbec3b70c77480f 100644 (file)
 
 #include <QDialog>
 
+#include "dhcpcd.h"
+
 class DhcpcdQt;
+class QCheckBox;
+class QComboBox;
 class QLabel;
+class QLineEdit;
+class QPushButton;
 
 class DhcpcdPreferences : public QDialog
 {
@@ -38,13 +44,44 @@ class DhcpcdPreferences : public QDialog
 
 public:
        DhcpcdPreferences(DhcpcdQt *parent = 0);
+       ~DhcpcdPreferences();
 
 protected:
        void closeEvent(QCloseEvent *e);
 
+private slots:
+       void clearConfig();
+       void showConfig();
+       void listBlocks(const QString &txt);
+       void showBlock(const QString &txt);
+       void rebind();
+       void tryClose();
+
 private:
        DhcpcdQt *parent;
-       QLabel *notLabel;
+       QComboBox *what;
+       QComboBox *blocks;
+       char *eBlock;
+       char *eWhat;
+
+       DHCPCD_IF *iface;
+       char *name;
+       DHCPCD_OPTION *config;
+       const char *getString(QLineEdit *le);
+       bool setOption(const char *opt, const char *val, bool *ret);
+       bool makeConfig();
+       bool changedConfig();
+       bool writeConfig(bool *cancel);
+       bool tryRebind(const char *ifname);
+
+       QCheckBox *autoConf;
+       QWidget *ipSetup;
+       QLineEdit *ip;
+       QLineEdit *router;
+       QLineEdit *rdnss;
+       QLineEdit *dnssl;
+
+       QPushButton *clear;
 };
 
 #endif
index 171a6ec2f5af1b6cadd51c86dbad32d793f80b96..b6702d55aa7f0b8c2e92c980cceb5a0054589273 100644 (file)
@@ -2,10 +2,12 @@ CONFIG+=              qt gui c++11 debug
 QMAKE_CXXFLAGS+=       -std=c++11 -O2
 
 HEADERS=               dhcpcd-qt.h dhcpcd-about.h dhcpcd-preferences.h \
-                       dhcpcd-wi.h dhcpcd-ifmenu.h dhcpcd-ssidmenu.h
+                       dhcpcd-wi.h dhcpcd-ifmenu.h dhcpcd-ssidmenu.h \
+                       dhcpcd-ipv4validator.h
 SOURCES=               main.cpp dhcpcd-qt.cpp dhcpcd-about.cpp \
                        dhcpcd-preferences.cpp dhcpcd-wi.cpp \
-                       dhcpcd-ifmenu.cpp dhcpcd-ssidmenu.cpp
+                       dhcpcd-ifmenu.cpp dhcpcd-ssidmenu.cpp \
+                       dhcpcd-ipv4validator.cpp
 
 INCLUDEPATH+=          ../../
 INCLUDEPATH+=          ../libdhcpcd/
index ed8f510a199e1ff9fc7af046aea7b3f76e442001..dc0795b9f98227d4d02fb2c3c93350377f430d0a 100644 (file)
@@ -57,6 +57,7 @@ DhcpcdSsidMenu::DhcpcdSsidMenu(QWidget *parent, QWidgetAction *wa,
        setScan(scan);
 
        this->installEventFilter(this);
+       button->installEventFilter(this);
 }
 
 QWidgetAction *DhcpcdSsidMenu::getWidgetAction()
@@ -81,7 +82,8 @@ void DhcpcdSsidMenu::setScan(DHCPCD_WI_SCAN *scan)
        wpa = wi->getWpa();
        i = dhcpcd_wpa_if(wpa);
 
-       button->setChecked(i->up && strcmp(scan->ssid, i->ssid) == 0);
+       button->setChecked(i->up && i->ssid &&
+           strcmp(scan->ssid, i->ssid) == 0);
        button->setText(scan->ssid);
        if (scan->flags[0] == '\0') {
                icon = DhcpcdQt::getIcon("devices", "network-wireless");
index 709a8e841c068f6950655b10c896717c2ac0c6c9..92aad29f6225faac19f5fcb918414b3569d15f91 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #define IN_LIBDHCPCD
 
@@ -395,6 +396,13 @@ dhcpcd_config_read(DHCPCD_CONNECTION *con, const char *block, const char *name)
 }
 
 bool
+dhcpcd_config_writeable(DHCPCD_CONNECTION *con)
+{
+
+       return (access(con->cffile, W_OK) == 0);
+}
+
+bool
 dhcpcd_config_write(DHCPCD_CONNECTION *con,
     const char *block, const char *name,
     const DHCPCD_OPTION *opts)
index 3bfbb56f3b162a022041ae2e4792fb06982726cb..13e9c8ec4606acf49634bbd2d0380c183f78b2a2 100644 (file)
@@ -141,12 +141,17 @@ dhcpcd_command_arg(DHCPCD_CONNECTION *con, const char *cmd, const char *arg,
        size_t cmdlen, len;
 
        cmdlen = strlen(cmd);
-       len = cmdlen + strlen(arg) + 2;
+       if (arg)
+               len = cmdlen + strlen(arg) + 2;
+       else
+               len = cmdlen + 1;
        if (!dhcpcd_realloc(con, len))
                return -1;
        strlcpy(con->buf, cmd, con->buflen);
-       con->buf[cmdlen] = ' ';
-       strlcpy(con->buf + cmdlen + 1, arg, con->buflen - 1 - cmdlen);
+       if (arg) {
+               con->buf[cmdlen] = ' ';
+               strlcpy(con->buf + cmdlen + 1, arg, con->buflen - 1 - cmdlen);
+       }
 
        return dhcpcd_command_fd(con, con->command_fd, con->buf, buffer);
 }
index d4f7aaea48005883030ef2577502771410cc578e..39aa36e299fe2c5a3af1e5d038b0976e672189f2 100644 (file)
@@ -255,6 +255,7 @@ const char * dhcpcd_config_get(DHCPCD_OPTION *, const char *);
 const char * dhcpcd_config_get_static(DHCPCD_OPTION *, const char *);
 bool dhcpcd_config_set(DHCPCD_OPTION **, const char *, const char *);
 bool dhcpcd_config_set_static(DHCPCD_OPTION **, const char *, const char *);
+bool dhcpcd_config_writeable(DHCPCD_CONNECTION *con);
 bool dhcpcd_config_write(DHCPCD_CONNECTION *,
     const char *, const char *, const DHCPCD_OPTION *);