[gnome-control-center/wip/networking2: 13/36] network: Implement the new design for wired



commit 1bdc1e3b11aa469a40dba619f70eb9bbb742186b
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 17 14:17:42 2012 -0500

    network: Implement the new design for wired
    
    This expands the connection editor to cover ethernet,
    and adds support for multiple wired profiles.

 panels/network/Makefile.am                         |    1 +
 panels/network/connection-editor/Makefile.am       |    9 +-
 .../connection-editor/ce-page-8021x-security.c     |  188 ++++++++
 .../connection-editor/ce-page-8021x-security.h     |   64 +++
 panels/network/connection-editor/ce-page-details.c |   45 ++-
 .../network/connection-editor/ce-page-ethernet.c   |  304 +++++++++++++
 .../network/connection-editor/ce-page-ethernet.h   |   75 ++++
 panels/network/connection-editor/ce-page-ip4.c     |    4 +
 panels/network/connection-editor/ce-page-ip6.c     |    4 +
 panels/network/connection-editor/ce-page.c         |  120 +++++-
 panels/network/connection-editor/ce-page.h         |    8 +
 panels/network/connection-editor/ethernet-page.ui  |  315 ++++++++++++++
 .../connection-editor/net-connection-editor.c      |   61 +++-
 panels/network/net-device-ethernet.c               |  451 +++++++++++++++++++-
 panels/network/net-device-ethernet.h               |   15 +-
 panels/network/network-ethernet.ui                 |  211 +++++++++
 panels/network/network-simple.ui                   |  374 ++++++++--------
 panels/network/panel-common.c                      |   18 +
 panels/network/panel-common.h                      |    3 +
 19 files changed, 2050 insertions(+), 220 deletions(-)
---
diff --git a/panels/network/Makefile.am b/panels/network/Makefile.am
index 2cefcff..ff7a0b6 100644
--- a/panels/network/Makefile.am
+++ b/panels/network/Makefile.am
@@ -54,6 +54,7 @@ dist_ui_DATA =						\
 	network-wifi.ui					\
 	network-simple.ui				\
 	network-mobile.ui				\
+	network-ethernet.ui				\
 	network.ui
 
 @INTLTOOL_DESKTOP_RULE@
diff --git a/panels/network/connection-editor/Makefile.am b/panels/network/connection-editor/Makefile.am
index 06e83f9..1755203 100644
--- a/panels/network/connection-editor/Makefile.am
+++ b/panels/network/connection-editor/Makefile.am
@@ -16,7 +16,11 @@ libconnection_editor_la_SOURCES = 		\
 	ce-page-security.h			\
 	ce-page-security.c			\
 	ce-page-reset.h				\
-	ce-page-reset.c
+	ce-page-reset.c				\
+	ce-page-ethernet.h			\
+	ce-page-ethernet.c			\
+	ce-page-8021x-security.h		\
+	ce-page-8021x-security.c
 
 libconnection_editor_la_CPPFLAGS = 		\
 	-I$(srcdir)/../wireless-security	\
@@ -37,7 +41,8 @@ ui_DATA = 					\
 	ip4-page.ui				\
 	ip6-page.ui				\
 	reset-page.ui				\
-	security-page.ui
+	security-page.ui			\
+	ethernet-page.ui
 
 EXTRA_DIST = \
 	$(ui_DATA)
diff --git a/panels/network/connection-editor/ce-page-8021x-security.c b/panels/network/connection-editor/ce-page-8021x-security.c
new file mode 100644
index 0000000..ed716c8
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-8021x-security.c
@@ -0,0 +1,188 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 - 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-8021x.h>
+#include <nm-setting-wireless.h>
+#include <nm-utils.h>
+
+#include "wireless-security.h"
+#include "ce-page-ethernet.h"
+#include "ce-page-8021x-security.h"
+
+G_DEFINE_TYPE (CEPage8021xSecurity, ce_page_8021x_security, CE_TYPE_PAGE)
+
+static void
+enable_toggled (GtkToggleButton *button, gpointer user_data)
+{
+	CEPage8021xSecurity *page = CE_PAGE_8021X_SECURITY (user_data);
+
+	gtk_widget_set_sensitive (page->security_widget, gtk_toggle_button_get_active (page->enabled));
+	ce_page_changed (CE_PAGE (page));
+}
+
+static void
+stuff_changed (WirelessSecurity *sec, gpointer user_data)
+{
+        ce_page_changed (CE_PAGE (user_data));
+}
+
+static void
+finish_setup (CEPage8021xSecurity *self, gpointer unused, GError *error, gpointer user_data)
+{
+	GtkWidget *parent;
+
+	if (error)
+		return;
+
+	self->security = (WirelessSecurity *) ws_wpa_eap_new (CE_PAGE (self)->connection, TRUE, FALSE);
+	if (!self->security) {
+		g_warning ("Could not load 802.1x user interface.");
+		return;
+	}
+
+	wireless_security_set_changed_notify (self->security, stuff_changed, self);
+	self->security_widget = wireless_security_get_widget (self->security);
+	parent = gtk_widget_get_parent (self->security_widget);
+	if (parent)
+		gtk_container_remove (GTK_CONTAINER (parent), self->security_widget);
+
+	gtk_toggle_button_set_active (self->enabled, self->initial_have_8021x);
+	g_signal_connect (self->enabled, "toggled", G_CALLBACK (enable_toggled), self);
+	gtk_widget_set_sensitive (self->security_widget, self->initial_have_8021x);
+
+	gtk_box_pack_start (GTK_BOX (CE_PAGE (self)->page), GTK_WIDGET (self->enabled), FALSE, TRUE, 12);
+	gtk_box_pack_start (GTK_BOX (CE_PAGE (self)->page), self->security_widget, TRUE, TRUE, 0);
+	gtk_widget_show_all (CE_PAGE (self)->page);
+}
+
+CEPage *
+ce_page_8021x_security_new (NMConnection     *connection,
+                            NMClient         *client,
+                            NMRemoteSettings *settings)
+{
+	CEPage8021xSecurity *self;
+
+	self = CE_PAGE_8021X_SECURITY (ce_page_new (CE_TYPE_PAGE_8021X_SECURITY,
+	                                            connection,
+	                                            client,
+	                                            settings,
+	                                            NULL,
+	                                            _("Security")));
+
+	CE_PAGE (self)->page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+
+	g_object_ref_sink (G_OBJECT (CE_PAGE (self)->page));
+	gtk_container_set_border_width (GTK_CONTAINER (CE_PAGE (self)->page), 6);
+
+	if (nm_connection_get_setting_802_1x (connection))
+		self->initial_have_8021x = TRUE;
+
+	self->enabled = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_mnemonic (_("Use 802.1_X security for this connection")));
+
+	g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+	if (self->initial_have_8021x)
+                CE_PAGE (self)->security_setting = NM_SETTING_802_1X_SETTING_NAME;
+
+	return CE_PAGE (self);
+}
+
+static gboolean
+validate (CEPage *page, NMConnection *connection, GError **error)
+{
+	CEPage8021xSecurity *self = CE_PAGE_8021X_SECURITY (page);
+	gboolean valid = TRUE;
+
+	if (gtk_toggle_button_get_active (self->enabled)) {
+		NMConnection *tmp_connection;
+		NMSetting *s_8021x;
+
+		/* FIXME: get failed property and error out of wireless security objects */
+		valid = wireless_security_validate (self->security, NULL);
+		if (valid) {
+			NMSetting *s_con;
+
+			/* Here's a nice hack to work around the fact that ws_802_1x_fill_connection needs wireless setting. */
+			tmp_connection = nm_connection_new ();
+			nm_connection_add_setting (tmp_connection, nm_setting_wireless_new ());
+
+			/* temp connection needs a 'connection' setting too, since most of
+			 * the EAP methods need the UUID for CA cert ignore stuff.
+			 */
+			s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+			nm_connection_add_setting (tmp_connection, nm_setting_duplicate (s_con));
+
+			ws_802_1x_fill_connection (self->security, "wpa_eap_auth_combo", tmp_connection);
+
+			s_8021x = nm_connection_get_setting (tmp_connection, NM_TYPE_SETTING_802_1X);
+			nm_connection_add_setting (connection, NM_SETTING (g_object_ref (s_8021x)));
+
+			g_object_unref (tmp_connection);
+		} else
+			g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Invalid 802.1x security");
+	} else {
+		nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
+		valid = TRUE;
+	}
+
+	return valid;
+}
+
+static void
+ce_page_8021x_security_init (CEPage8021xSecurity *self)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+	CEPage8021xSecurity *self = CE_PAGE_8021X_SECURITY (object);
+
+	if (self->security) {
+		wireless_security_unref (self->security);
+                self->security = NULL;
+        }
+
+	G_OBJECT_CLASS (ce_page_8021x_security_parent_class)->dispose (object);
+}
+
+static void
+ce_page_8021x_security_class_init (CEPage8021xSecurityClass *security_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (security_class);
+	CEPageClass *parent_class = CE_PAGE_CLASS (security_class);
+
+	/* virtual methods */
+	object_class->dispose = dispose;
+
+	parent_class->validate = validate;
+}
diff --git a/panels/network/connection-editor/ce-page-8021x-security.h b/panels/network/connection-editor/ce-page-8021x-security.h
new file mode 100644
index 0000000..1432b0e
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-8021x-security.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 - 2012 Red Hat, Inc.
+ */
+
+#ifndef __CE_PAGE_8021X_SECURITY_H
+#define __CE_PAGE_8021X_SECURITY_H
+
+#include <nm-connection.h>
+#include "wireless-security.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "ce-page.h"
+
+#define CE_TYPE_PAGE_8021X_SECURITY            (ce_page_8021x_security_get_type ())
+#define CE_PAGE_8021X_SECURITY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CE_TYPE_PAGE_8021X_SECURITY, CEPage8021xSecurity))
+#define CE_PAGE_8021X_SECURITY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CE_TYPE_PAGE_8021X_SECURITY, CEPage8021xSecurityClass))
+#define CE_IS_PAGE_8021X_SECURITY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CE_TYPE_PAGE_8021X_SECURITY))
+#define CE_IS_PAGE_8021X_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CE_TYPE_PAGE_8021X_SECURITY))
+#define CE_PAGE_8021X_SECURITY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CE_TYPE_PAGE_8021X_SECURITY, CEPage8021xSecurityClass))
+
+typedef struct CEPage8021xSecurity      CEPage8021xSecurity;
+typedef struct CEPage8021xSecurityClass CEPage8021xSecurityClass;
+
+struct CEPage8021xSecurity {
+	CEPage parent;
+
+        GtkToggleButton *enabled;
+        GtkWidget *security_widget;
+        WirelessSecurity *security;
+
+        gboolean initial_have_8021x;
+};
+
+struct CEPage8021xSecurityClass {
+	CEPageClass parent;
+};
+
+GType ce_page_8021x_security_get_type (void);
+
+CEPage *ce_page_8021x_security_new (NMConnection     *connection,
+                                    NMClient         *client,
+                                    NMRemoteSettings *settings);
+
+#endif  /* __CE_PAGE_8021X_SECURITY_H */
diff --git a/panels/network/connection-editor/ce-page-details.c b/panels/network/connection-editor/ce-page-details.c
index 0beb55f..ff8edb4 100644
--- a/panels/network/connection-editor/ce-page-details.c
+++ b/panels/network/connection-editor/ce-page-details.c
@@ -26,6 +26,7 @@
 
 #include <nm-utils.h>
 #include <nm-device-wifi.h>
