[gnome-control-center/wip/networking2: 9/36] network: break out the details dialog



commit 881122688832e4aed71abd90ad1e6254ffb47121
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Dec 11 00:20:35 2012 -0500

    network: break out the details dialog
    
    This code is fairly independent of the rest, and we don't want
    net-device-wifi.c to become too massive and unmaintainable.
    
    The code in connection-editor/ is fairly similar to
    nm-connection-editor, with some simplification because we
    currently only edit wireless connections.
    
    The code in wireless-security/ is almost a straight copy
    of the same code in nm-connection-editor, with some changes
    to the .ui files to make them fit better in the new design.

 configure.ac                                       |    2 +
 panels/network/Makefile.am                         |    7 +-
 panels/network/connection-editor/Makefile.am       |   44 +
 panels/network/connection-editor/ce-page-details.c |  249 +++++
 panels/network/connection-editor/ce-page-details.h |   66 ++
 panels/network/connection-editor/ce-page-ip4.c     |  901 +++++++++++++++++
 panels/network/connection-editor/ce-page-ip4.h     |   72 ++
 panels/network/connection-editor/ce-page-ip6.c     |  862 ++++++++++++++++
 panels/network/connection-editor/ce-page-ip6.h     |   72 ++
 panels/network/connection-editor/ce-page-reset.c   |   75 ++
 panels/network/connection-editor/ce-page-reset.h   |   61 ++
 .../network/connection-editor/ce-page-security.c   |  480 +++++++++
 .../network/connection-editor/ce-page-security.h   |   66 ++
 panels/network/connection-editor/ce-page-wifi.c    |  221 +++++
 panels/network/connection-editor/ce-page-wifi.h    |   63 ++
 panels/network/connection-editor/ce-page.c         |  454 +++++++++
 panels/network/connection-editor/ce-page.h         |  106 ++
 .../connection-editor.gresource.xml                |   12 +
 .../network/connection-editor/connection-editor.ui |  140 +++
 panels/network/connection-editor/details-page.ui   |  402 ++++++++
 panels/network/connection-editor/ip4-page.ui       |  221 +++++
 panels/network/connection-editor/ip6-page.ui       |  221 +++++
 .../connection-editor/net-connection-editor.c      |  420 ++++++++
 .../connection-editor/net-connection-editor.h      |   83 ++
 panels/network/connection-editor/reset-page.ui     |   80 ++
 panels/network/connection-editor/security-page.ui  |   61 ++
 panels/network/connection-editor/wifi-page.ui      |  140 +++
 panels/network/net-device-wifi.c                   |  145 +---
 panels/network/network-wifi.ui                     | 1039 ++++++++++++++++++--
 panels/network/wireless-security/Makefile.am       |   55 +
 panels/network/wireless-security/eap-method-fast.c |  443 +++++++++
 panels/network/wireless-security/eap-method-fast.h |   36 +
 .../network/wireless-security/eap-method-fast.ui   |  203 ++++
 panels/network/wireless-security/eap-method-leap.c |  183 ++++
 panels/network/wireless-security/eap-method-leap.h |   35 +
 .../network/wireless-security/eap-method-leap.ui   |  107 ++
 panels/network/wireless-security/eap-method-peap.c |  414 ++++++++
 panels/network/wireless-security/eap-method-peap.h |   36 +
 .../network/wireless-security/eap-method-peap.ui   |  202 ++++
 .../network/wireless-security/eap-method-simple.c  |  305 ++++++
 .../network/wireless-security/eap-method-simple.h  |   47 +
 .../network/wireless-security/eap-method-simple.ui |  143 +++
 panels/network/wireless-security/eap-method-tls.c  |  481 +++++++++
 panels/network/wireless-security/eap-method-tls.h  |   36 +
 panels/network/wireless-security/eap-method-tls.ui |  198 ++++
 panels/network/wireless-security/eap-method-ttls.c |  391 ++++++++
 panels/network/wireless-security/eap-method-ttls.h |   36 +
 .../network/wireless-security/eap-method-ttls.ui   |  149 +++
 panels/network/wireless-security/eap-method.c      |  660 +++++++++++++
 panels/network/wireless-security/eap-method.h      |  128 +++
 panels/network/wireless-security/helpers.c         |   51 +
 panels/network/wireless-security/helpers.h         |   40 +
 .../network/wireless-security/nag-user-dialog.ui   |  191 ++++
 .../network/wireless-security/wireless-security.c  |  554 +++++++++++
 .../wireless-security.gresource.xml                |   17 +
 .../network/wireless-security/wireless-security.h  |  147 +++
 panels/network/wireless-security/ws-dynamic-wep.c  |  143 +++
 panels/network/wireless-security/ws-dynamic-wep.h  |   35 +
 panels/network/wireless-security/ws-dynamic-wep.ui |   94 ++
 panels/network/wireless-security/ws-leap.c         |  192 ++++
 panels/network/wireless-security/ws-leap.h         |   33 +
 panels/network/wireless-security/ws-leap.ui        |  108 ++
 panels/network/wireless-security/ws-wep-key.c      |  349 +++++++
 panels/network/wireless-security/ws-wep-key.h      |   36 +
 panels/network/wireless-security/ws-wep-key.ui     |  196 ++++
 panels/network/wireless-security/ws-wpa-eap.c      |  139 +++
 panels/network/wireless-security/ws-wpa-eap.h      |   35 +
 panels/network/wireless-security/ws-wpa-eap.ui     |   87 ++
 panels/network/wireless-security/ws-wpa-psk.c      |  200 ++++
 panels/network/wireless-security/ws-wpa-psk.h      |   31 +
 panels/network/wireless-security/ws-wpa-psk.ui     |  118 +++
 71 files changed, 13651 insertions(+), 198 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index e425426..cbc2851 100644
--- a/configure.ac
+++ b/configure.ac
@@ -489,6 +489,8 @@ panels/printers/gnome-printers-panel.desktop.in
 panels/privacy/Makefile
 panels/privacy/gnome-privacy-panel.desktop.in
 panels/network/Makefile
+panels/network/wireless-security/Makefile
+panels/network/connection-editor/Makefile
 panels/network/gnome-network-panel.desktop.in
 panels/notifications/Makefile
 panels/notifications/gnome-notifications-panel.desktop.in
diff --git a/panels/network/Makefile.am b/panels/network/Makefile.am
index b588a8a..00a0514 100644
--- a/panels/network/Makefile.am
+++ b/panels/network/Makefile.am
@@ -1,10 +1,13 @@
 cappletname = network
 
+SUBDIRS = wireless-security connection-editor
+
 INCLUDES = 						\
 	$(PANEL_CFLAGS)					\
 	$(NETWORK_PANEL_CFLAGS)				\
 	$(NETWORK_MANAGER_CFLAGS)			\
 	-DGNOMELOCALEDIR="\"$(datadir)/locale\""	\
+	-I$(srcdir)/wireless-security			\
 	$(NULL)
 
 noinst_LTLIBRARIES = libnetwork.la
@@ -43,7 +46,9 @@ libnetwork_la_SOURCES =					\
 	rfkill-glib.h					\
 	rfkill.h
 
-libnetwork_la_LIBADD = $(PANEL_LIBS) $(NETWORK_PANEL_LIBS) $(NETWORK_MANAGER_LIBS)
+libnetwork_la_LIBADD = $(PANEL_LIBS) $(NETWORK_PANEL_LIBS) $(NETWORK_MANAGER_LIBS) $(builddir)/connection-editor/libconnection-editor.la
+
+libnetwork_la_LDFLAGS = $(PANEL_LDFLAGS)
 
 resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/network.gresource.xml)
 cc-network-resources.c: network.gresource.xml $(resource_files)
