[network-manager-applet] editor: improve the cloned MAC address selection



commit 85b6b659a140a59c3df787062e089a0b4e2a547d
Author: Beniamino Galvani <bgalvani redhat com>
Date:   Fri Nov 11 10:21:42 2016 +0100

    editor: improve the cloned MAC address selection
    
    Add a combo box with text entry that accepts a MAC address and also
    the selection of one of the predefined special values.
    
    It is not possible to configure properties like the generated MAC
    address mask or the stable id. For these advanced settings users
    should rely on nmcli.

 src/connection-editor/ce-page-ethernet.ui |   12 ++++-
 src/connection-editor/ce-page-vlan.ui     |   13 ++++--
 src/connection-editor/ce-page-wifi.ui     |   12 ++++-
 src/connection-editor/ce-page.c           |   70 ++++++++++++++++++++++++++--
 src/connection-editor/ce-page.h           |    3 +
 src/connection-editor/page-ethernet.c     |   11 ++---
 src/connection-editor/page-vlan.c         |   15 +++---
 src/connection-editor/page-wifi.c         |   11 ++---
 8 files changed, 113 insertions(+), 34 deletions(-)
---
diff --git a/src/connection-editor/ce-page-ethernet.ui b/src/connection-editor/ce-page-ethernet.ui
index 5f53acd..8eef5d9 100644
--- a/src/connection-editor/ce-page-ethernet.ui
+++ b/src/connection-editor/ce-page-ethernet.ui
@@ -168,10 +168,16 @@
       </packing>
     </child>
     <child>
-      <object class="GtkEntry" id="ethernet_cloned_mac">
+      <object class="GtkComboBoxText" id="ethernet_cloned_mac">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="tooltip_text" translatable="yes">The MAC address entered here will be used as 
hardware address for the network device this connection is activated on. This feature is known as MAC cloning 
or spoofing. Example: 00:11:22:33:44:55</property>
+        <property name="can_focus">False</property>
+        <property name="has_entry">True</property>
+        <property name="active_id">0</property>
+        <child internal-child="entry">
+          <object class="GtkEntry">
+            <property name="can_focus">True</property>
+          </object>
+        </child>
       </object>
       <packing>
         <property name="left_attach">1</property>
diff --git a/src/connection-editor/ce-page-vlan.ui b/src/connection-editor/ce-page-vlan.ui
index 9027353..86799cd 100644
--- a/src/connection-editor/ce-page-vlan.ui
+++ b/src/connection-editor/ce-page-vlan.ui
@@ -65,11 +65,16 @@
       </packing>
     </child>
     <child>
-      <object class="GtkEntry" id="vlan_cloned_mac_entry">
+      <object class="GtkComboBoxText" id="vlan_cloned_mac_entry">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="invisible_char">●</property>
-        <property name="invisible_char_set">True</property>
+        <property name="can_focus">False</property>
+        <property name="has_entry">True</property>
+        <property name="active_id">0</property>
+        <child internal-child="entry">
+          <object class="GtkEntry">
+            <property name="can_focus">True</property>
+          </object>
+        </child>
       </object>
       <packing>
         <property name="left_attach">1</property>
diff --git a/src/connection-editor/ce-page-wifi.ui b/src/connection-editor/ce-page-wifi.ui
index f91e1f0..4116c21 100644
--- a/src/connection-editor/ce-page-wifi.ui
+++ b/src/connection-editor/ce-page-wifi.ui
@@ -152,10 +152,16 @@
       </packing>
     </child>
     <child>
-      <object class="GtkEntry" id="wifi_cloned_mac">
+      <object class="GtkComboBoxText" id="wifi_cloned_mac">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="tooltip_text" translatable="yes">The MAC address entered here will be used as 
hardware address for the network device this connection is activated on. This feature is known as MAC cloning 
or spoofing. Example: 00:11:22:33:44:55</property>
+        <property name="can_focus">False</property>
+        <property name="has_entry">True</property>
+        <property name="active_id">0</property>
+        <child internal-child="entry">
+          <object class="GtkEntry">
+            <property name="can_focus">True</property>
+          </object>
+        </child>
       </object>
       <packing>
         <property name="left_attach">1</property>
diff --git a/src/connection-editor/ce-page.c b/src/connection-editor/ce-page.c
index c07157f..f88dce0 100644
--- a/src/connection-editor/ce-page.c
+++ b/src/connection-editor/ce-page.c
@@ -287,14 +287,53 @@ ce_page_setup_mac_combo (CEPage *self, GtkComboBox *combo,
        _set_active_combo_item (combo, mac, active_mac, active_idx);
 }
 