+#include <nm-device-ethernet.h>
 
 #include "../panel-common.h"
 #include "ce-page-details.h"
@@ -136,6 +137,7 @@ connect_details_page (CEPageDetails *page)
         NMDeviceState state;
         NMAccessPoint *active_ap;
         const gchar *str;
+        gboolean device_is_active;
 
         widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
                                                      "auto_connect_switch"));
@@ -150,12 +152,33 @@ connect_details_page (CEPageDetails *page)
         g_signal_connect (widget, "notify::active",
                           G_CALLBACK (all_user_changed), page);
 
-        active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (page->device));
+        if (NM_IS_DEVICE_WIFI (page->device))
+                active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (page->device));
+        else
+                active_ap = NULL;
+
         state = nm_device_get_state (page->device);
 
+        device_is_active = FALSE;
         speed = 0;
-        if (page->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) {
-                speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000;
+        if (active_ap && page->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) {
+                device_is_active = TRUE;
+                if (NM_IS_DEVICE_WIFI (page->device))
+                        speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000;
+        } else {
+                NMActiveConnection *ac;
+                const gchar *p1, *p2;
+
+                ac = nm_device_get_active_connection (page->device);
+                p1 = ac ? nm_active_connection_get_connection (ac) : NULL;
+                p2 = nm_connection_get_path (CE_PAGE (page)->connection);
+                if (g_strcmp0 (p1, p2) == 0) {
+                        device_is_active = TRUE;
+                        if (NM_IS_DEVICE_WIFI (page->device))
+                                speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000;
+                        else if (NM_IS_DEVICE_ETHERNET (page->device))
+                                speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (page->device));
+                }
         }
         if (speed > 0)
                 str = g_strdup_printf (_("%d Mb/s"), speed);
@@ -163,11 +186,15 @@ connect_details_page (CEPageDetails *page)
                 str = NULL;
         panel_set_device_widget_details (CE_PAGE (page)->builder, "speed", str);
 
-        str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (page->device));
+        if (NM_IS_DEVICE_WIFI (page->device))
+                str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (page->device));
+        else if (NM_IS_DEVICE_ETHERNET (page->device))
+                str = nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (page->device));
+
         panel_set_device_widget_details (CE_PAGE (page)->builder, "mac", str);
 
         str = NULL;
-        if (page->ap == active_ap)
+        if (device_is_active && active_ap)
                 str = get_ap_security_string (active_ap);
         panel_set_device_widget_details (CE_PAGE (page)->builder, "security", str);
 
@@ -190,12 +217,12 @@ connect_details_page (CEPageDetails *page)
         panel_set_device_widget_details (CE_PAGE (page)->builder, "strength", str);
 
         /* set IP entries */
-        if (page->ap != active_ap)
-                panel_unset_device_widgets (CE_PAGE (page)->builder);
-        else
+        if (device_is_active)
                 panel_set_device_widgets (CE_PAGE (page)->builder, page->device);
+        else
+                panel_unset_device_widgets (CE_PAGE (page)->builder);
 
-        if (page->ap != active_ap && CE_PAGE (page)->connection)
+        if (!device_is_active && CE_PAGE (page)->connection)
                 update_last_used (page, CE_PAGE (page)->connection);
         else
                 panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", NULL);