diff --git a/panels/network/connection-editor/Makefile.am b/panels/network/connection-editor/Makefile.am
new file mode 100644
index 0000000..ed0b11a
--- /dev/null
+++ b/panels/network/connection-editor/Makefile.am
@@ -0,0 +1,44 @@
+noinst_LTLIBRARIES = libconnection-editor.la
+
+BUILT_SOURCES =					\
+	net-connection-editor-resources.c	\
+	net-connection-editor-resources.h
+
+libconnection_editor_la_SOURCES = 		\
+	$(BUILT_SOURCES)			\
+	net-connection-editor.h			\
+	net-connection-editor.c			\
+	ce-page.h				\
+	ce-page.c				\
+	ce-page-details.h			\
+	ce-page-details.c			\
+	ce-page-wifi.h				\
+	ce-page-wifi.c				\
+	ce-page-ip4.h				\
+	ce-page-ip4.c				\
+	ce-page-ip6.h				\
+	ce-page-ip6.c				\
+	ce-page-security.h			\
+	ce-page-security.c			\
+	ce-page-reset.h				\
+	ce-page-reset.c
+
+libconnection_editor_la_CPPFLAGS = 		\
+	-I$(srcdir)/../wireless-security	\
+	$(NETWORK_PANEL_CFLAGS) 		\
+        $(NETWORK_MANAGER_CFLAGS)		\
+	-DGNOMECC_UI_DIR=\""$(uidir)"\"
+
+libconnection_editor_la_LIBADD = 		\
+	$(builddir)/../wireless-security/libwireless-security.la \
+	$(NETWORK_PANEL_LIBS) 			\
+	$(NETWORK_MANAGER_LIBS)
+
+resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/connection-editor.gresource.xml)
+net-connection-editor-resources.c: connection-editor.gresource.xml $(resource_files)
+	$(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name net_connection_editor $<
+net-connection-editor-resources.h: connection-editor.gresource.xml $(resource_files)
+	$(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name net_connection_editor $<
+
+EXTRA_DIST = \
+	$(resource_files)
diff --git a/panels/network/connection-editor/ce-page-details.c b/panels/network/connection-editor/ce-page-details.c
new file mode 100644
index 0000000..10b0d75
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-details.c
@@ -0,0 +1,249 @@
+/* -*- 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-wifi.h>
+
+#include "../panel-common.h"
+#include "ce-page-details.h"
+
+G_DEFINE_TYPE (CEPageDetails, ce_page_details, CE_TYPE_PAGE)
+
+static gchar *
+get_ap_security_string (NMAccessPoint *ap)
+{
+        NM80211ApSecurityFlags wpa_flags, rsn_flags;
+        NM80211ApFlags flags;
+        GString *str;
+
+        flags = nm_access_point_get_flags (ap);
+        wpa_flags = nm_access_point_get_wpa_flags (ap);
+        rsn_flags = nm_access_point_get_rsn_flags (ap);
+
+        str = g_string_new ("");
+        if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+            (wpa_flags == NM_802_11_AP_SEC_NONE) &&
+            (rsn_flags == NM_802_11_AP_SEC_NONE)) {
+                /* TRANSLATORS: this WEP WiFi security */
+                g_string_append_printf (str, "%s, ", _("WEP"));
+        }
+        if (wpa_flags != NM_802_11_AP_SEC_NONE) {
+                /* TRANSLATORS: this WPA WiFi security */
+                g_string_append_printf (str, "%s, ", _("WPA"));
+        }
+        if (rsn_flags != NM_802_11_AP_SEC_NONE) {
+                /* TRANSLATORS: this WPA WiFi security */
+                g_string_append_printf (str, "%s, ", _("WPA2"));
+        }
+        if ((wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) ||
+            (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
+                /* TRANSLATORS: this Enterprise WiFi security */
+                g_string_append_printf (str, "%s, ", _("Enterprise"));
+        }
+        if (str->len > 0)
+                g_string_set_size (str, str->len - 2);
+        else {
+                g_string_append (str, C_("Wifi security", "None"));
+        }
+        return g_string_free (str, FALSE);
+}
+
+static void
+update_last_used (CEPageDetails *page, 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:
+        panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", last_used);
+        if (now != NULL)
+                g_date_time_unref (now);
+        if (then != NULL)
+                g_date_time_unref (then);
+        g_free (last_used);
+}
+
+static void
+all_user_changed (GObject *sw, GParamSpec *pspec, CEPageDetails *page)
+{
+        gboolean all_users;
+        NMSettingConnection *sc;
+
+        sc = nm_connection_get_setting_connection (CE_PAGE (page)->connection);
+        all_users = gtk_switch_get_active (GTK_SWITCH (sw));
+
+        g_object_set (sc, "permissions", NULL, NULL);
+        if (!all_users)
+                nm_setting_connection_add_permission (sc, "user", g_get_user_name (), NULL);
+}
+
+static void
+connect_details_page (CEPageDetails *page)
+{
+        GtkWidget *widget;
+        NMSettingConnection *sc;
+        guint speed;
+        guint strength;
+        NMDeviceState state;
+        NMAccessPoint *active_ap;
+        const gchar *str;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+                                                     "auto_connect_switch"));
+        sc = nm_connection_get_setting_connection (CE_PAGE (page)->connection);
+        g_object_bind_property (sc, "autoconnect",
+                                widget, "active",
+                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+                                                     "all_user_switch"));
+        gtk_switch_set_active (GTK_SWITCH (widget),
+                               nm_setting_connection_get_num_permissions (sc) == 0);
+        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));
+        state = nm_device_get_state (page->device);
+
+        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 (speed > 0)
+                str = g_strdup_printf (_("%d Mb/s"), speed);
+        else
+                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));
+        panel_set_device_widget_details (CE_PAGE (page)->builder, "mac", str);
+
+        str = NULL;
+        if (page->ap == active_ap)
+                str = get_ap_security_string (active_ap);
+        panel_set_device_widget_details (CE_PAGE (page)->builder, "security", str);
+
+        strength = 0;
+        if (page->ap != NULL)
+                strength = nm_access_point_get_strength (page->ap);
+
+        if (strength <= 0)
+                str = NULL;
+        else if (strength < 20)
+                str = C_("Signal strength", "None");
+        else if (strength < 40)
+                str = C_("Signal strength", "Weak");
+        else if (strength < 50)
+                str = C_("Signal strength", "Ok");
+        else if (strength < 80)
+                str = C_("Signal strength", "Good");
+        else
+                str = C_("Signal strength", "Excellent");
+        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
+                panel_set_device_widgets (CE_PAGE (page)->builder, page->device);
+
+        if (page->ap != active_ap && 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);
+
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        return TRUE;
+}
+
+static void
+ce_page_details_init (CEPageDetails *page)
+{
+}
+
+static void
+ce_page_details_class_init (CEPageDetailsClass *class)
+{
+        CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_details_new (NMConnection     *connection,
+                     NMClient         *client,
+                     NMRemoteSettings *settings,
+                     NMDevice         *device,
+                     NMAccessPoint    *ap)
+{
+        CEPageDetails *page;
+
+        page = CE_PAGE_DETAILS (ce_page_new (CE_TYPE_PAGE_DETAILS,
+                                             connection,
+                                             client,
+                                             settings,
+                                             "/org/gnome/control-center/network/details-page.ui",
+                                             _("Details")));
+
+        page->device = device;
+        page->ap = ap;
+
+        connect_details_page (page);
+
+        return CE_PAGE (page);
+}
+
diff --git a/panels/network/connection-editor/ce-page-details.h b/panels/network/connection-editor/ce-page-details.h
new file mode 100644
index 0000000..5cb8f56
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-details.h
@@ -0,0 +1,66 @@
+/* -*- 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.
+ */
+
+#ifndef __CE_PAGE_DETAILS_H
+#define __CE_PAGE_DETAILS_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_DETAILS          (ce_page_details_get_type ())
+#define CE_PAGE_DETAILS(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_DETAILS, CEPageDetails))
+#define CE_PAGE_DETAILS_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_DETAILS, CEPageDetailsClass))
+#define CE_IS_PAGE_DETAILS(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_DETAILS))
+#define CE_IS_PAGE_DETAILS_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_DETAILS))
+#define CE_PAGE_DETAILS_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_DETAILS, CEPageDetailsClass))
+
+typedef struct _CEPageDetails          CEPageDetails;
+typedef struct _CEPageDetailsClass     CEPageDetailsClass;
+
+struct _CEPageDetails
+{
+        CEPage parent;
+
+        NMDevice *device;
+        NMAccessPoint *ap;
+};
+
+struct _CEPageDetailsClass
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_details_get_type (void);
+
+CEPage *ce_page_details_new      (NMConnection     *connection,
+                                  NMClient         *client,
+                                  NMRemoteSettings *settings,
+                                  NMDevice         *device,
+                                  NMAccessPoint    *ap);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_DETAILS_H */
+
diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c
new file mode 100644
index 0000000..a0bc368
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip4.c
@@ -0,0 +1,901 @@
+/* -*- 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 <errno.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "ce-page-ip4.h"
+#include <nm-utils.h>
+
+#include "egg-list-box/egg-list-box.h"
+
+G_DEFINE_TYPE (CEPageIP4, ce_page_ip4, CE_TYPE_PAGE)
+
+enum {
+        METHOD_COL_NAME,
+        METHOD_COL_METHOD
+};
+
+enum {
+        IP4_METHOD_AUTO,
+        IP4_METHOD_MANUAL,
+        IP4_METHOD_LINK_LOCAL,
+        IP4_METHOD_SHARED,
+        IP4_METHOD_DISABLED
+};
+
+static void
+method_changed (GtkComboBox *combo, CEPageIP4 *page)
+{
+        gboolean addr_enabled;
+        gboolean dns_enabled;
+        gboolean routes_enabled;
+        guint method;
+
+        method = gtk_combo_box_get_active (combo);
+        switch (method) {
+        case IP4_METHOD_AUTO:
+                addr_enabled = FALSE;
+                dns_enabled = TRUE;
+                routes_enabled = TRUE;
+                break;
+        case IP4_METHOD_MANUAL:
+                addr_enabled = TRUE;
+                dns_enabled = TRUE;
+                routes_enabled = TRUE;
+                break;
+        case IP4_METHOD_LINK_LOCAL:
+        default:
+                addr_enabled = FALSE;
+                dns_enabled = FALSE;
+                routes_enabled = FALSE;
+                break;
+        }
+
+        gtk_widget_set_sensitive (page->address_list, addr_enabled);
+        gtk_widget_set_sensitive (page->dns_list, dns_enabled);
+        gtk_widget_set_sensitive (page->routes_list, routes_enabled);
+        gtk_widget_set_sensitive (page->never_default, routes_enabled);
+
+        ce_page_changed (CE_PAGE (page));
+}
+
+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
+remove_row (GtkButton *button, CEPageIP4 *page)
+{
+        GtkWidget *row;
+        GtkWidget *list;
+
+        row = gtk_widget_get_parent (GTK_WIDGET (button));
+        list = gtk_widget_get_parent (row);
+
+        gtk_container_remove (GTK_CONTAINER (list), row);
+
+        ce_page_changed (CE_PAGE (page));
+}
+
+static gint
+sort_first_last (gconstpointer a, gconstpointer b, gpointer data)
+{
+        gboolean afirst, bfirst, alast, blast;
+
+        afirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "first"));
+        bfirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "first"));
+        alast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "last"));
+        blast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "last"));
+
+        if (afirst)
+                return -1;
+        if (bfirst)
+                return 1;
+        if (alast)
+                return 1;
+        if (blast)
+                return -1;
+
+        return 0;
+}
+
+static void
+add_address_row (CEPageIP4   *page,
+                 const gchar *address,
+                 const gchar *network,
+                 const gchar *gateway)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *delete_button;
+        GtkWidget *image;
+
+        row = gtk_grid_new ();
+        widget = gtk_label_new (_("Address"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+        widget = gtk_label_new (_("Netmask"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+        widget = gtk_label_new (_("Gateway"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "address", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), address);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "network", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), network);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "gateway", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+
+        delete_button = gtk_button_new ();
+        g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (delete_button), image);
+        gtk_grid_attach (GTK_GRID (row), delete_button, 3, 2, 1, 1);
+
+        gtk_widget_set_margin_left (row, 10);
+        gtk_widget_set_margin_right (row, 10);
+        gtk_widget_set_margin_top (row, 10);
+        gtk_widget_set_margin_bottom (row, 10);
+        gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (page->address_list), row);
+}
+
+static void
+add_empty_address_row (CEPageIP4 *page)
+{
+        add_address_row (page, "", "", "");
+}
+
+static void
+add_address_section (CEPageIP4 *page)
+{
+        GtkWidget *widget;
+        GtkWidget *frame;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *button;
+        GtkWidget *image;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "address_section"));
+
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (widget), frame);
+        page->address_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_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+        gtk_container_add (GTK_CONTAINER (frame), list);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+        button = gtk_button_new ();
+        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_address_row), page);
+        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (button), image);
+        gtk_widget_set_margin_top (button, 10);
+        gtk_widget_set_margin_bottom (button, 10);
+        gtk_widget_set_margin_left (button, 10);
+        gtk_widget_set_margin_right (button, 10);
+        gtk_widget_set_halign (button, GTK_ALIGN_END);
+        gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        gtk_widget_show_all (frame);
+
+        for (i = 0; i < nm_setting_ip4_config_get_num_addresses (page->setting); i++) {
+                NMIP4Address *addr;
+                struct in_addr tmp_addr;
+                gchar address[INET_ADDRSTRLEN + 1];
+                gchar network[INET_ADDRSTRLEN + 1];
+                gchar gateway[INET_ADDRSTRLEN + 1];
+
+                addr = nm_setting_ip4_config_get_address (page->setting, i);
+                if (!addr)
+                        continue;
+
+                tmp_addr.s_addr = nm_ip4_address_get_address (addr);
+                (void) inet_ntop (AF_INET, &tmp_addr, &address[0], sizeof (address));
+
+                tmp_addr.s_addr = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (addr));
+                (void) inet_ntop (AF_INET, &tmp_addr, &network[0], sizeof (network));
+
+                tmp_addr.s_addr = nm_ip4_address_get_gateway (addr);
+                (void) inet_ntop (AF_INET, &tmp_addr, &gateway[0], sizeof (gateway));
+
+                add_address_row (page, address, network, gateway);
+        }
+        if (nm_setting_ip4_config_get_num_addresses (page->setting) == 0)
+                add_empty_address_row (page);
+}
+
+static void
+add_dns_row (CEPageIP4   *page,
+             const gchar *address)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *delete_button;
+        GtkWidget *image;
+
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        widget = gtk_label_new (_("Address"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "address", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), address);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+
+        delete_button = gtk_button_new ();
+        g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (delete_button), image);
+        gtk_box_pack_start (GTK_BOX (row), delete_button, FALSE, FALSE, 0);
+
+        gtk_widget_set_margin_left (row, 10);
+        gtk_widget_set_margin_right (row, 10);
+        gtk_widget_set_margin_top (row, 10);
+        gtk_widget_set_margin_bottom (row, 10);
+        gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (page->dns_list), row);
+}
+
+static void
+add_empty_dns_row (CEPageIP4 *page)
+{
+        add_dns_row (page, "");
+}
+
+static void
+add_dns_section (CEPageIP4 *page)
+{
+        GtkWidget *widget;
+        GtkWidget *frame;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *button;
+        GtkWidget *image;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "dns_section"));
+
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (widget), frame);
+        page->dns_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_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+        gtk_container_add (GTK_CONTAINER (frame), list);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+        widget = gtk_label_new (_("Automatic"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+        widget = gtk_switch_new ();
+        page->auto_dns = GTK_SWITCH (widget);
+        gtk_switch_set_active (page->auto_dns, !nm_setting_ip4_config_get_ignore_auto_dns (page->setting));
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_END);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+        button = gtk_button_new ();
+        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_dns_row), page);
+        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (button), image);
+        gtk_widget_set_margin_top (button, 10);
+        gtk_widget_set_margin_bottom (button, 10);
+        gtk_widget_set_margin_left (button, 10);
+        gtk_widget_set_margin_right (button, 10);
+        gtk_widget_set_halign (button, GTK_ALIGN_END);
+        gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        gtk_widget_show_all (frame);
+
+        for (i = 0; i < nm_setting_ip4_config_get_num_dns (page->setting); i++) {
+                struct in_addr tmp_addr;
+                gchar address[INET_ADDRSTRLEN + 1];
+
+                tmp_addr.s_addr = nm_setting_ip4_config_get_dns (page->setting, i);
+                (void) inet_ntop (AF_INET, &tmp_addr, &address[0], sizeof (address));
+
+                add_dns_row (page, address);
+        }
+        if (nm_setting_ip4_config_get_num_dns (page->setting) == 0)
+                add_empty_dns_row (page);
+}
+
+static void
+add_route_row (CEPageIP4   *page,
+               const gchar *address,
+               const gchar *netmask,
+               const gchar *gateway,
+               gint         metric)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *delete_button;
+        GtkWidget *image;
+
+        row = gtk_grid_new ();
+        widget = gtk_label_new (_("Address"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+        widget = gtk_label_new (_("Netmask"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+        widget = gtk_label_new (_("Gateway"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+        widget = gtk_label_new (_("Metric"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 4, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "address", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), address);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "netmask", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), netmask);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "gateway", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "metric", widget);
+        if (metric > 0) {
+                gchar *s = g_strdup_printf ("%d", metric);
+                gtk_entry_set_text (GTK_ENTRY (widget), s);
+                g_free (s);
+        }
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 4, 1, 1);
+
+        delete_button = gtk_button_new ();
+        g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (delete_button), image);
+        gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
+        gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
+        gtk_grid_attach (GTK_GRID (row), delete_button, 3, 1, 1, 4);
+
+        gtk_widget_set_margin_left (row, 10);
+        gtk_widget_set_margin_right (row, 10);
+        gtk_widget_set_margin_top (row, 10);
+        gtk_widget_set_margin_bottom (row, 10);
+        gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (page->routes_list), row);
+}
+
+static void
+add_empty_route_row (CEPageIP4 *page)
+{
+        add_route_row (page, "", "", "", 0);
+}
+
+static void
+add_routes_section (CEPageIP4 *page)
+{
+        GtkWidget *widget;
+        GtkWidget *frame;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *button;
+        GtkWidget *image;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_section"));
+
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (widget), frame);
+        page->routes_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_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+        gtk_container_add (GTK_CONTAINER (frame), list);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+        widget = gtk_label_new (_("Automatic"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+        widget = gtk_switch_new ();
+        page->auto_routes = GTK_SWITCH (widget);
+        gtk_switch_set_active (GTK_SWITCH (widget), !nm_setting_ip4_config_get_ignore_auto_routes (page->setting));
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_END);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+        button = gtk_button_new ();
+        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_route_row), page);
+        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (button), image);
+        gtk_widget_set_margin_top (button, 10);
+        gtk_widget_set_margin_bottom (button, 10);
+        gtk_widget_set_margin_left (button, 10);
+        gtk_widget_set_margin_right (button, 10);
+        gtk_widget_set_halign (button, GTK_ALIGN_END);
+        gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        gtk_widget_show_all (frame);
+
+        for (i = 0; i < nm_setting_ip4_config_get_num_routes (page->setting); i++) {
+                NMIP4Route *route;
+                struct in_addr tmp_addr;
+                gchar address[INET_ADDRSTRLEN + 1];
+                gchar netmask[INET_ADDRSTRLEN + 1];
+                gchar gateway[INET_ADDRSTRLEN + 1];
+                gint metric;
+
+                route = nm_setting_ip4_config_get_route (page->setting, i);
+                if (!route)
+                        continue;
+
+                tmp_addr.s_addr = nm_ip4_route_get_dest (route);
+                (void) inet_ntop (AF_INET, &tmp_addr, &address[0], sizeof (address));
+
+                tmp_addr.s_addr = nm_utils_ip4_prefix_to_netmask (nm_ip4_route_get_prefix (route));
+                (void) inet_ntop (AF_INET, &tmp_addr, &netmask[0], sizeof (netmask));
+
+                tmp_addr.s_addr = nm_ip4_route_get_next_hop (route);
+                (void) inet_ntop (AF_INET, &tmp_addr, &gateway[0], sizeof (gateway));
+                metric = nm_ip4_route_get_metric (route);
+                add_route_row (page, address, netmask, gateway, metric);
+        }
+        if (nm_setting_ip4_config_get_num_routes (page->setting) == 0)
+                add_empty_route_row (page);
+}
+
+static void
+free_addr (gpointer addr)
+{
+        g_array_free ((GArray *)addr, TRUE);
+}
+
+static void
+connect_ip4_page (CEPageIP4 *page)
+{
+        GtkWidget *content;
+        const gchar *str_method;
+        gboolean disabled;
+        GtkListStore *store;
+        GtkTreeIter iter;
+        guint method;
+
+        add_address_section (page);
+        add_dns_section (page);
+        add_routes_section (page);
+
+        page->enabled = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "switch_enable"));
+
+        str_method = nm_setting_ip4_config_get_method (page->setting);
+        disabled = g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0;
+        gtk_switch_set_active (page->enabled, !disabled);
+        g_signal_connect_swapped (page->enabled, "notify::active", G_CALLBACK (ce_page_changed), page);
+        content = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "page_content"));
+        g_object_bind_property (page->enabled, "active",
+                                content, "sensitive",
+                                G_BINDING_SYNC_CREATE);
+
+        page->method = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_addresses"));
+
+        store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Automatic (DHCP)"),
+                                           METHOD_COL_METHOD, IP4_METHOD_AUTO,
+                                           -1);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Manual"),
+                                           METHOD_COL_METHOD, IP4_METHOD_MANUAL,
+                                           -1);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Link-Local Only"),
+                                           METHOD_COL_METHOD, IP4_METHOD_LINK_LOCAL,
+                                           -1);
+
+        gtk_combo_box_set_model (page->method, GTK_TREE_MODEL (store));
+
+        method = IP4_METHOD_AUTO;
+        if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) {
+                method = IP4_METHOD_LINK_LOCAL;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
+                method = IP4_METHOD_MANUAL;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
+                method = IP4_METHOD_SHARED;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) {
+                method = IP4_METHOD_DISABLED;
+        }
+
+        page->never_default = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "never_default_check"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->never_default),
+                                      nm_setting_ip4_config_get_never_default (page->setting));
+
+        g_signal_connect (page->method, "changed", G_CALLBACK (method_changed), page);
+        if (method != IP4_METHOD_SHARED && method != IP4_METHOD_DISABLED)
+                gtk_combo_box_set_active (page->method, method);
+}
+
+static gboolean
+parse_netmask (const char *str, guint32 *prefix)
+{
+        struct in_addr tmp_addr;
+        glong tmp_prefix;
+
+        errno = 0;
+
+        /* Is it a prefix? */
+        if (!strchr (str, '.')) {
+                tmp_prefix = strtol (str, NULL, 10);
+                if (!errno && tmp_prefix >= 0 && tmp_prefix <= 32) {
+                        *prefix = tmp_prefix;
+                        return TRUE;
+                }
+        }
+
+        /* Is it a netmask? */
+        if (inet_pton (AF_INET, str, &tmp_addr) > 0) {
+                *prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr);
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+static gboolean
+ui_to_setting (CEPageIP4 *page)
+{
+        gboolean valid = FALSE;
+        const gchar *method;
+        gboolean ignore_auto_dns;
+        gboolean ignore_auto_routes;
+        gboolean never_default;
+        GPtrArray *addresses = NULL;
+        GArray *dns_servers = NULL;
+        GPtrArray *routes = NULL;
+        GList *children, *l;
+
+        if (!gtk_switch_get_active (page->enabled)) {
+                method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+        } else {
+                switch (gtk_combo_box_get_active (page->method)) {
+                case IP4_METHOD_MANUAL:
+                        method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+                        break;
+                case IP4_METHOD_LINK_LOCAL:
+                        method = NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL;
+                        break;
+                default:
+                case IP4_METHOD_AUTO:
+                        method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+                        break;
+                }
+        }
+
+        addresses = g_ptr_array_new_with_free_func (free_addr);
+        children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkEntry *entry;
+                const gchar *text_address;
+                const gchar *text_netmask;
+                const gchar *text_gateway;
+                struct in_addr tmp_addr;
+                struct in_addr tmp_gateway = { 0 };
+                guint32 prefix;
+                guint32 empty_val = 0;
+                GArray *addr;
+
+                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+                if (!entry)
+                        continue;
+
+                text_address = gtk_entry_get_text (entry);
+                text_netmask = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "network")));
+                text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+
+                if (!*text_address && !*text_netmask && !*text_gateway) {
+                        /* ignore empty rows */
+                        continue;
+                }
+
+                if (inet_pton (AF_INET, text_address, &tmp_addr) <= 0) {
+                        g_warning ("IPv4 address %s missing or invalid", text_address);
+                        goto out;
+                }
+
+
+                if (!parse_netmask (text_netmask, &prefix)) {
+                        g_warning ("IPv4 prefix %s is invalid", text_netmask);
+                        goto out;
+                }
+
+                if (text_gateway && inet_pton (AF_INET, text_gateway, &tmp_gateway) <= 0) {
+                        g_warning ("IPv4 gateway %s is invalid", text_gateway);
+                        goto out;
+                }
+
+                addr = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
+                g_array_append_val (addr, tmp_addr.s_addr);
+                g_array_append_val (addr, prefix);
+                if (tmp_gateway.s_addr)
+                        g_array_append_val (addr, tmp_gateway.s_addr);
+                else
+                        g_array_append_val (addr, empty_val);
+                g_ptr_array_add (addresses, addr);
+        }
+        g_list_free (children);
+
+        if (addresses->len == 0) {
+                g_ptr_array_free (addresses, TRUE);
+                addresses = NULL;
+        }
+
+        dns_servers = g_array_new (FALSE, FALSE, sizeof (guint));
+        children = gtk_container_get_children (GTK_CONTAINER (page->dns_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkEntry *entry;
+                const gchar *text;
+                struct in_addr tmp_addr;
+
+                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+                if (!entry)
+                        continue;
+
+                text = gtk_entry_get_text (entry);
+                if (!*text) {
+                        /* ignore empty rows */
+                        continue;
+                }
+
+                if (inet_pton (AF_INET, text, &tmp_addr) <= 0) {
+                        g_warning ("IPv4 dns server %s invalid", text);
+                        goto out;
+                }
+
+                g_array_append_val (dns_servers, tmp_addr.s_addr);
+        }
+        g_list_free (children);
+
+
+        routes = g_ptr_array_new_with_free_func (free_addr);
+        children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkEntry *entry;
+                const gchar *text_address;
+                const gchar *text_netmask;
+                const gchar *text_gateway;
+                const gchar *text_metric;
+                struct in_addr tmp_addr = { 0 };
+                guint32 address, netmask, gateway, metric;
+                GArray *route;
+
+                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+                if (!entry)
+                        continue;
+
+                text_address = gtk_entry_get_text (entry);
+                text_netmask = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "netmask")));
+                text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+                text_metric = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "metric")));
+
+                if (!*text_address && !*text_netmask && !*text_gateway && !*text_metric) {
+                        /* ignore empty rows */
+                        continue;
+                }
+
+                if (inet_pton (AF_INET, text_address, &tmp_addr) <= 0) {
+                        g_warning ("IPv4 route address %s invalid", text_address);
+                        goto out;
+                }
+                address = tmp_addr.s_addr;
+
+                if (!parse_netmask (text_netmask, &netmask)) {
+                        g_warning ("IPv4 route netmask %s invalid", text_netmask);
+                        goto out;
+                }
+
+                if (inet_pton (AF_INET, text_gateway, &tmp_addr) <= 0) {
+                        g_warning ("IPv4 route gateway %s invalid", text_gateway);
+                        goto out;
+                }
+                gateway = tmp_addr.s_addr;
+
+                metric = 0;
+                if (*text_metric) {
+                        errno = 0;
+                        metric = strtoul (text_metric, NULL, 10);
+                        if (errno) {
+                                g_warning ("IPv4 route metric %s invalid", text_metric);
+                                goto out;
+                        }
+                }
+
+                route = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4);
+                g_array_append_val (route, address);
+                g_array_append_val (route, netmask);
+                g_array_append_val (route, gateway);
+                g_array_append_val (route, metric);
+                g_ptr_array_add (routes, route);
+        }
+        g_list_free (children);
+
+        if (routes->len == 0) {
+                g_ptr_array_free (routes, TRUE);
+                routes = NULL;
+        }
+        ignore_auto_dns = !gtk_switch_get_active (page->auto_dns);
+        ignore_auto_routes = !gtk_switch_get_active (page->auto_routes);
+        never_default = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->never_default));
+
+        g_object_set (page->setting,
+                      NM_SETTING_IP4_CONFIG_METHOD, method,
+                      NM_SETTING_IP4_CONFIG_ADDRESSES, addresses,
+                      NM_SETTING_IP4_CONFIG_DNS, dns_servers,
+                      NM_SETTING_IP4_CONFIG_ROUTES, routes,
+                      NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
+                      NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
+                      NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
+                      NULL);
+
+        valid = TRUE;
+
+out:
+        if (addresses)
+                g_ptr_array_free (addresses, TRUE);
+
+        if (dns_servers)
+                g_array_free (dns_servers, TRUE);
+
+        if (routes)
+                g_ptr_array_free (routes, TRUE);
+
+        return valid;
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        if (!ui_to_setting (CE_PAGE_IP4 (page)))
+                return FALSE;
+
+        return nm_setting_verify (NM_SETTING (CE_PAGE_IP4 (page)->setting), NULL, error);
+}
+
+static void
+ce_page_ip4_init (CEPageIP4 *page)
+{
+}
+
+static void
+ce_page_ip4_class_init (CEPageIP4Class *class)
+{
+        CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_ip4_new (NMConnection     *connection,
+                   NMClient         *client,
+                   NMRemoteSettings *settings)
+{
+        CEPageIP4 *page;
+
+        page = CE_PAGE_IP4 (ce_page_new (CE_TYPE_PAGE_IP4,
+                                           connection,
+                                           client,
+                                           settings,
+                                           "/org/gnome/control-center/network/ip4-page.ui",
+                                           _("IPv4")));
+
+        page->setting = nm_connection_get_setting_ip4_config (connection);
+
+        connect_ip4_page (page);
+
+        return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-ip4.h b/panels/network/connection-editor/ce-page-ip4.h
new file mode 100644
index 0000000..ca38d3e
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip4.h
@@ -0,0 +1,72 @@
+/* -*- 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 ip4.
+ *
+ * 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_IP4_H
+#define __CE_PAGE_IP4_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_IP4          (ce_page_ip4_get_type ())
+#define CE_PAGE_IP4(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_IP4, CEPageIP4))
+#define CE_PAGE_IP4_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_IP4, CEPageIP4Class))
+#define CE_IS_PAGE_IP4(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_IP4))
+#define CE_IS_PAGE_IP4_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_IP4))
+#define CE_PAGE_IP4_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_IP4, CEPageIP4Class))
+
+typedef struct _CEPageIP4          CEPageIP4;
+typedef struct _CEPageIP4Class     CEPageIP4Class;
+
+struct _CEPageIP4
+{
+        CEPage parent;
+
+        NMSettingIP4Config *setting;
+
+        GtkSwitch      *enabled;
+        GtkComboBox    *method;
+        GtkWidget      *address_list;
+        GtkSwitch      *auto_dns;
+        GtkWidget      *dns_list;
+        GtkSwitch      *auto_routes;
+        GtkWidget      *routes_list;
+        GtkWidget      *never_default;
+};
+
+struct _CEPageIP4Class
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_ip4_get_type (void);
+
+CEPage *ce_page_ip4_new      (NMConnection     *connection,
+                              NMClient         *client,
+                              NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_IP4_H */
+
diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c
new file mode 100644
index 0000000..9c54430
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip6.c
@@ -0,0 +1,862 @@
+/* -*- 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 <errno.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "ce-page-ip6.h"
+#include <nm-utils.h>
+
+#include "egg-list-box/egg-list-box.h"
+
+G_DEFINE_TYPE (CEPageIP6, ce_page_ip6, CE_TYPE_PAGE)
+
+enum {
+        METHOD_COL_NAME,
+        METHOD_COL_METHOD
+};
+
+enum {
+        IP6_METHOD_AUTO,
+        IP6_METHOD_DHCP,
+        IP6_METHOD_MANUAL,
+        IP6_METHOD_LINK_LOCAL,
+        IP6_METHOD_SHARED,
+        IP6_METHOD_IGNORE
+};
+
+static void
+method_changed (GtkComboBox *combo, CEPageIP6 *page)
+{
+        gboolean addr_enabled;
+        gboolean dns_enabled;
+        gboolean routes_enabled;
+        guint method;
+
+        method = gtk_combo_box_get_active (combo);
+        switch (method) {
+        case IP6_METHOD_AUTO:
+        case IP6_METHOD_DHCP:
+                addr_enabled = FALSE;
+                dns_enabled = TRUE;
+                routes_enabled = TRUE;
+                break;
+        case IP6_METHOD_MANUAL:
+                addr_enabled = TRUE;
+                dns_enabled = TRUE;
+                routes_enabled = TRUE;
+                break;
+        case IP6_METHOD_LINK_LOCAL:
+        default:
+                addr_enabled = FALSE;
+                dns_enabled = FALSE;
+                routes_enabled = FALSE;
+                break;
+        }
+
+        gtk_widget_set_sensitive (page->address_list, addr_enabled);
+        gtk_widget_set_sensitive (page->dns_list, dns_enabled);
+        gtk_widget_set_sensitive (page->routes_list, routes_enabled);
+        gtk_widget_set_sensitive (page->never_default, routes_enabled);
+
+        ce_page_changed (CE_PAGE (page));
+}
+
+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
+remove_row (GtkButton *button, CEPageIP6 *page)
+{
+        GtkWidget *row;
+        GtkWidget *list;
+
+        row = gtk_widget_get_parent (GTK_WIDGET (button));
+        list = gtk_widget_get_parent (row);
+
+        gtk_container_remove (GTK_CONTAINER (list), row);
+
+        ce_page_changed (CE_PAGE (page));
+}
+
+static gint
+sort_first_last (gconstpointer a, gconstpointer b, gpointer data)
+{
+        gboolean afirst, bfirst, alast, blast;
+
+        afirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "first"));
+        bfirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "first"));
+        alast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "last"));
+        blast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "last"));
+
+        if (afirst)
+                return -1;
+        if (bfirst)
+                return 1;
+        if (alast)
+                return 1;
+        if (blast)
+                return -1;
+
+        return 0;
+}
+
+static void
+add_address_row (CEPageIP6   *page,
+                 const gchar *address,
+                 const gchar *network,
+                 const gchar *gateway)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *delete_button;
+        GtkWidget *image;
+
+        row = gtk_grid_new ();
+        widget = gtk_label_new (_("Address"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+        widget = gtk_label_new (_("Prefix"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+        widget = gtk_label_new (_("Gateway"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "address", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), address);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "prefix", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), network);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "gateway", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+
+        delete_button = gtk_button_new ();
+        g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (delete_button), image);
+        gtk_grid_attach (GTK_GRID (row), delete_button, 3, 2, 1, 1);
+
+        gtk_widget_set_margin_left (row, 10);
+        gtk_widget_set_margin_right (row, 10);
+        gtk_widget_set_margin_top (row, 10);
+        gtk_widget_set_margin_bottom (row, 10);
+        gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (page->address_list), row);
+}
+
+static void
+add_empty_address_row (CEPageIP6 *page)
+{
+        add_address_row (page, "", "", "");
+}
+
+static void
+add_address_section (CEPageIP6 *page)
+{
+        GtkWidget *widget;
+        GtkWidget *frame;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *button;
+        GtkWidget *image;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "address_section"));
+
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (widget), frame);
+        page->address_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_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+        gtk_container_add (GTK_CONTAINER (frame), list);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+        button = gtk_button_new ();
+        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_address_row), page);
+        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (button), image);
+        gtk_widget_set_margin_top (button, 10);
+        gtk_widget_set_margin_bottom (button, 10);
+        gtk_widget_set_margin_left (button, 10);
+        gtk_widget_set_margin_right (button, 10);
+        gtk_widget_set_halign (button, GTK_ALIGN_END);
+        gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        gtk_widget_show_all (frame);
+
+        for (i = 0; i < nm_setting_ip6_config_get_num_addresses (page->setting); i++) {
+                NMIP6Address *addr;
+                const struct in6_addr *tmp_addr;
+                gchar address[INET6_ADDRSTRLEN + 1];
+                gchar network[INET6_ADDRSTRLEN + 1];
+                gchar gateway[INET6_ADDRSTRLEN + 1];
+
+                addr = nm_setting_ip6_config_get_address (page->setting, i);
+                if (!addr)
+                        continue;
+
+                tmp_addr = nm_ip6_address_get_address (addr);
+                (void) inet_ntop (AF_INET6, tmp_addr, &address[0], sizeof (address));
+
+                snprintf (network, sizeof (network), "%u", nm_ip6_address_get_prefix (addr));
+
+                tmp_addr = nm_ip6_address_get_gateway (addr);
+                if (tmp_addr && !IN6_IS_ADDR_UNSPECIFIED (tmp_addr))
+                        (void) inet_ntop (AF_INET6, tmp_addr, &gateway[0], sizeof (gateway));
+                else
+                        gateway[0] = '\0';
+
+                add_address_row (page, address, network, gateway);
+        }
+        if (nm_setting_ip6_config_get_num_addresses (page->setting) == 0)
+                add_empty_address_row (page);
+}
+
+static void
+add_dns_row (CEPageIP6   *page,
+             const gchar *address)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *delete_button;
+        GtkWidget *image;
+
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        widget = gtk_label_new (_("Address"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "address", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), address);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+
+        delete_button = gtk_button_new ();
+        g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (delete_button), image);
+        gtk_box_pack_start (GTK_BOX (row), delete_button, FALSE, FALSE, 0);
+
+        gtk_widget_set_margin_left (row, 10);
+        gtk_widget_set_margin_right (row, 10);
+        gtk_widget_set_margin_top (row, 10);
+        gtk_widget_set_margin_bottom (row, 10);
+        gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (page->dns_list), row);
+}
+
+static void
+add_empty_dns_row (CEPageIP6 *page)
+{
+        add_dns_row (page, "");
+}
+
+static void
+add_dns_section (CEPageIP6 *page)
+{
+        GtkWidget *widget;
+        GtkWidget *frame;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *button;
+        GtkWidget *image;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "dns_section"));
+
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (widget), frame);
+        page->dns_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_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+        gtk_container_add (GTK_CONTAINER (frame), list);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+        widget = gtk_label_new (_("Automatic"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+        widget = gtk_switch_new ();
+        page->auto_dns = GTK_SWITCH (widget);
+        gtk_switch_set_active (page->auto_dns, !nm_setting_ip6_config_get_ignore_auto_dns (page->setting));
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_END);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+        button = gtk_button_new ();
+        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_dns_row), page);
+        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (button), image);
+        gtk_widget_set_margin_top (button, 10);
+        gtk_widget_set_margin_bottom (button, 10);
+        gtk_widget_set_margin_left (button, 10);
+        gtk_widget_set_margin_right (button, 10);
+        gtk_widget_set_halign (button, GTK_ALIGN_END);
+        gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        gtk_widget_show_all (frame);
+
+        for (i = 0; i < nm_setting_ip6_config_get_num_dns (page->setting); i++) {
+                const struct in6_addr *tmp_addr;
+                gchar address[INET6_ADDRSTRLEN + 1];
+
+                tmp_addr = nm_setting_ip6_config_get_dns (page->setting, i);
+                (void) inet_ntop (AF_INET, tmp_addr, &address[0], sizeof (address));
+
+                add_dns_row (page, address);
+        }
+        if (nm_setting_ip6_config_get_num_dns (page->setting) == 0)
+                add_empty_dns_row (page);
+}
+
+static void
+add_route_row (CEPageIP6   *page,
+               const gchar *address,
+               gint         prefix,
+               const gchar *gateway,
+               gint         metric)
+{
+        GtkWidget *row;
+        GtkWidget *widget;
+        GtkWidget *delete_button;
+        GtkWidget *image;
+
+        row = gtk_grid_new ();
+        widget = gtk_label_new (_("Address"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+        widget = gtk_label_new (_("Prefix"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+        widget = gtk_label_new (_("Gateway"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+        widget = gtk_label_new (_("Metric"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+        gtk_grid_attach (GTK_GRID (row), widget, 1, 4, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "address", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), address);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "prefix", widget);
+        if (prefix > 0) {
+                gchar *s = g_strdup_printf ("%d", prefix);
+                gtk_entry_set_text (GTK_ENTRY (widget), s);
+                g_free (s);
+        }
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "gateway", widget);
+        gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+        widget = gtk_entry_new ();
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+        g_object_set_data (G_OBJECT (row), "metric", widget);
+        if (metric > 0) {
+                gchar *s = g_strdup_printf ("%d", metric);
+                gtk_entry_set_text (GTK_ENTRY (widget), s);
+                g_free (s);
+        }
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_hexpand (widget, TRUE);
+        gtk_grid_attach (GTK_GRID (row), widget, 2, 4, 1, 1);
+
+        delete_button = gtk_button_new ();
+        g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+        image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (delete_button), image);
+        gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
+        gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
+        gtk_grid_attach (GTK_GRID (row), delete_button, 3, 1, 1, 4);
+
+        gtk_widget_set_margin_left (row, 10);
+        gtk_widget_set_margin_right (row, 10);
+        gtk_widget_set_margin_top (row, 10);
+        gtk_widget_set_margin_bottom (row, 10);
+        gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (page->routes_list), row);
+}
+
+static void
+add_empty_route_row (CEPageIP6 *page)
+{
+        add_route_row (page, "", 0, "", 0);
+}
+
+static void
+add_routes_section (CEPageIP6 *page)
+{
+        GtkWidget *widget;
+        GtkWidget *frame;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *button;
+        GtkWidget *image;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_section"));
+
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (widget), frame);
+        page->routes_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_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+        gtk_container_add (GTK_CONTAINER (frame), list);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+        widget = gtk_label_new (_("Automatic"));
+        gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+        widget = gtk_switch_new ();
+        page->auto_routes = GTK_SWITCH (widget);
+        gtk_switch_set_active (GTK_SWITCH (widget), !nm_setting_ip6_config_get_ignore_auto_routes (page->setting));
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, 10);
+        gtk_widget_set_margin_right (widget, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_END);
+        gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+        gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+        button = gtk_button_new ();
+        g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_route_row), page);
+        image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (button), image);
+        gtk_widget_set_margin_top (button, 10);
+        gtk_widget_set_margin_bottom (button, 10);
+        gtk_widget_set_margin_left (button, 10);
+        gtk_widget_set_margin_right (button, 10);
+        gtk_widget_set_halign (button, GTK_ALIGN_END);
+        gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+        gtk_container_add (GTK_CONTAINER (list), row);
+        gtk_widget_show_all (frame);
+
+        for (i = 0; i < nm_setting_ip6_config_get_num_routes (page->setting); i++) {
+                NMIP6Route *route;
+                const struct in6_addr *tmp_addr;
+                gchar address[INET6_ADDRSTRLEN + 1];
+                gchar gateway[INET6_ADDRSTRLEN + 1];
+                gint prefix, metric;
+
+                route = nm_setting_ip6_config_get_route (page->setting, i);
+                if (!route)
+                        continue;
+
+                tmp_addr = nm_ip6_route_get_dest (route);
+                (void) inet_ntop (AF_INET6, tmp_addr, &address[0], sizeof (address));
+                prefix = nm_ip6_route_get_prefix (route);
+                tmp_addr = nm_ip6_route_get_next_hop (route);
+                (void) inet_ntop (AF_INET6, tmp_addr, &gateway[0], sizeof (gateway));
+                metric = nm_ip6_route_get_metric (route);
+                add_route_row (page, address, prefix, gateway, metric);
+        }
+        if (nm_setting_ip6_config_get_num_routes (page->setting) == 0)
+                add_empty_route_row (page);
+}
+
+static void
+connect_ip6_page (CEPageIP6 *page)
+{
+        GtkWidget *content;
+        const gchar *str_method;
+        gboolean disabled;
+        GtkListStore *store;
+        GtkTreeIter iter;
+        guint method;
+
+        add_address_section (page);
+        add_dns_section (page);
+        add_routes_section (page);
+
+        page->enabled = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "switch_enable"));
+
+        str_method = nm_setting_ip6_config_get_method (page->setting);
+        disabled = g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0;
+        gtk_switch_set_active (page->enabled, !disabled);
+        g_signal_connect_swapped (page->enabled, "notify::active", G_CALLBACK (ce_page_changed), page);
+        content = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "page_content"));
+        g_object_bind_property (page->enabled, "active",
+                                content, "sensitive",
+                                G_BINDING_SYNC_CREATE);
+
+        page->method = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_addresses"));
+
+        store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Automatic"),
+                                           METHOD_COL_METHOD, IP6_METHOD_AUTO,
+                                           -1);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Automatic, DHCP only"),
+                                           METHOD_COL_METHOD, IP6_METHOD_DHCP,
+                                           -1);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Manual"),
+                                           METHOD_COL_METHOD, IP6_METHOD_MANUAL,
+                                           -1);
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           METHOD_COL_NAME, _("Link-Local Only"),
+                                           METHOD_COL_METHOD, IP6_METHOD_LINK_LOCAL,
+                                           -1);
+
+        gtk_combo_box_set_model (page->method, GTK_TREE_MODEL (store));
+
+        method = IP6_METHOD_AUTO;
+        if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
+                method = IP6_METHOD_DHCP;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
+                method = IP6_METHOD_LINK_LOCAL;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) {
+                method = IP6_METHOD_MANUAL;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
+                method = IP6_METHOD_SHARED;
+        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
+                method = IP6_METHOD_IGNORE;
+        }
+
+        page->never_default = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "never_default_check"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->never_default),
+                                      nm_setting_ip6_config_get_never_default (page->setting));
+
+        g_signal_connect (page->method, "changed", G_CALLBACK (method_changed), page);
+        if (method != IP6_METHOD_SHARED && method != IP6_METHOD_IGNORE)
+                gtk_combo_box_set_active (page->method, method);
+}
+
+static gboolean
+ui_to_setting (CEPageIP6 *page)
+{
+        gboolean valid = FALSE;
+        const gchar *method;
+        gboolean ignore_auto_dns;
+        gboolean ignore_auto_routes;
+        gboolean never_default;
+        GList *children, *l;
+
+        if (!gtk_switch_get_active (page->enabled)) {
+                method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
+        } else {
+                switch (gtk_combo_box_get_active (page->method)) {
+                case IP6_METHOD_MANUAL:
+                        method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+                        break;
+                case IP6_METHOD_LINK_LOCAL:
+                        method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+                        break;
+                case IP6_METHOD_DHCP:
+                        method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
+                        break;
+                default:
+                case IP6_METHOD_AUTO:
+                        method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+                        break;
+                }
+        }
+
+        nm_setting_ip6_config_clear_addresses (page->setting);
+        children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkEntry *entry;
+                const gchar *text_address;
+                const gchar *text_prefix;
+                const gchar *text_gateway;
+                struct in6_addr tmp_addr;
+                struct in6_addr tmp_gateway;
+                guint32 prefix;
+                gchar *end;
+                NMIP6Address *addr;
+                gboolean have_gateway = FALSE;
+
+                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+                if (!entry)
+                        continue;
+
+                text_address = gtk_entry_get_text (entry);
+                text_prefix = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "prefix")));
+                text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+
+                if (!*text_address && !*text_prefix && !*text_gateway) {
+                        /* ignore empty rows */
+                        continue;
+                }
+
+                if (inet_pton (AF_INET6, text_address, &tmp_addr) <= 0) {
+                        g_warning ("IPv6 address %s missing or invalid", text_address);
+                        goto out;
+                }
+
+                prefix = strtoul (text_prefix, &end, 10);
+                if (!end || *end || prefix == 0 || prefix > 128) {
+                        g_warning ("IPv6 prefix %s is invalid", text_prefix);
+                        goto out;
+                }
+
+                if (text_gateway && *text_gateway) {
+                        if (inet_pton (AF_INET6, text_gateway, &tmp_gateway) <= 0) {
+                                g_warning ("IPv6 gateway %s is invalid", text_gateway);
+                                goto out;
+                        }
+                        if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_gateway))
+                                have_gateway = TRUE;
+                }
+
+                addr = nm_ip6_address_new ();
+                nm_ip6_address_set_address (addr, &tmp_addr);
+                nm_ip6_address_set_prefix (addr, prefix);
+                if (have_gateway)
+                        nm_ip6_address_set_gateway (addr, &tmp_gateway);
+                nm_setting_ip6_config_add_address (page->setting, addr);
+        }
+        g_list_free (children);
+
+        nm_setting_ip6_config_clear_dns (page->setting);
+        children = gtk_container_get_children (GTK_CONTAINER (page->dns_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkEntry *entry;
+                const gchar *text;
+                struct in6_addr tmp_addr;
+
+                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+                if (!entry)
+                        continue;
+
+                text = gtk_entry_get_text (entry);
+                if (!*text) {
+                        /* ignore empty rows */
+                        continue;
+                }
+
+                if (inet_pton (AF_INET6, text, &tmp_addr) <= 0) {
+                        g_warning ("IPv6 dns server %s invalid", text);
+                        goto out;
+                }
+
+                nm_setting_ip6_config_add_dns (page->setting, &tmp_addr);
+        }
+        g_list_free (children);
+
+        nm_setting_ip6_config_clear_routes (page->setting);
+        children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkEntry *entry;
+                const gchar *text_address;
+                const gchar *text_prefix;
+                const gchar *text_gateway;
+                const gchar *text_metric;
+                struct in6_addr dest, gateway;
+                guint32 prefix, metric;
+                gchar *end;
+                NMIP6Route *route;
+
+                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+                if (!entry)
+                        continue;
+
+                text_address = gtk_entry_get_text (entry);
+                text_prefix = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "prefix")));
+                text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+                text_metric = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "metric")));
+
+                if (!*text_address && !*text_prefix && !*text_gateway && !*text_metric) {
+                        /* ignore empty rows */
+                        continue;
+                }
+
+                if (inet_pton (AF_INET6, text_address, &dest) <= 0) {
+                        g_warning ("IPv6 route address %s invalid", text_address);
+                        goto out;
+                }
+
+                prefix = strtoul (text_prefix, &end, 10);
+                if (!end || *end || prefix == 0 || prefix > 128) {
+                        g_warning ("IPv6 route prefix %s invalid", text_prefix);
+                        goto out;
+                }
+
+                if (inet_pton (AF_INET6, text_gateway, &gateway) <= 0) {
+                        g_warning ("IPv6 route gateway %s invalid", text_gateway);
+                        goto out;
+                }
+
+                metric = 0;
+                if (*text_metric) {
+                        errno = 0;
+                        metric = strtoul (text_metric, NULL, 10);
+                        if (errno) {
+                                g_warning ("IPv6 route metric %s invalid", text_metric);
+                                goto out;
+                        }
+                }
+
+                route = nm_ip6_route_new ();
+                nm_ip6_route_set_dest (route, &dest);
+                nm_ip6_route_set_prefix (route, prefix);
+                nm_ip6_route_set_next_hop (route, &gateway);
+                nm_ip6_route_set_metric (route, metric);
+                nm_setting_ip6_config_add_route (page->setting, route);
+                nm_ip6_route_unref (route);
+        }
+        g_list_free (children);
+
+        ignore_auto_dns = !gtk_switch_get_active (page->auto_dns);
+        ignore_auto_routes = !gtk_switch_get_active (page->auto_routes);
+        never_default = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->never_default));
+
+        g_object_set (page->setting,
+                      NM_SETTING_IP6_CONFIG_METHOD, method,
+                      NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
+                      NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
+                      NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default,
+                      NULL);
+
+        valid = TRUE;
+
+out:
+
+        return valid;
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        if (!ui_to_setting (CE_PAGE_IP6 (page)))
+                return FALSE;
+
+        return nm_setting_verify (NM_SETTING (CE_PAGE_IP6 (page)->setting), NULL, error);
+}
+
+static void
+ce_page_ip6_init (CEPageIP6 *page)
+{
+}
+
+static void
+ce_page_ip6_class_init (CEPageIP6Class *class)
+{
+        CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_ip6_new (NMConnection     *connection,
+                   NMClient         *client,
+                   NMRemoteSettings *settings)
+{
+        CEPageIP6 *page;
+
+        page = CE_PAGE_IP6 (ce_page_new (CE_TYPE_PAGE_IP6,
+                                           connection,
+                                           client,
+                                           settings,
+                                           "/org/gnome/control-center/network/ip6-page.ui",
+                                           _("IPv6")));
+
+        page->setting = nm_connection_get_setting_ip6_config (connection);
+
+        connect_ip6_page (page);
+
+        return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-ip6.h b/panels/network/connection-editor/ce-page-ip6.h
new file mode 100644
index 0000000..71d8821
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip6.h
@@ -0,0 +1,72 @@
+/* -*- 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 ip6.
+ *
+ * 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_IP6_H
+#define __CE_PAGE_IP6_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_IP6          (ce_page_ip6_get_type ())
+#define CE_PAGE_IP6(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_IP6, CEPageIP6))
+#define CE_PAGE_IP6_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_IP6, CEPageIP6Class))
+#define CE_IS_PAGE_IP6(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_IP6))
+#define CE_IS_PAGE_IP6_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_IP6))
+#define CE_PAGE_IP6_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_IP6, CEPageIP6Class))
+
+typedef struct _CEPageIP6          CEPageIP6;
+typedef struct _CEPageIP6Class     CEPageIP6Class;
+
+struct _CEPageIP6
+{
+        CEPage parent;
+
+        NMSettingIP6Config *setting;
+
+        GtkSwitch      *enabled;
+        GtkComboBox    *method;
+        GtkWidget      *address_list;
+        GtkSwitch      *auto_dns;
+        GtkWidget      *dns_list;
+        GtkSwitch      *auto_routes;
+        GtkWidget      *routes_list;
+        GtkWidget      *never_default;
+};
+
+struct _CEPageIP6Class
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_ip6_get_type (void);
+
+CEPage *ce_page_ip6_new      (NMConnection     *connection,
+                              NMClient         *client,
+                              NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_IP6_H */
+
diff --git a/panels/network/connection-editor/ce-page-reset.c b/panels/network/connection-editor/ce-page-reset.c
new file mode 100644
index 0000000..6112024
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-reset.c
@@ -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 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 "ce-page-reset.h"
+
+G_DEFINE_TYPE (CEPageReset, ce_page_reset, CE_TYPE_PAGE)
+
+static void
+connect_reset_page (CEPageReset *page)
+{
+        /* FIXME */
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        return TRUE;
+}
+
+static void
+ce_page_reset_init (CEPageReset *page)
+{
+}
+
+static void
+ce_page_reset_class_init (CEPageResetClass *class)
+{
+        CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_reset_new (NMConnection     *connection,
+                   NMClient         *client,
+                   NMRemoteSettings *settings)
+{
+        CEPageReset *page;
+
+        page = CE_PAGE_RESET (ce_page_new (CE_TYPE_PAGE_RESET,
+                                           connection,
+                                           client,
+                                           settings,
+                                           "/org/gnome/control-center/network/reset-page.ui",
+                                           _("Reset")));
+
+        connect_reset_page (page);
+
+        return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-reset.h b/panels/network/connection-editor/ce-page-reset.h
new file mode 100644
index 0000000..3e9582a
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-reset.h
@@ -0,0 +1,61 @@
+/* -*- 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 reset.
+ *
+ * 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_RESET_H
+#define __CE_PAGE_RESET_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_RESET          (ce_page_reset_get_type ())
+#define CE_PAGE_RESET(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_RESET, CEPageReset))
+#define CE_PAGE_RESET_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_RESET, CEPageResetClass))
+#define CE_IS_PAGE_RESET(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_RESET))
+#define CE_IS_PAGE_RESET_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_RESET))
+#define CE_PAGE_RESET_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_RESET, CEPageResetClass))
+
+typedef struct _CEPageReset          CEPageReset;
+typedef struct _CEPageResetClass     CEPageResetClass;
+
+struct _CEPageReset
+{
+        CEPage parent;
+};
+
+struct _CEPageResetClass
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_reset_get_type (void);
+
+CEPage *ce_page_reset_new      (NMConnection     *connection,
+                                NMClient         *client,
+                                NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_RESET_H */
+
diff --git a/panels/network/connection-editor/ce-page-security.c b/panels/network/connection-editor/ce-page-security.c
new file mode 100644
index 0000000..9b187bf
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-security.c
@@ -0,0 +1,480 @@
+/* -*- 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-connection.h>
+
+#include "wireless-security.h"
+#include "ce-page-security.h"
+
+G_DEFINE_TYPE (CEPageSecurity, ce_page_security, CE_TYPE_PAGE)
+
+enum {
+        S_NAME_COLUMN,
+        S_SEC_COLUMN,
+        S_ADHOC_VALID_COLUMN
+};
+
+static gboolean
+find_proto (NMSettingWirelessSecurity *sec, const char *item)
+{
+        guint32 i;
+
+        for (i = 0; i < nm_setting_wireless_security_get_num_protos (sec); i++) {
+                if (!strcmp (item, nm_setting_wireless_security_get_proto (sec, i)))
+                        return TRUE;
+        }
+        return FALSE;
+}
+
+static NMUtilsSecurityType
+get_default_type_for_security (NMSettingWirelessSecurity *sec)
+{
+        const char *key_mgmt, *auth_alg;
+
+        g_return_val_if_fail (sec != NULL, NMU_SEC_NONE);
+
+        key_mgmt = nm_setting_wireless_security_get_key_mgmt (sec);
+        auth_alg = nm_setting_wireless_security_get_auth_alg (sec);
+
+        /* No IEEE 802.1x */
+        if (!strcmp (key_mgmt, "none"))
+                return NMU_SEC_STATIC_WEP;
+
+        if (!strcmp (key_mgmt, "ieee8021x")) {
+                if (auth_alg && !strcmp (auth_alg, "leap"))
+                        return NMU_SEC_LEAP;
+                return NMU_SEC_DYNAMIC_WEP;
+        }
+
+        if (   !strcmp (key_mgmt, "wpa-none")
+            || !strcmp (key_mgmt, "wpa-psk")) {
+                if (find_proto (sec, "rsn"))
+                        return NMU_SEC_WPA2_PSK;
+                else if (find_proto (sec, "wpa"))
+                        return NMU_SEC_WPA_PSK;
+                else
+                        return NMU_SEC_WPA_PSK;
+        }
+
+        if (!strcmp (key_mgmt, "wpa-eap")) {
+                if (find_proto (sec, "rsn"))
+                        return NMU_SEC_WPA2_ENTERPRISE;
+                else if (find_proto (sec, "wpa"))
+                        return NMU_SEC_WPA_ENTERPRISE;
+                else
+                        return NMU_SEC_WPA_ENTERPRISE;
+        }
+
+        return NMU_SEC_INVALID;
+}
+
+static WirelessSecurity *
+security_combo_get_active (CEPageSecurity *page)
+{
+        GtkTreeIter iter;
+        GtkTreeModel *model;
+        WirelessSecurity *sec = NULL;
+
+        model = gtk_combo_box_get_model (page->security_combo);
+        gtk_combo_box_get_active_iter (page->security_combo, &iter);
+        gtk_tree_model_get (model, &iter, S_SEC_COLUMN, &sec, -1);
+
+        return sec;
+}
+
+static void
+wsec_size_group_clear (GtkSizeGroup *group)
+{
+        GSList *children;
+        GSList *iter;
+
+        g_return_if_fail (group != NULL);
+
+        children = gtk_size_group_get_widgets (group);
+        for (iter = children; iter; iter = g_slist_next (iter))
+                gtk_size_group_remove_widget (group, GTK_WIDGET (iter->data));
+}
+
+static void
+security_combo_changed (GtkComboBox *combo,
+                        gpointer     user_data)
+{
+        CEPageSecurity *page = CE_PAGE_SECURITY (user_data);
+        GtkWidget *vbox;
+        GList *l, *children;
+        WirelessSecurity *sec;
+
+        wsec_size_group_clear (page->group);
+
+        vbox = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "vbox"));
+        children = gtk_container_get_children (GTK_CONTAINER (vbox));
+        for (l = children; l; l = l->next) {
+                gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (l->data));
+        }
+
+        sec = security_combo_get_active (page);
+        if (sec) {
+                GtkWidget *sec_widget;
+                GtkWidget *parent;
+
+                sec_widget = wireless_security_get_widget (sec);
+                g_assert (sec_widget);
+                parent = gtk_widget_get_parent (sec_widget);
+                if (parent)
+                        gtk_container_remove (GTK_CONTAINER (parent), sec_widget);
+
+                gtk_size_group_add_widget (page->group, page->security_heading);
+                wireless_security_add_to_size_group (sec, page->group);
+
+                gtk_container_add (GTK_CONTAINER (vbox), sec_widget);
+                wireless_security_unref (sec);
+        }
+
+        ce_page_changed (CE_PAGE (page));
+}
+
+static void
+stuff_changed_cb (WirelessSecurity *sec, gpointer user_data)
+{
+        ce_page_changed (CE_PAGE (user_data));
+}
+
+static void
+add_security_item (CEPageSecurity   *page,
+                   WirelessSecurity *sec,
+                   GtkListStore     *model,
+                   GtkTreeIter      *iter,
+                   const char       *text,
+                   gboolean          adhoc_valid)
+{
+        wireless_security_set_changed_notify (sec, stuff_changed_cb, page);
+        gtk_list_store_append (model, iter);
+        gtk_list_store_set (model, iter,
+                            S_NAME_COLUMN, text,
+                            S_SEC_COLUMN, sec,
+                            S_ADHOC_VALID_COLUMN, adhoc_valid,
+                            -1);
+        wireless_security_unref (sec);
+}
+
+static void
+set_sensitive (GtkCellLayout *cell_layout,
+               GtkCellRenderer *cell,
+               GtkTreeModel *tree_model,
+               GtkTreeIter *iter,
+               gpointer data)
+{
+        gboolean *adhoc = data;
+        gboolean sensitive = TRUE, adhoc_valid = TRUE;
+
+        gtk_tree_model_get (tree_model, iter, S_ADHOC_VALID_COLUMN, &adhoc_valid, -1);
+        if (*adhoc && !adhoc_valid)
+                sensitive = FALSE;
+
+        g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+static void
+finish_setup (CEPageSecurity *page)
+{
+        NMConnection *connection = CE_PAGE (page)->connection;
+        NMSettingWireless *sw;
+        NMSettingWirelessSecurity *sws;
+        gboolean is_adhoc = FALSE;
+        GtkListStore *sec_model;
+        GtkTreeIter iter;
+        const gchar *mode;
+        const gchar *security;
+        guint32 dev_caps = 0;
+        NMUtilsSecurityType default_type = NMU_SEC_NONE;
+        int active = -1;
+        int item = 0;
+        GtkComboBox *combo;
+        GtkCellRenderer *renderer;
+
+        sw = nm_connection_get_setting_wireless (connection);
+        g_assert (sw);
+
+        page->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+        page->security_heading = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "heading_sec"));
+        page->security_combo = combo = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_sec"));
+
+        dev_caps =   NM_WIFI_DEVICE_CAP_CIPHER_WEP40
+                   | NM_WIFI_DEVICE_CAP_CIPHER_WEP104
+                   | NM_WIFI_DEVICE_CAP_CIPHER_TKIP
+                   | NM_WIFI_DEVICE_CAP_CIPHER_CCMP
+                   | NM_WIFI_DEVICE_CAP_WPA
+                   | NM_WIFI_DEVICE_CAP_RSN;
+
+        mode = nm_setting_wireless_get_mode (sw);
+        if (mode && !strcmp (mode, "adhoc"))
+                is_adhoc = TRUE;
+        page->adhoc = is_adhoc;
+
+        sws = nm_connection_get_setting_wireless_security (connection);
+        security = nm_setting_wireless_get_security (sw);
+        if (!security || strcmp (security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != 0)
+                sws = NULL;
+        if (sws)
+                default_type = get_default_type_for_security (sws);
+
+        sec_model = gtk_list_store_new (3, G_TYPE_STRING, wireless_security_get_g_type (), G_TYPE_BOOLEAN);
+
+        if (nm_utils_security_valid (NMU_SEC_NONE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+                gtk_list_store_insert_with_values (sec_model, &iter, -1,
+                                                   S_NAME_COLUMN, C_("Wi-Fi/Ethernet security", "None"),
+                                                   S_ADHOC_VALID_COLUMN, TRUE,
+                                                   -1);
+                if (default_type == NMU_SEC_NONE)
+                        active = item;
+                item++;
+        }
+
+        if (nm_utils_security_valid (NMU_SEC_STATIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+                WirelessSecurityWEPKey *ws_wep;
+                NMWepKeyType wep_type = NM_WEP_KEY_TYPE_KEY;
+
+                if (default_type == NMU_SEC_STATIC_WEP) {
+                        sws = nm_connection_get_setting_wireless_security (connection);
+                        if (sws)
+                                wep_type = nm_setting_wireless_security_get_wep_key_type (sws);
+                        if (wep_type == NM_WEP_KEY_TYPE_UNKNOWN)
+                                wep_type = NM_WEP_KEY_TYPE_KEY;
+                }
+
+                ws_wep = ws_wep_key_new (connection, NM_WEP_KEY_TYPE_KEY, FALSE, FALSE);
+                if (ws_wep) {
+                        add_security_item (page, WIRELESS_SECURITY (ws_wep), sec_model,
+                                           &iter, _("WEP 40/128-bit Key (Hex or ASCII)"),
+                                           TRUE);
+                        if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_KEY))
+                                active = item;
+                        item++;
+                }
+
+                ws_wep = ws_wep_key_new (connection, NM_WEP_KEY_TYPE_PASSPHRASE, FALSE, FALSE);
+                if (ws_wep) {
+                        add_security_item (page, WIRELESS_SECURITY (ws_wep), sec_model,
+                                           &iter, _("WEP 128-bit Passphrase"), TRUE);
+                        if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE))
+                                active = item;
+                        item++;
+                }
+        }
+
+        if (nm_utils_security_valid (NMU_SEC_LEAP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+                WirelessSecurityLEAP *ws_leap;
+
+                ws_leap = ws_leap_new (connection, FALSE);
+                if (ws_leap) {
+                        add_security_item (page, WIRELESS_SECURITY (ws_leap), sec_model,
+                                           &iter, _("LEAP"), FALSE);
+                        if ((active < 0) && (default_type == NMU_SEC_LEAP))
+                                active = item;
+                        item++;
+                }
+        }
+
+        if (nm_utils_security_valid (NMU_SEC_DYNAMIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+                WirelessSecurityDynamicWEP *ws_dynamic_wep;
+
+                ws_dynamic_wep = ws_dynamic_wep_new (connection, TRUE, FALSE);
+                if (ws_dynamic_wep) {
+                        add_security_item (page, WIRELESS_SECURITY (ws_dynamic_wep), sec_model,
+                                           &iter, _("Dynamic WEP (802.1x)"), FALSE);
+                        if ((active < 0) && (default_type == NMU_SEC_DYNAMIC_WEP))
+                                active = item;
+                        item++;
+                }
+        }
+
+        if (nm_utils_security_valid (NMU_SEC_WPA_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
+            nm_utils_security_valid (NMU_SEC_WPA2_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+                WirelessSecurityWPAPSK *ws_wpa_psk;
+
+                ws_wpa_psk = ws_wpa_psk_new (connection, FALSE);
+                if (ws_wpa_psk) {
+                        add_security_item (page, WIRELESS_SECURITY (ws_wpa_psk), sec_model,
+                                           &iter, _("WPA & WPA2 Personal"), FALSE);
+                        if ((active < 0) && ((default_type == NMU_SEC_WPA_PSK) || (default_type == NMU_SEC_WPA2_PSK)))
+                                active = item;
+                        item++;
+                }
+        }
+
+        if (nm_utils_security_valid (NMU_SEC_WPA_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
+            nm_utils_security_valid (NMU_SEC_WPA2_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+                WirelessSecurityWPAEAP *ws_wpa_eap;
+
+                ws_wpa_eap = ws_wpa_eap_new (connection, TRUE, FALSE);
+                if (ws_wpa_eap) {
+                        add_security_item (page, WIRELESS_SECURITY (ws_wpa_eap), sec_model,
+                                           &iter, _("WPA & WPA2 Enterprise"), FALSE);
+                        if ((active < 0) && ((default_type == NMU_SEC_WPA_ENTERPRISE) || (default_type == NMU_SEC_WPA2_ENTERPRISE)))
+                                active = item;
+                        item++;
+                }
+        }
+
+        gtk_combo_box_set_model (combo, GTK_TREE_MODEL (sec_model));
+        gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer, "text", S_NAME_COLUMN, NULL);
+        gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), renderer, set_sensitive, &page->adhoc, NULL);
+
+        gtk_combo_box_set_active (combo, active < 0 ? 0 : (guint32) active);
+        g_object_unref (G_OBJECT (sec_model));
+
+        page->security_combo = combo;
+
+        security_combo_changed (combo, page);
+        g_signal_connect (combo, "changed",
+                          G_CALLBACK (security_combo_changed), page);
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        NMSettingWireless *sw;
+        WirelessSecurity *sec;
+        gboolean valid = FALSE;
+        const char *mode;
+
+        sw = nm_connection_get_setting_wireless (connection);
+
+        mode = nm_setting_wireless_get_mode (sw);
+        if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0)
+                CE_PAGE_SECURITY (page)->adhoc = TRUE;
+        else
+                CE_PAGE_SECURITY (page)->adhoc = FALSE;
+
+        sec = security_combo_get_active (CE_PAGE_SECURITY (page));
+        if (sec) {
+                const GByteArray *ssid = nm_setting_wireless_get_ssid (sw);
+
+                if (ssid) {
+                        /* FIXME: get failed property and error out of wifi security objects */
+                        valid = wireless_security_validate (sec, ssid);
+                        if (valid)
+                                wireless_security_fill_connection (sec, connection);
+                        else
+                                g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Invalid Wi-Fi security");
+                } else {
+                        g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Missing SSID");
+                        valid = FALSE;
+                }
+
+                if (CE_PAGE_SECURITY (page)->adhoc) {
+                        if (!wireless_security_adhoc_compatible (sec)) {
+                                g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Security not compatible with Ad-Hoc mode");
+                                valid = FALSE;
+                        }
+                }
+
+                wireless_security_unref (sec);
+        } else {
+                /* No security, unencrypted */
+                g_object_set (sw, NM_SETTING_WIRELESS_SEC, NULL, NULL);
+                nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+                nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
+                valid = TRUE;
+        }
+
+        return valid;
+}
+
+static void
+ce_page_security_init (CEPageSecurity *page)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+        CEPageSecurity *page = CE_PAGE_SECURITY (object);
+
+        g_clear_object (&page->group);
+
+        G_OBJECT_CLASS (ce_page_security_parent_class)->dispose (object);
+}
+
+static void
+ce_page_security_class_init (CEPageSecurityClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+        CEPageClass *page_class = CE_PAGE_CLASS (class);
+
+        object_class->dispose = dispose;
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_security_new (NMConnection      *connection,
+                      NMClient          *client,
+                      NMRemoteSettings  *settings)
+{
+        CEPageSecurity *page;
+        const gchar *security;
+        NMUtilsSecurityType default_type = NMU_SEC_NONE;
+        NMSettingWirelessSecurity *sws;
+
+        page = CE_PAGE_SECURITY (ce_page_new (CE_TYPE_PAGE_SECURITY,
+                                              connection,
+                                              client,
+                                              settings,
+                                              "/org/gnome/control-center/network/security-page.ui",
+                                              _("Security")));
+
+        sws = nm_connection_get_setting_wireless_security (connection);
+        security = nm_setting_wireless_get_security (nm_connection_get_setting_wireless (connection));
+        if (!security || strcmp (security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != 0)
+                sws = NULL;
+        if (sws)
+                default_type = get_default_type_for_security (sws);
+
+        if (default_type == NMU_SEC_STATIC_WEP
+            || default_type == NMU_SEC_LEAP
+            || default_type == NMU_SEC_WPA_PSK
+            || default_type == NMU_SEC_WPA2_PSK) {
+                CE_PAGE (page)->security_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
+        }
+
+        if (default_type == NMU_SEC_DYNAMIC_WEP
+            || default_type == NMU_SEC_WPA_ENTERPRISE
+            || default_type == NMU_SEC_WPA2_ENTERPRISE) {
+                CE_PAGE (page)->security_setting = NM_SETTING_802_1X_SETTING_NAME;
+        }
+
+        g_signal_connect (page, "initialized", G_CALLBACK (finish_setup), NULL);
+
+        return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-security.h b/panels/network/connection-editor/ce-page-security.h
new file mode 100644
index 0000000..ab19bb7
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-security.h
@@ -0,0 +1,66 @@
+/* -*- 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 security.
+ *
+ * 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_SECURITY_H
+#define __CE_PAGE_SECURITY_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_SECURITY          (ce_page_security_get_type ())
+#define CE_PAGE_SECURITY(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_SECURITY, CEPageSecurity))
+#define CE_PAGE_SECURITY_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_SECURITY, CEPageSecurityClass))
+#define CE_IS_PAGE_SECURITY(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_SECURITY))
+#define CE_IS_PAGE_SECURITY_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_SECURITY))
+#define CE_PAGE_SECURITY_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_SECURITY, CEPageSecurityClass))
+
+typedef struct _CEPageSecurity          CEPageSecurity;
+typedef struct _CEPageSecurityClass     CEPageSecurityClass;
+
+struct _CEPageSecurity
+{
+        CEPage parent;
+
+        GtkComboBox *security_combo;
+        GtkWidget   *security_heading;
+        GtkSizeGroup *group;
+        gboolean     adhoc;
+};
+
+struct _CEPageSecurityClass
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_security_get_type (void);
+
+CEPage *ce_page_security_new      (NMConnection     *connection,
+                                   NMClient         *client,
+                                   NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_SECURITY_H */
+
diff --git a/panels/network/connection-editor/ce-page-wifi.c b/panels/network/connection-editor/ce-page-wifi.c
new file mode 100644
index 0000000..aa5984d
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-wifi.c
@@ -0,0 +1,221 @@
+/* -*- 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-setting-wireless.h>
+#include <nm-utils.h>
+#include <nm-device-wifi.h>
+
+#include <net/if_arp.h>
+
+#include "ce-page-wifi.h"
+
+G_DEFINE_TYPE (CEPageWifi, ce_page_wifi, CE_TYPE_PAGE)
+
+static void
+connect_wifi_page (CEPageWifi *page)
+{
+        GtkWidget *widget;
+        const GByteArray *ssid;
+        gchar *utf8_ssid;
+        GPtrArray *bssid_array;
+        gchar **bssid_list;
+        const GByteArray *s_bssid;
+        gchar *s_bssid_str;
+        gchar **mac_list;
+        const GByteArray *s_mac;
+        gchar *s_mac_str;
+        gint i;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+                                                     "entry_ssid"));
+
+        ssid = nm_setting_wireless_get_ssid (page->setting);
+        if (ssid)
+                utf8_ssid = nm_utils_ssid_to_utf8 (ssid);
+        else
+                utf8_ssid = g_strdup ("");
+        gtk_entry_set_text (GTK_ENTRY (widget), utf8_ssid);
+        g_free (utf8_ssid);
+
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+                                                     "combo_bssid"));
+
+        bssid_array = g_ptr_array_new ();
+        for (i = 0; i < nm_setting_wireless_get_num_seen_bssids (page->setting); i++) {
+                g_ptr_array_add (bssid_array, g_strdup (nm_setting_wireless_get_seen_bssid (page->setting, i)));
+        }
+        g_ptr_array_add (bssid_array, NULL);
+        bssid_list = (gchar **) g_ptr_array_free (bssid_array, FALSE);
+        s_bssid = nm_setting_wireless_get_bssid (page->setting);
+        s_bssid_str = s_bssid ? nm_utils_hwaddr_ntoa (s_bssid->data, ARPHRD_ETHER) : NULL;
+        ce_page_setup_mac_combo (GTK_COMBO_BOX_TEXT (widget), s_bssid_str, bssid_list);
+        g_free (s_bssid_str);
+        g_strfreev (bssid_list);
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+                                                     "combo_mac"));
+        mac_list = ce_page_get_mac_list (CE_PAGE (page)->client, NM_TYPE_DEVICE_WIFI,
+                                         NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
+        s_mac = nm_setting_wireless_get_mac_address (page->setting);
+        s_mac_str = s_mac ? nm_utils_hwaddr_ntoa (s_mac->data, ARPHRD_ETHER) : NULL;
+        ce_page_setup_mac_combo (GTK_COMBO_BOX_TEXT (widget), s_mac_str, mac_list);
+        g_free (s_mac_str);
+        g_strfreev (mac_list);
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+
+
+        widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+                                                     "entry_cloned_mac"));
+        ce_page_mac_to_entry (nm_setting_wireless_get_cloned_mac_address (page->setting),
+                              ARPHRD_ETHER, GTK_ENTRY (widget));
+        g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+}
+
+static void
+ui_to_setting (CEPageWifi *page)
+{
+        GByteArray *ssid;
+        GByteArray *bssid = NULL;
+        GByteArray *device_mac = NULL;
+        GByteArray *cloned_mac = NULL;
+        GtkWidget *entry;
+        const gchar *utf8_ssid;
+
+        entry = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_ssid"));
+        utf8_ssid = gtk_entry_get_text (GTK_ENTRY (entry));
+        if (!utf8_ssid || !*utf8_ssid)
+                ssid = NULL;
+        else {
+                ssid = g_byte_array_sized_new (strlen (utf8_ssid));
+                g_byte_array_append (ssid, (const guint8*)utf8_ssid, strlen (utf8_ssid));
+        }
+        entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_bssid")));
+        bssid = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+        entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_mac")));
+        device_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+        entry = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_cloned_mac"));
+        cloned_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+
+        g_object_set (page->setting,
+                      NM_SETTING_WIRELESS_SSID, ssid,
+                      NM_SETTING_WIRELESS_BSSID, bssid,
+                      NM_SETTING_WIRELESS_MAC_ADDRESS, device_mac,
+                      NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac,
+                      NULL);
+
+        if (ssid)
+                g_byte_array_free (ssid, TRUE);
+        if (bssid)
+                g_byte_array_free (bssid, TRUE);
+        if (device_mac)
+                g_byte_array_free (device_mac, TRUE);
+        if (cloned_mac)
+                g_byte_array_free (cloned_mac, TRUE);
+}
+
+static gboolean
+validate (CEPage        *page,
+          NMConnection  *connection,
+          GError       **error)
+{
+        GtkWidget *entry;
+        GByteArray *ignore;
+        gboolean invalid;
+        gboolean success;
+        gchar *security;
+        NMSettingWireless *setting;
+
+        entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (page->builder, "combo_bssid")));
+        ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+        if (invalid)
+                return FALSE;
+        if (ignore)
+                g_byte_array_free (ignore, TRUE);
+
+        entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (page->builder, "combo_mac")));
+        ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+        if (invalid)
+                return FALSE;
+        if (ignore)
+                g_byte_array_free (ignore, TRUE);
+
+        entry = GTK_WIDGET (gtk_builder_get_object (page->builder, "entry_cloned_mac"));
+        ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+        if (invalid)
+                return FALSE;
+        if (ignore)
+                g_byte_array_free (ignore, TRUE);
+
+
+        ui_to_setting (CE_PAGE_WIFI (page));
+
+        /* A hack to not check the wifi security here */
+        setting = CE_PAGE_WIFI (page)->setting;
+        security = g_strdup (nm_setting_wireless_get_security (setting));
+        g_object_set (setting, NM_SETTING_WIRELESS_SEC, NULL, NULL);
+        success = nm_setting_verify (NM_SETTING (setting), NULL, error);
+        g_object_set (setting, NM_SETTING_WIRELESS_SEC, security, NULL);
+        g_free (security);
+
+        return success;
+}
+
+static void
+ce_page_wifi_init (CEPageWifi *page)
+{
+}
+
+static void
+ce_page_wifi_class_init (CEPageWifiClass *class)
+{
+        CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+        page_class->validate = validate;
+}
+
+CEPage *
+ce_page_wifi_new (NMConnection     *connection,
+                      NMClient         *client,
+                      NMRemoteSettings *settings)
+{
+        CEPageWifi *page;
+
+        page = CE_PAGE_WIFI (ce_page_new (CE_TYPE_PAGE_WIFI,
+                                          connection,
+                                          client,
+                                          settings,
+                                          "/org/gnome/control-center/network/wifi-page.ui",
+                                          _("Identity")));
+
+        page->setting = nm_connection_get_setting_wireless (connection);
+
+        connect_wifi_page (page);
+
+        return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-wifi.h b/panels/network/connection-editor/ce-page-wifi.h
new file mode 100644
index 0000000..88087e7
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-wifi.h
@@ -0,0 +1,63 @@
+/* -*- 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 wifi.
+ *
+ * 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_WIFI_H
+#define __CE_PAGE_WIFI_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_WIFI          (ce_page_wifi_get_type ())
+#define CE_PAGE_WIFI(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_WIFI, CEPageWifi))
+#define CE_PAGE_WIFI_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_WIFI, CEPageWifiClass))
+#define CE_IS_PAGE_WIFI(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_WIFI))
+#define CE_IS_PAGE_WIFI_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_WIFI))
+#define CE_PAGE_WIFI_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_WIFI, CEPageWifiClass))
+
+typedef struct _CEPageWifi          CEPageWifi;
+typedef struct _CEPageWifiClass     CEPageWifiClass;
+
+struct _CEPageWifi
+{
+        CEPage parent;
+
+        NMSettingWireless *setting;
+};
+
+struct _CEPageWifiClass
+{
+        CEPageClass parent_class;
+};
+
+GType   ce_page_wifi_get_type (void);
+
+CEPage *ce_page_wifi_new      (NMConnection     *connection,
+                               NMClient         *client,
+                               NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_WIFI_H */
+
diff --git a/panels/network/connection-editor/ce-page.c b/panels/network/connection-editor/ce-page.c
new file mode 100644
index 0000000..99b20e7
--- /dev/null
+++ b/panels/network/connection-editor/ce-page.c
@@ -0,0 +1,454 @@
+/* -*- 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 <string.h>
+
+#include <net/if_arp.h>
+#include <netinet/ether.h>
+
+#include <nm-utils.h>
+
+#include "ce-page.h"
+
+
+G_DEFINE_ABSTRACT_TYPE (CEPage, ce_page, G_TYPE_OBJECT)
+
+enum {
+        PROP_0,
+        PROP_CONNECTION,
+        PROP_INITIALIZED,
+};
+
+enum {
+        CHANGED,
+        INITIALIZED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+gboolean
+ce_page_validate (CEPage *page, NMConnection *connection, GError **error)
+{
+        g_return_val_if_fail (CE_IS_PAGE (page), FALSE);
+        g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+        if (CE_PAGE_GET_CLASS (page)->validate)
+                return CE_PAGE_GET_CLASS (page)->validate (page, connection, error);
+
+        return TRUE;
+}
+
+static void
+dispose (GObject *object)
+{
+        CEPage *self = CE_PAGE (object);
+
+        g_clear_object (&self->page);
+        g_clear_object (&self->builder);
+        g_clear_object (&self->connection);
+
+        G_OBJECT_CLASS (ce_page_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+        CEPage *self = CE_PAGE (object);
+
+        g_free (self->title);
+
+        G_OBJECT_CLASS (ce_page_parent_class)->finalize (object);
+}
+
+GtkWidget *
+ce_page_get_page (CEPage *self)
+{
+        g_return_val_if_fail (CE_IS_PAGE (self), NULL);
+
+        return self->page;
+}
+
+const char *
+ce_page_get_title (CEPage *self)
+{
+        g_return_val_if_fail (CE_IS_PAGE (self), NULL);
+
+        return self->title;
+}
+
+gboolean
+ce_page_get_initialized (CEPage *self)
+{
+        g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
+
+        return self->initialized;
+}
+
+void
+ce_page_changed (CEPage *self)
+{
+        g_return_if_fail (CE_IS_PAGE (self));
+
+        g_signal_emit (self, signals[CHANGED], 0);
+}
+
+static void
+get_property (GObject    *object,
+              guint       prop_id,
+              GValue     *value,
+              GParamSpec *pspec)
+{
+        CEPage *self = CE_PAGE (object);
+
+        switch (prop_id) {
+        case PROP_CONNECTION:
+                g_value_set_object (value, self->connection);
+                break;
+        case PROP_INITIALIZED:
+                g_value_set_boolean (value, self->initialized);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+set_property (GObject      *object,
+              guint         prop_id,
+              const GValue *value,
+              GParamSpec   *pspec)
+{
+        CEPage *self = CE_PAGE (object);
+
+        switch (prop_id) {
+        case PROP_CONNECTION:
+                if (self->connection)
+                        g_object_unref (self->connection);
+                self->connection = g_value_dup_object (value);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+ce_page_init (CEPage *self)
+{
+        self->builder = gtk_builder_new ();
+}
+
+static void
+ce_page_class_init (CEPageClass *page_class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (page_class);
+
+        /* virtual methods */
+        object_class->dispose      = dispose;
+        object_class->finalize     = finalize;
+        object_class->get_property = get_property;
+        object_class->set_property = set_property;
+
+        /* Properties */
+        g_object_class_install_property
+                (object_class, PROP_CONNECTION,
+                 g_param_spec_object ("connection",
+                                      "Connection",
+                                      "Connection",
+                                      NM_TYPE_CONNECTION,
+                                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+        g_object_class_install_property
+                (object_class, PROP_INITIALIZED,
+                 g_param_spec_boolean ("initialized",
+                                       "Initialized",
+                                       "Initialized",
+                                       FALSE,
+                                       G_PARAM_READABLE));
+
+        signals[CHANGED] =
+                g_signal_new ("changed",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (CEPageClass, changed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE, 0);
+
+        signals[INITIALIZED] =
+                g_signal_new ("initialized",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (CEPageClass, initialized),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__POINTER,
+                              G_TYPE_NONE, 1, G_TYPE_POINTER);
+}
+
+CEPage *
+ce_page_new (GType             type,
+             NMConnection     *connection,
+             NMClient         *client,
+             NMRemoteSettings *settings,
+             const gchar      *ui_resource,
+             const gchar      *title)
+{
+        CEPage *page;
+        GError *error = NULL;
+
+        page = CE_PAGE (g_object_new (type,
+                                      "connection", connection,
+                                      NULL));
+        page->title = g_strdup (title);
+        page->client = client;
+        page->settings= settings;
+        if (!gtk_builder_add_from_resource (page->builder, ui_resource, &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_resource);
+                g_object_unref (page);
+                return NULL;
+        }
+
+        g_object_ref_sink (page->page);
+
+        return page;
+}
+
+static void
+emit_initialized (CEPage *page,
+                  GError *error)
+{
+        page->initialized = TRUE;
+        g_signal_emit (page, signals[INITIALIZED], 0, error);
+}
+
+void
+ce_page_complete_init (CEPage      *page,
+                       const gchar *setting_name,
+                       GHashTable  *secrets,
+                       GError      *error)
+{
+        GHashTable *setting_hash;
+        GError *update_error = NULL;
+
+        if (error
+            && !dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.InvalidSetting")
+            && !dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.AgentManager.NoSecrets")) {
+                emit_initialized (page, error);
+                return;
+        } else if (!setting_name || !secrets || !g_hash_table_size (secrets)) {
+                /* Success, no secrets */
+                emit_initialized (page, NULL);
+                return;
+        }
+
+        setting_hash = g_hash_table_lookup (secrets, setting_name);
+        if (!setting_hash) {
+                /* Success, no secrets */
+                emit_initialized (page, NULL);
+                return;
+        }
+
+        if (nm_connection_update_secrets (page->connection,
+                                          setting_name,
+                                          secrets,
+                                          &update_error)) {
+                emit_initialized (page, NULL);
+                return;
+        }
+
+        if (!update_error) {
+                g_set_error_literal (&update_error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN,
+                                     "Failed to update connection secrets due to an unknown error.");
+        }
+
+        emit_initialized (page, update_error);
+        g_clear_error (&update_error);
+}
+
+gchar **
+ce_page_get_mac_list (NMClient    *client,
+                      GType        device_type,
+                      const gchar *mac_property)
+{
+        const GPtrArray *devices;
+        GPtrArray *macs;
+        int i;
+
+        macs = g_ptr_array_new ();
+        devices = nm_client_get_devices (client);
+        for (i = 0; devices && (i < devices->len); i++) {
+                NMDevice *dev = g_ptr_array_index (devices, i);
+                const char *iface;
+                char *mac, *item;
+
+                if (!G_TYPE_CHECK_INSTANCE_TYPE (dev, device_type))
+                        continue;
+
+                g_object_get (G_OBJECT (dev), mac_property, &mac, NULL);
+                iface = nm_device_get_iface (NM_DEVICE (dev));
+                item = g_strdup_printf ("%s (%s)", mac, iface);
+                g_free (mac);
+                g_ptr_array_add (macs, item);
+        }
+
+        g_ptr_array_add (macs, NULL);
+        return (char **)g_ptr_array_free (macs, FALSE);
+}
+
+void
+ce_page_setup_mac_combo (GtkComboBoxText  *combo,
+                         const gchar      *current_mac,
+                         gchar           **mac_list)
+{
+        gchar **m, *active_mac = NULL;
+        gint current_mac_len;
+        GtkWidget *entry;
+
+        if (current_mac)
+                current_mac_len = strlen (current_mac);
+        else
+                current_mac_len = -1;
+
+        for (m= mac_list; m && *m; m++) {
+                gtk_combo_box_text_append_text (combo, *m);
+                if (current_mac &&
+                    g_ascii_strncasecmp (*m, current_mac, current_mac_len) == 0
+                    && ((*m)[current_mac_len] == '\0' || (*m)[current_mac_len] == ' '))
+                        active_mac = *m;
+        }
+
+        if (current_mac) {
+                if (!active_mac) {
+                        gtk_combo_box_text_prepend_text (combo, current_mac);
+                }
+
+                entry = gtk_bin_get_child (GTK_BIN (combo));
+                if (entry)
+                        gtk_entry_set_text (GTK_ENTRY (entry), active_mac ? active_mac : current_mac);
+        }
+}
+
+void
+ce_page_mac_to_entry (const GByteArray *mac,
+                      gint              type,
+                      GtkEntry         *entry)
+{
+        char *str_addr;
+
+        g_return_if_fail (entry != NULL);
+        g_return_if_fail (GTK_IS_ENTRY (entry));
+
+        if (!mac || !mac->len)
+                return;
+
+        if (mac->len != nm_utils_hwaddr_len (type))
+                return;
+
+        str_addr = nm_utils_hwaddr_ntoa (mac->data, type);
+        gtk_entry_set_text (entry, str_addr);
+        g_free (str_addr);
+}
+
+static gboolean
+utils_ether_addr_valid (const struct ether_addr *test_addr)
+{
+        guint8 invalid_addr1[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+        guint8 invalid_addr2[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+        guint8 invalid_addr3[ETH_ALEN] = {0x44, 0x44, 0x44, 0x44, 0x44, 0x44};
+        guint8 invalid_addr4[ETH_ALEN] = {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}; /* prism54 dummy MAC */
+
+        g_return_val_if_fail (test_addr != NULL, FALSE);
+
+        /* Compare the AP address the card has with invalid ethernet MAC addresses. */
+        if (!memcmp (test_addr->ether_addr_octet, &invalid_addr1, ETH_ALEN))
+                return FALSE;
+
+        if (!memcmp (test_addr->ether_addr_octet, &invalid_addr2, ETH_ALEN))
+                return FALSE;
+
+        if (!memcmp (test_addr->ether_addr_octet, &invalid_addr3, ETH_ALEN))
+                return FALSE;
+        if (!memcmp (test_addr->ether_addr_octet, &invalid_addr4, ETH_ALEN))
+                return FALSE;
+
+        if (test_addr->ether_addr_octet[0] & 1)  /* Multicast addresses */
+                return FALSE;
+        
+        return TRUE;
+}
+
+GByteArray *
+ce_page_entry_to_mac (GtkEntry *entry,
+                      gint      type,
+                      gboolean *invalid)
+{
+        const char *temp, *sp;
+        char *buf = NULL;
+        GByteArray *mac;
+
+        g_return_val_if_fail (entry != NULL, NULL);
+        g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
+
+        if (invalid)
+                *invalid = FALSE;
+
+        temp = gtk_entry_get_text (entry);
+        if (!temp || !strlen (temp))
+                return NULL;
+
+        sp = strchr (temp, ' ');
+        if (sp)
+                temp = buf = g_strndup (temp, sp - temp);
+
+        mac = nm_utils_hwaddr_atoba (temp, type);
+        g_free (buf);
+        if (!mac) {
+                if (invalid)
+                        *invalid = TRUE;
+                return NULL;
+        }
+
+        if (type == ARPHRD_ETHER && !utils_ether_addr_valid ((struct ether_addr *)mac->data)) {
+                g_byte_array_free (mac, TRUE);
+                if (invalid)
+                        *invalid = TRUE;
+                return NULL;
+        }
+
+        return mac;
+}
+
+const gchar *
+ce_page_get_security_setting (CEPage *page)
+{
+        return page->security_setting;
+}
diff --git a/panels/network/connection-editor/ce-page.h b/panels/network/connection-editor/ce-page.h
new file mode 100644
index 0000000..7a08380
--- /dev/null
+++ b/panels/network/connection-editor/ce-page.h
@@ -0,0 +1,106 @@
+/* -*- 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.
+ */
+
+#ifndef __CE_PAGE_H
+#define __CE_PAGE_H
+
+#include <glib-object.h>
+
+#include <nm-connection.h>
+#include <nm-client.h>
+#include <nm-remote-settings.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE          (ce_page_get_type ())
+#define CE_PAGE(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE, CEPage))
+#define CE_PAGE_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE, CEPageClass))
+#define CE_IS_PAGE(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE))
+#define CE_IS_PAGE_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE))
+#define CE_PAGE_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE, CEPageClass))
+
+typedef struct _CEPage          CEPage;
+typedef struct _CEPageClass     CEPageClass;
+
+struct _CEPage
+{
+        GObject parent;
+
+        gboolean initialized;
+        GtkBuilder *builder;
+        GtkWidget *page;
+        gchar *title;
+        const gchar *security_setting;
+
+        NMConnection *connection;
+        NMClient *client;
+        NMRemoteSettings *settings;
+};
+
+struct _CEPageClass
+{
+        GObjectClass parent_class;
+
+        gboolean (*validate) (CEPage *page, NMConnection *connection, GError **error);
+        void (*changed)     (CEPage *page);
+        void (*initialized) (CEPage *page, GError *error);
+};
+
+GType        ce_page_get_type        (void);
+
+GtkWidget   *ce_page_get_page        (CEPage           *page);
+const gchar *ce_page_get_title       (CEPage           *page);
+const gchar *ce_page_get_security_setting (CEPage           *page);
+gboolean     ce_page_validate        (CEPage           *page,
+                                      NMConnection     *connection,
+                                      GError          **error);
+gboolean     ce_page_get_initialized (CEPage           *page);
+void         ce_page_changed         (CEPage           *page);
+CEPage      *ce_page_new             (GType             type,
+                                      NMConnection     *connection,
+                                      NMClient         *client,
+                                      NMRemoteSettings *settings,
+                                      const gchar      *ui_resource,
+                                      const gchar      *title);
+void         ce_page_complete_init   (CEPage           *page,
+                                      const gchar      *setting_name,
+                                      GHashTable       *secrets,
+                                      GError           *error);
+
+gchar      **ce_page_get_mac_list    (NMClient         *client,
+                                      GType             device_type,
+                                      const gchar      *mac_property);
+void         ce_page_setup_mac_combo (GtkComboBoxText  *combo,
+                                      const gchar      *current_mac,
+                                      gchar           **mac_list);
+void         ce_page_mac_to_entry    (const GByteArray *mac,
+                                      gint              type,
+                                      GtkEntry         *entry);
+GByteArray  *ce_page_entry_to_mac    (GtkEntry         *entry,
+                                      gint              type,
+                                      gboolean         *invalid);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_H */
+
diff --git a/panels/network/connection-editor/connection-editor.gresource.xml b/panels/network/connection-editor/connection-editor.gresource.xml
new file mode 100644
index 0000000..a15e9bd
--- /dev/null
+++ b/panels/network/connection-editor/connection-editor.gresource.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/control-center/network">
+    <file preprocess="xml-stripblanks">connection-editor.ui</file>
+    <file preprocess="xml-stripblanks">details-page.ui</file>
+    <file preprocess="xml-stripblanks">ip4-page.ui</file>
+    <file preprocess="xml-stripblanks">ip6-page.ui</file>
+    <file preprocess="xml-stripblanks">reset-page.ui</file>
+    <file preprocess="xml-stripblanks">security-page.ui</file>
+    <file preprocess="xml-stripblanks">wifi-page.ui</file>
+  </gresource>
+</gresources>
diff --git a/panels/network/connection-editor/connection-editor.ui b/panels/network/connection-editor/connection-editor.ui
new file mode 100644
index 0000000..a8cb2d9
--- /dev/null
+++ b/panels/network/connection-editor/connection-editor.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="details_store">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name page -->
+      <column type="gint"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="details_dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="modal">True</property>
+    <property name="default_width">600</property>
+    <property name="default_height">300</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox2">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area2">
+            <property name="can_focus">False</property>
+            <property name="valign">end</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="details_cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="details_apply_button">
+                <property name="label">gtk-apply</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box6">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkScrolledWindow" id="details_sidebar">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="details_page_list">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="model">details_store</property>
+                    <property name="headers_visible">False</property>
+                    <property name="headers_clickable">False</property>
+                    <property name="search_column">0</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection" id="details_page_list_selection"/>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="details_column">
+                        <child>
+                          <object class="GtkCellRendererText" id="details_cell">
+                            <property name="xpad">10</property>
+                          </object>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
+                        </child>
+                        <child>
+                          <object class="GtkCellRendererText" id="padding_cell">
+                            <property name="xpad">20</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkNotebook" id="details_notebook">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="show_tabs">False</property>
+                <property name="show_border">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">details_cancel_button</action-widget>
+      <action-widget response="0">details_apply_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/details-page.ui b/panels/network/connection-editor/details-page.ui
new file mode 100644
index 0000000..02c9eca
--- /dev/null
+++ b/panels/network/connection-editor/details-page.ui
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkBox" id="page">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkBox" id="auto_connect_box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="halign">end</property>
+        <property name="valign">center</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label8">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Automatic _Connect</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">auto_connect_switch</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSwitch" id="auto_connect_switch">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</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">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="halign">end</property>
+        <property name="valign">center</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="all_users_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Available to all _users</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">all_user_switch</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSwitch" id="all_user_switch">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</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>
+    <child>
+      <object class="GtkGrid" id="grid1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="valign">start</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_strength">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Signal Strength</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="label_strength">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="xalign">0</property>
+            <property name="label">Weak</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="heading_speed">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Link speed</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="label_speed">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="xalign">0</property>
+            <property name="label">1Mb/sec</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="heading_security">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Security</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_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>
+            <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>
+            <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_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>
+            <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_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>
+            <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="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>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </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="GtkLabel" id="heading_last_used">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Last used</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">8</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_security">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="xalign">0</property>
+            <property name="label">WPA</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_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">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">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">5</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">6</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">7</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_last_used">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="xalign">0</property>
+            <property name="label">today</property>
+            <property name="selectable">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">8</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/ip4-page.ui b/panels/network/connection-editor/ip4-page.ui
new file mode 100644
index 0000000..e5a46ab
--- /dev/null
+++ b/panels/network/connection-editor/ip4-page.ui
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkScrolledWindow" id="page">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="hscrollbar_policy">never</property>
+    <child>
+      <object class="GtkViewport" id="viewport1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkBox" id="box2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">20</property>
+            <property name="margin_right">20</property>
+            <property name="margin_top">10</property>
+            <property name="margin_bottom">10</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">10</property>
+            <child>
+              <object class="GtkBox" id="box5">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkLabel" id="heading_enable">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">IPv_4</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">switch_enable</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="switch_enable">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="halign">end</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</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">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="page_content">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">10</property>
+                <child>
+                  <object class="GtkBox" id="box7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="heading_addresses">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">_Addresses</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">combo_addresses</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="combo_addresses">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="hexpand">True</property>
+                        <property name="entry_text_column">0</property>
+                        <property name="id_column">1</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</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">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="address_section">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_dns">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_top">24</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">DNS</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="dns_section">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_routes">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_top">24</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Routes</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="routes_section">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="never_default_check">
+                    <property name="label" translatable="yes">Use this connection _only for resources on its network</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="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">7</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>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/ip6-page.ui b/panels/network/connection-editor/ip6-page.ui
new file mode 100644
index 0000000..8ac22e5
--- /dev/null
+++ b/panels/network/connection-editor/ip6-page.ui
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkScrolledWindow" id="page">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="hscrollbar_policy">never</property>
+    <child>
+      <object class="GtkViewport" id="viewport1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkBox" id="box2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">20</property>
+            <property name="margin_right">20</property>
+            <property name="margin_top">10</property>
+            <property name="margin_bottom">10</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">10</property>
+            <child>
+              <object class="GtkBox" id="box5">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkLabel" id="heading_enable">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">IPv_6</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">switch_enable</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="switch_enable">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="halign">end</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</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">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="page_content">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">10</property>
+                <child>
+                  <object class="GtkBox" id="box7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="heading_addresses">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">_Addresses</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">combo_addresses</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="combo_addresses">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="hexpand">True</property>
+                        <property name="entry_text_column">0</property>
+                        <property name="id_column">1</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</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">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="address_section">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_dns">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_top">24</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">DNS</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="dns_section">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="heading_routes">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_top">24</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Routes</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="routes_section">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="never_default_check">
+                    <property name="label" translatable="yes">Use this connection _only for resources on its network</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="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">7</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>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c
new file mode 100644
index 0000000..5faafb0
--- /dev/null
+++ b/panels/network/connection-editor/net-connection-editor.c
@@ -0,0 +1,420 @@
+/* -*- 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-wifi.h>
+
+#include "net-connection-editor.h"
+#include "net-connection-editor-resources.h"
+#include "ce-page-details.h"
+#include "ce-page-wifi.h"
+#include "ce-page-ip4.h"
+#include "ce-page-ip6.h"
+#include "ce-page-security.h"
+#include "ce-page-reset.h"
+
+#include "egg-list-box/egg-list-box.h"
+
+enum {
+        DONE,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (NetConnectionEditor, net_connection_editor, G_TYPE_OBJECT)
+
+static void
+selection_changed (GtkTreeSelection *selection, NetConnectionEditor *editor)
+{
+        GtkWidget *widget;
+        GtkTreeModel *model;
+        GtkTreeIter iter;
+        gint page;
+
+        gtk_tree_selection_get_selected (selection, &model, &iter);
+        gtk_tree_model_get (model, &iter, 1, &page, -1);
+
+        widget = GTK_WIDGET (gtk_builder_get_object (editor->builder,
+                                                     "details_notebook"));
+        gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), page);
+}
+
+static void
+cancel_editing (NetConnectionEditor *editor)
+{
+        gtk_widget_hide (editor->window);
+        g_signal_emit (editor, signals[DONE], 0, FALSE);
+}
+
+static void
+update_connection (NetConnectionEditor *editor)
+{
+        GHashTable *settings;
+
+        settings = nm_connection_to_hash (editor->connection, NM_SETTING_HASH_FLAG_ALL);
+        nm_connection_replace_settings (editor->orig_connection, settings, NULL);
+        g_hash_table_destroy (settings);
+}
+
+static void
+update_complete (NetConnectionEditor *editor, GError *error)
+{
+        gtk_widget_hide (editor->window);
+        g_signal_emit (editor, signals[DONE], 0, !error);
+}
+
+static void
+updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer data)
+{
+        NetConnectionEditor *editor = data;
+
+        nm_connection_clear_secrets (NM_CONNECTION (connection));
+
+        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);
+}
+
+static void
+net_connection_editor_init (NetConnectionEditor *editor)
+{
+        GtkTreeSelection *selection;
+        GError *error = NULL;
+        GtkWidget *button;
+
+        editor->builder = gtk_builder_new ();
+
+        gtk_builder_add_from_resource (editor->builder,
+                                       "/org/gnome/control-center/network/connection-editor.ui",
+                                       &error);
+        if (error != NULL) {
+                g_warning ("Could not load ui file: %s", error->message);
+                g_error_free (error);
+                return;
+        }
+
+        /* set up widgets */
+
+        editor->window = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_dialog"));
+        selection = GTK_TREE_SELECTION (gtk_builder_get_object (editor->builder,
+                                                                "details_page_list_selection"));
+        g_signal_connect (selection, "changed",
+                          G_CALLBACK (selection_changed), editor);
+
+        button = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_cancel_button"));
+        g_signal_connect_swapped (button, "clicked",
+                                  G_CALLBACK (cancel_editing), editor);
+        g_signal_connect_swapped (editor->window, "delete-event",
+                                  G_CALLBACK (cancel_editing), editor);
+
+        button = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button"));
+        g_signal_connect_swapped (button, "clicked",
+                                  G_CALLBACK (apply_edits), editor);
+}
+
+static void
+net_connection_editor_finalize (GObject *object)
+{
+        NetConnectionEditor *editor = NET_CONNECTION_EDITOR (object);
+
+        g_clear_object (&editor->connection);
+        g_clear_object (&editor->orig_connection);
+        if (editor->window) {
+                gtk_widget_destroy (editor->window);
+                editor->window = NULL;
+        }
+        g_clear_object (&editor->parent_window);
+        g_clear_object (&editor->builder);
+        g_clear_object (&editor->device);
+        g_clear_object (&editor->settings);
+        g_clear_object (&editor->client);
+        g_clear_object (&editor->ap);
+
+        G_OBJECT_CLASS (net_connection_editor_parent_class)->finalize (object);
+}
+
+static void
+net_connection_editor_class_init (NetConnectionEditorClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+        g_resources_register (net_connection_editor_get_resource ());
+
+        object_class->finalize = net_connection_editor_finalize;
+
+        signals[DONE] = g_signal_new ("done",
+                                      G_OBJECT_CLASS_TYPE (object_class),
+                                      G_SIGNAL_RUN_FIRST,
+                                      G_STRUCT_OFFSET (NetConnectionEditorClass, done),
+                                      NULL, NULL,
+                                      NULL,
+                                      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+net_connection_editor_update_title (NetConnectionEditor *editor)
+{
+        NMSettingWireless *sw;
+        const GByteArray *ssid;
+        gchar *id;
+
+        sw = nm_connection_get_setting_wireless (editor->connection);
+        ssid = nm_setting_wireless_get_ssid (sw);
+        id = nm_utils_ssid_to_utf8 (ssid);
+        gtk_window_set_title (GTK_WINDOW (editor->window), id);
+        g_free (id);
+}
+
+static gboolean
+editor_is_initialized (NetConnectionEditor *editor)
+{
+        return editor->initializing_pages == NULL;
+}
+
+static void
+validate (NetConnectionEditor *editor)
+{
+        gboolean valid = FALSE;
+        GSList *l;
+
+        if (!editor_is_initialized (editor))
+                goto done;
+
+        valid = TRUE;
+        for (l = editor->pages; l; l = l->next) {
+                GError *error = NULL;
+
+                if (!ce_page_validate (CE_PAGE (l->data), editor->connection, &error)) {
+                        valid = FALSE;
+                        if (error) {
+                                g_warning ("Invalid setting %s: %s", ce_page_get_title (CE_PAGE (l->data)), error->message);
+                                g_error_free (error);
+                        } else {
+                                g_warning ("Invalid setting %s", ce_page_get_title (CE_PAGE (l->data)));
+                        }
+                }
+        }
+
+done:
+        gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button")), valid);
+}
+
+static void
+page_changed (CEPage *page, gpointer user_data)
+{
+        NetConnectionEditor *editor= user_data;
+
+        validate (editor);
+}
+
+static gboolean
+idle_validate (gpointer user_data)
+{
+        validate (NET_CONNECTION_EDITOR (user_data));
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+recheck_initialization (NetConnectionEditor *editor)
+{
+        GtkNotebook *notebook;
+
+        if (!editor_is_initialized (editor))
+                return;
+
+        notebook = GTK_NOTEBOOK (gtk_builder_get_object (editor->builder, "details_notebook"));
+        gtk_notebook_set_current_page (notebook, 0);
+
+        g_idle_add (idle_validate, editor);
+}
+
+static void
+page_initialized (CEPage *page, GError *error, NetConnectionEditor *editor)
+{
+        GtkNotebook *notebook;
+        GtkWidget *widget;
+        gint position;
+        GList *children, *l;
+        gint i;
+
+        notebook = GTK_NOTEBOOK (gtk_builder_get_object (editor->builder, "details_notebook"));
+        widget = ce_page_get_page (page);
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "position"));
+        g_object_set_data (G_OBJECT (widget), "position", GINT_TO_POINTER (position));
+        children = gtk_container_get_children (GTK_CONTAINER (notebook));
+        for (l = children, i = 0; l; l = l->next, i++) {
+                gint pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (l->data), "position"));
+                if (pos > position)
+                        break;
+        }
+        g_list_free (children);
+        gtk_notebook_insert_page (notebook, widget, NULL, i);
+
+        editor->initializing_pages = g_slist_remove (editor->initializing_pages, page);
+        editor->pages = g_slist_append (editor->pages, page);
+
+        recheck_initialization (editor);
+}
+
+typedef struct {
+        NetConnectionEditor *editor;
+        CEPage *page;
+        const gchar *setting_name;
+        gboolean canceled;
+} GetSecretsInfo;
+
+static void
+get_secrets_cb (NMRemoteConnection *connection,
+                GHashTable         *secrets,
+                GError             *error,
+                gpointer            user_data)
+{
+        GetSecretsInfo *info = user_data;
+
+        if (info->canceled) {
+                g_free (info);
+                return;
+        }
+
+        ce_page_complete_init (info->page, info->setting_name, secrets, error);
+        g_free (info);
+}
+
+static void
+get_secrets_for_page (NetConnectionEditor *editor,
+                      CEPage              *page,
+                      const gchar         *setting_name)
+{
+        GetSecretsInfo *info;
+
+        info = g_new0 (GetSecretsInfo, 1);
+        info->editor = editor;
+        info->page = page;
+        info->setting_name = setting_name;
+
+        nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (editor->orig_connection),
+                                          setting_name,
+                                          get_secrets_cb,
+                                          info);
+}
+
+static void
+add_page (NetConnectionEditor *editor, CEPage *page)
+{
+        GtkListStore *store;
+        GtkTreeIter iter;
+        const gchar *title;
+        gint position;
+
+        store = GTK_LIST_STORE (gtk_builder_get_object (editor->builder,
+                                                "details_store"));
+        title = ce_page_get_title (page);
+        position = g_slist_length (editor->initializing_pages);
+        g_object_set_data (G_OBJECT (page), "position", GINT_TO_POINTER (position));
+        gtk_list_store_insert_with_values (store, &iter, -1,
+                                           0, title,
+                                           1, position,
+                                           -1);
+        editor->initializing_pages = g_slist_append (editor->initializing_pages, page);
+
+        g_signal_connect (page, "changed", G_CALLBACK (page_changed), editor);
+        g_signal_connect (page, "initialized", G_CALLBACK (page_initialized), editor);
+}
+
+static void
+net_connection_editor_set_connection (NetConnectionEditor *editor,
+                              NMConnection        *connection)
+{
+        GSList *pages, *l;
+
+        editor->connection = nm_connection_duplicate (connection);
+        editor->orig_connection = g_object_ref (connection);
+
+        net_connection_editor_update_title (editor);
+
+        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));
+        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));
+        add_page (editor, ce_page_reset_new (editor->connection, editor->client, editor->settings));
+
+        pages = g_slist_copy (editor->initializing_pages);
+        for (l = pages; l; l = l->next) {
+                CEPage *page = l->data;
+                const gchar *security_setting;
+
+                security_setting = ce_page_get_security_setting (page);
+                if (!security_setting) {
+                        ce_page_complete_init (page, NULL, NULL, NULL);
+                } else {
+                        get_secrets_for_page (editor, page, security_setting);
+                }
+        }
+        g_slist_free (pages);
+}
+
+NetConnectionEditor *
+net_connection_editor_new (GtkWindow        *parent_window,
+                           NMConnection     *connection,
+                           NMDevice         *device,
+                           NMAccessPoint    *ap,
+                           NMClient         *client,
+                           NMRemoteSettings *settings)
+{
+        NetConnectionEditor *editor;
+
+        editor = g_object_new (NET_TYPE_CONNECTION_EDITOR, NULL);
+
+        if (parent_window) {
+                editor->parent_window = g_object_ref (parent_window);
+                gtk_window_set_transient_for (GTK_WINDOW (editor->window),
+                                              parent_window);
+        }
+        if (ap)
+                editor->ap = g_object_ref (ap);
+        editor->device = g_object_ref (device);
+        editor->client = g_object_ref (client);
+        editor->settings = g_object_ref (settings);
+
+        net_connection_editor_set_connection (editor, connection);
+
+        return editor;
+}
+
+void
+net_connection_editor_present (NetConnectionEditor *editor)
+{
+        gtk_window_present (GTK_WINDOW (editor->window));
+}
diff --git a/panels/network/connection-editor/net-connection-editor.h b/panels/network/connection-editor/net-connection-editor.h
new file mode 100644
index 0000000..274c2c1
--- /dev/null
+++ b/panels/network/connection-editor/net-connection-editor.h
@@ -0,0 +1,83 @@
+/* -*- 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.
+ */
+
+#ifndef __NET_CONNECTION_EDITOR_H
+#define __NET_CONNECTION_EDITOR_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <nm-client.h>
+#include <nm-access-point.h>
+#include <nm-remote-settings.h>
+
+G_BEGIN_DECLS
+
+#define NET_TYPE_CONNECTION_EDITOR         (net_connection_editor_get_type ())
+#define NET_CONNECTION_EDITOR(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), NET_TYPE_CONNECTION_EDITOR, NetConnectionEditor))
+#define NET_CONNECTION_EDITOR_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), NET_TYPE_CONNECTION_EDITOR, NetConnectionEditorClass))
+#define NET_IS_CONNECTION_EDITOR(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), NET_TYPE_CONNECTION_EDITOR))
+#define NET_IS_CONNECTION_EDITOR_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), NET_TYPE_CONNECTION_EDITOR))
+#define NET_CONNECTION_EDITOR_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), NET_TYPE_CONNECTION_EDITOR, NetConnectionEditorClass))
+
+typedef struct _NetConnectionEditor          NetConnectionEditor;
+typedef struct _NetConnectionEditorClass     NetConnectionEditorClass;
+
+struct _NetConnectionEditor
+{
+         GObject parent;
+
+        GtkWidget        *parent_window;
+        NMClient         *client;
+        NMDevice         *device;
+        NMRemoteSettings *settings;
+
+        NMConnection     *connection;
+        NMConnection     *orig_connection;
+        NMAccessPoint    *ap;
+
+        GtkBuilder       *builder;
+        GtkWidget        *window;
+
+        GSList *initializing_pages;
+        GSList *pages;
+};
+
+struct _NetConnectionEditorClass
+{
+        GObjectClass parent_class;
+
+        void (*done) (NetConnectionEditor *details, gboolean success);
+};
+
+GType                net_connection_editor_get_type (void);
+NetConnectionEditor *net_connection_editor_new      (GtkWindow        *parent_window,
+                                                     NMConnection     *connection,
+                                                     NMDevice         *device,
+                                                     NMAccessPoint    *ap,
+                                                     NMClient         *client,
+                                                     NMRemoteSettings *settings);
+void                 net_connection_editor_present  (NetConnectionEditor   *details);
+
+G_END_DECLS
+
+#endif /* __NET_CONNECTION_EDITOR_H */
+
diff --git a/panels/network/connection-editor/reset-page.ui b/panels/network/connection-editor/reset-page.ui
new file mode 100644
index 0000000..91ca84b
--- /dev/null
+++ b/panels/network/connection-editor/reset-page.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <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="row_spacing">10</property>
+    <property name="column_spacing">10</property>
+    <child>
+      <object class="GtkButton" id="button_reset">
+        <property name="label" translatable="yes">_Reset</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="valign">start</property>
+        <property name="use_underline">True</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="GtkButton" id="button_forget">
+        <property name="label" translatable="yes">_Forget</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="valign">start</property>
+        <property name="use_underline">True</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="label_reset">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Reset the settings for this connection to their defaults, but remember as a preferred connection.</property>
+        <property name="wrap">True</property>
+        <property name="max_width_chars">40</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_forget">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Remove all details relating to this network and do not try to automatically connect to it.</property>
+        <property name="wrap">True</property>
+        <property name="max_width_chars">30</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>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/security-page.ui b/panels/network/connection-editor/security-page.ui
new file mode 100644
index 0000000..969b566
--- /dev/null
+++ b/panels/network/connection-editor/security-page.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <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_sec">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">S_ecurity</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">combo_sec</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="GtkComboBox" id="combo_sec">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">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="GtkBox" id="vbox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+        <property name="width">2</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/connection-editor/wifi-page.ui b/panels/network/connection-editor/wifi-page.ui
new file mode 100644
index 0000000..5e46730
--- /dev/null
+++ b/panels/network/connection-editor/wifi-page.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <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_ssid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">_SSID</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">entry_ssid</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="GtkLabel" id="heading_bssid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="label" translatable="yes">_BSSID</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">combo_bssid</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="GtkEntry" id="entry_ssid">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hexpand">True</property>
+        <property name="invisible_char">â</property>
+        <property name="text" translatable="yes">My Home Network</property>
+        <property name="invisible_char_set">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="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">2</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">3</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">3</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkComboBoxText" id="combo_bssid">
+        <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>
+      </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="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>
+      </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>
+  </object>
+</interface>
diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c
index 6bac72a..98deed2 100644
--- a/panels/network/net-device-wifi.c
+++ b/panels/network/net-device-wifi.c
@@ -41,6 +41,7 @@
 
 #include "egg-list-box/egg-list-box.h"
 