-gboolean
-ce_page_mac_entry_valid (GtkEntry *entry, int type, const char *property_name, GError **error)
+void
+ce_page_setup_cloned_mac_combo (GtkComboBoxText *combo, const char *current)
 {
-       const char *mac;
+       GtkWidget *entry;
+       static const char *entries[][2] = { { "preserve",  N_("Preserve") },
+                                           { "permanent", N_("Permanent") },
+                                           { "random",    N_("Random") },
+                                           { "stable",    N_("Stable") } };
+       int i, active = -1;
+
+       gtk_widget_set_tooltip_text (GTK_WIDGET (combo),
+               _("The MAC address entered here will be used as hardware address for "
+                 "the network device this connection is activated on. This feature is "
+                 "known as MAC cloning or spoofing. Example: 00:11:22:33:44:55"));
+
+       gtk_combo_box_text_remove_all (combo);
+
+       for (i = 0; i < G_N_ELEMENTS (entries); i++) {
+               gtk_combo_box_text_append (combo, entries[i][0], _(entries[i][1]));
+               if (nm_streq0 (current, entries[i][0]))
+                       active = i;
+       }
 
-       g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
+       if (active != -1) {
+               gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+       } else if (current && current[0]) {
+               entry = gtk_bin_get_child (GTK_BIN (combo));
+               g_assert (entry);
+               gtk_entry_set_text (GTK_ENTRY (entry), current);
+       }
+}
+
+const char *
+ce_page_cloned_mac_get (GtkComboBoxText *combo)
+{
+       const char *id;
 
-       mac = gtk_entry_get_text (entry);
+       id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo));
+       if (id)
+               return id;
+
+       return gtk_combo_box_text_get_active_text (combo);
+}
+
+static gboolean
+mac_valid (const char *mac, int type, const char *property_name, GError **error)
+{
        if (mac && *mac) {
                if (!nm_utils_hwaddr_valid (mac, nm_utils_hwaddr_len (type))) {
                        const char *addr_type;
@@ -312,10 +351,31 @@ ce_page_mac_entry_valid (GtkEntry *entry, int type, const char *property_name, G
                        return FALSE;
                }
        }
+
        return TRUE;
 }
 
 gboolean
+ce_page_cloned_mac_combo_valid (GtkComboBoxText *combo, int type, const char *property_name, GError **error)
+{
+       if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) != -1)
+               return TRUE;
+
+       return mac_valid (gtk_combo_box_text_get_active_text (combo),
+                         type,
+                         property_name,
+                         error);
+}
+
+gboolean
+ce_page_mac_entry_valid (GtkEntry *entry, int type, const char *property_name, GError **error)
+{
+       g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
+
+       return mac_valid (gtk_entry_get_text (entry), type, property_name, error);
+}
+
+gboolean
 ce_page_interface_name_valid (const char *iface, const char *property_name, GError **error)
 {
        if (iface && *iface) {
diff --git a/src/connection-editor/ce-page.h b/src/connection-editor/ce-page.h
index dd71fa2..e869bb6 100644
--- a/src/connection-editor/ce-page.h
+++ b/src/connection-editor/ce-page.h
@@ -136,6 +136,7 @@ void ce_page_setup_mac_combo (CEPage *self, GtkComboBox *combo,
                               const char *mac, char **mac_list);
 void ce_page_setup_data_combo (CEPage *self, GtkComboBox *combo,
                                const char *data, char **list);
+void ce_page_setup_cloned_mac_combo (GtkComboBoxText *combo, const char *current);
 void ce_page_setup_device_combo (CEPage *self,
                                  GtkComboBox *combo,
                                  GType device_type,
@@ -149,6 +150,8 @@ gboolean ce_page_device_entry_get (GtkEntry *entry, int type,
                                    char **ifname, char **mac,
                                    const char *device_name,
                                    GError **error);
+const char *ce_page_cloned_mac_get (GtkComboBoxText *combo);
+gboolean ce_page_cloned_mac_combo_valid (GtkComboBoxText *combo, int type, const char *property_name, GError 
**error);
 
 void ce_page_changed (CEPage *self);
 
diff --git a/src/connection-editor/page-ethernet.c b/src/connection-editor/page-ethernet.c
index 813fbf8..fbdafaa 100644
--- a/src/connection-editor/page-ethernet.c
+++ b/src/connection-editor/page-ethernet.c
@@ -35,7 +35,7 @@ typedef struct {
        NMSettingWired *setting;
 
        GtkComboBoxText *device_combo; /* Device identification (ifname and/or MAC) */
-       GtkEntry *cloned_mac;          /* Cloned MAC - used for MAC spoofing */
+       GtkComboBoxText *cloned_mac;   /* Cloned MAC - used for MAC spoofing */
        GtkComboBox *port;
        GtkComboBox *speed;
        GtkComboBox *duplex;
@@ -91,7 +91,7 @@ ethernet_private_init (CEPageEthernet *self)
        label = GTK_LABEL (gtk_builder_get_object (builder, "ethernet_device_label"));
        gtk_label_set_mnemonic_widget (label, GTK_WIDGET (priv->device_combo));
 
-       priv->cloned_mac = GTK_ENTRY (gtk_builder_get_object (builder, "ethernet_cloned_mac"));
+       priv->cloned_mac = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "ethernet_cloned_mac"));
        priv->port = GTK_COMBO_BOX (gtk_builder_get_object (builder, "ethernet_port"));
        priv->speed = GTK_COMBO_BOX (gtk_builder_get_object (builder, "ethernet_speed"));
        priv->duplex = GTK_COMBO_BOX (gtk_builder_get_object (builder, "ethernet_duplex"));
@@ -249,8 +249,7 @@ populate_ui (CEPageEthernet *self)
 
        /* Cloned MAC address */
        s_mac = nm_setting_wired_get_cloned_mac_address (setting);
-       if (s_mac)
-               gtk_entry_set_text (priv->cloned_mac, s_mac);
+       ce_page_setup_cloned_mac_combo (priv->cloned_mac, s_mac);
        g_signal_connect (priv->cloned_mac, "changed", G_CALLBACK (stuff_changed), self);
 
        /* MTU */
@@ -454,7 +453,7 @@ ui_to_setting (CEPageEthernet *self)
        entry = gtk_bin_get_child (GTK_BIN (priv->device_combo));
        if (entry)
                ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, TRUE, &ifname, &device_mac, NULL, 
NULL);
-       cloned_mac = gtk_entry_get_text (priv->cloned_mac);
+       cloned_mac = ce_page_cloned_mac_get (priv->cloned_mac);
 
        /* Wake-on-LAN */
        if (gtk_toggle_button_get_active (priv->wol_default))
@@ -516,7 +515,7 @@ ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
                        return FALSE;
        }
 