diff --git a/panels/network/connection-editor/ce-page-ethernet.c b/panels/network/connection-editor/ce-page-ethernet.c
new file mode 100644
index 0000000..d11b7cb
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ethernet.c
@@ -0,0 +1,304 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <nm-utils.h>
+#include <nm-device-ethernet.h>
+
+#include <net/if_arp.h>
+
+#include "ce-page-ethernet.h"
+
+G_DEFINE_TYPE (CEPageEthernet, ce_page_ethernet, CE_TYPE_PAGE)
+
+enum {
+        PORT_DEFAULT,
+        PORT_TP,
+        PORT_AUI,
+        PORT_BNC,
+        PORT_MII
+};
+
+enum {
+        SPEED_DEFAULT,
+        SPEED_10,
+        SPEED_100,
+        SPEED_1000,
+        SPEED_10000
+};
+
+static void
+connect_ethernet_page (CEPageEthernet *page)
+{
+        NMSettingWired *setting = page->setting_wired;
+        const char *port;
+        const char *duplex;
+        int port_idx = PORT_DEFAULT;
+        int speed_idx;
+        int mtu_def;
+        char **mac_list;
+        const GByteArray *s_mac;
+        char *s_mac_str;
+        GtkWidget *widget;
+        const gchar *name;
+
+        name = nm_setting_connection_get_id (page->setting_connection);
+        gtk_entry_set_text (page->name, name);
+
+        /* Port */
+        port = nm_setting_wired_get_port (setting);
+        if (port) {
+                if (!strcmp (port, "tp"))
+                        port_idx = PORT_TP;
+                else if (!strcmp (port, "aui"))
+                        port_idx = PORT_AUI;
+                else if (!strcmp (port, "bnc"))
+                        port_idx = PORT_BNC;
+                else if (!strcmp (port, "mii"))
+                        port_idx = PORT_MII;
+        }
+        gtk_combo_box_set_active (page->port, port_idx);
+
+        /* Speed */
+        switch (nm_setting_wired_get_speed (setting)) {
+        case 10:
+                speed_idx = SPEED_10;
+                break;
+        case 100:
+                speed_idx = SPEED_100;
+                break;
+        case 1000:
+                speed_idx = SPEED_1000;
+                break;
+        case 10000:
+                speed_idx = SPEED_10000;
+                break;
+        default:
+                speed_idx = SPEED_DEFAULT;
+                break;
+        }
+        gtk_combo_box_set_active (page->speed, speed_idx);
+        /* Duplex */
+        duplex = nm_setting_wired_get_duplex (setting);
+        if (duplex && !strcmp (duplex, "half"))
+                gtk_toggle_button_set_active (page->duplex, FALSE);
+        else
+                gtk_toggle_button_set_active (page->duplex, TRUE);
+
+        /* Autonegotiate */
+        gtk_toggle_button_set_active (page->autonegotiate,
+                                      nm_setting_wired_get_auto_negotiate (setting));
+
+        /* Device MAC address */
+        mac_list = ce_page_get_mac_list (CE_PAGE (page)->client, NM_TYPE_DEVICE_ETHERNET,
+                                         NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
+        s_mac = nm_setting_wired_get_mac_address (setting);
+        s_mac_str = s_mac ? nm_utils_hwaddr_ntoa (s_mac->data, ARPHRD_ETHER) : NULL;
+        ce_page_setup_mac_combo (page->device_mac, s_mac_str, mac_list);
+        g_free (s_mac_str);
+        g_strfreev (mac_list);
+        g_signal_connect_swapped (page->device_mac, "changed", G_CALLBACK (ce_page_changed), page);
+
+        /* Cloned MAC address */
+        ce_page_mac_to_entry (nm_setting_wired_get_cloned_mac_address (setting),
+                              ARPHRD_ETHER, page->cloned_mac);
+        g_signal_connect_swapped (page->cloned_mac, "changed", G_CALLBACK (ce_page_changed), page);
+
+        /* MTU */
+        mtu_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRED_MTU);
+        g_signal_connect (page->mtu, "output",
+                          G_CALLBACK (ce_spin_output_with_default),
+                          GINT_TO_POINTER (mtu_def));
+
+        gtk_spin_button_set_value (page->mtu, (gdouble) nm_setting_wired_get_mtu (setting));
+
+        g_signal_connect_swapped (page->name, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (page->port, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (page->speed, "changed", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (page->duplex, "toggled", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (page->autonegotiate, "toggled", G_CALLBACK (ce_page_changed), page);
+        g_signal_connect_swapped (page->mtu, "value-changed", G_CALLBACK (ce_page_changed), page);
+
+        /* Hide widgets we don't yet support */
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "heading_port"));
+        gtk_widget_hide (widget);
+        gtk_widget_hide (GTK_WIDGET (page->port));
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "heading_speed"));
+        gtk_widget_hide (widget);
+        gtk_widget_hide (GTK_WIDGET (page->speed));
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "check_duplex"));
+        gtk_widget_hide (widget);
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "check_renegotiate"));
+        gtk_widget_hide (widget);
+}
+
+static void
+ui_to_setting (CEPageEthernet *page)
+{
+        const char *port;
+        guint32 speed;
+        GByteArray *device_mac = NULL;
+        GByteArray *cloned_mac = NULL;
+        GtkWidget *entry;
+
+        /* Port */
+        switch (gtk_combo_box_get_active (page->port)) {
+        case PORT_TP:
+                port = "tp";
+                break;
+        case PORT_AUI:
+                port = "aui";
+                break;
+        case PORT_BNC:
+                port = "bnc";
+                break;
+        case PORT_MII:
+                port = "mii";
+                break;
+        default:
+                port = NULL;
+                break;
+        }
+
+        /* Speed */
+        switch (gtk_combo_box_get_active (page->speed)) {
+        case SPEED_10:
+                speed = 10;
+                break;
+        case SPEED_100:
+                speed = 100;
+                break;
+        case SPEED_1000:
+                speed = 1000;
+                break;
+        case SPEED_10000:
+                speed = 10000;
+                break;
+        default:
+                speed = 0;
+                break;
+        }
+
+        entry = gtk_bin_get_child (GTK_BIN (page->device_mac));
+        if (entry)
+                device_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+        cloned_mac = ce_page_entry_to_mac (page->cloned_mac, ARPHRD_ETHER, NULL);
+
+        g_object_set (page->setting_wired,
+                      NM_SETTING_WIRED_MAC_ADDRESS, device_mac,
+                      NM_SETTING_WIRED_CLONED_MAC_ADDRESS, cloned_mac,
+                      NM_SETTING_WIRED_PORT, port,
+                      NM_SETTING_WIRED_SPEED, speed,
+                      NM_SETTING_WIRED_DUPLEX, gtk_toggle_button_get_active (page->duplex) ? "full" : "half",
+                      NM_SETTING_WIRED_AUTO_NEGOTIATE, gtk_toggle_button_get_active (page->autonegotiate),
+                      NM_SETTING_WIRED_MTU, (guint32) gtk_spin_button_get_value_as_int (page->mtu),
+                      NULL);
+
+        if (device_mac)
+                g_byte_array_free (device_mac, TRUE);
+        if (cloned_mac)
+                g_byte_array_free (cloned_mac, TRUE);
+
+        g_object_set (page->setting_connection,
+                      NM_SETTING_CONNECTION_ID, gtk_entry_get_text (page->name),
+                      NULL);
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        CEPageEthernet *self = CE_PAGE_ETHERNET (page);
+        gboolean invalid = FALSE;
+        GByteArray *ignore;
+        GtkWidget *entry;
+
+        entry = gtk_bin_get_child (GTK_BIN (self->device_mac));
+        if (entry) {
+                ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+                if (invalid)
+                        return FALSE;
+                if (ignore)
+                        g_byte_array_free (ignore, TRUE);
+        }
+
+        ignore = ce_page_entry_to_mac (self->cloned_mac, ARPHRD_ETHER, &invalid);
+        if (invalid)
+                return FALSE;
+        if (ignore)
+                g_byte_array_free (ignore, TRUE);
+
+        ui_to_setting (self);
+
+        return nm_setting_verify (NM_SETTING (self->setting_connection), NULL, error) &&
+               nm_setting_verify (NM_SETTING (self->setting_wired), NULL, error);
+}
+
+static void
+ce_page_ethernet_init (CEPageEthernet *page)
+{
+}
+
+static void
+ce_page_ethernet_class_init (CEPageEthernetClass *class)
+{
+        CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_ethernet_new (NMConnection     *connection,
+                      NMClient         *client,
+                      NMRemoteSettings *settings)
+{
+        CEPageEthernet *page;
+
+        page = CE_PAGE_ETHERNET (ce_page_new (CE_TYPE_PAGE_ETHERNET,
+                                              connection,
+                                              client,
+                                              settings,
+                                              GNOMECC_UI_DIR "/ethernet-page.ui",
+                                              _("Identity")));
+
+        page->name = GTK_ENTRY (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_name"));
+        page->device_mac = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_mac"));
+        page->cloned_mac = GTK_ENTRY (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_cloned_mac"));
+        page->port = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_port"));
+        page->speed = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_speed"));
+        page->duplex = GTK_TOGGLE_BUTTON (gtk_builder_get_object (CE_PAGE (page)->builder, "check_duplex"));
+        page->autonegotiate = GTK_TOGGLE_BUTTON (gtk_builder_get_object (CE_PAGE (page)->builder, "check_renegotiate"));
+        page->mtu = GTK_SPIN_BUTTON (gtk_builder_get_object (CE_PAGE (page)->builder, "spin_mtu"));
+
+        page->setting_connection = nm_connection_get_setting_connection (connection);
+        page->setting_wired = nm_connection_get_setting_wired (connection);
+
+        connect_ethernet_page (page);
+
+        return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-ethernet.h b/panels/network/connection-editor/ce-page-ethernet.h
new file mode 100644
index 0000000..3f0942e
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ethernet.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more ethernet.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_ETHERNET_H
+#define __CE_PAGE_ETHERNET_H
+
+#include <glib-object.h>
+
+#include <nm-setting-wired.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_ETHERNET          (ce_page_ethernet_get_type ())
+#define CE_PAGE_ETHERNET(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_ETHERNET, CEPageEthernet))
+#define CE_PAGE_ETHERNET_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_ETHERNET, CEPageEthernetClass))
+#define CE_IS_PAGE_ETHERNET(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_ETHERNET))
+#define CE_IS_PAGE_ETHERNET_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_ETHERNET))
+#define CE_PAGE_ETHERNET_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_ETHERNET, CEPageEthernetClass))
+
+typedef struct _CEPageEthernet          CEPageEthernet;
+typedef struct _CEPageEthernetClass     CEPageEthernetClass;
+
+struct _CEPageEthernet
+{
+        CEPage parent;
+
+        NMSettingConnection *setting_connection;
+        NMSettingWired *setting_wired;
+
+        GtkEntry        *name;
+        GtkComboBoxText *device_mac;
+        GtkEntry        *cloned_mac;
+        GtkComboBox     *port;
+        GtkComboBox     *speed;
+        GtkToggleButton *duplex;
+        GtkToggleButton *autonegotiate;
+        GtkSpinButton   *mtu;
+};
+
+struct _CEPageEthernetClass
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_ethernet_get_type (void);
+
+CEPage *ce_page_ethernet_new      (NMConnection     *connection,
+                                   NMClient         *client,
+                                   NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_ETHERNET_H */
+
diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c
index 7a7e862..5cdb080 100644
--- a/panels/network/connection-editor/ce-page-ip4.c
+++ b/panels/network/connection-editor/ce-page-ip4.c
@@ -894,6 +894,10 @@ ce_page_ip4_new (NMConnection     *connection,
                                            _("IPv4")));
 
         page->setting = nm_connection_get_setting_ip4_config (connection);
+        if (!page->setting) {
+                page->setting = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+                nm_connection_add_setting (connection, NM_SETTING (page->setting));
+        }
 
         connect_ip4_page (page);
 
diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c
index 06c0214..099d207 100644
--- a/panels/network/connection-editor/ce-page-ip6.c
+++ b/panels/network/connection-editor/ce-page-ip6.c
@@ -855,6 +855,10 @@ ce_page_ip6_new (NMConnection     *connection,
                                            _("IPv6")));
 
         page->setting = nm_connection_get_setting_ip6_config (connection);
+        if (!page->setting) {
+                page->setting = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
+                nm_connection_add_setting (connection, NM_SETTING (page->setting));
+        }
 
         connect_ip6_page (page);
 
diff --git a/panels/network/connection-editor/ce-page.c b/panels/network/connection-editor/ce-page.c
index 4794a5f..f6c1f40 100644
--- a/panels/network/connection-editor/ce-page.c
+++ b/panels/network/connection-editor/ce-page.c
@@ -28,6 +28,8 @@
 
 #include <nm-utils.h>
 
+#include <glib/gi18n.h>
+
 #include "ce-page.h"
 
 
@@ -224,20 +226,23 @@ ce_page_new (GType             type,
         page->title = g_strdup (title);
         page->client = client;
         page->settings= settings;
-        if (!gtk_builder_add_from_file (page->builder, ui_file, &error)) {
-                g_warning ("Couldn't load builder file: %s", error->message);
-                g_error_free (error);
-                g_object_unref (page);
-                return NULL;
-        }
-        page->page = GTK_WIDGET (gtk_builder_get_object (page->builder, "page"));
-        if (!page->page) {
-                g_warning ("Couldn't load page widget from %s", ui_file);
-                g_object_unref (page);
-                return NULL;
-        }
 
-        g_object_ref_sink (page->page);
+        if (ui_file) {
+                if (!gtk_builder_add_from_file (page->builder, ui_file, &error)) {
+                        g_warning ("Couldn't load builder file: %s", error->message);
+                        g_error_free (error);
+                        g_object_unref (page);
+                        return NULL;
+                }
+                page->page = GTK_WIDGET (gtk_builder_get_object (page->builder, "page"));
+                if (!page->page) {
+                        g_warning ("Couldn't load page widget from %s", ui_file);
+                        g_object_unref (page);
+                        return NULL;
+                }
+
+                g_object_ref_sink (page->page);
+        }
 
         return page;
 }
@@ -452,3 +457,92 @@ ce_page_get_security_setting (CEPage *page)
 {
         return page->security_setting;
 }
+
+gint
+ce_get_property_default (NMSetting *setting, const gchar *property_name)
+{
+        GParamSpec *spec;
+        GValue value = { 0, };
+
+        spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
+        g_return_val_if_fail (spec != NULL, -1);
+
+        g_value_init (&value, spec->value_type);
+        g_param_value_set_default (spec, &value);
+
+        if (G_VALUE_HOLDS_CHAR (&value))
+                return (int) g_value_get_schar (&value);
+        else if (G_VALUE_HOLDS_INT (&value))
+                return g_value_get_int (&value);
+        else if (G_VALUE_HOLDS_INT64 (&value))
+                return (int) g_value_get_int64 (&value);
+        else if (G_VALUE_HOLDS_LONG (&value))
+                return (int) g_value_get_long (&value);
+        else if (G_VALUE_HOLDS_UINT (&value))
+                return (int) g_value_get_uint (&value);
+        else if (G_VALUE_HOLDS_UINT64 (&value))
+                return (int) g_value_get_uint64 (&value);
+        else if (G_VALUE_HOLDS_ULONG (&value))
+                return (int) g_value_get_ulong (&value);
+        else if (G_VALUE_HOLDS_UCHAR (&value))
+                return (int) g_value_get_uchar (&value);
+        g_return_val_if_fail (FALSE, 0);
+        return 0;
+}
+
+gint
+ce_spin_output_with_default (GtkSpinButton *spin, gpointer user_data)
+{
+        gint defvalue = GPOINTER_TO_INT (user_data);
+        gint val;
+        gchar *buf = NULL;
+
+        val = gtk_spin_button_get_value_as_int (spin);
+        if (val == defvalue)
+                buf = g_strdup (_("automatic"));
+        else
+                buf = g_strdup_printf ("%d", val);
+
+        if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin))))
+                gtk_entry_set_text (GTK_ENTRY (spin), buf);
+
+        g_free (buf);
+        return TRUE;
+}
+
+gchar *
+ce_page_get_next_available_name (GSList *connections, const gchar *format)
+{
+        GSList *names = NULL, *l;
+        gchar *cname = NULL;
+        gint i = 0;
+
+        for (l = connections; l; l = l->next) {
+                const gchar *id;
+
+                id = nm_connection_get_id (NM_CONNECTION (l->data));
+                g_assert (id);
+                names = g_slist_append (names, (gpointer) id);
+        }
+
+        /* Find the next available unique connection name */
+        while (!cname && (i++ < 10000)) {
+                gchar *temp;
+                gboolean found = FALSE;
+
+                temp = g_strdup_printf (format, i);
+                for (l = names; l; l = l->next) {
+                        if (!strcmp (l->data, temp)) {
+                                found = TRUE;
+                                break;
+                        }
+                }
+                if (!found)
+                        cname = temp;
+                else
+                        g_free (temp);
+        }
+        g_slist_free (names);
+
+        return cname;
+}
diff --git a/panels/network/connection-editor/ce-page.h b/panels/network/connection-editor/ce-page.h
index 2de2ada..58cd41d 100644
--- a/panels/network/connection-editor/ce-page.h
+++ b/panels/network/connection-editor/ce-page.h
@@ -99,6 +99,14 @@ void         ce_page_mac_to_entry    (const GByteArray *mac,
 GByteArray  *ce_page_entry_to_mac    (GtkEntry         *entry,
                                       gint              type,
                                       gboolean         *invalid);
+gint         ce_get_property_default (NMSetting        *setting,
+                                      const gchar      *property_name);
+gint         ce_spin_output_with_default (GtkSpinButton *spin,
+                                          gpointer       user_data);
+
+gchar * ce_page_get_next_available_name (GSList *connections, const gchar *format);
+
+
 
 G_END_DECLS
 
diff --git a/panels/network/connection-editor/ethernet-page.ui b/panels/network/connection-editor/ethernet-page.ui
new file mode 100644
index 0000000..477b0ad
--- /dev/null
+++ b/panels/network/connection-editor/ethernet-page.ui
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkAdjustment" id="adjustment1">
+    <property name="upper">10000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkListStore" id="model1">
+    <columns>
+      <!-- column-name gchararray1 -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Automatic</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Twisted Pair (TP)</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Attachment Unit Interface (AUI)</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">BNC</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Media Independent Interface (MII)</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="model2">
+    <columns>
+      <!-- column-name < -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Automatic</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">10 Mb/s</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">100 Mb/s</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">1 Gb/s</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">10 Gb/s</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkGrid" id="page">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="margin_left">50</property>
+    <property name="margin_right">50</property>
+    <property name="margin_top">12</property>
+    <property name="margin_bottom">12</property>
+    <property name="hexpand">True</property>
+    <property name="vexpand">True</property>
+    <property name="row_spacing">10</property>
+    <property name="column_spacing">6</property>
+    <child>
+      <object class="GtkLabel" id="heading_mtu">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">_MTU</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">spin_mtu</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">7</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkSpinButton" id="spin_mtu">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">â</property>
+            <property name="adjustment">adjustment1</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_mtu">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">bytes</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">7</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="heading_cloned_mac">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">_Cloned MAC Address</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">entry_cloned_mac</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">6</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="heading_mac">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">_MAC Address</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">combo_mac</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">5</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkEntry" id="entry_cloned_mac">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hexpand">True</property>
+        <property name="invisible_char">â</property>
+        <property name="invisible_char_set">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">6</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkComboBoxText" id="combo_mac">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="has_entry">True</property>
+        <property name="entry_text_column">0</property>
+        <property name="id_column">1</property>
+        <child internal-child="entry">
+          <object class="GtkEntry" id="comboboxtext-entry2">
+            <property name="can_focus">False</property>
+            <property name="invisible_char">â</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">5</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="heading_port">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">_Port</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">combo_port</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="heading_speed">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">_Speed</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">combo_speed</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">2</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkCheckButton" id="check_duplex">
+        <property name="label" translatable="yes">_Full duplex</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+        <property name="xalign">0</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">3</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkCheckButton" id="check_renegotiate">
+        <property name="label" translatable="yes">_Automatic renegotiation</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+        <property name="xalign">0</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">4</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkComboBox" id="combo_port">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="model">model1</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">1</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkComboBox" id="combo_speed">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="model">model2</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">2</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="heading_name">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">Name</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">entry_name</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkEntry" id="entry_name">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="invisible_char">â</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">0</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c
index b3d0672..b4b5034 100644
--- a/panels/network/connection-editor/net-connection-editor.c
+++ b/panels/network/connection-editor/net-connection-editor.c
@@ -34,6 +34,8 @@
 #include "ce-page-ip6.h"
 #include "ce-page-security.h"
 #include "ce-page-reset.h"
+#include "ce-page-ethernet.h"
+#include "ce-page-8021x-security.h"
 
 #include "egg-list-box/egg-list-box.h"
 
@@ -87,7 +89,9 @@ update_complete (NetConnectionEditor *editor, GError *error)
 }
 
 static void
-updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer data)
+updated_connection_cb (NMRemoteConnection *connection,
+                       GError             *error,
+                       gpointer            data)
 {
         NetConnectionEditor *editor = data;
 
@@ -97,11 +101,36 @@ updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer d
 }
 
 static void
+added_connection_cb (NMRemoteSettings   *settings,
+                     NMRemoteConnection *connection,
+                     GError             *error,
+                     gpointer            data)
+{
+        NetConnectionEditor *editor = data;
+
+        if (error) {
+                g_warning ("Failed to add connection: %s", error->message);
+                /* Leave the editor open */
+                return;
+        }
+
+        update_complete (editor, error);
+}
+
+static void
 apply_edits (NetConnectionEditor *editor)
 {
         update_connection (editor);
-        nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (editor->orig_connection),
-                                             updated_connection_cb, editor);
+
+        if (!nm_remote_settings_get_connection_by_uuid (editor->settings, nm_connection_get_uuid (editor->orig_connection)))
+                nm_remote_settings_add_connection (editor->settings,
+                                                   editor->orig_connection,
+                                                   added_connection_cb,
+                                                   editor);
+        else {
+                nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (editor->orig_connection),
+                                                     updated_connection_cb, editor);
+        }
 }
 
 static void
@@ -191,8 +220,12 @@ net_connection_editor_update_title (NetConnectionEditor *editor)
         gchar *id;
 
         sw = nm_connection_get_setting_wireless (editor->connection);