+#include "connection-editor/net-connection-editor.h"
 #include "net-device-wifi.h"
 
 #define NET_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NET_TYPE_DEVICE_WIFI, NetDeviceWifiPrivate))
@@ -557,20 +558,6 @@ nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
                                          "speed",
                                          str_tmp);
 
-        /* set device state, with status and optionally speed */
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder, "label_status"));
-        if (ap != active_ap) {
-                if (ap)
-                        gtk_label_set_label (GTK_LABEL (widget), _("Not connected"));
-                else
-                        gtk_label_set_label (GTK_LABEL (widget), _("Out of range"));
-                gtk_widget_set_tooltip_text (widget, "");
-        } else {
-                gtk_label_set_label (GTK_LABEL (widget),
-                                     panel_device_state_to_localized_string (nm_device));
-                gtk_widget_set_tooltip_text (widget, panel_device_state_reason_to_localized_string (nm_device));
-        }
-
         /* device MAC */
         str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (nm_device));
         panel_set_device_widget_details (device_wifi->priv->builder,
@@ -607,29 +594,6 @@ nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
                                          "strength",
                                          str);
 
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder, "label_device"));
-        gtk_label_set_label (GTK_LABEL (widget),
-                             priv->selected_ssid_title ? priv->selected_ssid_title : net_object_get_title (NET_OBJECT (device_wifi)));
-
-        /* only disconnect when connection active */
-        if (ap == active_ap) {
-                widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                             "button_disconnect1"));
-                gtk_widget_set_sensitive (widget, state == NM_DEVICE_STATE_ACTIVATED);
-                gtk_widget_show (widget);
-                widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                             "button_connect1"));
-                gtk_widget_hide (widget);
-        } else {
-                widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                             "button_disconnect1"));
-                gtk_widget_hide (widget);
-                widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                             "button_connect1"));
-                gtk_widget_show (widget);
-                gtk_widget_set_sensitive (widget, ap != NULL);
-        }
-
         /* device MAC */
         if (ap != active_ap)
                 str = NULL;