-       if (!ce_page_mac_entry_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
+       if (!ce_page_cloned_mac_combo_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
                return FALSE;
 
        if (gtk_widget_get_sensitive (GTK_WIDGET (priv->wol_passwd))) {
diff --git a/src/connection-editor/page-vlan.c b/src/connection-editor/page-vlan.c
index 38ce92e..6806d8b 100644
--- a/src/connection-editor/page-vlan.c
+++ b/src/connection-editor/page-vlan.c
@@ -52,7 +52,7 @@ typedef struct {
        GtkEntry *parent_entry;
        GtkSpinButton *id_entry;
        GtkEntry *name_entry;
-       GtkEntry *cloned_mac;
+       GtkComboBoxText *cloned_mac;
        GtkSpinButton *mtu;
        GtkToggleButton *flag_reorder_hdr, *flag_gvrp, *flag_loose_binding, *flag_mvrp;
 
@@ -84,7 +84,7 @@ vlan_private_init (CEPageVlan *self)
 
        priv->id_entry = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "vlan_id_entry"));
        priv->name_entry = GTK_ENTRY (gtk_builder_get_object (builder, "vlan_name_entry"));
-       priv->cloned_mac = GTK_ENTRY (gtk_builder_get_object (builder, "vlan_cloned_mac_entry"));
+       priv->cloned_mac = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "vlan_cloned_mac_entry"));
        priv->mtu = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "vlan_mtu"));
        priv->flag_reorder_hdr = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "reorder_hdr_flag"));
        priv->flag_gvrp = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "gvrp_flag"));
@@ -285,7 +285,7 @@ parent_changed (GtkWidget *widget, gpointer user_data)
                gtk_widget_set_sensitive (GTK_WIDGET (priv->mtu), TRUE);
        } else {
                gtk_widget_set_sensitive (GTK_WIDGET (priv->cloned_mac), FALSE);
-               gtk_entry_set_text (priv->cloned_mac, "");
+               ce_page_setup_cloned_mac_combo (priv->cloned_mac, NULL);
                gtk_widget_set_sensitive (GTK_WIDGET (priv->mtu), FALSE);
                gtk_spin_button_set_value (priv->mtu, 1500);
        }