-        ssid = nm_setting_wireless_get_ssid (sw);
-        id = nm_utils_ssid_to_utf8 (ssid);
+        if (sw) {
+                ssid = nm_setting_wireless_get_ssid (sw);
+                id = nm_utils_ssid_to_utf8 (ssid);
+        } else {
+                id = g_strdup (nm_connection_get_id (editor->connection));
+        }
         gtk_window_set_title (GTK_WINDOW (editor->window), id);
         g_free (id);
 }
@@ -385,17 +418,31 @@ net_connection_editor_set_connection (NetConnectionEditor *editor,
                                       NMConnection        *connection)
 {
         GSList *pages, *l;
+        NMSettingConnection *sc;
+        const gchar *type;
 
         editor->connection = nm_connection_duplicate (connection);
         editor->orig_connection = g_object_ref (connection);
 
         net_connection_editor_update_title (editor);
 
+        sc = nm_connection_get_setting_connection (connection);
+        type = nm_setting_connection_get_connection_type (sc);
+
         add_page (editor, ce_page_details_new (editor->connection, editor->client, editor->settings, editor->device, editor->ap));
-        add_page (editor, ce_page_wifi_new (editor->connection, editor->client, editor->settings));
+        if (strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME) == 0)
+                add_page (editor, ce_page_wifi_new (editor->connection, editor->client, editor->settings));
+        else if (strcmp (type, NM_SETTING_WIRED_SETTING_NAME) == 0)
+                add_page (editor, ce_page_ethernet_new (editor->connection, editor->client, editor->settings));
+
         add_page (editor, ce_page_ip4_new (editor->connection, editor->client, editor->settings));
         add_page (editor, ce_page_ip6_new (editor->connection, editor->client, editor->settings));
-        add_page (editor, ce_page_security_new (editor->connection, editor->client, editor->settings));
+
+        if (strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME) == 0)
+                add_page (editor, ce_page_security_new (editor->connection, editor->client, editor->settings));
+        else if (strcmp (type, NM_SETTING_WIRED_SETTING_NAME) == 0)
+                add_page (editor, ce_page_8021x_security_new (editor->connection, editor->client, editor->settings));
+
         add_page (editor, ce_page_reset_new (editor->connection, editor->client, editor->settings, editor));
 
         pages = g_slist_copy (editor->initializing_pages);
diff --git a/panels/network/net-device-ethernet.c b/panels/network/net-device-ethernet.c
index 3ac6faa..f3ef774 100644
--- a/panels/network/net-device-ethernet.c
+++ b/panels/network/net-device-ethernet.c
@@ -28,9 +28,14 @@
 #include <nm-device.h>
 #include <nm-device-ethernet.h>
 #include <nm-remote-connection.h>
+#include <nm-utils.h>
 
 #include "panel-common.h"
 
+#include "egg-list-box/egg-list-box.h"
+#include "connection-editor/net-connection-editor.h"
+#include "connection-editor/ce-page.h"
+
 #include "net-device-ethernet.h"
 
 G_DEFINE_TYPE (NetDeviceEthernet, net_device_ethernet, NET_TYPE_DEVICE_SIMPLE)