@@ -643,7 +607,7 @@ nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
         else
                 panel_set_device_widgets (priv->builder, nm_device);
 
-        if (ap != active_ap)
+        if (ap != active_ap && connection)
                 update_last_used (device_wifi, connection);
         else
                 panel_set_device_widget_details (priv->builder, "last_used", NULL);
@@ -1276,27 +1240,6 @@ show_wifi_list (NetDeviceWifi *device_wifi)
 }
 
 static void
-edit_connection (GtkButton *button, NetDeviceWifi *device_wifi)
-{
-        GtkWidget *dialog;
-        NMConnection *connection;
-        const gchar *uuid;
-        gchar *cmdline;
-        GError *error = NULL;
-
-        dialog = gtk_widget_get_toplevel (GTK_WIDGET (button));
-        connection = g_object_get_data (G_OBJECT (dialog), "connection");
-        uuid = nm_connection_get_uuid (connection);
-        cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
-        g_debug ("Launching '%s'\n", cmdline);
-        if (!g_spawn_command_line_async (cmdline, &error)) {
-                g_warning ("Failed to launch nm-connection-editor: %s", error->message);
-                g_error_free (error);
-        }
-        g_free (cmdline);
-}
-
-static void
 remote_settings_read_cb (NMRemoteSettings *remote_settings,
                          NetDeviceWifi *device_wifi)
 {
@@ -1723,65 +1666,11 @@ ap_sort (gconstpointer a, gconstpointer b, gpointer data)
 }
 
 static void
-close_details (GtkWidget *widget)
-{
-        gtk_widget_hide (widget);
-        g_object_set_data (G_OBJECT (widget), "connection", NULL);
-        g_object_set_data (G_OBJECT (widget), "ap", NULL);
-}
-
-static void
-open_details (NMConnection  *connection,
-              NMAccessPoint *ap,
-              NetDeviceWifi *device_wifi,
-              GtkWidget     *toplevel)
+editor_done (NetConnectionEditor *editor,
+             gboolean             success,
+             NetDeviceWifi       *device_wifi)
 {
-        GtkWidget *dialog;
-        GtkWidget *widget;
-        NMSettingWireless *sw;
-        const GByteArray *ssid;
-        gchar *title;
-
-        g_assert (connection != NULL);
-
-        dialog = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                     "details_dialog"));
-
-        g_object_set_data (G_OBJECT (dialog), "connection", connection);
-        g_object_set_data (G_OBJECT (dialog), "ap", ap);
-
-        nm_device_wifi_refresh_ui (device_wifi);
-#if 1
-        /* hide unimplemented editing stuff */
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                     "auto_connect_box"));
-        gtk_widget_hide (widget);
-
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                     "details_sidebar"));
-        gtk_widget_hide (widget);
-
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                     "details_apply_button"));
-        gtk_widget_hide (widget);
-#endif
-
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                     "details_cancel_button"));
-        gtk_button_set_label (GTK_BUTTON (widget), _("_Close"));
-        g_signal_connect_swapped (widget, "clicked",
-                                  G_CALLBACK (close_details), dialog);
-        g_signal_connect (dialog, "delete-event",
-                          G_CALLBACK (close_details), NULL);
-
-        sw = nm_connection_get_setting_wireless (connection);
-        ssid = nm_setting_wireless_get_ssid (sw);
-        title = g_markup_escape_text (nm_utils_escape_ssid (ssid->data, ssid->len), -1);
-        gtk_window_set_title (GTK_WINDOW (dialog), title);
-        g_free (title);
-        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
-
-        gtk_window_present (GTK_WINDOW (dialog));
+        g_object_unref (editor);
 }
 
 static void
@@ -1791,6 +1680,10 @@ show_details_for_row (GtkButton *button, NetDeviceWifi *device_wifi)
         NMConnection *connection;
         NMAccessPoint *ap;
         GtkWidget *window;
+        NetConnectionEditor *editor;
+        NMClient *client;
+        NMRemoteSettings *settings;
+        NMDevice *device;
 
         window = gtk_widget_get_toplevel (GTK_WIDGET (button));
 
@@ -1798,7 +1691,12 @@ show_details_for_row (GtkButton *button, NetDeviceWifi *device_wifi)
         connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection"));
         ap = NM_ACCESS_POINT (g_object_get_data (G_OBJECT (row), "ap"));
 
-        open_details (connection, ap, device_wifi, window);
+        device = net_device_get_nm_device (NET_DEVICE (device_wifi));
+        client = net_object_get_client (NET_OBJECT (device_wifi));
+        settings = net_object_get_remote_settings (NET_OBJECT (device_wifi));
+        editor = net_connection_editor_new (GTK_WINDOW (window), connection, device, ap, client, settings);
+        g_signal_connect (editor, "done", G_CALLBACK (editor_done), device_wifi);
+        net_connection_editor_present (editor);
 }
 
 static void
@@ -1894,8 +1792,7 @@ open_history (NetDeviceWifi *device_wifi)
                         const GByteArray *ssid_ap;
                         ap = NM_ACCESS_POINT (g_ptr_array_index (aps_unique, i));
                         ssid_ap = nm_access_point_get_ssid (ap);
-                        if (ssid->len == ssid_ap->len &&
-                            memcmp (ssid->data, ssid_ap->data, ssid->len) == 0)
+                        if (nm_utils_same_ssid (ssid, ssid_ap, TRUE))
                                 break;
                         ap = NULL;
                 }
@@ -1971,8 +1868,7 @@ populate_ap_list (NetDeviceWifi *device_wifi)
 
                         setting = nm_connection_get_setting_by_name (connection, NM_SETTING_WIRELESS_SETTING_NAME);
                         ssid = nm_setting_wireless_get_ssid (NM_SETTING_WIRELESS (setting));
-                        if (ssid->len == ssid_ap->len &&
-                            memcmp (ssid->data, ssid_ap->data, ssid->len) == 0)
+                        if (nm_utils_same_ssid (ssid, ssid_ap, TRUE))
                                 break;
                         connection = NULL;
                 }
@@ -2054,11 +1950,6 @@ net_device_wifi_init (NetDeviceWifi *device_wifi)
         g_signal_connect (widget, "notify::active",
                           G_CALLBACK (device_off_toggled), device_wifi);
 
-        widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
-                                                     "button_options1"));
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (edit_connection), device_wifi);
-
         swin = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
                                                    "scrolledwindow_list"));
         list = GTK_WIDGET (egg_list_box_new ());
diff --git a/panels/network/network-wifi.ui b/panels/network/network-wifi.ui
index 2d80c3c..9e76ac8 100644
--- a/panels/network/network-wifi.ui
+++ b/panels/network/network-wifi.ui
@@ -1,40 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkListStore" id="details_store">
-    <columns>
-      <!-- column-name name -->
-      <column type="gchararray"/>
-      <!-- column-name page -->
-      <column type="gint"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Details</col>
-        <col id="1">0</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Identity</col>
-        <col id="1">1</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">IPv4</col>
-        <col id="1">2</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">IPv6</col>
-        <col id="1">3</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Hardware</col>
-        <col id="1">4</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Reset</col>
-        <col id="1">5</col>
-      </row>
-    </data>
-  </object>
   <object class="GtkDialog" id="details_dialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
@@ -53,25 +19,6 @@
             <property name="valign">end</property>
             <property name="layout_style">end</property>
             <child>
-              <object class="GtkButton" id="button_options1">
-                <property name="label" translatable="yes">_Settingsâ</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="halign">end</property>
-                <property name="valign">end</property>
-                <property name="hexpand">True</property>
-                <property name="vexpand">True</property>
-                <property name="use_underline">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-                <property name="secondary">True</property>
-              </packing>
-            </child>
-            <child>
               <object class="GtkButton" id="details_cancel_button">
                 <property name="label">gtk-cancel</property>
                 <property name="visible">True</property>
@@ -126,18 +73,24 @@
                     <property name="headers_clickable">False</property>
                     <property name="search_column">0</property>
                     <child internal-child="selection">
-                      <object class="GtkTreeSelection" id="treeview-selection"/>
+                      <object class="GtkTreeSelection" id="details_page_list_selection"/>
                     </child>
                     <child>
                       <object class="GtkTreeViewColumn" id="details_column">
                         <child>
                           <object class="GtkCellRendererText" id="details_cell">
-                            <property name="width_chars">50</property>
+                            <property name="xpad">10</property>
                           </object>
                           <attributes>
                             <attribute name="text">0</attribute>
                           </attributes>
                         </child>
+                        <child>
+                          <object class="GtkCellRendererText" id="padding_cell">
+                            <property name="xpad">20</property>
+                            <property name="text"></property>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>
@@ -154,6 +107,7 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="show_tabs">False</property>
+                <property name="show_border">False</property>
                 <child>
                   <object class="GtkBox" id="box8">
                     <property name="visible">True</property>