@@ -532,8 +532,9 @@ populate_ui (CEPageVlan *self)
        /* Cloned MAC address */
        if (NM_IS_SETTING_WIRED (priv->s_hw)) {
                const char *mac = nm_setting_wired_get_cloned_mac_address (NM_SETTING_WIRED (priv->s_hw));
-               if (mac)
-                       gtk_entry_set_text (priv->cloned_mac, mac);
+               ce_page_setup_cloned_mac_combo (priv->cloned_mac, mac);
+       } else {
+               ce_page_setup_cloned_mac_combo (priv->cloned_mac, NULL);
        }
        g_signal_connect (priv->cloned_mac, "changed", G_CALLBACK (stuff_changed), self);
 
@@ -693,7 +694,7 @@ ui_to_setting (CEPageVlan *self)
                      NULL);
 
        if (hwtype != G_TYPE_NONE) {
-               cloned_mac = gtk_entry_get_text (priv->cloned_mac);
+               cloned_mac = ce_page_cloned_mac_get (priv->cloned_mac);
                if (cloned_mac && !*cloned_mac)
                        cloned_mac = NULL;
                mtu_set = g_ascii_isdigit (*gtk_entry_get_text (GTK_ENTRY (priv->mtu)));
@@ -737,7 +738,7 @@ ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
                g_free (parent_iface);
        }
 
-       if (!ce_page_mac_entry_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
+       if (!ce_page_cloned_mac_combo_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
                return FALSE;
 
        ui_to_setting (self);
diff --git a/src/connection-editor/page-wifi.c b/src/connection-editor/page-wifi.c
index a83507c..f97365d 100644
--- a/src/connection-editor/page-wifi.c
+++ b/src/connection-editor/page-wifi.c
@@ -38,7 +38,7 @@ typedef struct {
        GtkEntry *ssid;
        GtkComboBoxText *bssid;
        GtkComboBoxText *device_combo; /* Device identification (ifname and/or MAC) */
-       GtkEntry *cloned_mac;          /* Cloned MAC - used for MAC spoofing */
+       GtkComboBoxText *cloned_mac;   /* Cloned MAC - used for MAC spoofing */
        GtkComboBox *mode;
        GtkComboBox *band;
        GtkSpinButton *channel;
@@ -65,7 +65,7 @@ wifi_private_init (CEPageWifi *self)
        priv->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
        priv->ssid     = GTK_ENTRY (gtk_builder_get_object (builder, "wifi_ssid"));
-       priv->cloned_mac = GTK_ENTRY (gtk_builder_get_object (builder, "wifi_cloned_mac"));
+       priv->cloned_mac = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "wifi_cloned_mac"));
        priv->mode     = GTK_COMBO_BOX (gtk_builder_get_object (builder, "wifi_mode"));
        priv->band     = GTK_COMBO_BOX (gtk_builder_get_object (builder, "wifi_band"));
        priv->channel  = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "wifi_channel"));
@@ -387,8 +387,7 @@ populate_ui (CEPageWifi *self)
 
        /* Cloned MAC address */
        s_mac = nm_setting_wireless_get_cloned_mac_address (setting);
-       if (s_mac)
-               gtk_entry_set_text (priv->cloned_mac, s_mac);
+       ce_page_setup_cloned_mac_combo (priv->cloned_mac, s_mac);
        g_signal_connect_swapped (priv->cloned_mac, "changed", G_CALLBACK (ce_page_changed), self);
 
        gtk_spin_button_set_value (priv->rate, (gdouble) nm_setting_wireless_get_rate (setting));
@@ -528,7 +527,7 @@ ui_to_setting (CEPageWifi *self)
        entry = gtk_bin_get_child (GTK_BIN (priv->device_combo));
        if (entry)
                ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, TRUE, &ifname, &device_mac, NULL, 
NULL);
-       cloned_mac = gtk_entry_get_text (priv->cloned_mac);
+       cloned_mac = ce_page_cloned_mac_get (priv->cloned_mac);
 
        g_object_set (s_con,
                      NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
@@ -571,7 +570,7 @@ ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
                        return FALSE;
        }
 
-       if (!ce_page_mac_entry_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
+       if (!ce_page_cloned_mac_combo_valid (priv->cloned_mac, ARPHRD_ETHER, _("cloned MAC"), error))
                return FALSE;
 
        ui_to_setting (self);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]