@@ -51,15 +56,459 @@ device_ethernet_get_speed (NetDeviceSimple *device_simple)
                 return NULL;
 }
 
+static GSList *
+valid_connections_for_device (NMRemoteSettings *remote_settings,
+                              NetDevice        *device)
+{
+        GSList *all, *filtered, *iterator, *valid;
+        NMConnection *connection;
+        NMSettingConnection *s_con;
+
+        all = nm_remote_settings_list_connections (remote_settings);
+        filtered = nm_device_filter_connections (net_device_get_nm_device (device), all);
+        g_slist_free (all);
+
+        valid = NULL;
+        for (iterator = filtered; iterator; iterator = iterator->next) {
+                connection = iterator->data;
+                s_con = nm_connection_get_setting_connection (connection);
+                if (!s_con)
+                        continue;
+
+                if (nm_setting_connection_get_master (s_con))
+                        continue;
+
+                valid = g_slist_prepend (valid, connection);
+        }
+        g_slist_free (filtered);
+
+        return g_slist_reverse (valid);
+}
+
+static GtkWidget *
+device_ethernet_add_to_notebook (NetObject    *object,
+                                 GtkNotebook  *notebook,
+                                 GtkSizeGroup *heading_size_group)
+{
+        NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
+        GtkWidget *vbox;
+
+        vbox = GTK_WIDGET (gtk_builder_get_object (device->builder, "vbox6"));
+        g_object_ref (vbox);
+        gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (vbox)), vbox);
+        gtk_notebook_append_page (notebook, vbox, NULL);
+        g_object_unref (vbox);
+        return vbox;
+}
+
+static void
+add_details_row (GtkWidget *details, gint top, const gchar *heading, const gchar *value)
+{
+        GtkWidget *label;
+
+        label = gtk_label_new (heading);
+        gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+        gtk_widget_set_halign (label, GTK_ALIGN_END);
+        gtk_widget_set_hexpand (label, TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
+
+        gtk_grid_attach (GTK_GRID (details), label, 0, top, 1, 1);
+
+        label = gtk_label_new (value);
+        gtk_widget_set_halign (label, GTK_ALIGN_START);
+        gtk_widget_set_hexpand (label, TRUE);
+        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+        gtk_grid_attach (GTK_GRID (details), label, 1, top, 1, 1);
+}
+
+static gchar *
+get_last_used_string (NMConnection *connection)
+{
+        gchar *last_used = NULL;
+        GDateTime *now = NULL;
+        GDateTime *then = NULL;
+        gint days;
+        GTimeSpan diff;
+        guint64 timestamp;
+        NMSettingConnection *s_con;
+
+        s_con = nm_connection_get_setting_connection (connection);
+        if (s_con == NULL)
+                goto out;
+        timestamp = nm_setting_connection_get_timestamp (s_con);
+        if (timestamp == 0) {
+                last_used = g_strdup (_("never"));
+                goto out;
+        }
+
+        /* calculate the amount of time that has elapsed */
+        now = g_date_time_new_now_utc ();
+        then = g_date_time_new_from_unix_utc (timestamp);
+        diff = g_date_time_difference  (now, then);
+        days = diff / G_TIME_SPAN_DAY;
+        if (days == 0)
+                last_used = g_strdup (_("today"));
+        else if (days == 1)
+                last_used = g_strdup (_("yesterday"));
+        else
+                last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
+out:
+        if (now != NULL)
+                g_date_time_unref (now);
+        if (then != NULL)
+                g_date_time_unref (then);
+
+        return last_used;
+}
+
+static void
+add_details (GtkWidget *details, NMDevice *device, NMConnection *connection)
+{
+        NMIP4Config *ip4_config = NULL;
+        NMIP6Config *ip6_config = NULL;
+        gchar *ip4_address = NULL;
+        gchar *ip4_route = NULL;
+        gchar *ip4_dns = NULL;
+        gchar *ip6_address = NULL;
+        gint i = 0;
+
+        ip4_config = nm_device_get_ip4_config (device);
+        if (ip4_config) {
+                ip4_address = panel_get_ip4_address_as_string (ip4_config, "address");
+                ip4_route = panel_get_ip4_address_as_string (ip4_config, "gateway");
+                ip4_dns = panel_get_ip4_dns_as_string (ip4_config);
+        }
+        ip6_config = nm_device_get_ip6_config (device);
+        if (ip6_config) {
+                ip6_address = panel_get_ip6_address_as_string (ip6_config);
+        }
+
+        if (ip4_address && ip6_address) {
+                add_details_row (details, i++, _("IP4 Address"), ip4_address);
+                add_details_row (details, i++, _("IP6 Address"), ip6_address);
+        } else if (ip4_address) {
+                add_details_row (details, i++, _("IP Address"), ip4_address);
+        } else if (ip6_address) {
+                add_details_row (details, i++, _("IP Address"), ip6_address);
+        }
+
+        add_details_row (details, i++, _("Hardware Address"),
+                         nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)));
+
+        if (ip4_route)
+                add_details_row (details, i++, _("Default Route"), ip4_route);
+        if (ip4_dns)
+                add_details_row (details, i++, _("DNS"), ip4_dns);
+
+        if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) {
+                gchar *last_used;
+                last_used = get_last_used_string (connection);
+                add_details_row (details, i++, _("Last used"), last_used);
+                g_free (last_used);
+        }
+
+        g_free (ip4_address);
+        g_free (ip4_route);
+        g_free (ip4_dns);
+        g_free (ip6_address);
+}
+
+static void populate_ui (NetDeviceEthernet *device);
+
+static void
+editor_done (NetConnectionEditor *editor,
+             gboolean             success,
+             NetDeviceEthernet   *device)
+{
+        g_object_unref (editor);
+        populate_ui (device);
+}
+
+static void
+show_details_for_row (GtkButton *button, NetDeviceEthernet *device)
+{
+        GtkWidget *row;
+        NMConnection *connection;
+        GtkWidget *window;
+        NetConnectionEditor *editor;
+        NMClient *client;
+        NMRemoteSettings *settings;
+        NMDevice *nmdev;
+
+        window = gtk_widget_get_toplevel (GTK_WIDGET (button));
+
+        row = GTK_WIDGET (g_object_get_data (G_OBJECT (button), "row"));
+        connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection"));
+
+        nmdev = net_device_get_nm_device (NET_DEVICE (device));
+        client = net_object_get_client (NET_OBJECT (device));
+        settings = net_object_get_remote_settings (NET_OBJECT (device));
+        editor = net_connection_editor_new (GTK_WINDOW (window), connection, nmdev, NULL, client, settings);
+        g_signal_connect (editor, "done", G_CALLBACK (editor_done), device);
+        net_connection_editor_run (editor);
+}
+
+static void
+add_row (NetDeviceEthernet *device, NMConnection *connection)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *box;
+        GtkWidget *details;
+        NMDevice *nmdev;
+        NMActiveConnection *aconn;
+        gboolean active;
+        GtkWidget *image;
+
+        active = FALSE;
+
+        nmdev = net_device_get_nm_device (NET_DEVICE (device));
+        aconn = nm_device_get_active_connection (nmdev);
+        if (aconn) {
+                const gchar *path1, *path2;
+                path1 = nm_active_connection_get_connection (aconn);
+                path2 = nm_connection_get_path (connection);
+                active = g_strcmp0 (path1, path2) == 0;
+        }
+
+        row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        gtk_box_pack_start (GTK_BOX (row), box, FALSE, TRUE, 0);
+        widget = gtk_label_new (nm_connection_get_id (connection));
+        gtk_widget_set_margin_left (widget, 12);
+        gtk_widget_set_margin_right (widget, 12);
+        gtk_widget_set_margin_top (widget, 12);
+        gtk_widget_set_margin_bottom (widget, 12);
+        gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
+
+        if (active) {
+                widget = gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU);
+                gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+                gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+                gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
+
+                details = gtk_grid_new ();
+                gtk_grid_set_row_spacing (GTK_GRID (details), 10);
+                gtk_grid_set_column_spacing (GTK_GRID (details), 10);
+
+                gtk_box_pack_start (GTK_BOX (row), details, FALSE, TRUE, 0);
+
+                add_details (details, nmdev, connection);
+        }
+
+        /* filler */
+        widget = gtk_label_new ("");
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
+
+        image = gtk_image_new_from_icon_name ("emblem-system-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_widget_show (image);
+        widget = gtk_button_new ();
+        gtk_widget_set_margin_left (widget, 12);
+        gtk_widget_set_margin_right (widget, 12);
+        gtk_widget_set_margin_top (widget, 12);
+        gtk_widget_set_margin_bottom (widget, 12);
+        gtk_widget_show (widget);
+        gtk_container_add (GTK_CONTAINER (widget), image);
+        gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
+        g_object_set_data (G_OBJECT (row), "edit", widget);
+        g_object_set_data (G_OBJECT (widget), "row", row);
+        g_signal_connect (widget, "clicked",
+                          G_CALLBACK (show_details_for_row), device);
+
+        gtk_widget_show_all (row);
+
+        g_object_set_data (G_OBJECT (row), "connection", connection);
+
+        gtk_container_add (GTK_CONTAINER (device->list), row);
+}
+
+static void
+populate_ui (NetDeviceEthernet *device)
+{
+        NMRemoteSettings *settings;
+        GList *children, *c;
+        GSList *connections, *l;
+        NMConnection *connection;
+        gint n_connections;
+
+        children = gtk_container_get_children (GTK_CONTAINER (device->list));
+        for (c = children; c; c = c->next) {
+                gtk_container_remove (GTK_CONTAINER (device->list), c->data);
+        }
+        g_list_free (children);
+
+        children = gtk_container_get_children (GTK_CONTAINER (device->details));
+        for (c = children; c; c = c->next) {
+                gtk_container_remove (GTK_CONTAINER (device->details), c->data);
+        }
+        g_list_free (children);
+
+        settings = net_object_get_remote_settings (NET_OBJECT (device));
+        connections = valid_connections_for_device (settings, NET_DEVICE (device));
+
+        n_connections = g_slist_length (connections);
+        if (n_connections > 1) {
+                gtk_widget_hide (device->details);
+                gtk_widget_hide (device->details_button);
+                for (l = connections; l; l = l->next) {
+                        NMConnection *connection = l->data;
+                        add_row (device, connection);
+                }
+                gtk_widget_show (device->scrolled_window);
+        } else if (n_connections == 1) {
+                connection = connections->data;
+                gtk_widget_hide (device->scrolled_window);
+                add_details (device->details, net_device_get_nm_device (NET_DEVICE (device)), connection);
+                gtk_widget_show_all (device->details);
+                gtk_widget_show (device->details_button);
+                g_object_set_data (G_OBJECT (device->details_button), "row", device->details_button);
+                g_object_set_data (G_OBJECT (device->details_button), "connection", connection);
+
+        } else {
+                gtk_widget_hide (device->scrolled_window);
+                gtk_widget_hide (device->details);
+                gtk_widget_hide (device->details_button);
+        }
+}
+
+static void
+remote_settings_read_cb (NMRemoteSettings  *settings,
+                         NetDeviceEthernet *device)
+{
+        populate_ui (device);
+}
+
+static void
+update_separator (GtkWidget **separator,
+                  GtkWidget  *child,
+                  GtkWidget  *before,
+                  gpointer    user_data)
+{
+  if (before == NULL)
+    return;
+
+  if (*separator == NULL)
+    {
+      *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+      gtk_widget_show (*separator);
+      g_object_ref_sink (*separator);
+    }
+}
+
+static void
+add_profile (GtkButton *button, NetDeviceEthernet *device)
+{
+        NMRemoteSettings *settings;
+        NMConnection *connection;
+        NMSettingConnection *sc;
+        gchar *uuid, *id;
+        NetConnectionEditor *editor;
+        GtkWidget *window;
+        NMClient *client;
+        NMDevice *nmdev;
+        GSList *connections;
+
+        connection = nm_connection_new ();
+        sc = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+        nm_connection_add_setting (connection, NM_SETTING (sc));
+
+        uuid = nm_utils_uuid_generate ();
+
+        settings = net_object_get_remote_settings (NET_OBJECT (device));
+        connections = nm_remote_settings_list_connections (settings);
+        id = ce_page_get_next_available_name (connections, _("Profile %d"));
+        g_slist_free (connections);
+
+        g_object_set (sc,
+                      NM_SETTING_CONNECTION_UUID, uuid,
+                      NM_SETTING_CONNECTION_ID, id,
+                      NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+                      NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+                      NULL);
+
+        nm_connection_add_setting (connection, nm_setting_wired_new ());
+
+        g_free (uuid);
+        g_free (id);
+
+        window = gtk_widget_get_toplevel (GTK_WIDGET (button));
+
+        nmdev = net_device_get_nm_device (NET_DEVICE (device));
+        client = net_object_get_client (NET_OBJECT (device));
+        editor = net_connection_editor_new (GTK_WINDOW (window), connection, nmdev, NULL, client, settings);
+        g_signal_connect (editor, "done", G_CALLBACK (editor_done), device);
+        net_connection_editor_run (editor);
+}
+
+static void
+device_ethernet_constructed (GObject *object)
+{
+        NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
+        NMRemoteSettings *settings;
+        GtkWidget *list;
+        GtkWidget *swin;
+
+        device->scrolled_window = swin = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "list"));
+        device->list = list = GTK_WIDGET (egg_list_box_new ());
+        egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+        egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+        egg_list_box_add_to_scrolled (EGG_LIST_BOX (list), GTK_SCROLLED_WINDOW (swin));
+        gtk_widget_show (list);
+
+        device->details = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "details"));
+
+        device->details_button = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "details_button"));
+        g_signal_connect (device->details_button, "clicked",
+                          G_CALLBACK (show_details_for_row), device);
+
+        device->add_profile_button = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "add_profile_button"));
+        g_signal_connect (device->add_profile_button, "clicked",
+                          G_CALLBACK (add_profile), device);
+
+        settings = net_object_get_remote_settings (NET_OBJECT (object));
+        g_signal_connect (settings, "connections-read",
+                          G_CALLBACK (remote_settings_read_cb), object);
+}
+
+static void
+device_ethernet_finalize (GObject *object)
+{
+        NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
+
+        g_object_unref (device->builder);
+
+        G_OBJECT_CLASS (net_device_ethernet_parent_class)->finalize (object);
+}
+
 static void
 net_device_ethernet_class_init (NetDeviceEthernetClass *klass)
 {
         NetDeviceSimpleClass *simple_class = NET_DEVICE_SIMPLE_CLASS (klass);
+        NetObjectClass *obj_class = NET_OBJECT_CLASS (klass);
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
         simple_class->get_speed = device_ethernet_get_speed;
+        obj_class->add_to_notebook = device_ethernet_add_to_notebook;
+        object_class->constructed = device_ethernet_constructed;
+        object_class->finalize = device_ethernet_finalize;
 }
 
 static void