@@ -207,6 +161,8 @@
                         <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>
@@ -216,7 +172,6 @@
                             <property name="hexpand">True</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">Signal Strength</property>
-                            <property name="mnemonic_widget">label_strength2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -250,7 +205,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">Link speed</property>
-                            <property name="mnemonic_widget">label_speed2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -283,7 +237,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">Security</property>
-                            <property name="mnemonic_widget">label_security2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -301,7 +254,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">IPv4 Address</property>
-                            <property name="mnemonic_widget">label_ipv42</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -319,7 +271,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">IPv6 Address</property>
-                            <property name="mnemonic_widget">label_ipv62</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -337,7 +288,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">Hardware Address</property>
-                            <property name="mnemonic_widget">label_mac2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -355,7 +305,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">Default Route</property>
-                            <property name="mnemonic_widget">label_route2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -374,7 +323,6 @@
                             <property name="xalign">1</property>
                             <property name="yalign">0</property>
                             <property name="label" translatable="yes">DNS</property>
-                            <property name="mnemonic_widget">label_dns2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -392,7 +340,6 @@
                             <property name="can_focus">False</property>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">Last used</property>
-                            <property name="mnemonic_widget">label_last_used2</property>
                             <style>
                               <class name="dim-label"/>
                             </style>
@@ -524,20 +471,213 @@
                   <object class="GtkLabel" id="label4">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">page 1</property>
+                    <property name="label" translatable="yes">details</property>
                   </object>
                   <packing>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
                 <child>
-                  <placeholder/>
+                  <object class="GtkGrid" id="grid3">
+                    <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_ssid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">_SSID</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry_ssid</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="GtkLabel" id="heading_bssid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">_BSSID</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry_bssid</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_sec">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">S_ecurity</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">combo_sec</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="GtkLabel" id="label_password">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">_Password</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry_password</property>
+                      </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="GtkEntry" id="entry_ssid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="invisible_char">â</property>
+                        <property name="text" translatable="yes">My Home Network</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="GtkEntry" id="entry_bssid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="invisible_char">â</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="GtkComboBoxText" id="combo_sec">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="entry_text_column">0</property>
+                        <property name="id_column">1</property>
+                        <items>
+                          <item translatable="yes">WPA</item>
+                          <item translatable="yes">None</item>
+                        </items>
+                      </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="GtkEntry" id="entry_password">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="visibility">False</property>
+                        <property name="invisible_char">â</property>
+                        <property name="text" translatable="yes">blablabla</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="show_password_check">
+                        <property name="label" translatable="yes">Show P_assword</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="valign">center</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="GtkLabel" id="label9">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </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="GtkCheckButton" id="all_user_check">
+                        <property name="label" translatable="yes">Make available to other users</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="valign">end</property>
+                        <property name="vexpand">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">5</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
                 <child type="tab">
                   <object class="GtkLabel" id="label6">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">page 2</property>
+                    <property name="label" translatable="yes">identity</property>
                   </object>
                   <packing>
                     <property name="position">1</property>
@@ -545,19 +685,745 @@
                   </packing>
                 </child>
                 <child>
-                  <placeholder/>
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkViewport" id="viewport1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkBox" id="box2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <property name="spacing">10</property>
+                            <property name="margin-left">20</property>
+                            <property name="margin-right">20</property>
+                            <property name="margin-top">10</property>
+                            <property name="margin-bottom">10</property>
+                            <child>
+                              <object class="GtkBox" id="box5">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="heading_ipv4_ipv4">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">IPv_4</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">switch_ipv4_ipv4</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSwitch" id="switch_ipv4_ipv4">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="halign">end</property>
+                                    <property name="hexpand">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</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">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="box7">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="heading_ipv4_addresses">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">_Addresses</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">combo_ipv4_addresses</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkComboBoxText" id="combo_ipv4_addresses">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">end</property>
+                                    <property name="hexpand">True</property>
+                                    <property name="entry_text_column">0</property>
+                                    <property name="id_column">1</property>
+                                    <items>
+                                      <item translatable="yes">Manual</item>
+                                      <item translatable="yes">Automatic (DHCP)</item>
+                                      <item translatable="yes">Automatic (DHCP) addresses only</item>
+                                      <item translatable="yes">Link-local only</item>
+                                      <item translatable="yes">Shared with other computers</item>
+                                      <item translatable="yes">Disabled</item>
+                                    </items>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</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>
+                            <child>
+                              <object class="GtkBox" id="details_ipv4_address_section">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="label10">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">Address
+section
+goes
+here</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="details_ipv4_dns_heading">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_top">24</property>
+                                <property name="margin_bottom">6</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">DNS</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="details_ipv4_dns_section">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="label11">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">DNS
+section
+goes
+here</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="details_ipv4_routes_heading">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_top">24</property>
+                                <property name="margin_bottom">6</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Routes</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">5</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="details_ipv4_routes_section">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="label12">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">Routes
+section
+goes
+here</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">6</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="details_ipv4_auto_routes_check">
+                                <property name="label" translatable="yes">_Ignore automatically obtained routes</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="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">7</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="details_ipv4_network_resources_check">
+                                <property name="label" translatable="yes">Use this connection _only for resources on its network</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="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">8</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
                 </child>
                 <child type="tab">
                   <object class="GtkLabel" id="label7">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">page 3</property>
+                    <property name="label" translatable="yes">ipv4</property>
                   </object>
                   <packing>
                     <property name="position">2</property>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkViewport" id="viewport2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkBox" id="box10">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <property name="spacing">10</property>
+                            <child>
+                              <object class="GtkBox" id="box11">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="heading_ipv6_ipv6">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">IPv_6</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">switch_ipv6_ipv6</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSwitch" id="switch_ipv6_ipv6">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="halign">end</property>
+                                    <property name="hexpand">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</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">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="box12">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" id="heading_ipv6_addresses">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">_Addresses</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">combo_ipv6_addresses</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkComboBoxText" id="combo_ipv6_addresses">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">end</property>
+                                    <property name="hexpand">True</property>
+                                    <property name="entry_text_column">0</property>
+                                    <property name="id_column">1</property>
+                                    <items>
+                                      <item translatable="yes">Manual</item>
+                                      <item translatable="yes">Automatic (DHCP)</item>
+                                      <item translatable="yes">Automatic (DHCP) addresses only</item>
+                                      <item translatable="yes">Link-local only</item>
+                                      <item translatable="yes">Shared with other computers</item>
+                                      <item translatable="yes">Disabled</item>
+                                    </items>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</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>
+                            <child>
+                              <object class="GtkBox" id="details_ipv6_address_section">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="label13">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">Address
+section
+goes
+here</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="details_ipv6_dns_heading">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_top">24</property>
+                                <property name="margin_bottom">6</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">DNS</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="details_ipv6_dns_section">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="label14">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">DNS
+section
+goes
+here</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="details_ipv6_routes_heading">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="margin_top">24</property>
+                                <property name="margin_bottom">6</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Routes</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">5</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="details_ipv6_routes_section">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="label15">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">Routes
+section
+goes
+here</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">6</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="details_ipv6_auto_routes_check">
+                                <property name="label" translatable="yes">_Ignore automatically obtained routes</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="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">7</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="details_ipv6_network_resources_check">
+                                <property name="label" translatable="yes">Use this connection _only for resources on its network</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="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">8</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">ipv6</property>
+                  </object>
+                  <packing>
+                    <property name="position">3</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkGrid" id="grid4">
+                    <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_hw_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">label_hw_mac</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="GtkLabel" id="heading_hw_cloned_mac">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">_Cloned MAC Address</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry_hw_cloned_mac</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="label_hw_mac">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">00:24:16:31:8G:7A</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="GtkEntry" id="entry_hw_cloned_mac">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="invisible_char">â</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>
+                  </object>
+                  <packing>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">hardware</property>
+                  </object>
+                  <packing>
+                    <property name="position">4</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkGrid" id="grid5">
+                    <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="row_spacing">10</property>
+                    <property name="column_spacing">10</property>
+                    <child>
+                      <object class="GtkButton" id="button_reset">
+                        <property name="label" translatable="yes">_Reset</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="valign">start</property>
+                        <property name="use_underline">True</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="GtkButton" id="button_forget">
+                        <property name="label" translatable="yes">_Forget</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="valign">start</property>
+                        <property name="use_underline">True</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="label_reset">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Reset the settings for this connection to their defaults, but remember as a preferred connection.</property>
+                        <property name="wrap">True</property>
+                        <property name="max_width_chars">40</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_forget">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Remove all details relating to this network and do not try to automatically connect to it.</property>
+                        <property name="wrap">True</property>
+                        <property name="max_width_chars">30</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>
+                  </object>
+                  <packing>
+                    <property name="position">5</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">reset</property>
+                  </object>
+                  <packing>
+                    <property name="position">5</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
               </object>
               <packing>
                 <property name="expand">True</property>
@@ -575,11 +1441,44 @@
       </object>
     </child>
     <action-widgets>
-      <action-widget response="0">button_options1</action-widget>
       <action-widget response="0">details_cancel_button</action-widget>
       <action-widget response="0">details_apply_button</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkListStore" id="details_store">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name page -->
+      <column type="gint"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Details</col>
+        <col id="1">0</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Identity</col>
+        <col id="1">1</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">IPv4</col>
+        <col id="1">2</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">IPv6</col>
+        <col id="1">3</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Hardware</col>
+        <col id="1">4</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Reset</col>
+        <col id="1">5</col>
+      </row>
+    </data>
+  </object>
   <object class="GtkDialog" id="hotspot-dialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