-net_device_ethernet_init (NetDeviceEthernet *device_ethernet)
+net_device_ethernet_init (NetDeviceEthernet *device)
 {
+        GError *error = NULL;
+
+        device->builder = gtk_builder_new ();
+        gtk_builder_add_from_file (device->builder,
+                                   GNOMECC_UI_DIR "/network-ethernet.ui",
+                                   &error);
+        if (error != NULL) {
+                g_warning ("Could not load interface file: %s", error->message);
+                g_error_free (error);
+                return;
+        }
 }
diff --git a/panels/network/net-device-ethernet.h b/panels/network/net-device-ethernet.h
index 5c22937..d7a2f7a 100644
--- a/panels/network/net-device-ethernet.h
+++ b/panels/network/net-device-ethernet.h
@@ -41,16 +41,23 @@ typedef struct _NetDeviceEthernetClass     NetDeviceEthernetClass;
 
 struct _NetDeviceEthernet
 {
-         NetDeviceSimple                 parent;
-         NetDeviceEthernetPrivate          *priv;
+        NetDeviceSimple parent;
+
+        GtkBuilder *builder;
+
+        GtkWidget *list;
+        GtkWidget *scrolled_window;
+        GtkWidget *details;
+        GtkWidget *details_button;
+        GtkWidget *add_profile_button;
 };
 
 struct _NetDeviceEthernetClass
 {
-        NetDeviceSimpleClass             parent_class;
+        NetDeviceSimpleClass parent_class;
 };
 