diff --git a/panels/network/wireless-security/Makefile.am b/panels/network/wireless-security/Makefile.am
new file mode 100644
index 0000000..9c951a0
--- /dev/null
+++ b/panels/network/wireless-security/Makefile.am
@@ -0,0 +1,55 @@
+noinst_LTLIBRARIES = libwireless-security.la
+
+BUILT_SOURCES = \
+	wireless-security-resources.h \
+	wireless-security-resources.c
+
+libwireless_security_la_SOURCES = \
+	$(BUILT_SOURCES) \
+	wireless-security.h \
+	wireless-security.c \
+	ws-wep-key.h \
+	ws-wep-key.c \
+	ws-wpa-psk.h \
+	ws-wpa-psk.c \
+	ws-leap.h \
+	ws-leap.c \
+	ws-wpa-eap.h \
+	ws-wpa-eap.c \
+	ws-dynamic-wep.h \
+	ws-dynamic-wep.c \
+	eap-method.h \
+	eap-method.c \
+	eap-method-tls.h \
+	eap-method-tls.c \
+	eap-method-leap.h \
+	eap-method-leap.c \
+	eap-method-fast.h \
+	eap-method-fast.c \
+	eap-method-ttls.h \
+	eap-method-ttls.c \
+	eap-method-peap.h \
+	eap-method-peap.c \
+	eap-method-simple.h \
+	eap-method-simple.c \
+	helpers.h \
+	helpers.c
+
+libwireless_security_la_CPPFLAGS = \
+	$(NETWORK_PANEL_CFLAGS) \
+        $(NETWORK_MANAGER_CFLAGS)                       \
+	-DUIDIR=\""$(uidir)"\"
+
+libwireless_security_la_LIBADD = \
+	$(NETWORK_PANEL_LIBS) \
+	$(NETWORK_MANAGER_LIBS)
+
+resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/wireless-security.gresource.xml)
+wireless-security-resources.c: wireless-security.gresource.xml $(resource_files)
+	$(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name wireless_security $<
+wireless-security-resources.h: wireless-security.gresource.xml $(resource_files)
+	$(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name wireless_security $<
+
+EXTRA_DIST = \
+	$(resource_files)
+
diff --git a/panels/network/wireless-security/eap-method-fast.c b/panels/network/wireless-security/eap-method-fast.c
new file mode 100644
index 0000000..dc042dd
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.c
@@ -0,0 +1,443 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * 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 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+
+#define I_NAME_COLUMN   0
+#define I_METHOD_COLUMN 1
+
+struct _EAPMethodFAST {
+	EAPMethod parent;
+
+	GtkSizeGroup *size_group;
+	WirelessSecurity *sec_parent;
+	gboolean is_editor;
+};
+
+static void
+destroy (EAPMethod *parent)
+{
+	EAPMethodFAST *method = (EAPMethodFAST *) parent;
+
+	if (method->size_group)
+		g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap = NULL;
+	const char *file;
+	gboolean provisioning;
+	gboolean valid = FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+	g_assert (widget);
+	provisioning = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+	g_assert (widget);
+	file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	if (!provisioning && !file)
+		return FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+	g_assert (widget);
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	valid = eap_method_validate (eap);
+	eap_method_unref (eap);
+	return valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+	EAPMethodFAST *method = (EAPMethodFAST *) parent;
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap;
+
+	if (method->size_group)
+		g_object_unref (method->size_group);
+	method->size_group = g_object_ref (group);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	eap_method_add_to_size_group (eap, group);
+	eap_method_unref (eap);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+	NMSetting8021x *s_8021x;
+	GtkWidget *widget;
+	const char *text;
+	char *filename;
+	EAPMethod *eap = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean enabled;
+	int pac_provisioning = 0;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	nm_setting_802_1x_add_eap_method (s_8021x, "fast");
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (text && strlen (text))
+		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+	g_assert (widget);
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	g_object_set (s_8021x, NM_SETTING_802_1X_PAC_FILE, filename, NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+	enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+	if (!enabled)
+		g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "0", NULL);
+	else {
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+		pac_provisioning = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+		switch (pac_provisioning) {
+		case 0:  /* Anonymous */
+			g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+			break;
+		case 1:  /* Authenticated */
+			g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "2", NULL);
+			break;
+		case 2:  /* Both - anonymous and authenticated */
+			g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "3", NULL);
+			break;
+		default: /* Should not happen */
+			g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+			break;
+		}
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_method_fill_connection (eap, connection);
+	eap_method_unref (eap);
+}
+
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	EAPMethod *parent = (EAPMethod *) user_data;
+	EAPMethodFAST *method = (EAPMethodFAST *) parent;
+	GtkWidget *vbox;
+	EAPMethod *eap = NULL;
+	GList *elt, *children;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkWidget *eap_widget;
+
+	vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_vbox"));
+	g_assert (vbox);
+
+	/* Remove any previous wireless security widgets */
+	children = gtk_container_get_children (GTK_CONTAINER (vbox));
+	for (elt = children; elt; elt = g_list_next (elt))
+		gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+	g_list_free (children);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_widget = eap_method_get_widget (eap);
+	g_assert (eap_widget);
+	gtk_widget_unparent (eap_widget);
+
+	if (method->size_group)
+		eap_method_add_to_size_group (eap, method->size_group);
+	gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+	eap_method_unref (eap);
+
+	wireless_security_changed_cb (combo, method->sec_parent);
+}
+
+static GtkWidget *
+inner_auth_combo_init (EAPMethodFAST *method,
+                       NMConnection *connection,
+                       NMSetting8021x *s_8021x,
+                       gboolean secrets_only)
+{
+	EAPMethod *parent = (EAPMethod *) method;
+	GtkWidget *combo;
+	GtkListStore *auth_model;
+	GtkTreeIter iter;
+	EAPMethodSimple *em_gtc;
+	EAPMethodSimple *em_mschap_v2;
+	guint32 active = 0;
+	const char *phase2_auth = NULL;
+
+	auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+	if (s_8021x) {
+		if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+			phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+		else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+			phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+	}
+
+	em_gtc = eap_method_simple_new (method->sec_parent,
+	                                connection,
+	                                EAP_METHOD_SIMPLE_TYPE_GTC,
+	                                TRUE,
+	                                method->is_editor,
+	                                secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("GTC"),
+	                    I_METHOD_COLUMN, em_gtc,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_gtc));
+
+	/* Check for defaulting to GTC */
+	if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+		active = 0;
+
+	em_mschap_v2 = eap_method_simple_new (method->sec_parent,
+	                                      connection,
+	                                      EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+	                                      TRUE,
+	                                      method->is_editor, secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("MSCHAPv2"),
+	                    I_METHOD_COLUMN, em_mschap_v2,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_mschap_v2));
+
+	/* Check for defaulting to MSCHAPv2 */
+	if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+		active = 1;
+
+	combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+	g_assert (combo);
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+	g_object_unref (G_OBJECT (auth_model));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+	g_signal_connect (G_OBJECT (combo), "changed",
+	                  (GCallback) inner_auth_combo_changed_cb,
+	                  method);
+	return combo;
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+	eap_method_phase2_update_secrets_helper (parent,
+	                                         connection,
+	                                         "eap_fast_inner_auth_combo",
+	                                         I_METHOD_COLUMN);
+}
+
+static void
+pac_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+	EAPMethod *parent = (EAPMethod *) user_data;
+	EAPMethodFAST *method = (EAPMethodFAST *) parent;
+	gboolean enabled = FALSE;
+	GtkWidget *provision_combo;
+
+	provision_combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+	g_return_if_fail (provision_combo);
+
+	enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+	gtk_widget_set_sensitive (provision_combo, enabled);
+
+	wireless_security_changed_cb (widget, method->sec_parent);
+}
+
+EAPMethodFAST *
+eap_method_fast_new (WirelessSecurity *ws_parent,
+                     NMConnection *connection,
+                     gboolean is_editor,
+                     gboolean secrets_only)
+{
+	EAPMethod *parent;
+	EAPMethodFAST *method;
+	GtkWidget *widget;
+	GtkFileFilter *filter;
+	NMSetting8021x *s_8021x = NULL;
+	const char *filename;
+	gboolean provisioning_enabled = TRUE;
+
+	parent = eap_method_init (sizeof (EAPMethodFAST),
+	                          validate,
+	                          add_to_size_group,
+	                          fill_connection,
+	                          update_secrets,
+	                          destroy,
+	                          "/org/gnome/control-center/network/eap-method-fast.ui",
+	                          "eap_fast_notebook",
+	                          "eap_fast_anon_identity_entry",
+	                          FALSE);
+	if (!parent)
+		return NULL;
+
+	method = (EAPMethodFAST *) parent;
+	method->sec_parent = ws_parent;
+	method->is_editor = is_editor;
+
+	if (connection)
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+	g_assert (widget);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+	if (s_8021x) {
+		const char *fast_prov;
+
+		fast_prov = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
+		if (fast_prov) {
+			if (!strcmp (fast_prov, "0"))
+				provisioning_enabled = FALSE;
+			else if (!strcmp (fast_prov, "1"))
+				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+			else if (!strcmp (fast_prov, "2"))
+				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+			else if (!strcmp (fast_prov, "3"))
+				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
+		}
+	}
+	gtk_widget_set_sensitive (widget, provisioning_enabled);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), provisioning_enabled);
+	g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (pac_toggled_cb), parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+	if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+	g_assert (widget);
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+	                                   _("Choose a PAC file..."));
+	g_signal_connect (G_OBJECT (widget), "selection-changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	filter = gtk_file_filter_new ();
+	gtk_file_filter_add_pattern (filter, "*.pac");
+	gtk_file_filter_set_name (filter, _("PAC files (*.pac)"));
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+	filter = gtk_file_filter_new ();
+	gtk_file_filter_add_pattern (filter, "*");
+	gtk_file_filter_set_name (filter, _("All files"));
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+	if (connection && s_8021x) {
+		filename = nm_setting_802_1x_get_pac_file (s_8021x);
+		if (filename)
+			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+	}
+
+	widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+	inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+	if (secrets_only) {
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+		gtk_widget_hide (widget);
+	}
+
+	return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-fast.h b/panels/network/wireless-security/eap-method-fast.h
new file mode 100644
index 0000000..32b9a4b
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * 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 2012 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_FAST_H
+#define EAP_METHOD_FAST_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodFAST EAPMethodFAST;
+
+EAPMethodFAST *eap_method_fast_new (WirelessSecurity *ws_parent,
+                                    NMConnection *connection,
+                                    gboolean is_editor,
+                                    gboolean secrets_only);
+
+#endif /* EAP_METHOD_FAST_H */
+
diff --git a/panels/network/wireless-security/eap-method-fast.ui b/panels/network/wireless-security/eap-method-fast.ui
new file mode 100644
index 0000000..fdfc7f8
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.ui
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkNotebook" id="eap_fast_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table13">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">5</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="eap_fast_anon_identity_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Anony_mous identity</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_fast_anon_identity_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_fast_anon_identity_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_fast_pac_file_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">PAC _file</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_fast_pac_file_button</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="eap_fast_pac_file_button">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="eap_fast_inner_auth_vbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_fast_inner_auth_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Inner authentication</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_fast_inner_auth_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="eap_fast_inner_auth_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model8</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer8"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="eap_fast_pac_provision_checkbutton">
+            <property name="label" translatable="yes">PAC pro_visioning</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.5</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="eap_fast_pac_provision_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model9</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer9"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label61">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkListStore" id="model8">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes"> </col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="model9">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Anonymous</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Authenticated</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Both</col>
+      </row>
+    </data>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-leap.c b/panels/network/wireless-security/eap-method-leap.c
new file mode 100644
index 0000000..58d8c54
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.c
@@ -0,0 +1,183 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _EAPMethodLEAP {
+	EAPMethod parent;
+
+	gboolean new_connection;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, EAPMethod *method)
+{
+	GtkWidget *widget;
+	gboolean visible;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (method->builder, "eap_leap_password_entry"));
+	g_assert (widget);
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+	GtkWidget *widget;
+	const char *text;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!text || !strlen (text))
+		return FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!text || !strlen (text))
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+	EAPMethodLEAP *method = (EAPMethodLEAP *) parent;
+	NMSetting8021x *s_8021x;
+	GtkWidget *widget;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	nm_setting_802_1x_add_eap_method (s_8021x, "leap");
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+	g_assert (widget);
+	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+	g_assert (widget);
+	g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+	/* Default to agent-owned secrets for new connections */
+	if (method->new_connection) {
+		g_object_set (s_8021x,
+		              NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+		              NM_SETTING_802_1X_SYSTEM_CA_CERTS, TRUE,
+		              NULL);
+	}
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+	helper_fill_secret_entry (connection,
+	                          parent->builder,
+	                          "eap_leap_password_entry",
+	                          NM_TYPE_SETTING_802_1X,
+	                          (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+EAPMethodLEAP *
+eap_method_leap_new (WirelessSecurity *ws_parent,
+                     NMConnection *connection,
+                     gboolean secrets_only)
+{
+	EAPMethodLEAP *method;
+	EAPMethod *parent;
+	GtkWidget *widget;
+
+	parent = eap_method_init (sizeof (EAPMethodLEAP),
+	                          validate,
+	                          add_to_size_group,
+	                          fill_connection,
+	                          update_secrets,
+	                          NULL,
+	                          "/org/gnome/control-center/network/eap-method-leap.ui",
+	                          "eap_leap_notebook",
+	                          "eap_leap_username_entry",
+	                          FALSE);
+	if (!parent)
+		return NULL;
+
+	method = (EAPMethodLEAP *) parent;
+	method->new_connection = secrets_only ? FALSE : TRUE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+	if (connection) {
+		NMSetting8021x *s_8021x;
+
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+		if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+			gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
+	}
+
+	if (secrets_only)
+		gtk_widget_set_sensitive (widget, FALSE);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	/* Fill secrets, if any */
+	if (connection)
+		update_secrets (parent, connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapleap"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  parent);
+
+	return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-leap.h b/panels/network/wireless-security/eap-method-leap.h
new file mode 100644
index 0000000..e3525ba
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_LEAP_H
+#define EAP_METHOD_LEAP_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodLEAP EAPMethodLEAP;
+
+EAPMethodLEAP *eap_method_leap_new (WirelessSecurity *ws_parent,
+                                    NMConnection *connection,
+                                    gboolean secrets_only);
+
+#endif /* EAP_METHOD_LEAP_H */
+
diff --git a/panels/network/wireless-security/eap-method-leap.ui b/panels/network/wireless-security/eap-method-leap.ui
new file mode 100644
index 0000000..8b475fb
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.ui
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkNotebook" id="eap_leap_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table9">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">3</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_leap_username_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Username</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_leap_username_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_leap_password_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Password</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_leap_password_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_leap_password_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="visibility">False</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="show_checkbutton_eapleap">
+            <property name="label" translatable="yes">Sho_w password</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="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_leap_username_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label43">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-peap.c b/panels/network/wireless-security/eap-method-peap.c
new file mode 100644
index 0000000..2c1387a
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+
+#define I_NAME_COLUMN   0
+#define I_METHOD_COLUMN 1
+
+struct _EAPMethodPEAP {
+	EAPMethod parent;
+
+	GtkSizeGroup *size_group;
+	WirelessSecurity *sec_parent;
+	gboolean is_editor;
+};
+
+static void
+destroy (EAPMethod *parent)
+{
+	EAPMethodPEAP *method = (EAPMethodPEAP *) parent;
+
+	if (method->size_group)
+		g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap = NULL;
+	gboolean valid = FALSE;
+
+	if (!eap_method_validate_filepicker (parent->builder, "eap_peap_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
+		return FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	valid = eap_method_validate (eap);
+	eap_method_unref (eap);
+	return valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+	EAPMethodPEAP *method = (EAPMethodPEAP *) parent;
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap;
+
+	if (method->size_group)
+		g_object_unref (method->size_group);
+	method->size_group = g_object_ref (group);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	eap_method_add_to_size_group (eap, group);
+	eap_method_unref (eap);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+	NMSetting8021x *s_8021x;
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	GtkWidget *widget;
+	const char *text;
+	char *filename;
+	EAPMethod *eap = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	int peapver_active = 0;
+	GError *error = NULL;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	nm_setting_802_1x_add_eap_method (s_8021x, "peap");
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (text && strlen (text))
+		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
+	g_assert (widget);
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+		g_clear_error (&error);
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+	peapver_active = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+	switch (peapver_active) {
+	case 1:  /* PEAP v0 */
+		g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL);
+		break;
+	case 2:  /* PEAP v1 */
+		g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "1", NULL);
+		break;
+	default: /* Automatic */
+		g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, NULL, NULL);
+		break;
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_method_fill_connection (eap, connection);
+	eap_method_unref (eap);
+}
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	EAPMethod *parent = (EAPMethod *) user_data;
+	EAPMethodPEAP *method = (EAPMethodPEAP *) parent;
+	GtkWidget *vbox;
+	EAPMethod *eap = NULL;
+	GList *elt, *children;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkWidget *eap_widget;
+
+	vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_vbox"));
+	g_assert (vbox);
+
+	/* Remove any previous wireless security widgets */
+	children = gtk_container_get_children (GTK_CONTAINER (vbox));
+	for (elt = children; elt; elt = g_list_next (elt))
+		gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_widget = eap_method_get_widget (eap);
+	g_assert (eap_widget);
+	gtk_widget_unparent (eap_widget);
+
+	if (method->size_group)
+		eap_method_add_to_size_group (eap, method->size_group);
+	gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+	eap_method_unref (eap);
+
+	wireless_security_changed_cb (combo, method->sec_parent);
+}
+
+static GtkWidget *
+inner_auth_combo_init (EAPMethodPEAP *method,
+                       NMConnection *connection,
+                       NMSetting8021x *s_8021x,
+                       gboolean secrets_only)
+{
+	EAPMethod *parent = (EAPMethod *) method;
+	GtkWidget *combo;
+	GtkListStore *auth_model;
+	GtkTreeIter iter;
+	EAPMethodSimple *em_mschap_v2;
+	EAPMethodSimple *em_md5;
+	EAPMethodSimple *em_gtc;
+	guint32 active = 0;
+	const char *phase2_auth = NULL;
+
+	auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+	if (s_8021x) {
+		if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+			phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+		else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+			phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+	}
+
+	em_mschap_v2 = eap_method_simple_new (method->sec_parent,
+	                                      connection,
+	                                      EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+	                                      TRUE,
+	                                      method->is_editor,
+	                                      secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("MSCHAPv2"),
+	                    I_METHOD_COLUMN, em_mschap_v2,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_mschap_v2));
+
+	/* Check for defaulting to MSCHAPv2 */
+	if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+		active = 0;
+
+	em_md5 = eap_method_simple_new (method->sec_parent,
+	                                connection,
+	                                EAP_METHOD_SIMPLE_TYPE_MD5,
+	                                TRUE,
+	                                method->is_editor,
+	                                secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("MD5"),
+	                    I_METHOD_COLUMN, em_md5,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_md5));
+
+	/* Check for defaulting to MD5 */
+	if (phase2_auth && !strcasecmp (phase2_auth, "md5"))
+		active = 1;
+
+	em_gtc = eap_method_simple_new (method->sec_parent,
+	                                connection,
+	                                EAP_METHOD_SIMPLE_TYPE_GTC,
+	                                TRUE,
+	                                method->is_editor,
+	                                secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("GTC"),
+	                    I_METHOD_COLUMN, em_gtc,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_gtc));
+
+	/* Check for defaulting to GTC */
+	if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+		active = 2;
+
+	combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+	g_assert (combo);
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+	g_object_unref (G_OBJECT (auth_model));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+	g_signal_connect (G_OBJECT (combo), "changed",
+	                  (GCallback) inner_auth_combo_changed_cb,
+	                  method);
+	return combo;
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+	eap_method_phase2_update_secrets_helper (parent,
+	                                         connection,
+	                                         "eap_peap_inner_auth_combo",
+	                                         I_METHOD_COLUMN);
+}
+
+EAPMethodPEAP *
+eap_method_peap_new (WirelessSecurity *ws_parent,
+                     NMConnection *connection,
+                     gboolean is_editor,
+                     gboolean secrets_only)
+{
+	EAPMethod *parent;
+	EAPMethodPEAP *method;
+	GtkWidget *widget;
+	GtkFileFilter *filter;
+	NMSetting8021x *s_8021x = NULL;
+	const char *filename;
+
+	parent = eap_method_init (sizeof (EAPMethodPEAP),
+	                          validate,
+	                          add_to_size_group,
+	                          fill_connection,
+	                          update_secrets,
+	                          destroy,
+	                          "/org/gnome/control-center/network/eap-method-peap.ui",
+	                          "eap_peap_notebook",
+	                          "eap_peap_anon_identity_entry",
+	                          FALSE);
+	if (!parent)
+		return NULL;
+
+	eap_method_nag_init (parent, "eap_peap_ca_cert_button", connection);
+
+	method = (EAPMethodPEAP *) parent;
+	method->sec_parent = ws_parent;
+	method->is_editor = is_editor;
+
+	if (connection)
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
+	g_assert (widget);
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+	                                   _("Choose a Certificate Authority certificate..."));
+	g_signal_connect (G_OBJECT (widget), "selection-changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+	filter = eap_method_default_file_chooser_filter_new (FALSE);
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+	if (connection && s_8021x) {
+		if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+			filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+			if (filename)
+				gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
+	}
+
+	widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+	inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+	g_assert (widget);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+	if (s_8021x) {
+		const char *peapver;
+
+		peapver = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+		if (peapver) {
+			/* Index 0 is "Automatic" */
+			if (!strcmp (peapver, "0"))
+				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+			else if (!strcmp (peapver, "1"))
+				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
+		}
+	}
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+	if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	if (secrets_only) {
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+		gtk_widget_hide (widget);
+	}
+
+	return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-peap.h b/panels/network/wireless-security/eap-method-peap.h
new file mode 100644
index 0000000..752306c
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_PEAP_H
+#define EAP_METHOD_PEAP_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodPEAP EAPMethodPEAP;
+
+EAPMethodPEAP *eap_method_peap_new (WirelessSecurity *ws_parent,
+                                    NMConnection *connection,
+                                    gboolean is_editor,
+                                    gboolean secrets_only);
+
+#endif /* EAP_METHOD_PEAP_H */
+
diff --git a/panels/network/wireless-security/eap-method-peap.ui b/panels/network/wireless-security/eap-method-peap.ui
new file mode 100644
index 0000000..4202237
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.ui
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="model8">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes"> </col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="model9">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Automatic</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Version 0</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Version 1</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkNotebook" id="eap_peap_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table13">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">5</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="eap_peap_anon_identity_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Anony_mous identity</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_peap_anon_identity_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_peap_anon_identity_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_peap_ca_cert_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">C_A certificate</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_peap_ca_cert_button</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="eap_peap_ca_cert_button">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="eap_peap_inner_auth_vbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_peap_inner_auth_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Inner authentication</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_peap_inner_auth_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="eap_peap_inner_auth_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model8</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer8"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_peap_version_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">PEAP _version</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_peap_version_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="eap_peap_version_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model9</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer9"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label61">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-simple.c b/panels/network/wireless-security/eap-method-simple.c
new file mode 100644
index 0000000..aa92cde
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.c
@@ -0,0 +1,305 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2011 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-8021x.h>
+#include <nm-setting-connection.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _EAPMethodSimple {
+	EAPMethod parent;
+
+	EAPMethodSimpleType type;
+	gboolean is_editor;
+	gboolean new_connection;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, EAPMethod *method)
+{
+	GtkWidget *widget;
+	gboolean visible;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (method->builder, "eap_simple_password_entry"));
+	g_assert (widget);
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+	GtkWidget *widget;
+	const char *text;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!text || !strlen (text))
+		return FALSE;
+
+	/* Check if the password should always be requested */
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
+	g_assert (widget);
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+		return TRUE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!text || !strlen (text))
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+	EAPMethodSimple *method = (EAPMethodSimple *) parent;
+	NMSetting8021x *s_8021x;
+	GtkWidget *widget;
+	gboolean not_saved = FALSE;
+	const char *eap = NULL;
+	NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	/* If this is the main EAP method, clear any existing methods because the
+	 * user-selected on will replace it.
+	 */
+	if (parent->phase2 == FALSE)
+		nm_setting_802_1x_clear_eap_methods (s_8021x);
+
+	switch (method->type) {
+		case EAP_METHOD_SIMPLE_TYPE_PAP:
+			eap = "pap";
+			break;
+		case EAP_METHOD_SIMPLE_TYPE_MSCHAP:
+			eap = "mschap";
+			break;
+		case EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2:
+			eap = "mschapv2";
+			break;
+		case EAP_METHOD_SIMPLE_TYPE_MD5:
+			eap = "md5";
+			break;
+		case EAP_METHOD_SIMPLE_TYPE_CHAP:
+			eap = "chap";
+			break;
+		case EAP_METHOD_SIMPLE_TYPE_GTC:
+			eap = "gtc";
+			break;
+		default:
+			g_assert_not_reached ();
+			break;
+	}
+
+	if (parent->phase2)
+		g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, eap, NULL);
+	else
+		nm_setting_802_1x_add_eap_method (s_8021x, eap);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+	g_assert (widget);
+	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+	/* Save the password always ask setting */
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
+	g_assert (widget);
+	not_saved = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+	nm_setting_get_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, &flags, NULL);
+	flags &= ~(NM_SETTING_SECRET_FLAG_NOT_SAVED);
+	if (not_saved)
+		flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED;
+	nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, flags, NULL);
+
+	/* Fill the connection's password if we're in the applet so that it'll get
+	 * back to NM.  From the editor though, since the connection isn't going
+	 * back to NM in response to a GetSecrets() call, we don't save it if the
+	 * user checked "Always Ask".
+	 */
+	if (method->is_editor == FALSE || not_saved == FALSE) {
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+		g_assert (widget);
+		g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+	}
+
+	/* Default to agent-owned secrets for new connections */
+	if (method->new_connection && (not_saved == FALSE)) {
+		g_object_set (s_8021x,
+		              NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+		              NM_SETTING_802_1X_SYSTEM_CA_CERTS, TRUE,
+		              NULL);
+	}
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+	helper_fill_secret_entry (connection,
+	                          parent->builder,
+	                          "eap_simple_password_entry",
+	                          NM_TYPE_SETTING_802_1X,
+	                          (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+static void
+password_always_ask_changed (GtkButton *button, EAPMethodSimple *method)
+{
+	EAPMethod *parent = (EAPMethod *) method;
+	GtkWidget *password_entry;
+	GtkWidget *show_checkbox;
+	gboolean always_ask;
+
+	always_ask = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+	password_entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+	g_assert (password_entry);
+
+	show_checkbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapsimple"));
+	g_assert (show_checkbox);
+
+	if (always_ask) {
+		gtk_entry_set_text (GTK_ENTRY (password_entry), "");
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (show_checkbox), FALSE);
+	}
+
+	gtk_widget_set_sensitive (password_entry, !always_ask);
+	gtk_widget_set_sensitive (show_checkbox, !always_ask);
+}
+
+EAPMethodSimple *
+eap_method_simple_new (WirelessSecurity *ws_parent,
+                       NMConnection *connection,
+                       EAPMethodSimpleType type,
+                       gboolean phase2,
+                       gboolean is_editor,
+                       gboolean secrets_only)
+{
+	EAPMethod *parent;
+	EAPMethodSimple *method;
+	GtkWidget *widget;
+	gboolean not_saved = FALSE;
+	NMSetting8021x *s_8021x = NULL;
+
+	parent = eap_method_init (sizeof (EAPMethodSimple),
+	                          validate,
+	                          add_to_size_group,
+	                          fill_connection,
+	                          update_secrets,
+	                          NULL,
+	                          "/org/gnome/control-center/network/eap-method-simple.ui",
+	                          "eap_simple_notebook",
+	                          "eap_simple_username_entry",
+	                          phase2);
+	if (!parent)
+		return NULL;
+
+	method = (EAPMethodSimple *) parent;
+	method->type = type;
+	method->is_editor = is_editor;
+	method->new_connection = secrets_only ? FALSE : TRUE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+	if (connection) {
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+		if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+			gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
+	}
+
+	if (secrets_only)
+		gtk_widget_set_sensitive (widget, FALSE);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+	if (is_editor) {
+		/* We only desensitize the password entry from the editor, because
+		 * from nm-applet if the entry was desensitized, there'd be no way to
+		 * get the password back to NetworkManager when NM asked for it.  Since
+		 * the editor only sets up the initial connection though, it's safe to
+		 * do there.
+		 */
+		g_signal_connect (G_OBJECT (widget), "toggled",
+		                  G_CALLBACK (password_always_ask_changed),
+		                  method);
+	}
+
+	if (secrets_only)
+		gtk_widget_hide (widget);
+
+	if (s_8021x) {
+		NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+		nm_setting_get_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, &flags, NULL);
+		not_saved = (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED);
+	}
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), not_saved);
+
+	/* Fill secrets if there's a static (ie, not OTP) password */
+	if (connection && (not_saved == FALSE))
+		update_secrets (EAP_METHOD (method), connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapsimple"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  method);
+
+	return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-simple.h b/panels/network/wireless-security/eap-method-simple.h
new file mode 100644
index 0000000..8a955dc
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_SIMPLE_H
+#define EAP_METHOD_SIMPLE_H
+
+#include "wireless-security.h"
+
+typedef enum {
+	EAP_METHOD_SIMPLE_TYPE_PAP = 0,
+	EAP_METHOD_SIMPLE_TYPE_MSCHAP,
+	EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+	EAP_METHOD_SIMPLE_TYPE_MD5,
+	EAP_METHOD_SIMPLE_TYPE_CHAP,
+	EAP_METHOD_SIMPLE_TYPE_GTC
+} EAPMethodSimpleType;
+
+typedef struct _EAPMethodSimple EAPMethodSimple;
+
+EAPMethodSimple *eap_method_simple_new (WirelessSecurity *ws_parent,
+                                        NMConnection *connection,
+                                        EAPMethodSimpleType type,
+                                        gboolean phase2,
+                                        gboolean is_editor,
+                                        gboolean secrets_only);
+
+#endif /* EAP_METHOD_SIMPLE_H */
+
diff --git a/panels/network/wireless-security/eap-method-simple.ui b/panels/network/wireless-security/eap-method-simple.ui
new file mode 100644
index 0000000..854c86f
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.ui
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkNotebook" id="eap_simple_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table11">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">3</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_simple_username_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Username</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_simple_username_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_simple_password_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Password</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_simple_password_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_simple_password_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="visibility">False</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_simple_username_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkVBox" id="vbox5">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkCheckButton" id="eap_password_always_ask">
+                    <property name="label" translatable="yes">As_k for this password every time</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.5</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="show_checkbutton_eapsimple">
+                    <property name="label" translatable="yes">Sho_w password</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="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label53">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-tls.c b/panels/network/wireless-security/eap-method-tls.c
new file mode 100644
index 0000000..d3ea1d3
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _EAPMethodTLS {
+	EAPMethod parent;
+
+	gboolean new_connection;
+};
+
+
+static void
+show_toggled_cb (GtkCheckButton *button, EAPMethod *method)
+{
+	GtkWidget *widget;
+	gboolean visible;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (method->builder, "eap_tls_private_key_password_entry"));
+	g_assert (widget);
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	GtkWidget *widget;
+	const char *password, *identity;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+	g_assert (widget);
+	identity = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!identity || !strlen (identity))
+		return FALSE;
+
+	if (!eap_method_validate_filepicker (parent->builder, "eap_tls_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
+		return FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+	g_assert (widget);
+	password = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (!password || !strlen (password))
+		return FALSE;
+
+	if (!eap_method_validate_filepicker (parent->builder,
+	                                     "eap_tls_private_key_button",
+	                                     TYPE_PRIVATE_KEY,
+	                                     password,
+	                                     &format))
+		return FALSE;
+
+	if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+		if (!eap_method_validate_filepicker (parent->builder, "eap_tls_user_cert_button", TYPE_CLIENT_CERT, NULL, NULL))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+	EAPMethodTLS *method = (EAPMethodTLS *) parent;
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	NMSetting8021x *s_8021x;
+	GtkWidget *widget;
+	char *ca_filename, *pk_filename, *cc_filename;
+	const char *password = NULL;
+	GError *error = NULL;
+	const char *secret_flag_prop = NULL;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	if (parent->phase2)
+		g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL);
+	else
+		nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+	g_assert (widget);
+	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+	/* TLS private key */
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+	g_assert (widget);
+	password = gtk_entry_get_text (GTK_ENTRY (widget));
+	g_assert (password);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
+	g_assert (widget);
+	pk_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	g_assert (pk_filename);
+
+	if (parent->phase2) {
+		if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read phase2 private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
+		secret_flag_prop = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS;
+	} else {
+		if (!nm_setting_802_1x_set_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
+		secret_flag_prop = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS;
+	}
+	g_free (pk_filename);
+
+	/* Default to agent-owned secrets for new connections */
+	if (method->new_connection) {
+		g_object_set (s_8021x,
+		              secret_flag_prop, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+		              NM_SETTING_802_1X_SYSTEM_CA_CERTS, TRUE,
+		              NULL);
+	}
+
+	/* TLS client certificate */
+	if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+		/* If the key is pkcs#12 nm_setting_802_1x_set_private_key() already
+		 * set the client certificate for us.
+		 */
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_button"));
+		g_assert (widget);
+		cc_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+		g_assert (cc_filename);
+
+		format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+		if (parent->phase2) {
+			if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+				g_warning ("Couldn't read phase2 client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+				g_clear_error (&error);
+			}
+		} else {
+			if (!nm_setting_802_1x_set_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+				g_warning ("Couldn't read client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+				g_clear_error (&error);
+			}
+		}
+		g_free (cc_filename);
+	}
+
+	/* TLS CA certificate */
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_button"));
+	g_assert (widget);
+	ca_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+
+	format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	if (parent->phase2) {
+		if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read phase2 CA certificate '%s': %s", ca_filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
+	} else {
+		if (!nm_setting_802_1x_set_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+			g_warning ("Couldn't read CA certificate '%s': %s", ca_filename, error ? error->message : "(unknown)");
+			g_clear_error (&error);
+		}
+	}
+}
+
+static void
+private_key_picker_helper (EAPMethod *parent, const char *filename, gboolean changed)
+{
+	NMSetting8021x *setting;
+	NMSetting8021xCKFormat cert_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	const char *password;
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+	g_assert (widget);
+	password = gtk_entry_get_text (GTK_ENTRY (widget));
+
+	setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+	nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &cert_format, NULL);
+	g_object_unref (setting);
+
+	/* With PKCS#12, the client cert must be the same as the private key */
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_button"));
+	if (cert_format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+		gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (widget));
+		gtk_widget_set_sensitive (widget, FALSE);
+	} else if (changed)
+		gtk_widget_set_sensitive (widget, TRUE);
+
+	/* Warn the user if the private key is unencrypted */
+	if (!eap_method_is_encrypted_private_key (filename)) {
+		GtkWidget *dialog;
+		GtkWidget *toplevel;
+		GtkWindow *parent_window = NULL;
+
+		toplevel = gtk_widget_get_toplevel (parent->ui_widget);
+		if (gtk_widget_is_toplevel (toplevel))
+			parent_window = GTK_WINDOW (toplevel);
+
+		dialog = gtk_message_dialog_new (parent_window,
+		                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+		                                 GTK_MESSAGE_WARNING,
+		                                 GTK_BUTTONS_OK,
+		                                 "%s",
+		                                 _("Unencrypted private keys are insecure"));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+		                                          "%s",
+		                                          _("The selected private key does not appear to be protected by a password.  This could allow your security credentials to be compromised.  Please select a password-protected private key.\n\n(You can password-protect your private key with openssl)"));
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+	}
+}
+
+static void
+private_key_picker_file_set_cb (GtkWidget *chooser, gpointer user_data)
+{
+	EAPMethod *parent = (EAPMethod *) user_data;
+	char *filename;
+
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+	if (filename)
+		private_key_picker_helper (parent, filename, TRUE);
+	g_free (filename);
+}
+
+static void reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_data)
+{
+	if (!gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (widget))) {
+		g_signal_handlers_block_by_func (widget, reset_filter, user_data);
+		gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), GTK_FILE_FILTER (user_data));
+		g_signal_handlers_unblock_by_func (widget, reset_filter, user_data);
+	}
+}
+
+typedef const char * (*PathFunc) (NMSetting8021x *setting);
+typedef NMSetting8021xCKScheme (*SchemeFunc)  (NMSetting8021x *setting);
+
+static void
+setup_filepicker (GtkBuilder *builder,
+                  const char *name,
+                  const char *title,
+                  WirelessSecurity *ws_parent,
+                  EAPMethod *parent,
+                  NMSetting8021x *s_8021x,
+                  SchemeFunc scheme_func,
+                  PathFunc path_func,
+                  gboolean privkey,
+                  gboolean client_cert)
+{
+	GtkWidget *widget;
+	GtkFileFilter *filter;
+	const char *filename = NULL;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, name));
+	g_assert (widget);
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget), title);
+
+	if (s_8021x && path_func && scheme_func) {
+		if (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+			filename = path_func (s_8021x);
+			if (filename)
+				gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
+	}
+
+	/* Connect a special handler for private keys to intercept PKCS#12 key types
+	 * and desensitize the user cert button.
+	 */
+	if (privkey) {
+		g_signal_connect (G_OBJECT (widget), "selection-changed",
+		                  (GCallback) private_key_picker_file_set_cb,
+		                  parent);
+		if (filename)
+			private_key_picker_helper (parent, filename, FALSE);
+	}
+
+	g_signal_connect (G_OBJECT (widget), "selection-changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	filter = eap_method_default_file_chooser_filter_new (privkey);
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+	/* For some reason, GTK+ calls set_current_filter (..., NULL) from 
+	 * gtkfilechooserdefault.c::show_and_select_files_finished_loading() on our
+	 * dialog; so force-reset the filter to what we want it to be whenever
+	 * it gets cleared.
+	 */
+	if (client_cert)
+		g_signal_connect (G_OBJECT (widget), "notify::filter", (GCallback) reset_filter, filter);
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+	NMSetting8021x *s_8021x;
+	HelperSecretFunc password_func;
+	SchemeFunc scheme_func;
+	PathFunc path_func;
+	const char *filename;
+	GtkWidget *widget;
+
+	if (parent->phase2) {
+		password_func = (HelperSecretFunc) nm_setting_802_1x_get_phase2_private_key_password;
+		scheme_func = nm_setting_802_1x_get_phase2_private_key_scheme;
+		path_func = nm_setting_802_1x_get_phase2_private_key_path;
+	} else {
+		password_func = (HelperSecretFunc) nm_setting_802_1x_get_private_key_password;
+		scheme_func = nm_setting_802_1x_get_private_key_scheme;
+		path_func = nm_setting_802_1x_get_private_key_path;
+	}
+
+	helper_fill_secret_entry (connection,
+	                          parent->builder,
+	                          "eap_tls_private_key_password_entry",
+	                          NM_TYPE_SETTING_802_1X,
+	                          password_func);
+
+	/* Set the private key filepicker button path if we have a private key */
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	if (s_8021x && (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH)) {
+		filename = path_func (s_8021x);
+		if (filename) {
+			widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
+			g_assert (widget);
+			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
+	}
+}
+
+EAPMethodTLS *
+eap_method_tls_new (WirelessSecurity *ws_parent,
+                    NMConnection *connection,
+                    gboolean phase2,
+                    gboolean secrets_only)
+{
+	EAPMethodTLS *method;
+	EAPMethod *parent;
+	GtkWidget *widget;
+	NMSetting8021x *s_8021x = NULL;
+
+	parent = eap_method_init (sizeof (EAPMethodTLS),
+	                          validate,
+	                          add_to_size_group,
+	                          fill_connection,
+	                          update_secrets,
+	                          NULL,
+	                          "/org/gnome/control-center/network/eap-method-tls.ui",
+	                          "eap_tls_notebook",
+	                          "eap_tls_identity_entry",
+	                          phase2);
+	if (!parent)
+		return NULL;
+
+	method = (EAPMethodTLS *) parent;
+	method->new_connection = secrets_only ? FALSE : TRUE;
+
+	eap_method_nag_init (parent, "eap_tls_ca_cert_button", connection);
+
+	if (connection)
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+	if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
+
+	setup_filepicker (parent->builder, "eap_tls_user_cert_button",
+	                  _("Choose your personal certificate..."),
+	                  ws_parent, parent, s_8021x,
+	                  phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme : nm_setting_802_1x_get_client_cert_scheme,
+	                  phase2 ? nm_setting_802_1x_get_phase2_client_cert_path : nm_setting_802_1x_get_client_cert_path,
+	                  FALSE, TRUE);
+	setup_filepicker (parent->builder, "eap_tls_ca_cert_button",
+	                  _("Choose a Certificate Authority certificate..."),
+	                  ws_parent, parent, s_8021x,
+	                  phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme : nm_setting_802_1x_get_ca_cert_scheme,
+	                  phase2 ? nm_setting_802_1x_get_phase2_ca_cert_path : nm_setting_802_1x_get_ca_cert_path,
+	                  FALSE, FALSE);
+	setup_filepicker (parent->builder, "eap_tls_private_key_button",
+	                  _("Choose your private key..."),
+	                  ws_parent, parent, s_8021x,
+	                  phase2 ? nm_setting_802_1x_get_phase2_private_key_scheme : nm_setting_802_1x_get_private_key_scheme,
+	                  phase2 ? nm_setting_802_1x_get_phase2_private_key_path : nm_setting_802_1x_get_private_key_path,
+	                  TRUE, FALSE);
+
+	/* Fill secrets, if any */
+	if (connection)
+		update_secrets (parent, connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eaptls"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  parent);
+
+	if (secrets_only) {
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+		gtk_widget_set_sensitive (widget, FALSE);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_button"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_button"));
+		gtk_widget_hide (widget);
+	}
+
+	return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-tls.h b/panels/network/wireless-security/eap-method-tls.h
new file mode 100644
index 0000000..147a75f
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_TLS_H
+#define EAP_METHOD_TLS_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodTLS EAPMethodTLS;
+
+EAPMethodTLS *eap_method_tls_new (WirelessSecurity *ws_parent,
+                                  NMConnection *connection,
+                                  gboolean phase2,
+                                  gboolean secrets_only);
+
+#endif /* EAP_METHOD_TLS_H */
+
diff --git a/panels/network/wireless-security/eap-method-tls.ui b/panels/network/wireless-security/eap-method-tls.ui
new file mode 100644
index 0000000..028e73e
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.ui
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkNotebook" id="eap_tls_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table8">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">6</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_tls_identity_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">I_dentity</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_tls_identity_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_tls_identity_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_tls_user_cert_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_User certificate</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_tls_user_cert_button</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_tls_ca_cert_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">C_A certificate</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_tls_ca_cert_button</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="eap_tls_ca_cert_button">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_tls_private_key_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Private _key</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_tls_private_key_button</property>
+          </object>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="eap_tls_private_key_button">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_tls_private_key_password_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Private key password</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_tls_private_key_password_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_tls_private_key_password_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="visibility">False</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="show_checkbutton_eaptls">
+            <property name="label" translatable="yes">Sho_w password</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="right_attach">2</property>
+            <property name="top_attach">5</property>
+            <property name="bottom_attach">6</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="eap_tls_user_cert_button">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label34">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-ttls.c b/panels/network/wireless-security/eap-method-ttls.c
new file mode 100644
index 0000000..5ad8599
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.c
@@ -0,0 +1,391 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+
+#define I_NAME_COLUMN   0
+#define I_METHOD_COLUMN 1
+
+struct _EAPMethodTTLS {
+	EAPMethod parent;
+
+	GtkSizeGroup *size_group;
+	WirelessSecurity *sec_parent;
+	gboolean is_editor;
+};
+
+static void
+destroy (EAPMethod *parent)
+{
+	EAPMethodTTLS *method = (EAPMethodTTLS *) parent;
+
+	if (method->size_group)
+		g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap = NULL;
+	gboolean valid = FALSE;
+
+	if (!eap_method_validate_filepicker (parent->builder, "eap_ttls_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
+		return FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	valid = eap_method_validate (eap);
+	eap_method_unref (eap);
+	return valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+	EAPMethodTTLS *method = (EAPMethodTTLS *) parent;
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap;
+
+	if (method->size_group)
+		g_object_unref (method->size_group);
+	method->size_group = g_object_ref (group);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
+	g_assert (widget);
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	eap_method_add_to_size_group (eap, group);
+	eap_method_unref (eap);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+	NMSetting8021x *s_8021x;
+	NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+	GtkWidget *widget;
+	const char *text;
+	char *filename;
+	EAPMethod *eap = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GError *error = NULL;
+
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+	g_assert (widget);
+	text = gtk_entry_get_text (GTK_ENTRY (widget));
+	if (text && strlen (text))
+		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
+	g_assert (widget);
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+		g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+		g_clear_error (&error);
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_method_fill_connection (eap, connection);
+	eap_method_unref (eap);
+}
+
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	EAPMethod *parent = (EAPMethod *) user_data;
+	EAPMethodTTLS *method = (EAPMethodTTLS *) parent;
+	GtkWidget *vbox;
+	EAPMethod *eap = NULL;
+	GList *elt, *children;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkWidget *eap_widget;
+
+	vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_vbox"));
+	g_assert (vbox);
+
+	/* Remove any previous wireless security widgets */
+	children = gtk_container_get_children (GTK_CONTAINER (vbox));
+	for (elt = children; elt; elt = g_list_next (elt))
+		gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+	g_list_free (children);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+	gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_widget = eap_method_get_widget (eap);
+	g_assert (eap_widget);
+	gtk_widget_unparent (eap_widget);
+
+	if (method->size_group)
+		eap_method_add_to_size_group (eap, method->size_group);
+	gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+	eap_method_unref (eap);
+
+	wireless_security_changed_cb (combo, method->sec_parent);
+}
+
+static GtkWidget *
+inner_auth_combo_init (EAPMethodTTLS *method,
+                       NMConnection *connection,
+                       NMSetting8021x *s_8021x,
+                       gboolean secrets_only)
+{
+	EAPMethod *parent = (EAPMethod *) method;
+	GtkWidget *combo;
+	GtkListStore *auth_model;
+	GtkTreeIter iter;
+	EAPMethodSimple *em_pap;
+	EAPMethodSimple *em_mschap;
+	EAPMethodSimple *em_mschap_v2;
+	EAPMethodSimple *em_chap;
+	guint32 active = 0;
+	const char *phase2_auth = NULL;
+
+	auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+	if (s_8021x) {
+		if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+			phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+		else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+			phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+	}
+
+	em_pap = eap_method_simple_new (method->sec_parent,
+	                                connection,
+	                                EAP_METHOD_SIMPLE_TYPE_PAP,
+	                                TRUE,
+	                                method->is_editor,
+	                                secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("PAP"),
+	                    I_METHOD_COLUMN, em_pap,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_pap));
+
+	/* Check for defaulting to PAP */
+	if (phase2_auth && !strcasecmp (phase2_auth, "pap"))
+		active = 0;
+
+	em_mschap = eap_method_simple_new (method->sec_parent,
+	                                   connection,
+	                                   EAP_METHOD_SIMPLE_TYPE_MSCHAP,
+	                                   TRUE,
+	                                   method->is_editor,
+	                                   secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("MSCHAP"),
+	                    I_METHOD_COLUMN, em_mschap,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_mschap));
+
+	/* Check for defaulting to MSCHAP */
+	if (phase2_auth && !strcasecmp (phase2_auth, "mschap"))
+		active = 1;
+
+	em_mschap_v2 = eap_method_simple_new (method->sec_parent,
+	                                      connection,
+	                                      EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+	                                      TRUE,
+	                                      method->is_editor, secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("MSCHAPv2"),
+	                    I_METHOD_COLUMN, em_mschap_v2,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_mschap_v2));
+
+	/* Check for defaulting to MSCHAPv2 */
+	if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+		active = 2;
+
+	em_chap = eap_method_simple_new (method->sec_parent,
+	                                 connection,
+	                                 EAP_METHOD_SIMPLE_TYPE_CHAP,
+	                                 TRUE,
+	                                 method->is_editor,
+	                                 secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    I_NAME_COLUMN, _("CHAP"),
+	                    I_METHOD_COLUMN, em_chap,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_chap));
+
+	/* Check for defaulting to CHAP */
+	if (phase2_auth && !strcasecmp (phase2_auth, "chap"))
+		active = 3;
+
+	combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+	g_assert (combo);
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+	g_object_unref (G_OBJECT (auth_model));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+	g_signal_connect (G_OBJECT (combo), "changed",
+	                  (GCallback) inner_auth_combo_changed_cb,
+	                  method);
+	return combo;
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+	eap_method_phase2_update_secrets_helper (parent,
+	                                         connection,
+	                                         "eap_ttls_inner_auth_combo",
+	                                         I_METHOD_COLUMN);
+}
+
+EAPMethodTTLS *
+eap_method_ttls_new (WirelessSecurity *ws_parent,
+                     NMConnection *connection,
+                     gboolean is_editor,
+                     gboolean secrets_only)
+{
+	EAPMethod *parent;
+	EAPMethodTTLS *method;
+	GtkWidget *widget;
+	GtkFileFilter *filter;
+	NMSetting8021x *s_8021x = NULL;
+	const char *filename;
+
+	parent = eap_method_init (sizeof (EAPMethodTTLS),
+	                          validate,
+	                          add_to_size_group,
+	                          fill_connection,
+	                          update_secrets,
+	                          destroy,
+	                          "/org/gnome/control-center/network/eap-method-ttls.ui",
+	                          "eap_ttls_notebook",
+	                          "eap_ttls_anon_identity_entry",
+	                          FALSE);
+	if (!parent)
+		return NULL;
+
+	eap_method_nag_init (parent, "eap_ttls_ca_cert_button", connection);
+
+	method = (EAPMethodTTLS *) parent;
+	method->sec_parent = ws_parent;
+	method->is_editor = is_editor;
+
+	if (connection)
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
+	g_assert (widget);
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+	                                   _("Choose a Certificate Authority certificate..."));
+	g_signal_connect (G_OBJECT (widget), "selection-changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+	filter = eap_method_default_file_chooser_filter_new (FALSE);
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+	if (connection && s_8021x) {
+		if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+			filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+			if (filename)
+				gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+		}
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+	if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  ws_parent);
+
+	widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+	inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+	if (secrets_only) {
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+		gtk_widget_hide (widget);
+	}
+
+	return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-ttls.h b/panels/network/wireless-security/eap-method-ttls.h
new file mode 100644
index 0000000..16467f6
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_TTLS_H
+#define EAP_METHOD_TTLS_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodTTLS EAPMethodTTLS;
+
+EAPMethodTTLS *eap_method_ttls_new (WirelessSecurity *ws_parent,
+                                    NMConnection *connection,
+                                    gboolean is_editor,
+                                    gboolean secrets_only);
+
+#endif /* EAP_METHOD_TLS_H */
+
diff --git a/panels/network/wireless-security/eap-method-ttls.ui b/panels/network/wireless-security/eap-method-ttls.ui
new file mode 100644
index 0000000..39465cf
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.ui
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="model6">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes"> </col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkNotebook" id="eap_ttls_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table10">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">4</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="eap_ttls_anon_identity_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Anony_mous identity</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_ttls_anon_identity_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="eap_ttls_anon_identity_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_ttls_ca_cert_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">C_A certificate</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_ttls_ca_cert_button</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="eap_ttls_ca_cert_button">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="eap_ttls_inner_auth_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Inner authentication</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">eap_ttls_inner_auth_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="eap_ttls_inner_auth_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model6</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer6"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="eap_ttls_inner_auth_vbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">6</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label49">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method.c b/panels/network/wireless-security/eap-method.c
new file mode 100644
index 0000000..8ff9778
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.c
@@ -0,0 +1,660 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+#include "eap-method.h"
+#include "nm-utils.h"
+
+GType
+eap_method_get_g_type (void)
+{
+	static GType type_id = 0;
+
+	if (!type_id) {
+		type_id = g_boxed_type_register_static ("EAPMethod",
+		                                        (GBoxedCopyFunc) eap_method_ref,
+		                                        (GBoxedFreeFunc) eap_method_unref);
+	}
+
+	return type_id;
+}
+
+GtkWidget *
+eap_method_get_widget (EAPMethod *method)
+{
+	g_return_val_if_fail (method != NULL, NULL);
+
+	return method->ui_widget;
+}
+
+gboolean
+eap_method_validate (EAPMethod *method)
+{
+	g_return_val_if_fail (method != NULL, FALSE);
+
+	g_assert (method->validate);
+	return (*(method->validate)) (method);
+}
+
+void
+eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+	g_return_if_fail (method != NULL);
+	g_return_if_fail (group != NULL);
+
+	g_assert (method->add_to_size_group);
+	return (*(method->add_to_size_group)) (method, group);
+}
+
+void
+eap_method_fill_connection (EAPMethod *method, NMConnection *connection)
+{
+	g_return_if_fail (method != NULL);
+	g_return_if_fail (connection != NULL);
+
+	g_assert (method->fill_connection);
+	return (*(method->fill_connection)) (method, connection);
+}
+
+void
+eap_method_update_secrets (EAPMethod *method, NMConnection *connection)
+{
+	g_return_if_fail (method != NULL);
+	g_return_if_fail (connection != NULL);
+
+	if (method->update_secrets)
+		method->update_secrets (method, connection);
+}
+
+typedef struct {
+	EAPMethod *method;
+	NMConnection *connection;
+} NagDialogResponseInfo;
+
+static void
+nag_dialog_destroyed (gpointer data, GObject *dialog_ptr)
+{
+	NagDialogResponseInfo *info = (NagDialogResponseInfo *) data;
+
+	memset (info, '\0', sizeof (NagDialogResponseInfo));
+	g_free (info);
+}
+
+static GSettings *
+_get_ca_ignore_settings (const char *uuid)
+{
+	GSettings *settings;
+	char *path = NULL;
+
+	path = g_strdup_printf ("/org/gnome/nm-applet/eap/%s", uuid);
+	settings = g_settings_new_with_path ("org.gnome.nm-applet.eap", path);
+	g_free (path);
+
+	return settings;
+}
+
+static void
+_set_ignore_ca_cert (const char *uuid, gboolean phase2, gboolean ignore)
+{
+	GSettings *settings;
+	const char *key;
+
+	g_return_if_fail (uuid != NULL);
+
+	settings = _get_ca_ignore_settings (uuid);
+	key = phase2 ? "ignore-phase2-ca-cert" : "ignore-ca-cert";
+	g_settings_set_boolean (settings, key, ignore);
+	g_object_unref (settings);
+}
+
+static void
+nag_dialog_response_cb (GtkDialog *nag_dialog,
+                        gint response,
+                        gpointer user_data)
+{
+	NagDialogResponseInfo *info = (NagDialogResponseInfo *) user_data;
+	EAPMethod *method = (EAPMethod *) info->method;
+	NMConnection *connection = (NMConnection *) info->connection;
+	GtkWidget *widget;
+
+	if (response == GTK_RESPONSE_NO) {
+		/* Grab the value of the "don't bother me" checkbox */
+		widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "ignore_checkbox"));
+		g_assert (widget);
+
+		method->ignore_ca_cert = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+		/* And save it */
+		_set_ignore_ca_cert (nm_connection_get_uuid (connection),
+		                     method->phase2,
+		                     method->ignore_ca_cert);
+	}
+
+	gtk_widget_hide (GTK_WIDGET (nag_dialog));
+}
+
+static gboolean 
+nag_dialog_delete_event_cb (GtkDialog *nag_dialog, GdkEvent *e, gpointer user_data) 
+{ 
+	// FIXME?: By emitting response signal, dismissing nag dialog with upper right "x" icon,
+	// Alt-F4, or Esc would have the same behaviour as clicking "Ignore" button.
+	//g_signal_emit_by_name (nag_dialog, "response", GTK_RESPONSE_NO, user_data);
+	return TRUE;  /* do not destroy */
+} 
+
+GtkWidget *
+eap_method_nag_user (EAPMethod *method)
+{
+	GtkWidget *widget;
+	char *filename = NULL;
+
+	g_return_val_if_fail (method != NULL, NULL);
+
+	if (!method->nag_dialog || method->ignore_ca_cert)
+		return NULL;
+
+	/* Checkbox should be unchecked each time dialog comes up */
+	widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "ignore_checkbox"));
+	g_assert (widget);
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+
+	/* Nag the user if the CA Cert is blank, since it's a security risk. */
+	widget = GTK_WIDGET (gtk_builder_get_object (method->builder, method->ca_cert_chooser));
+	g_assert (widget);
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	if (filename != NULL) {
+		g_free (filename);
+		return NULL;
+	}
+
+	gtk_window_present (GTK_WINDOW (method->nag_dialog));
+	return method->nag_dialog;
+}
+
+#define NAG_DIALOG_UI "/org/gnome/control-center/network/nag-user-dialog.ui"
+
+static gboolean
+_get_ignore_ca_cert (const char *uuid, gboolean phase2)
+{
+	GSettings *settings;
+	const char *key;
+	gboolean ignore = FALSE;
+
+	g_return_val_if_fail (uuid != NULL, FALSE);
+
+	settings = _get_ca_ignore_settings (uuid);
+
+	key = phase2 ? "ignore-phase2-ca-cert" : "ignore-ca-cert";
+	ignore = g_settings_get_boolean (settings, key);
+
+	g_object_unref (settings);
+	return ignore;
+}
+
+gboolean
+eap_method_nag_init (EAPMethod *method,
+                     const char *ca_cert_chooser,
+                     NMConnection *connection)
+{
+	GtkWidget *dialog, *widget;
+	NagDialogResponseInfo *info;
+	GError *error = NULL;
+	char *text;
+
+	g_return_val_if_fail (method != NULL, FALSE);
+	g_return_val_if_fail (ca_cert_chooser != NULL, FALSE);
+
+	method->nag_builder = gtk_builder_new ();
+	if (!gtk_builder_add_from_resource (method->nag_builder, NAG_DIALOG_UI, &error)) {
+		g_warning ("Couldn't load UI builder file " NAG_DIALOG_UI ": %s",
+		           error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	method->ca_cert_chooser = g_strdup (ca_cert_chooser);
+	if (connection) {
+		NMSettingConnection *s_con;
+		const char *uuid;
+
+		s_con = nm_connection_get_setting_connection (connection);
+		g_assert (s_con);
+		uuid = nm_setting_connection_get_uuid (s_con);
+		g_assert (uuid);
+
+		/* Figure out if the user wants to ignore missing CA cert */
+		method->ignore_ca_cert = _get_ignore_ca_cert (uuid, method->phase2);
+	}
+
+	info = g_malloc0 (sizeof (NagDialogResponseInfo));
+	info->method = method;
+	info->connection = connection;
+
+	dialog = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "nag_user_dialog"));
+	g_assert (dialog);
+	g_signal_connect (dialog, "response", G_CALLBACK (nag_dialog_response_cb), info);
+	g_signal_connect (dialog, "delete-event", G_CALLBACK (nag_dialog_delete_event_cb), info);
+	g_object_weak_ref (G_OBJECT (dialog), nag_dialog_destroyed, info);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "content_label"));
+	g_assert (widget);
+
+	text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+	                        _("No Certificate Authority certificate chosen"),
+	                        _("Not using a Certificate Authority (CA) certificate can result in connections to insecure, rogue Wi-Fi networks.  Would you like to choose a Certificate Authority certificate?"));
+	gtk_label_set_markup (GTK_LABEL (widget), text);
+	g_free (text);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "ignore_button"));
+	gtk_button_set_label (GTK_BUTTON (widget), _("Ignore"));
+	g_assert (widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "change_button"));
+	gtk_button_set_label (GTK_BUTTON (widget), _("Choose CA Certificate"));
+	g_assert (widget);
+
+	method->nag_dialog = dialog;
+	return TRUE;
+}
+
+void
+eap_method_phase2_update_secrets_helper (EAPMethod *method,
+                                         NMConnection *connection,
+                                         const char *combo_name,
+                                         guint32 column)
+{
+	GtkWidget *combo;
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+
+	g_return_if_fail (method != NULL);
+	g_return_if_fail (connection != NULL);
+	g_return_if_fail (combo_name != NULL);
+
+	combo = GTK_WIDGET (gtk_builder_get_object (method->builder, combo_name));
+	g_assert (combo);
+
+	/* Let each EAP phase2 method try to update its secrets */
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			EAPMethod *eap = NULL;
+
+			gtk_tree_model_get (model, &iter, column, &eap, -1);
+			if (eap) {
+				eap_method_update_secrets (eap, connection);
+				eap_method_unref (eap);
+			}
+		} while (gtk_tree_model_iter_next (model, &iter));
+	}
+}
+
+EAPMethod *
+eap_method_init (gsize obj_size,
+                 EMValidateFunc validate,
+                 EMAddToSizeGroupFunc add_to_size_group,
+                 EMFillConnectionFunc fill_connection,
+                 EMUpdateSecretsFunc update_secrets,
+                 EMDestroyFunc destroy,
+                 const char *ui_resource,
+                 const char *ui_widget_name,
+                 const char *default_field,
+                 gboolean phase2)
+{
+	EAPMethod *method;
+	GError *error = NULL;
+
+	g_return_val_if_fail (obj_size > 0, NULL);
+	g_return_val_if_fail (ui_resource != NULL, NULL);
+	g_return_val_if_fail (ui_widget_name != NULL, NULL);
+
+	method = g_slice_alloc0 (obj_size);
+	g_assert (method);
+
+	method->refcount = 1;
+	method->obj_size = obj_size;
+	method->validate = validate;
+	method->add_to_size_group = add_to_size_group;
+	method->fill_connection = fill_connection;
+	method->update_secrets = update_secrets;
+	method->destroy = destroy;
+	method->default_field = default_field;
+	method->phase2 = phase2;
+
+	method->builder = gtk_builder_new ();
+	if (!gtk_builder_add_from_resource (method->builder, ui_resource, &error)) {
+		g_warning ("Couldn't load UI builder file %s: %s",
+		           ui_resource, error->message);
+		eap_method_unref (method);
+		return NULL;
+	}
+
+	method->ui_widget = GTK_WIDGET (gtk_builder_get_object (method->builder, ui_widget_name));
+	if (!method->ui_widget) {
+		g_warning ("Couldn't load UI widget '%s' from UI file %s",
+		           ui_widget_name, ui_resource);
+		eap_method_unref (method);
+		return NULL;
+	}
+	g_object_ref_sink (method->ui_widget);
+
+	return method;
+}
+
+
+EAPMethod *
+eap_method_ref (EAPMethod *method)
+{
+	g_return_val_if_fail (method != NULL, NULL);
+	g_return_val_if_fail (method->refcount > 0, NULL);
+
+	method->refcount++;
+	return method;
+}
+
+void
+eap_method_unref (EAPMethod *method)
+{
+	g_return_if_fail (method != NULL);
+	g_return_if_fail (method->refcount > 0);
+
+	method->refcount--;
+	if (method->refcount == 0) {
+		if (method->destroy)
+			method->destroy (method);
+
+		if (method->nag_dialog)
+			gtk_widget_destroy (method->nag_dialog);
+		if (method->nag_builder)
+			g_object_unref (method->nag_builder);
+		g_free (method->ca_cert_chooser);
+		if (method->builder)
+			g_object_unref (method->builder);
+		if (method->ui_widget)
+			g_object_unref (method->ui_widget);
+
+		g_slice_free1 (method->obj_size, method);
+	}
+}
+
+gboolean
+eap_method_validate_filepicker (GtkBuilder *builder,
+                                const char *name,
+                                guint32 item_type,
+                                const char *password,
+                                NMSetting8021xCKFormat *out_format)
+{
+	GtkWidget *widget;
+	char *filename;
+	NMSetting8021x *setting;
+	gboolean success = FALSE;
+	GError *error = NULL;
+
+	if (item_type == TYPE_PRIVATE_KEY) {
+		g_return_val_if_fail (password != NULL, FALSE);
+		g_return_val_if_fail (strlen (password), FALSE);
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, name));
+	g_assert (widget);
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	if (!filename)
+		return (item_type == TYPE_CA_CERT) ? TRUE : FALSE;
+
+	if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+		goto out;
+
+	setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+	if (item_type == TYPE_PRIVATE_KEY) {
+		if (!nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, &error)) {
+			g_warning ("Error: couldn't verify private key: %d %s",
+			           error ? error->code : -1, error ? error->message : "(none)");
+			g_clear_error (&error);
+		} else
+			success = TRUE;
+	} else if (item_type == TYPE_CLIENT_CERT) {
+		if (!nm_setting_802_1x_set_client_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, &error)) {
+			g_warning ("Error: couldn't verify client certificate: %d %s",
+			           error ? error->code : -1, error ? error->message : "(none)");
+			g_clear_error (&error);
+		} else
+			success = TRUE;
+	} else if (item_type == TYPE_CA_CERT) {
+		if (!nm_setting_802_1x_set_ca_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, &error)) {
+			g_warning ("Error: couldn't verify CA certificate: %d %s",
+			           error ? error->code : -1, error ? error->message : "(none)");
+			g_clear_error (&error);
+		} else
+			success = TRUE;
+	} else
+		g_warning ("%s: invalid item type %d.", __func__, item_type);
+
+	g_object_unref (setting);
+
+out:
+	g_free (filename);
+	return success;
+}
+
+static const char *
+find_tag (const char *tag, const char *buf, gsize len)
+{
+	gsize i, taglen;
+
+	taglen = strlen (tag);
+	if (len < taglen)
+		return NULL;
+
+	for (i = 0; i < len - taglen + 1; i++) {
+		if (memcmp (buf + i, tag, taglen) == 0)
+			return buf + i;
+	}
+	return NULL;
+}
+
+static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
+static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
+static const char *pem_pkcs8_enc_key_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+static const char *pem_pkcs8_dec_key_begin = "-----BEGIN PRIVATE KEY-----";
+static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
+static const char *proc_type_tag = "Proc-Type: 4,ENCRYPTED";
+static const char *dek_info_tag = "DEK-Info:";
+
+static gboolean
+file_has_extension (const char *filename, const char *extensions[])
+{
+	char *p, *ext;
+	int i = 0;
+	gboolean found = FALSE;
+
+	p = strrchr (filename, '.');
+	if (!p)
+		return FALSE;
+
+	ext = g_ascii_strdown (p, -1);
+	if (ext) {
+		while (extensions[i]) {
+			if (!strcmp (ext, extensions[i++])) {
+				found = TRUE;
+				break;
+			}
+		}
+	}
+	g_free (ext);
+
+	return found;
+}
+
+static gboolean
+pem_file_is_encrypted (const char *buffer, gsize bytes_read)
+{
+	/* Check if the private key is encrypted or not by looking for the
+	 * old OpenSSL-style proc-type and dec-info tags.
+	 */
+	if (find_tag (proc_type_tag, (const char *) buffer, bytes_read)) {
+		if (find_tag (dek_info_tag, (const char *) buffer, bytes_read))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+file_is_der_or_pem (const char *filename,
+                    gboolean privkey,
+                    gboolean *out_privkey_encrypted)
+{
+	int fd;
+	unsigned char buffer[8192];
+	ssize_t bytes_read;
+	gboolean success = FALSE;
+
+	fd = open (filename, O_RDONLY);
+	if (fd < 0)
+		return FALSE;
+
+	bytes_read = read (fd, buffer, sizeof (buffer) - 1);
+	if (bytes_read < 400)  /* needs to be lower? */
+		goto out;
+	buffer[bytes_read] = '\0';
+
+	/* Check for DER signature */
+	if (bytes_read > 2 && buffer[0] == 0x30 && buffer[1] == 0x82) {
+		success = TRUE;
+		goto out;
+	}
+
+	/* Check for PEM signatures */
+	if (privkey) {
+		if (find_tag (pem_rsa_key_begin, (const char *) buffer, bytes_read)) {
+			success = TRUE;
+			if (out_privkey_encrypted)
+				*out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+			goto out;
+		}
+
+		if (find_tag (pem_dsa_key_begin, (const char *) buffer, bytes_read)) {
+			success = TRUE;
+			if (out_privkey_encrypted)
+				*out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+			goto out;
+		}
+
+		if (find_tag (pem_pkcs8_enc_key_begin, (const char *) buffer, bytes_read)) {
+			success = TRUE;
+			if (out_privkey_encrypted)
+				*out_privkey_encrypted = TRUE;
+			goto out;
+		}
+
+		if (find_tag (pem_pkcs8_dec_key_begin, (const char *) buffer, bytes_read)) {
+			success = TRUE;
+			if (out_privkey_encrypted)
+				*out_privkey_encrypted = FALSE;
+			goto out;
+		}
+	} else {
+		if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
+			success = TRUE;
+			goto out;
+		}
+	}
+
+out:
+	close (fd);
+	return success;
+}
+
+static gboolean
+default_filter_privkey (const GtkFileFilterInfo *filter_info, gpointer user_data)
+{
+	const char *extensions[] = { ".der", ".pem", ".p12", NULL };
+	gboolean require_encrypted = !!user_data;
+	gboolean is_encrypted = TRUE;
+
+	if (!filter_info->filename)
+		return FALSE;
+
+	if (!file_has_extension (filter_info->filename, extensions))
+		return FALSE;
+
+	if (   !file_is_der_or_pem (filter_info->filename, TRUE, &is_encrypted)
+	    && !nm_utils_file_is_pkcs12 (filter_info->filename))
+		return FALSE;
+
+	return require_encrypted ? is_encrypted : TRUE;
+}
+
+static gboolean
+default_filter_cert (const GtkFileFilterInfo *filter_info, gpointer user_data)
+{
+	const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL };
+
+	if (!filter_info->filename)
+		return FALSE;
+
+	if (!file_has_extension (filter_info->filename, extensions))
+		return FALSE;
+
+	if (!file_is_der_or_pem (filter_info->filename, FALSE, NULL))
+		return FALSE;
+
+	return TRUE;
+}
+
+GtkFileFilter *
+eap_method_default_file_chooser_filter_new (gboolean privkey)
+{
+	GtkFileFilter *filter;
+
+	filter = gtk_file_filter_new ();
+	if (privkey) {
+		gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter_privkey, NULL, NULL);
+		gtk_file_filter_set_name (filter, _("DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12)"));
+	} else {
+		gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter_cert, NULL, NULL);
+		gtk_file_filter_set_name (filter, _("DER or PEM certificates (*.der, *.pem, *.crt, *.cer)"));
+	}
+	return filter;
+}
+
+gboolean
+eap_method_is_encrypted_private_key (const char *path)
+{
+	GtkFileFilterInfo info = { .filename = path };
+
+	return default_filter_privkey (&info, (gpointer) TRUE);
+}
+
diff --git a/panels/network/wireless-security/eap-method.h b/panels/network/wireless-security/eap-method.h
new file mode 100644
index 0000000..d2933c7
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.h
@@ -0,0 +1,128 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2012 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_H
+#define EAP_METHOD_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <nm-connection.h>
+#include <nm-setting-8021x.h>
+
+typedef struct _EAPMethod EAPMethod;
+
+typedef void        (*EMAddToSizeGroupFunc) (EAPMethod *method, GtkSizeGroup *group);
+typedef void        (*EMFillConnectionFunc) (EAPMethod *method, NMConnection *connection);
+typedef void        (*EMUpdateSecretsFunc)  (EAPMethod *method, NMConnection *connection);
+typedef void        (*EMDestroyFunc)        (EAPMethod *method);
+typedef gboolean    (*EMValidateFunc)       (EAPMethod *method);
+
+struct _EAPMethod {
+	guint32 refcount;
+	gsize obj_size;
+
+	GtkBuilder *builder;
+	GtkWidget *ui_widget;
+
+	GtkBuilder *nag_builder;
+	char *ca_cert_chooser;
+	const char *default_field;
+	GtkWidget *nag_dialog;
+
+	gboolean phase2;
+	gboolean secrets_only;
+	gboolean ignore_ca_cert;
+
+	EMAddToSizeGroupFunc add_to_size_group;
+	EMFillConnectionFunc fill_connection;
+	EMUpdateSecretsFunc update_secrets;
+	EMValidateFunc validate;
+	EMDestroyFunc destroy;
+};
+
+#define EAP_METHOD(x) ((EAPMethod *) x)
+
+
+GtkWidget *eap_method_get_widget (EAPMethod *method);
+
+gboolean eap_method_validate (EAPMethod *method);
+
+void eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group);
+
+void eap_method_fill_connection (EAPMethod *method, NMConnection *connection);
+
+void eap_method_update_secrets (EAPMethod *method, NMConnection *connection);
+
+GtkWidget * eap_method_nag_user (EAPMethod *method);
+
+EAPMethod *eap_method_ref (EAPMethod *method);
+
+void eap_method_unref (EAPMethod *method);
+
+GType eap_method_get_g_type (void);
+
+/* Below for internal use only */
+
+#include "eap-method-tls.h"
+#include "eap-method-leap.h"
+#include "eap-method-fast.h"
+#include "eap-method-ttls.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+
+EAPMethod *eap_method_init (gsize obj_size,
+                            EMValidateFunc validate,
+                            EMAddToSizeGroupFunc add_to_size_group,
+                            EMFillConnectionFunc fill_connection,
+                            EMUpdateSecretsFunc update_secrets,
+                            EMDestroyFunc destroy,
+                            const char *ui_resource,
+                            const char *ui_widget_name,
+                            const char *default_field,
+                            gboolean phase2);
+
+GtkFileFilter * eap_method_default_file_chooser_filter_new (gboolean privkey);
+
+gboolean eap_method_is_encrypted_private_key (const char *path);
+
+#define TYPE_CLIENT_CERT 0
+#define TYPE_CA_CERT     1
+#define TYPE_PRIVATE_KEY 2
+
+gboolean eap_method_validate_filepicker (GtkBuilder *builder,
+                                         const char *name,
+                                         guint32 item_type,
+                                         const char *password,
+                                         NMSetting8021xCKFormat *out_format);
+
+gboolean eap_method_nag_init (EAPMethod *method,
+                              const char *ca_cert_chooser,
+                              NMConnection *connection);
+
+void eap_method_phase2_update_secrets_helper (EAPMethod *method,
+                                              NMConnection *connection,
+                                              const char *combo_name,
+                                              guint32 column);
+
+#endif /* EAP_METHOD_H */
+
diff --git a/panels/network/wireless-security/helpers.c b/panels/network/wireless-security/helpers.c
new file mode 100644
index 0000000..5d7941d
--- /dev/null
+++ b/panels/network/wireless-security/helpers.c
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2009 Red Hat, Inc.
+ */
+
+#include "helpers.h"
+
+void
+helper_fill_secret_entry (NMConnection *connection,
+                          GtkBuilder *builder,
+                          const char *entry_name,
+                          GType setting_type,
+                          HelperSecretFunc func)
+{
+	GtkWidget *widget;
+	NMSetting *setting;
+	const char *tmp;
+
+	g_return_if_fail (connection != NULL);
+	g_return_if_fail (builder != NULL);
+	g_return_if_fail (entry_name != NULL);
+	g_return_if_fail (func != NULL);
+
+	setting = nm_connection_get_setting (connection, setting_type);
+	if (setting) {
+		tmp = (*func) (setting);
+		if (tmp) {
+			widget = GTK_WIDGET (gtk_builder_get_object (builder, entry_name));
+			g_assert (widget);
+			gtk_entry_set_text (GTK_ENTRY (widget), tmp);
+		}
+	}
+}
+
diff --git a/panels/network/wireless-security/helpers.h b/panels/network/wireless-security/helpers.h
new file mode 100644
index 0000000..75c01ea
--- /dev/null
+++ b/panels/network/wireless-security/helpers.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2009 Red Hat, Inc.
+ */
+
+#ifndef _HELPERS_H_
+#define _HELPERS_H_
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <nm-connection.h>
+#include <nm-setting.h>
+
+typedef const char * (*HelperSecretFunc)(NMSetting *);
+
+void helper_fill_secret_entry (NMConnection *connection,
+                               GtkBuilder *builder,
+                               const char *entry_name,
+                               GType setting_type,
+                               HelperSecretFunc func);
+
+#endif  /* _HELPERS_H_ */
+
diff --git a/panels/network/wireless-security/nag-user-dialog.ui b/panels/network/wireless-security/nag-user-dialog.ui
new file mode 100644
index 0000000..d821e11
--- /dev/null
+++ b/panels/network/wireless-security/nag-user-dialog.ui
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 2.6 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkDialog" id="nag_user_dialog">
+    <property name="border_width">5</property>
+    <property name="modal">True</property>
+    <property name="window_position">center</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">14</property>
+        <child>
+          <object class="GtkHBox" id="hbox5">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkImage" id="image4">
+                <property name="visible">True</property>
+                <property name="yalign">0</property>
+                <property name="stock">gtk-dialog-warning</property>
+                <property name="icon-size">6</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="content_vbox">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkLabel" id="content_label">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="yalign">0</property>
+                    <property name="label">alert text</property>
+                    <property name="use_markup">True</property>
+                    <property name="wrap">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="ignore_checkbox">
+                    <property name="label" translatable="yes">Don't _warn me again</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="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="ignore_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment3">
+                    <property name="visible">True</property>
+                    <property name="xscale">0</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <object class="GtkHBox" id="hbox4">
+                        <property name="visible">True</property>
+                        <property name="spacing">2</property>
+                        <child>
+                          <object class="GtkImage" id="image3">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-no</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label57">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">No</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="change_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment2">
+                    <property name="visible">True</property>
+                    <property name="xscale">0</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <object class="GtkHBox" id="hbox3">
+                        <property name="visible">True</property>
+                        <property name="spacing">2</property>
+                        <child>
+                          <object class="GtkImage" id="image2">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-ok</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label56">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Yes</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-9">ignore_button</action-widget>
+      <action-widget response="-8">change_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/wireless-security.c b/panels/network/wireless-security/wireless-security.c
new file mode 100644
index 0000000..42093ea
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.c
@@ -0,0 +1,554 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-setting-8021x.h>
+
+#include "wireless-security.h"
+#include "wireless-security-resources.h"
+#include "eap-method.h"
+
+GType
+wireless_security_get_g_type (void)
+{
+	static GType type_id = 0;
+
+	if (!type_id) {
+		g_resources_register (wireless_security_get_resource ());
+
+		type_id = g_boxed_type_register_static ("WirelessSecurity",
+		                                        (GBoxedCopyFunc) wireless_security_ref,
+		                                        (GBoxedFreeFunc) wireless_security_unref);
+	}
+
+	return type_id;
+}
+
+GtkWidget *
+wireless_security_get_widget (WirelessSecurity *sec)
+{
+	g_return_val_if_fail (sec != NULL, NULL);
+
+	return sec->ui_widget;
+}
+
+void
+wireless_security_set_changed_notify (WirelessSecurity *sec,
+                                      WSChangedFunc func,
+                                      gpointer user_data)
+{
+	g_return_if_fail (sec != NULL);
+
+	sec->changed_notify = func;
+	sec->changed_notify_data = user_data;
+}
+
+void
+wireless_security_changed_cb (GtkWidget *ignored, gpointer user_data)
+{
+	WirelessSecurity *sec = WIRELESS_SECURITY (user_data);
+
+	if (sec->changed_notify)
+		(*(sec->changed_notify)) (sec, sec->changed_notify_data);
+}
+
+gboolean
+wireless_security_validate (WirelessSecurity *sec, const GByteArray *ssid)
+{
+	g_return_val_if_fail (sec != NULL, FALSE);
+
+	g_assert (sec->validate);
+	return (*(sec->validate)) (sec, ssid);
+}
+
+void
+wireless_security_add_to_size_group (WirelessSecurity *sec, GtkSizeGroup *group)
+{
+	g_return_if_fail (sec != NULL);
+	g_return_if_fail (group != NULL);
+
+	g_assert (sec->add_to_size_group);
+	return (*(sec->add_to_size_group)) (sec, group);
+}
+
+void
+wireless_security_fill_connection (WirelessSecurity *sec,
+                                   NMConnection *connection)
+{
+	g_return_if_fail (sec != NULL);
+	g_return_if_fail (connection != NULL);
+
+	g_assert (sec->fill_connection);
+	return (*(sec->fill_connection)) (sec, connection);
+}
+
+void
+wireless_security_update_secrets (WirelessSecurity *sec, NMConnection *connection)
+{
+	g_return_if_fail (sec != NULL);
+	g_return_if_fail (connection != NULL);
+
+	if (sec->update_secrets)
+		sec->update_secrets (sec, connection);
+}
+
+WirelessSecurity *
+wireless_security_ref (WirelessSecurity *sec)
+{
+	g_return_val_if_fail (sec != NULL, NULL);
+	g_return_val_if_fail (sec->refcount > 0, NULL);
+
+	sec->refcount++;
+	return sec;
+}
+
+void
+wireless_security_unref (WirelessSecurity *sec)
+{
+	g_return_if_fail (sec != NULL);
+	g_return_if_fail (sec->refcount > 0);
+
+	sec->refcount--;
+	if (sec->refcount == 0) {
+		if (sec->destroy)
+			sec->destroy (sec);
+
+		if (sec->builder)
+			g_object_unref (sec->builder);
+		if (sec->ui_widget)
+			g_object_unref (sec->ui_widget);
+		g_slice_free1 (sec->obj_size, sec);
+	}
+}
+
+WirelessSecurity *
+wireless_security_init (gsize obj_size,
+                        WSValidateFunc validate,
+                        WSAddToSizeGroupFunc add_to_size_group,
+                        WSFillConnectionFunc fill_connection,
+                        WSUpdateSecretsFunc update_secrets,
+                        WSDestroyFunc destroy,
+                        const char *ui_resource,
+                        const char *ui_widget_name,
+                        const char *default_field)
+{
+	WirelessSecurity *sec;
+	GError *error = NULL;
+
+	g_return_val_if_fail (obj_size > 0, NULL);
+	g_return_val_if_fail (ui_resource != NULL, NULL);
+	g_return_val_if_fail (ui_widget_name != NULL, NULL);
+
+	sec = g_slice_alloc0 (obj_size);
+	g_assert (sec);
+
+	sec->refcount = 1;
+	sec->obj_size = obj_size;
+
+	sec->validate = validate;
+	sec->add_to_size_group = add_to_size_group;
+	sec->fill_connection = fill_connection;
+	sec->update_secrets = update_secrets;
+	sec->destroy = destroy;
+	sec->default_field = default_field;
+
+	sec->builder = gtk_builder_new ();
+	if (!gtk_builder_add_from_resource (sec->builder, ui_resource, &error)) {
+		g_warning ("Couldn't load UI builder file %s: %s",
+		           ui_resource, error->message);
+		g_error_free (error);
+		wireless_security_unref (sec);
+		return NULL;
+	}
+
+	sec->ui_widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, ui_widget_name));
+	if (!sec->ui_widget) {
+		g_warning ("Couldn't load UI widget '%s' from UI file %s",
+		           ui_widget_name, ui_resource);
+		wireless_security_unref (sec);
+		return NULL;
+	}
+	g_object_ref_sink (sec->ui_widget);
+
+	sec->adhoc_compatible = TRUE;
+
+	return sec;
+}
+
+GtkWidget *
+wireless_security_nag_user (WirelessSecurity *sec)
+{
+	g_return_val_if_fail (sec != NULL, NULL);
+
+	if (sec->nag_user)
+		return (*(sec->nag_user)) (sec);
+	return NULL;
+}
+
+gboolean
+wireless_security_adhoc_compatible (WirelessSecurity *sec)
+{
+	g_return_val_if_fail (sec != NULL, FALSE);
+
+	return sec->adhoc_compatible;
+}
+
+void
+wireless_security_clear_ciphers (NMConnection *connection)
+{
+	NMSettingWirelessSecurity *s_wireless_sec;
+
+	g_return_if_fail (connection != NULL);
+
+	s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+	g_assert (s_wireless_sec);
+
+	nm_setting_wireless_security_clear_protos (s_wireless_sec);
+	nm_setting_wireless_security_clear_pairwise (s_wireless_sec);
+	nm_setting_wireless_security_clear_groups (s_wireless_sec);
+}
+
+void
+ws_802_1x_add_to_size_group (WirelessSecurity *sec,
+                             GtkSizeGroup *size_group,
+                             const char *label_name,
+                             const char *combo_name)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, label_name));
+	g_assert (widget);
+	gtk_size_group_add_widget (size_group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	eap_method_add_to_size_group (eap, size_group);
+	eap_method_unref (eap);
+}
+
+gboolean
+ws_802_1x_validate (WirelessSecurity *sec, const char *combo_name)
+{
+	GtkWidget *widget;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap = NULL;
+	gboolean valid = FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+	g_assert (widget);
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+	valid = eap_method_validate (eap);
+	eap_method_unref (eap);
+	return valid;
+}
+
+void
+ws_802_1x_auth_combo_changed (GtkWidget *combo,
+                              WirelessSecurity *sec,
+                              const char *vbox_name,
+                              GtkSizeGroup *size_group)
+{
+	GtkWidget *vbox;
+	EAPMethod *eap = NULL;
+	GList *elt, *children;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkWidget *eap_widget;
+	GtkWidget *eap_default_widget = NULL;
+
+	vbox = GTK_WIDGET (gtk_builder_get_object (sec->builder, vbox_name));
+	g_assert (vbox);
+
+	/* Remove any previous wireless security widgets */
+	children = gtk_container_get_children (GTK_CONTAINER (vbox));
+	for (elt = children; elt; elt = g_list_next (elt))
+		gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+	gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_widget = eap_method_get_widget (eap);
+	g_assert (eap_widget);
+	gtk_widget_unparent (eap_widget);
+
+	if (size_group)
+		eap_method_add_to_size_group (eap, size_group);
+	gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+	/* Refocus the EAP method's default widget */
+	if (eap->default_field) {
+		eap_default_widget = GTK_WIDGET (gtk_builder_get_object (eap->builder, eap->default_field));
+		if (eap_default_widget)
+			gtk_widget_grab_focus (eap_default_widget);
+	}
+
+	eap_method_unref (eap);
+
+	wireless_security_changed_cb (combo, WIRELESS_SECURITY (sec));
+}
+
+GtkWidget *
+ws_802_1x_auth_combo_init (WirelessSecurity *sec,
+                           const char *combo_name,
+                           const char *combo_label,
+                           GCallback auth_combo_changed_cb,
+                           NMConnection *connection,
+                           gboolean is_editor,
+                           gboolean secrets_only)
+{
+	GtkWidget *combo, *widget;
+	GtkListStore *auth_model;
+	GtkTreeIter iter;
+	EAPMethodSimple *em_md5;
+	EAPMethodTLS *em_tls;
+	EAPMethodLEAP *em_leap;
+	EAPMethodFAST *em_fast;
+	EAPMethodTTLS *em_ttls;
+	EAPMethodPEAP *em_peap;
+	const char *default_method = NULL, *ctype = NULL;
+	int active = -1, item = 0;
+	gboolean wired = FALSE;
+
+	/* Grab the default EAP method out of the security object */
+	if (connection) {
+		NMSettingConnection *s_con;
+		NMSetting8021x *s_8021x;
+
+		s_con = nm_connection_get_setting_connection (connection);
+		if (s_con)
+			ctype = nm_setting_connection_get_connection_type (s_con);
+		if (   (g_strcmp0 (ctype, NM_SETTING_WIRED_SETTING_NAME) == 0)
+		    || nm_connection_get_setting_wired (connection))
+			wired = TRUE;
+
+		s_8021x = nm_connection_get_setting_802_1x (connection);
+		if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+			default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+	}
+
+	auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+	if (wired) {
+		em_md5 = eap_method_simple_new (sec,
+		                                connection,
+		                                EAP_METHOD_SIMPLE_TYPE_MD5,
+		                                FALSE,
+		                                is_editor,
+		                                secrets_only);
+		gtk_list_store_append (auth_model, &iter);
+		gtk_list_store_set (auth_model, &iter,
+			                AUTH_NAME_COLUMN, _("MD5"),
+			                AUTH_METHOD_COLUMN, em_md5,
+			                -1);
+		eap_method_unref (EAP_METHOD (em_md5));
+		if (default_method && (active < 0) && !strcmp (default_method, "md5"))
+			active = item;
+		item++;
+	}
+
+	em_tls = eap_method_tls_new (sec, connection, FALSE, secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    AUTH_NAME_COLUMN, _("TLS"),
+	                    AUTH_METHOD_COLUMN, em_tls,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_tls));
+	if (default_method && (active < 0) && !strcmp (default_method, "tls"))
+		active = item;
+	item++;
+
+	if (!wired) {
+		em_leap = eap_method_leap_new (sec, connection, secrets_only);
+		gtk_list_store_append (auth_model, &iter);
+		gtk_list_store_set (auth_model, &iter,
+		                    AUTH_NAME_COLUMN, _("LEAP"),
+		                    AUTH_METHOD_COLUMN, em_leap,
+		                    -1);
+		eap_method_unref (EAP_METHOD (em_leap));
+		if (default_method && (active < 0) && !strcmp (default_method, "leap"))
+			active = item;
+		item++;
+	}
+
+	em_fast = eap_method_fast_new (sec, connection, is_editor, secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    AUTH_NAME_COLUMN, _("FAST"),
+	                    AUTH_METHOD_COLUMN, em_fast,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_fast));
+	if (default_method && (active < 0) && !strcmp (default_method, "fast"))
+		active = item;
+	item++;
+
+	em_ttls = eap_method_ttls_new (sec, connection, is_editor, secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    AUTH_NAME_COLUMN, _("Tunneled TLS"),
+	                    AUTH_METHOD_COLUMN, em_ttls,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_ttls));
+	if (default_method && (active < 0) && !strcmp (default_method, "ttls"))
+		active = item;
+	item++;
+
+	em_peap = eap_method_peap_new (sec, connection, is_editor, secrets_only);
+	gtk_list_store_append (auth_model, &iter);
+	gtk_list_store_set (auth_model, &iter,
+	                    AUTH_NAME_COLUMN, _("Protected EAP (PEAP)"),
+	                    AUTH_METHOD_COLUMN, em_peap,
+	                    -1);
+	eap_method_unref (EAP_METHOD (em_peap));
+	if (default_method && (active < 0) && !strcmp (default_method, "peap"))
+		active = item;
+	item++;
+
+	combo = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+	g_assert (combo);
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+	g_object_unref (G_OBJECT (auth_model));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active < 0 ? 0 : (guint32) active);
+
+	g_signal_connect (G_OBJECT (combo), "changed", auth_combo_changed_cb, sec);
+
+	if (secrets_only) {
+		gtk_widget_hide (combo);
+		widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_label));
+		gtk_widget_hide (widget);
+	}
+
+	return combo;
+}
+
+void
+ws_802_1x_fill_connection (WirelessSecurity *sec,
+                           const char *combo_name,
+                           NMConnection *connection)
+{
+	GtkWidget *widget;
+	NMSettingWireless *s_wireless;
+	NMSettingWirelessSecurity *s_wireless_sec;
+	NMSetting8021x *s_8021x;
+	EAPMethod *eap = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	s_wireless = nm_connection_get_setting_wireless (connection);
+	g_assert (s_wireless);
+
+	g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+	/* Blow away the old wireless security setting by adding a clear one */
+	s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+	/* Blow away the old 802.1x setting by adding a clear one */
+	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+	nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+	g_assert (eap);
+
+	eap_method_fill_connection (eap, connection);
+	eap_method_unref (eap);
+}
+
+void
+ws_802_1x_update_secrets (WirelessSecurity *sec,
+                          const char *combo_name,
+                          NMConnection *connection)
+{
+	GtkWidget *widget;
+	EAPMethod *eap = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_if_fail (sec != NULL);
+	g_return_if_fail (combo_name != NULL);
+	g_return_if_fail (connection != NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+	g_return_if_fail (widget != NULL);
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+
+	/* Let each EAP method try to update its secrets */
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+			if (eap) {
+				eap_method_update_secrets (eap, connection);
+				eap_method_unref (eap);
+			}
+		} while (gtk_tree_model_iter_next (model, &iter));
+	}
+}
+
+GtkWidget *
+ws_802_1x_nag_user (WirelessSecurity *sec,
+                    const char *combo_name)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EAPMethod *eap = NULL;
+	GtkWidget *widget;	
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+	gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+	g_return_val_if_fail (eap != NULL, NULL);
+
+	widget = eap_method_nag_user (eap);
+	eap_method_unref (eap);
+	return widget;
+}
+
diff --git a/panels/network/wireless-security/wireless-security.gresource.xml b/panels/network/wireless-security/wireless-security.gresource.xml
new file mode 100644
index 0000000..76329de
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.gresource.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/control-center/network">
+    <file preprocess="xml-stripblanks">eap-method-leap.ui</file>
+    <file preprocess="xml-stripblanks">eap-method-fast.ui</file>
+    <file preprocess="xml-stripblanks">eap-method-peap.ui</file>
+    <file preprocess="xml-stripblanks">eap-method-simple.ui</file>
+    <file preprocess="xml-stripblanks">eap-method-tls.ui</file>
+    <file preprocess="xml-stripblanks">eap-method-ttls.ui</file>
+    <file preprocess="xml-stripblanks">nag-user-dialog.ui</file>
+    <file preprocess="xml-stripblanks">ws-dynamic-wep.ui</file>
+    <file preprocess="xml-stripblanks">ws-leap.ui</file>
+    <file preprocess="xml-stripblanks">ws-wep-key.ui</file>
+    <file preprocess="xml-stripblanks">ws-wpa-eap.ui</file>
+    <file preprocess="xml-stripblanks">ws-wpa-psk.ui</file>
+  </gresource>
+</gresources>
diff --git a/panels/network/wireless-security/wireless-security.h b/panels/network/wireless-security/wireless-security.h
new file mode 100644
index 0000000..23a725b
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.h
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WIRELESS_SECURITY_H
+#define WIRELESS_SECURITY_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurity WirelessSecurity;
+
+typedef void (*WSChangedFunc) (WirelessSecurity *sec, gpointer user_data);
+
+typedef void (*WSAddToSizeGroupFunc) (WirelessSecurity *sec, GtkSizeGroup *group);
+typedef void (*WSFillConnectionFunc) (WirelessSecurity *sec, NMConnection *connection);
+typedef void (*WSUpdateSecretsFunc)  (WirelessSecurity *sec, NMConnection *connection);
+typedef void (*WSDestroyFunc)        (WirelessSecurity *sec);
+typedef gboolean (*WSValidateFunc)   (WirelessSecurity *sec, const GByteArray *ssid);
+typedef GtkWidget * (*WSNagUserFunc) (WirelessSecurity *sec);
+
+struct _WirelessSecurity {
+	guint32 refcount;
+	gsize obj_size;
+	GtkBuilder *builder;
+	GtkWidget *ui_widget;
+	WSChangedFunc changed_notify;
+	gpointer changed_notify_data;
+	const char *default_field;
+	gboolean adhoc_compatible;
+
+	WSAddToSizeGroupFunc add_to_size_group;
+	WSFillConnectionFunc fill_connection;
+	WSUpdateSecretsFunc update_secrets;
+	WSValidateFunc validate;
+	WSNagUserFunc nag_user;
+	WSDestroyFunc destroy;
+};
+
+#define WIRELESS_SECURITY(x) ((WirelessSecurity *) x)
+
+
+GtkWidget *wireless_security_get_widget (WirelessSecurity *sec);
+
+void wireless_security_set_changed_notify (WirelessSecurity *sec,
+                                           WSChangedFunc func,
+                                           gpointer user_data);
+
+gboolean wireless_security_validate (WirelessSecurity *sec, const GByteArray *ssid);
+
+void wireless_security_add_to_size_group (WirelessSecurity *sec,
+                                          GtkSizeGroup *group);
+
+void wireless_security_fill_connection (WirelessSecurity *sec,
+                                        NMConnection *connection);
+
+void wireless_security_update_secrets (WirelessSecurity *sec,
+                                       NMConnection *connection);
+
+GtkWidget * wireless_security_nag_user (WirelessSecurity *sec);
+
+gboolean wireless_security_adhoc_compatible (WirelessSecurity *sec);
+
+WirelessSecurity *wireless_security_ref (WirelessSecurity *sec);
+
+void wireless_security_unref (WirelessSecurity *sec);
+
+GType wireless_security_get_g_type (void);
+
+/* Below for internal use only */
+
+#include "ws-wep-key.h"
+#include "ws-wpa-psk.h"
+#include "ws-leap.h"
+#include "ws-wpa-eap.h"
+#include "ws-dynamic-wep.h"
+
+WirelessSecurity *wireless_security_init (gsize obj_size,
+                                          WSValidateFunc validate,
+                                          WSAddToSizeGroupFunc add_to_size_group,
+                                          WSFillConnectionFunc fill_connection,
+                                          WSUpdateSecretsFunc update_secrets,
+                                          WSDestroyFunc destroy,
+                                          const char *ui_resource,
+                                          const char *ui_widget_name,
+                                          const char *default_field);
+
+void wireless_security_changed_cb (GtkWidget *entry, gpointer user_data);
+
+void wireless_security_clear_ciphers (NMConnection *connection);
+
+#define AUTH_NAME_COLUMN   0
+#define AUTH_METHOD_COLUMN 1
+
+GtkWidget *ws_802_1x_auth_combo_init (WirelessSecurity *sec,
+                                      const char *combo_name,
+                                      const char *combo_label,
+                                      GCallback auth_combo_changed_cb,
+                                      NMConnection *connection,
+                                      gboolean is_editor,
+                                      gboolean secrets_only);
+
+void ws_802_1x_auth_combo_changed (GtkWidget *combo,
+                                   WirelessSecurity *sec,
+                                   const char *vbox_name,
+                                   GtkSizeGroup *size_group);
+
+gboolean ws_802_1x_validate (WirelessSecurity *sec, const char *combo_name);
+
+void ws_802_1x_add_to_size_group (WirelessSecurity *sec,
+                                  GtkSizeGroup *size_group,
+                                  const char *label_name,
+                                  const char *combo_name);
+
+void ws_802_1x_fill_connection (WirelessSecurity *sec,
+                                const char *combo_name,
+                                NMConnection *connection);
+
+void ws_802_1x_update_secrets (WirelessSecurity *sec,
+                               const char *combo_name,
+                               NMConnection *connection);
+
+GtkWidget * ws_802_1x_nag_user (WirelessSecurity *sec,
+                                const char *combo_name);
+
+#endif /* WIRELESS_SECURITY_H */
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.c b/panels/network/wireless-security/ws-dynamic-wep.c
new file mode 100644
index 0000000..481196a
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.c
@@ -0,0 +1,143 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "eap-method.h"
+
+struct _WirelessSecurityDynamicWEP {
+	WirelessSecurity parent;
+
+	GtkSizeGroup *size_group;
+};
+
+static void
+destroy (WirelessSecurity *parent)
+{
+	WirelessSecurityDynamicWEP *sec = (WirelessSecurityDynamicWEP *) parent;
+
+	if (sec->size_group)
+		g_object_unref (sec->size_group);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+	return ws_802_1x_validate (parent, "dynamic_wep_auth_combo");
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+	WirelessSecurityDynamicWEP *sec = (WirelessSecurityDynamicWEP *) parent;
+
+	if (sec->size_group)
+		g_object_unref (sec->size_group);
+	sec->size_group = g_object_ref (group);
+
+	ws_802_1x_add_to_size_group (parent,
+	                             sec->size_group,
+	                             "dynamic_wep_auth_label",
+	                             "dynamic_wep_auth_combo");
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+	NMSettingWirelessSecurity *s_wireless_sec;
+
+	ws_802_1x_fill_connection (parent, "dynamic_wep_auth_combo", connection);
+
+	s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+	g_assert (s_wireless_sec);
+
+	g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", NULL);
+
+	nm_setting_wireless_security_add_pairwise (s_wireless_sec, "wep40");
+	nm_setting_wireless_security_add_pairwise (s_wireless_sec, "wep104");
+	nm_setting_wireless_security_add_group (s_wireless_sec, "wep40");
+	nm_setting_wireless_security_add_group (s_wireless_sec, "wep104");
+}
+
+static void
+auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	WirelessSecurity *parent = WIRELESS_SECURITY (user_data);
+	WirelessSecurityDynamicWEP *sec = (WirelessSecurityDynamicWEP *) parent;
+
+	ws_802_1x_auth_combo_changed (combo,
+	                              parent,
+	                              "dynamic_wep_method_vbox",
+	                              sec->size_group);
+}
+
+static GtkWidget *
+nag_user (WirelessSecurity *parent)
+{
+	return ws_802_1x_nag_user (parent, "dynamic_wep_auth_combo");
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+	ws_802_1x_update_secrets (parent, "dynamic_wep_auth_combo", connection);
+}
+
+WirelessSecurityDynamicWEP *
+ws_dynamic_wep_new (NMConnection *connection,
+                    gboolean is_editor,
+                    gboolean secrets_only)
+{
+	WirelessSecurity *parent;
+	GtkWidget *widget;
+
+	parent = wireless_security_init (sizeof (WirelessSecurityDynamicWEP),
+	                                 validate,
+	                                 add_to_size_group,
+	                                 fill_connection,
+	                                 update_secrets,
+	                                 destroy,
+	                                 "/org/gnome/control-center/network/ws-dynamic-wep.ui",
+	                                 "dynamic_wep_notebook",
+	                                 NULL);
+	if (!parent)
+		return NULL;
+
+	parent->nag_user = nag_user;
+	parent->adhoc_compatible = FALSE;
+
+	widget = ws_802_1x_auth_combo_init (parent,
+	                                    "dynamic_wep_auth_combo",
+	                                    "dynamic_wep_auth_label",
+	                                    (GCallback) auth_combo_changed_cb,
+	                                    connection,
+	                                    is_editor,
+	                                    secrets_only);
+	auth_combo_changed_cb (widget, (gpointer) parent);
+
+	return (WirelessSecurityDynamicWEP *) parent;
+}
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.h b/panels/network/wireless-security/ws-dynamic-wep.h
new file mode 100644
index 0000000..54979f4
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_DYNAMIC_WEP_H
+#define WS_DYNAMIC_WEP_H
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurityDynamicWEP WirelessSecurityDynamicWEP;
+
+WirelessSecurityDynamicWEP *ws_dynamic_wep_new (NMConnection *connection,
+                                                gboolean is_editor,
+                                                gboolean secrets_only);
+
+#endif /* WS_DYNAMIC_WEP_H */
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.ui b/panels/network/wireless-security/ws-dynamic-wep.ui
new file mode 100644
index 0000000..d6bc12b
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="model7">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes"> </col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkNotebook" id="dynamic_wep_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table12">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">3</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel" id="dynamic_wep_auth_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Au_thentication</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">dynamic_wep_auth_combo</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="dynamic_wep_auth_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model7</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer7"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="dynamic_wep_method_vbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">6</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label55">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-leap.c b/panels/network/wireless-security/ws-leap.c
new file mode 100644
index 0000000..a2ddb72
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _WirelessSecurityLEAP {
+	WirelessSecurity parent;
+	gboolean new_connection;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, WirelessSecurity *sec)
+{
+	GtkWidget *widget;
+	gboolean visible;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, "leap_password_entry"));
+	g_assert (widget);
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+	GtkWidget *entry;
+	const char *text;
+
+	entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_entry"));
+	g_assert (entry);
+	text = gtk_entry_get_text (GTK_ENTRY (entry));
+	if (!text || !strlen (text))
+		return FALSE;
+
+	entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+	g_assert (entry);
+	text = gtk_entry_get_text (GTK_ENTRY (entry));
+	if (!text || !strlen (text))
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_label"));
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_label"));
+	gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+	WirelessSecurityLEAP *sec = (WirelessSecurityLEAP *) parent;
+	NMSettingWireless *s_wireless;
+	NMSettingWirelessSecurity *s_wireless_sec;
+	GtkWidget *widget;
+	const char *leap_password = NULL, *leap_username = NULL;
+
+	s_wireless = nm_connection_get_setting_wireless (connection);
+	g_assert (s_wireless);
+
+	g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+	/* Blow away the old security setting by adding a clear one */
+	s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_entry"));
+	leap_username = gtk_entry_get_text (GTK_ENTRY (widget));
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+	leap_password = gtk_entry_get_text (GTK_ENTRY (widget));
+
+	g_object_set (s_wireless_sec,
+	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+	              NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap",
+	              NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username,
+	              NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, leap_password,
+	              NULL);
+
+	/* Default to agent-owned secrets for new connections */
+	if (sec->new_connection) {
+		g_object_set (s_wireless_sec,
+		              NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+		              NULL);
+	}
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+	helper_fill_secret_entry (connection,
+	                          parent->builder,
+	                          "leap_password_entry",
+	                          NM_TYPE_SETTING_WIRELESS_SECURITY,
+	                          (HelperSecretFunc) nm_setting_wireless_security_get_leap_password);
+}
+
+WirelessSecurityLEAP *
+ws_leap_new (NMConnection *connection, gboolean secrets_only)
+{
+	WirelessSecurity *parent;
+	WirelessSecurityLEAP *sec;
+	GtkWidget *widget;
+	NMSettingWirelessSecurity *wsec = NULL;
+
+	parent = wireless_security_init (sizeof (WirelessSecurityLEAP),
+	                                 validate,
+	                                 add_to_size_group,
+	                                 fill_connection,
+	                                 update_secrets,
+	                                 NULL,
+	                                 "/org/gnome/control-center/network/ws-leap.ui",
+	                                 "leap_notebook",
+	                                 "leap_username_entry");
+	if (!parent)
+		return NULL;
+
+	if (connection) {
+		wsec = nm_connection_get_setting_wireless_security (connection);
+		if (wsec) {
+			const char *auth_alg;
+
+			/* Ignore if wireless security doesn't specify LEAP */
+			auth_alg = nm_setting_wireless_security_get_auth_alg (wsec);
+			if (!auth_alg || strcmp (auth_alg, "leap"))
+				wsec = NULL;
+		}
+	}
+
+	parent->adhoc_compatible = FALSE;
+	sec = (WirelessSecurityLEAP *) parent;
+	sec->new_connection = secrets_only ? FALSE : TRUE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  sec);
+	if (wsec)
+		update_secrets (WIRELESS_SECURITY (sec), connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  sec);
+	if (wsec)
+		gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_wireless_security_get_leap_username (wsec));
+
+	if (secrets_only)
+		gtk_widget_hide (widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_leap"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  sec);
+
+	return sec;
+}
+
diff --git a/panels/network/wireless-security/ws-leap.h b/panels/network/wireless-security/ws-leap.h
new file mode 100644
index 0000000..6f1d705
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_LEAP_H
+#define WS_LEAP_H
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurityLEAP WirelessSecurityLEAP;
+
+WirelessSecurityLEAP * ws_leap_new (NMConnection *connection, gboolean secrets_only);
+
+#endif /* WS_LEAP_H */
+
diff --git a/panels/network/wireless-security/ws-leap.ui b/panels/network/wireless-security/ws-leap.ui
new file mode 100644
index 0000000..76bca3a
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.ui
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkNotebook" id="leap_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table5">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">3</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel" id="leap_username_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Username</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">leap_username_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="leap_password_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Password</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">leap_password_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="leap_password_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="visibility">False</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="show_checkbutton_leap">
+            <property name="label" translatable="yes">Sho_w password</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="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="leap_username_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="GtkLabel1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-wep-key.c b/panels/network/wireless-security/ws-wep-key.c
new file mode 100644
index 0000000..6de18dc
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.c
@@ -0,0 +1,349 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+
+#include "wireless-security.h"
+
+struct _WirelessSecurityWEPKey {
+	WirelessSecurity parent;
+
+	NMWepKeyType type;
+	char keys[4][65];
+	guint8 cur_index;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, WirelessSecurity *sec)
+{
+	GtkWidget *widget;
+	gboolean visible;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, "wep_key_entry"));
+	g_assert (widget);
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static void
+key_index_combo_changed_cb (GtkWidget *combo, WirelessSecurity *parent)
+{
+	WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+	GtkWidget *entry;
+	const char *key;
+	int key_index;
+
+	/* Save WEP key for old key index */
+	entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+	key = gtk_entry_get_text (GTK_ENTRY (entry));
+	if (key)
+		strcpy (sec->keys[sec->cur_index], key);
+	else
+		memset (sec->keys[sec->cur_index], 0, sizeof (sec->keys[sec->cur_index]));
+
+	key_index = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+	g_return_if_fail (key_index <= 3);
+	g_return_if_fail (key_index >= 0);
+
+	/* Populate entry with key from new index */
+	gtk_entry_set_text (GTK_ENTRY (entry), sec->keys[key_index]);
+	sec->cur_index = key_index;
+
+	wireless_security_changed_cb (combo, parent);
+}
+
+static void
+destroy (WirelessSecurity *parent)
+{
+	WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+	int i;
+
+	for (i = 0; i < 4; i++)
+		memset (sec->keys[i], 0, sizeof (sec->keys[i]));
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+	WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+	GtkWidget *entry;
+	const char *key;
+	int i;
+
+	entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+	g_assert (entry);
+
+	key = gtk_entry_get_text (GTK_ENTRY (entry));
+	if (!key)
+		return FALSE;
+
+	if (sec->type == NM_WEP_KEY_TYPE_KEY) {
+		if ((strlen (key) == 10) || (strlen (key) == 26)) {
+			for (i = 0; i < strlen (key); i++) {
+				if (!isxdigit (key[i]))
+					return FALSE;
+			}
+		} else if ((strlen (key) == 5) || (strlen (key) == 13)) {
+			for (i = 0; i < strlen (key); i++) {
+				if (!isascii (key[i]))
+					return FALSE;
+			}
+		} else {
+			return FALSE;
+		}
+	} else if (sec->type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+		if (!strlen (key) || (strlen (key) > 64))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_label"));
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_label"));
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "key_index_label"));
+	gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+	WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+	NMSettingWireless *s_wireless;
+	NMSettingWirelessSecurity *s_wsec;
+	GtkWidget *widget;
+	gint auth_alg;
+	const char *key;
+	int i;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_combo"));
+	auth_alg = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+	key = gtk_entry_get_text (GTK_ENTRY (widget));
+	strcpy (sec->keys[sec->cur_index], key);
+
+	s_wireless = nm_connection_get_setting_wireless (connection);
+	g_assert (s_wireless);
+
+	g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+	/* Blow away the old security setting by adding a clear one */
+	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	nm_connection_add_setting (connection, (NMSetting *) s_wsec);
+
+	g_object_set (s_wsec,
+	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+	              NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, sec->cur_index,
+	              NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, (auth_alg == 1) ? "shared" : "open",
+	              NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, sec->type,
+	              NULL);
+
+	for (i = 0; i < 4; i++) {
+		if (strlen (sec->keys[i]))
+			nm_setting_wireless_security_set_wep_key (s_wsec, i, sec->keys[i]);
+	}
+}
+
+static void
+wep_entry_filter_cb (GtkEntry *   entry,
+                     const gchar *text,
+                     gint         length,
+                     gint *       position,
+                     gpointer     data)
+{
+	WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) data;
+	GtkEditable *editable = GTK_EDITABLE (entry);
+	int i, count = 0;
+	gchar *result;
+
+	result = g_malloc0 (length + 1);
+
+	if (sec->type == NM_WEP_KEY_TYPE_KEY) {
+		for (i = 0; i < length; i++) {
+			if (isxdigit(text[i]) || isascii(text[i]))
+				result[count++] = text[i];
+		}
+	} else if (sec->type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+		for (i = 0; i < length; i++)
+			result[count++] = text[i];
+	}
+
+	if (count > 0) {
+		g_signal_handlers_block_by_func (G_OBJECT (editable),
+			                             G_CALLBACK (wep_entry_filter_cb),
+			                             data);
+		gtk_editable_insert_text (editable, result, count, position);
+		g_signal_handlers_unblock_by_func (G_OBJECT (editable),
+			                               G_CALLBACK (wep_entry_filter_cb),
+			                               data);
+	}
+
+	g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
+	g_free (result);
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+	WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+	NMSettingWirelessSecurity *s_wsec;
+	GtkWidget *widget;
+	const char *tmp;
+	int i;
+
+	s_wsec = nm_connection_get_setting_wireless_security (connection);
+	for (i = 0; s_wsec && i < 4; i++) {
+		tmp = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+		if (tmp)
+			strcpy (sec->keys[i], tmp);
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+	if (strlen (sec->keys[sec->cur_index]))
+		gtk_entry_set_text (GTK_ENTRY (widget), sec->keys[sec->cur_index]);
+}
+
+WirelessSecurityWEPKey *
+ws_wep_key_new (NMConnection *connection,
+                NMWepKeyType type,
+                gboolean adhoc_create,
+                gboolean secrets_only)
+{
+	WirelessSecurity *parent;
+	WirelessSecurityWEPKey *sec;
+	GtkWidget *widget;
+	NMSettingWirelessSecurity *s_wsec = NULL;
+	guint8 default_key_idx = 0;
+	gboolean is_adhoc = adhoc_create;
+	gboolean is_shared_key = FALSE;
+
+	parent = wireless_security_init (sizeof (WirelessSecurityWEPKey),
+	                                 validate,
+	                                 add_to_size_group,
+	                                 fill_connection,
+	                                 update_secrets,
+	                                 destroy,
+	                                 "/org/gnome/control-center/network/ws-wep-key.ui",
+	                                 "wep_key_notebook",
+	                                 "wep_key_entry");
+	if (!parent)
+		return NULL;
+	
+	sec = (WirelessSecurityWEPKey *) parent;
+	sec->type = type;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+	g_assert (widget);
+	gtk_entry_set_width_chars (GTK_ENTRY (widget), 28);
+
+	if (connection) {
+		NMSettingWireless *s_wireless;
+		const char *mode, *auth_alg;
+
+		s_wireless = nm_connection_get_setting_wireless (connection);
+		mode = s_wireless ? nm_setting_wireless_get_mode (s_wireless) : NULL;
+		if (mode && !strcmp (mode, "adhoc"))
+			is_adhoc = TRUE;
+
+		s_wsec = nm_connection_get_setting_wireless_security (connection);
+		if (s_wsec) {
+			auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+			if (auth_alg && !strcmp (auth_alg, "shared"))
+				is_shared_key = TRUE;
+		}
+	}
+
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  sec);
+	g_signal_connect (G_OBJECT (widget), "insert-text",
+	                  (GCallback) wep_entry_filter_cb,
+	                  sec);
+	if (sec->type == NM_WEP_KEY_TYPE_KEY)
+		gtk_entry_set_max_length (GTK_ENTRY (widget), 26);
+	else if (sec->type == NM_WEP_KEY_TYPE_PASSPHRASE)
+		gtk_entry_set_max_length (GTK_ENTRY (widget), 64);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "key_index_combo"));
+	if (connection && s_wsec)
+		default_key_idx = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
+
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), default_key_idx);
+	sec->cur_index = default_key_idx;
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) key_index_combo_changed_cb,
+	                  sec);
+
+	/* Key index is useless with adhoc networks */
+	if (is_adhoc || secrets_only) {
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "key_index_label"));
+		gtk_widget_hide (widget);
+	}
+
+	/* Fill the key entry with the key for that index */
+	if (connection)
+		update_secrets (WIRELESS_SECURITY (sec), connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_wep"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  sec);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_combo"));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), is_shared_key ? 1 : 0);
+
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  sec);
+
+	/* Don't show auth method for adhoc (which always uses open-system) or
+	 * when in "simple" mode.
+	 */
+	if (is_adhoc || secrets_only) {
+		/* Ad-Hoc connections can't use Shared Key auth */
+		if (is_adhoc)
+			gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+		gtk_widget_hide (widget);
+		widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_label"));
+		gtk_widget_hide (widget);
+	}
+
+	return sec;
+}
+
diff --git a/panels/network/wireless-security/ws-wep-key.h b/panels/network/wireless-security/ws-wep-key.h
new file mode 100644
index 0000000..fdd70da
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_WEP_KEY_H
+#define WS_WEP_KEY_H
+
+#include <nm-setting-wireless-security.h>
+
+typedef struct _WirelessSecurityWEPKey WirelessSecurityWEPKey;
+
+WirelessSecurityWEPKey *ws_wep_key_new (NMConnection *connection,
+                                        NMWepKeyType type,
+                                        gboolean adhoc_create,
+                                        gboolean secrets_only);
+
+#endif /* WS_WEP_KEY_H */
+
diff --git a/panels/network/wireless-security/ws-wep-key.ui b/panels/network/wireless-security/ws-wep-key.ui
new file mode 100644
index 0000000..b50aa62
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.ui
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="model4">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">1 (Default)</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">2</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">3</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">4</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="model3">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Open System</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Shared Key</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkNotebook" id="wep_key_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="table6">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">4</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="wep_key_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Key</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">wep_key_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="wep_key_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="visibility">False</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label31">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="show_checkbutton_wep">
+            <property name="label" translatable="yes">Sho_w key</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="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="auth_method_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Au_thentication</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">auth_method_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="auth_method_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model3</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer3"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="key_index_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">WEP inde_x</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">key_index_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="key_index_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model4</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer4"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="label23">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-eap.c b/panels/network/wireless-security/ws-wpa-eap.c
new file mode 100644
index 0000000..313c483
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.c
@@ -0,0 +1,139 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "eap-method.h"
+
+struct _WirelessSecurityWPAEAP {
+	WirelessSecurity parent;
+
+	GtkSizeGroup *size_group;
+};
+
+
+static void
+destroy (WirelessSecurity *parent)
+{
+	WirelessSecurityWPAEAP *sec = (WirelessSecurityWPAEAP *) parent;
+
+	if (sec->size_group)
+		g_object_unref (sec->size_group);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+	return ws_802_1x_validate (parent, "wpa_eap_auth_combo");
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+	WirelessSecurityWPAEAP *sec = (WirelessSecurityWPAEAP *) parent;
+
+	if (sec->size_group)
+		g_object_unref (sec->size_group);
+	sec->size_group = g_object_ref (group);
+
+	ws_802_1x_add_to_size_group (parent,
+	                             sec->size_group,
+	                             "wpa_eap_auth_label",
+	                             "wpa_eap_auth_combo");
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+	NMSettingWirelessSecurity *s_wireless_sec;
+
+	ws_802_1x_fill_connection (parent, "wpa_eap_auth_combo", connection);
+
+	s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+	g_assert (s_wireless_sec);
+
+	g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
+}
+
+static void
+auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+	WirelessSecurity *parent = WIRELESS_SECURITY (user_data);
+	WirelessSecurityWPAEAP *sec = (WirelessSecurityWPAEAP *) parent;
+
+	ws_802_1x_auth_combo_changed (combo,
+	                              parent,
+	                              "wpa_eap_method_vbox",
+	                              sec->size_group);
+}
+
+static GtkWidget *
+nag_user (WirelessSecurity *parent)
+{
+	return ws_802_1x_nag_user (parent, "wpa_eap_auth_combo");
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+	ws_802_1x_update_secrets (parent, "wpa_eap_auth_combo", connection);
+}
+
+WirelessSecurityWPAEAP *
+ws_wpa_eap_new (NMConnection *connection,
+                gboolean is_editor,
+                gboolean secrets_only)
+{
+	WirelessSecurity *parent;
+	GtkWidget *widget;
+
+	parent = wireless_security_init (sizeof (WirelessSecurityWPAEAP),
+	                                 validate,
+	                                 add_to_size_group,
+	                                 fill_connection,
+	                                 update_secrets,
+	                                 destroy,
+	                                 "/org/gnome/control-center/network/ws-wpa-eap.ui",
+	                                 "wpa_eap_notebook",
+	                                 NULL);
+	if (!parent)
+		return NULL;
+
+	parent->nag_user = nag_user;
+	parent->adhoc_compatible = FALSE;
+
+	widget = ws_802_1x_auth_combo_init (parent,
+	                                    "wpa_eap_auth_combo",
+	                                    "wpa_eap_auth_label",
+	                                    (GCallback) auth_combo_changed_cb,
+	                                    connection,
+	                                    is_editor,
+	                                    secrets_only);
+	auth_combo_changed_cb (widget, parent);
+
+	return (WirelessSecurityWPAEAP *) parent;
+}
+
diff --git a/panels/network/wireless-security/ws-wpa-eap.h b/panels/network/wireless-security/ws-wpa-eap.h
new file mode 100644
index 0000000..5c8faea
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_WPA_EAP_H
+#define WS_WPA_EAP_H
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurityWPAEAP WirelessSecurityWPAEAP;
+
+WirelessSecurityWPAEAP * ws_wpa_eap_new (NMConnection *connection,
+                                         gboolean is_editor,
+                                         gboolean secrets_only);
+
+#endif /* WS_WPA_EAP_H */
+
diff --git a/panels/network/wireless-security/ws-wpa-eap.ui b/panels/network/wireless-security/ws-wpa-eap.ui
new file mode 100644
index 0000000..5d71936
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.ui
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="model5">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes"> </col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkNotebook" id="wpa_eap_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="wpa_eap_table">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">2</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="wpa_eap_auth_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Au_thentication</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">wpa_eap_auth_combo</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="wpa_eap_auth_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="model">model5</property>
+            <child>
+              <object class="GtkCellRendererText" id="renderer5"/>
+              <attributes>
+                <attribute name="text">0</attribute>
+              </attributes>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="wpa_eap_method_vbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="GtkLabel3">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-psk.c b/panels/network/wireless-security/ws-wpa-psk.c
new file mode 100644
index 0000000..2075ce4
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.c
@@ -0,0 +1,200 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "helpers.h"
+
+#define WPA_PMK_LEN 32
+
+struct _WirelessSecurityWPAPSK {
+	WirelessSecurity parent;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, WirelessSecurity *sec)
+{
+	GtkWidget *widget;
+	gboolean visible;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, "wpa_psk_entry"));
+	g_assert (widget);
+
+	visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+	gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+	GtkWidget *entry;
+	const char *key;
+	guint32 len;
+	int i;
+
+	entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+	g_assert (entry);
+
+	key = gtk_entry_get_text (GTK_ENTRY (entry));
+	len = strlen (key);
+	if ((len < 8) || (len > 64))
+		return FALSE;
+
+	if (len == 64) {
+		/* Hex PSK */
+		for (i = 0; i < len; i++) {
+			if (!isxdigit (key[i]))
+				return FALSE;
+		}
+	}
+
+	/* passphrase can be between 8 and 63 characters inclusive */
+
+	return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_type_label"));
+	gtk_size_group_add_widget (group, widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_label"));
+	gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+	GtkWidget *widget;
+	const char *key;
+	NMSettingWireless *s_wireless;
+	NMSettingWirelessSecurity *s_wireless_sec;
+	const char *mode;
+	gboolean is_adhoc = FALSE;
+
+	s_wireless = nm_connection_get_setting_wireless (connection);
+	g_assert (s_wireless);
+
+	mode = nm_setting_wireless_get_mode (s_wireless);
+	if (mode && !strcmp (mode, "adhoc"))
+		is_adhoc = TRUE;
+
+	g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+	/* Blow away the old security setting by adding a clear one */
+	s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+	key = gtk_entry_get_text (GTK_ENTRY (widget));
+	g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
+
+	wireless_security_clear_ciphers (connection);
+	if (is_adhoc) {
+		/* Ad-Hoc settings as specified by the supplicant */
+		g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL);
+		nm_setting_wireless_security_add_proto (s_wireless_sec, "wpa");
+		nm_setting_wireless_security_add_pairwise (s_wireless_sec, "none");
+
+		/* Ad-hoc can only have _one_ group cipher... default to TKIP to be more
+		 * compatible for now.  Maybe we'll support selecting CCMP later.
+		 */
+		nm_setting_wireless_security_add_group (s_wireless_sec, "tkip");
+	} else {
+		g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL);
+
+		/* Just leave ciphers and protocol empty, the supplicant will
+		 * figure that out magically based on the AP IEs and card capabilities.
+		 */
+	}
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+	helper_fill_secret_entry (connection,
+	                          parent->builder,
+	                          "wpa_psk_entry",
+	                          NM_TYPE_SETTING_WIRELESS_SECURITY,
+	                          (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+}
+
+WirelessSecurityWPAPSK *
+ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only)
+{
+	WirelessSecurity *parent;
+	WirelessSecurityWPAPSK *sec;
+	GtkWidget *widget;
+
+	parent = wireless_security_init (sizeof (WirelessSecurityWPAPSK),
+	                                 validate,
+	                                 add_to_size_group,
+	                                 fill_connection,
+	                                 update_secrets,
+	                                 NULL,
+	                                 "/org/gnome/control-center/network/ws-wpa-psk.ui",
+	                                 "wpa_psk_notebook",
+	                                 "wpa_psk_entry");
+	if (!parent)
+		return NULL;
+
+	parent->adhoc_compatible = FALSE;
+	sec = (WirelessSecurityWPAPSK *) parent;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "changed",
+	                  (GCallback) wireless_security_changed_cb,
+	                  sec);
+	gtk_entry_set_width_chars (GTK_ENTRY (widget), 28);
+
+	/* Fill secrets, if any */
+	if (connection)
+		update_secrets (WIRELESS_SECURITY (sec), connection);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_wpa"));
+	g_assert (widget);
+	g_signal_connect (G_OBJECT (widget), "toggled",
+	                  (GCallback) show_toggled_cb,
+	                  sec);
+
+	/* Hide WPA/RSN for now since this can be autodetected by NM and the
+	 * supplicant when connecting to the AP.
+	 */
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_type_combo"));
+	g_assert (widget);
+	gtk_widget_hide (widget);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_type_label"));
+	g_assert (widget);
+	gtk_widget_hide (widget);
+
+	return sec;
+}
+
diff --git a/panels/network/wireless-security/ws-wpa-psk.h b/panels/network/wireless-security/ws-wpa-psk.h
new file mode 100644
index 0000000..a89552f
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * 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 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_WPA_PSK_H
+#define WS_WPA_PSK_H
+
+typedef struct _WirelessSecurityWPAPSK WirelessSecurityWPAPSK;
+
+WirelessSecurityWPAPSK * ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only);
+
+#endif /* WS_WEP_KEY_H */
+
diff --git a/panels/network/wireless-security/ws-wpa-psk.ui b/panels/network/wireless-security/ws-wpa-psk.ui
new file mode 100644
index 0000000..5bc756a
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.ui
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkNotebook" id="wpa_psk_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="show_tabs">False</property>
+    <property name="show_border">False</property>
+    <child>
+      <object class="GtkTable" id="wpa_psk_table">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="n_rows">3</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="wpa_psk_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Password</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">wpa_psk_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="wpa_psk_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="max_length">64</property>
+            <property name="visibility">False</property>
+            <property name="activates_default">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="wpa_psk_type_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Type</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">wpa_psk_type_combo</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label32">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="show_checkbutton_wpa">
+            <property name="label" translatable="yes">Sho_w password</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.5</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"/>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="wpa_psk_type_combo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="GtkLabel2">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+</interface>



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