-GType            net_device_ethernet_get_type      (void);
+GType net_device_ethernet_get_type (void);
 
 G_END_DECLS
 
diff --git a/panels/network/network-ethernet.ui b/panels/network/network-ethernet.ui
new file mode 100644
index 0000000..574e84a
--- /dev/null
+++ b/panels/network/network-ethernet.ui
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkImage" id="image1">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">emblem-system-symbolic</property>
+  </object>
+  <object class="GtkWindow" id="window_tmp">
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkVBox" id="vbox6">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkGrid" id="grid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="row_spacing">10</property>
+            <property name="column_spacing">6</property>
+            <child>
+              <object class="GtkImage" id="image_device">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="valign">start</property>
+                <property name="xalign">1</property>
+                <property name="pixel_size">48</property>
+                <property name="icon_name">network-wired</property>
+                <property name="icon-size">6</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="valign">start</property>
+                <property name="hexpand">True</property>
+                <property name="spacing">3</property>
+                <child>
+                  <object class="GtkLabel" id="label_device">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Wired</property>
+                    <property name="ellipsize">end</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                      <attribute name="scale" value="1.2"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_status">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Cable unplugged</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkAlignment" id="alignment_switch">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="valign">start</property>
+                <child>
+                  <object class="GtkSwitch" id="device_off_switch">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="halign">end</property>
+                    <property name="valign">start</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="list">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="shadow_type">in</property>
+                <property name="margin_top">20</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">3</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="details">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="row_spacing">10</property>
+                <property name="column_spacing">10</property>
+                <property name="margin_top">20</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">3</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="actions">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_top">20</property>
+            <child>
+              <object class="GtkButton" id="add_profile_button">
+                <property name="label" translatable="yes">_Add profileâ</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="halign">start</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="details_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="halign">end</property>
+                <property name="image">image1</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkSizeGroup" id="sizegroup1"/>
+</interface>
diff --git a/panels/network/network-simple.ui b/panels/network/network-simple.ui
index a5ceb47..194e25f 100644
--- a/panels/network/network-simple.ui
+++ b/panels/network/network-simple.ui
@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkOffscreenWindow" id="offscreenwindow1">
+    <property name="can_focus">False</property>
+    <child>
+      <placeholder/>
+    </child>
+  </object>
   <object class="GtkWindow" id="window_tmp">
     <property name="can_focus">False</property>
     <child>
@@ -82,174 +88,6 @@
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="heading_mac">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">1</property>
-                <property name="label" translatable="yes">Hardware Address</property>
-                <property name="mnemonic_widget">label_mac</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">1</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="heading_ipv4">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">1</property>
-                <property name="label" translatable="yes">IPv4 Address</property>
-                <property name="mnemonic_widget">label_ipv4</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">3</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="heading_ipv6">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">1</property>
-                <property name="label" translatable="yes">IPv6 Address</property>
-                <property name="mnemonic_widget">label_ipv6</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">4</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="heading_route">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">1</property>
-                <property name="label" translatable="yes">Default Route</property>
-                <property name="mnemonic_widget">label_route</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">5</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="heading_dns">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">1</property>
-                <property name="yalign">0</property>
-                <property name="label" translatable="yes">DNS</property>
-                <property name="mnemonic_widget">label_dns</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">6</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label_mac">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="xalign">0</property>
-                <property name="label">AA:BB:CC:DD:55:66:77:88</property>
-                <property name="selectable">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">1</property>
-                <property name="width">2</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label_ipv4">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="xalign">0</property>
-                <property name="label">127.0.0.1</property>
-                <property name="selectable">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">3</property>
-                <property name="width">2</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label_ipv6">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="xalign">0</property>
-                <property name="label">::1</property>
-                <property name="selectable">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">4</property>
-                <property name="width">2</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label_route">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="xalign">0</property>
-                <property name="label">127.0.0.1</property>
-                <property name="selectable">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">5</property>
-                <property name="width">2</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label_dns">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="xalign">0</property>
-                <property name="yalign">0</property>
-                <property name="label">127.0.0.1</property>
-                <property name="wrap">True</property>
-                <property name="selectable">True</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">6</property>
-                <property name="width">2</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
               <object class="GtkAlignment" id="alignment_switch">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -272,13 +110,189 @@
               </packing>
             </child>
             <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">20</property>
+                <property name="row_spacing">10</property>
+                <property name="column_spacing">6</property>
+                <property name="row_homogeneous">True</property>
+                <property name="column_homogeneous">True</property>
+                <child>
+                  <object class="GtkLabel" id="heading_mac">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Hardware Address</property>
+                    <property name="mnemonic_widget">label_mac</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_ipv4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">IPv4 Address</property>
+                    <property name="mnemonic_widget">label_ipv4</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_ipv6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">IPv6 Address</property>
+                    <property name="mnemonic_widget">label_ipv6</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_route">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Default Route</property>
+                    <property name="mnemonic_widget">label_route</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">3</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_dns">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="yalign">0</property>
+                    <property name="label" translatable="yes">DNS</property>
+                    <property name="mnemonic_widget">label_dns</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">4</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_mac">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">AA:BB:CC:DD:55:66:77:88</property>
+                    <property name="selectable">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_ipv4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">127.0.0.1</property>
+                    <property name="selectable">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_ipv6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">::1</property>
+                    <property name="selectable">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_route">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label">127.0.0.1</property>
+                    <property name="selectable">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">3</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_dns">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="xalign">0</property>
+                    <property name="yalign">0</property>
+                    <property name="label">127.0.0.1</property>
+                    <property name="wrap">True</property>
+                    <property name="selectable">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">4</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">3</property>
+                <property name="height">1</property>
+              </packing>
             </child>
           </object>
           <packing>
@@ -321,13 +335,5 @@
       </object>
     </child>
   </object>
-  <object class="GtkSizeGroup" id="sizegroup1">
-    <widgets>
-      <widget name="heading_mac"/>
-      <widget name="heading_ipv4"/>
-      <widget name="heading_ipv6"/>
-      <widget name="heading_route"/>
-      <widget name="heading_dns"/>
-    </widgets>
-  </object>
+  <object class="GtkSizeGroup" id="sizegroup1"/>
 </interface>
diff --git a/panels/network/panel-common.c b/panels/network/panel-common.c
index fe7baf4..cafdc32 100644
--- a/panels/network/panel-common.c
+++ b/panels/network/panel-common.c
@@ -655,3 +655,21 @@ panel_unset_device_widgets (GtkBuilder *builder)
         panel_set_device_widget_details (builder, "dns", NULL);
         panel_set_device_widget_details (builder, "route", NULL);
 }
+
+gchar *
+panel_get_ip4_address_as_string (NMIP4Config *ip4, const gchar *what)
+{
+        return get_ipv4_config_address_as_string (ip4, what);
+}
+
+gchar *
+panel_get_ip4_dns_as_string (NMIP4Config *ip4)
+{
+        return get_ipv4_config_name_servers_as_string (ip4);
+}
+
+gchar *
+panel_get_ip6_address_as_string (NMIP6Config *ip6)
+{
+        return get_ipv6_config_address_as_string (ip6);
+}
diff --git a/panels/network/panel-common.h b/panels/network/panel-common.h
index c55d46b..9288e4f 100644
--- a/panels/network/panel-common.h
+++ b/panels/network/panel-common.h
@@ -45,6 +45,9 @@ gboolean         panel_set_device_widget_header                (GtkBuilder *buil
 void             panel_set_device_widgets                      (GtkBuilder *builder,
                                                                 NMDevice *device);
 void             panel_unset_device_widgets                    (GtkBuilder *builder);
+gchar           *panel_get_ip4_address_as_string               (NMIP4Config *config, const gchar *what);
+gchar           *panel_get_ip4_dns_as_string                   (NMIP4Config *config);
+gchar           *panel_get_ip6_address_as_string               (NMIP6Config *config);
 
 G_END_DECLS
 



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