[gnome-control-center/setup: 2/2] More complete



commit a693366f8bbd542f9d466f63f07501b460cb495c
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed May 11 00:25:39 2011 -0400

    More complete
    
    With this commit, the network and account pages are basically
    functional. The copy-paste of the network cell renderers as well
    as various bits of the network and user panels should perhaps
    be reworked, longer-term.

 configure.ac                         |    2 +-
 setup/Makefile.am                    |   15 +-
 setup/gnome-setup-assistant.c        | 1196 +++++++++++++++++++++++++++++++++-
 setup/panel-cell-renderer-mode.c     |  145 ++++
 setup/panel-cell-renderer-mode.h     |   58 ++
 setup/panel-cell-renderer-security.c |  155 +++++
 setup/panel-cell-renderer-security.h |   66 ++
 setup/panel-cell-renderer-signal.c   |  161 +++++
 setup/panel-cell-renderer-signal.h   |   58 ++
 setup/setup.ui                       |  272 ++++++++-
 10 files changed, 2093 insertions(+), 35 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 472d419..96bc5b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,7 +91,7 @@ PKG_CHECK_MODULES(LIBGNOME_CONTROL_CENTER, $COMMON_MODULES gconf-2.0)
 PKG_CHECK_MODULES(LIBLANGUAGE, $COMMON_MODULES gnome-desktop-3.0)
 PKG_CHECK_MODULES(LIBSHORTCUTS, $COMMON_MODULES x11)
 PKG_CHECK_MODULES(SHELL, $COMMON_MODULES libgnome-menu gio-unix-2.0)
-PKG_CHECK_MODULES(SETUP, $COMMON_MODULES)
+PKG_CHECK_MODULES(SETUP, $COMMON_MODULES accountsservice)
 PKG_CHECK_MODULES(BACKGROUND_PANEL, $COMMON_MODULES libxml-2.0 gnome-desktop-3.0
                   gdk-pixbuf-2.0 >= $GDKPIXBUF_REQUIRED_VERSION)
 PKG_CHECK_MODULES(DATETIME_PANEL, $COMMON_MODULES dbus-glib-1
diff --git a/setup/Makefile.am b/setup/Makefile.am
index f76cbe1..2ad8cca 100644
--- a/setup/Makefile.am
+++ b/setup/Makefile.am
@@ -1,11 +1,18 @@
-INCLUDES = $(SETUP_CFLAGS)
+INCLUDES = \
+	$(SETUP_CFLAGS)	\
+	$(NETWORK_MANAGER_CFLAGS)
 
-LIBS = $(SETUP_LIBS)
+LIBS = \
+	$(SETUP_LIBS)	\
+	$(NETWORK_MANAGER_LIBS)
 
 bin_PROGRAMS = gnome-setup-assistant
 
-gnome_setup_assistant_sources =	\
-	gnome-setup-assistant.c
+gnome_setup_assistant_SOURCES =	\
+	gnome-setup-assistant.c \
+	panel-cell-renderer-signal.c panel-cell-renderer-signal.h \
+	panel-cell-renderer-mode.c panel-cell-renderer-mode.h \
+	panel-cell-renderer-security.c panel-cell-renderer-security.h
 
 AM_CPPFLAGS = \
 	-DGNOMELOCALEDIR="\"$(datadir)/locale\"" \
diff --git a/setup/gnome-setup-assistant.c b/setup/gnome-setup-assistant.c
index 3318638..f19b764 100644
--- a/setup/gnome-setup-assistant.c
+++ b/setup/gnome-setup-assistant.c
@@ -1,19 +1,1151 @@
+#include <config.h>
+#include <glib/gi18n.h>
+
 #include <stdlib.h>
 #include <gtk/gtk.h>
 
+#include <nm-client.h>
+#include <nm-device-wifi.h>
+#include <nm-access-point.h>
+#include <nm-utils.h>
+#include <nm-remote-settings.h>
+
+#include "panel-cell-renderer-signal.h"
+#include "panel-cell-renderer-mode.h"
+#include "panel-cell-renderer-security.h"
+
+#include <act/act-user-manager.h>
+
+
+typedef struct {
+        GtkBuilder *builder;
+        GtkAssistant *assistant;
+
+        /* network data */
+        NMClient *nm_client;
+        NMRemoteSettings *nm_settings;
+        NMDevice *nm_device;
+        GtkListStore *ap_list;
+        gboolean refreshing;
+
+        GtkTreeRowReference *row;
+        guint pulse;
+
+        /* account data */
+        ActUserManager *act_client;
+        ActUser *act_user;
+
+        gboolean valid_name;
+        gboolean valid_username;
+        gboolean valid_password;
+        ActUserPasswordMode password_mode;
+        ActUserAccountType account_type;
+
+        gboolean user_data_unsaved;
+} SetupData;
+
+#define OBJ(type,name) ((type)gtk_builder_get_object(setup->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
+/* --- Welcome page --- */
+
 static void
-prepare_cb (GtkAssistant *assi, gpointer data)
+prepare_welcome_page (SetupData *setup)
 {
-        GtkWidget *page;
-        gint n;
+        GtkWidget *widget;
+        const gchar *filename;
 
-        n = gtk_assistant_get_current_page (assi);
-        page = gtk_assistant_get_nth_page (assi, n);
+        widget = WID("welcome-image");
+        filename = UIDIR "/welcome-image.jpg";
+        if (!g_file_test (filename, G_FILE_TEST_EXISTS))
+                filename = "welcome-image.jpg";
+        gtk_image_set_from_file (GTK_IMAGE (widget), filename);
+}
 
-        gtk_assistant_set_page_complete (assi, page, TRUE);
+/* --- Network page --- */
+
+enum {
+        PANEL_WIRELESS_COLUMN_ID,
+        PANEL_WIRELESS_COLUMN_TITLE,
+        PANEL_WIRELESS_COLUMN_SORT,
+        PANEL_WIRELESS_COLUMN_STRENGTH,
+        PANEL_WIRELESS_COLUMN_MODE,
+        PANEL_WIRELESS_COLUMN_SECURITY,
+        PANEL_WIRELESS_COLUMN_ACTIVATING,
+        PANEL_WIRELESS_COLUMN_ACTIVE,
+        PANEL_WIRELESS_COLUMN_PULSE
+};
+
+static gint
+wireless_sort_cb (GtkTreeModel *model,
+                  GtkTreeIter  *a,
+                  GtkTreeIter  *b,
+                  gpointer      user_data)
+{
+        gchar *str_a;
+        gchar *str_b;
+        gint retval;
+
+        gtk_tree_model_get (model, a, PANEL_WIRELESS_COLUMN_SORT, &str_a, -1);
+        gtk_tree_model_get (model, b, PANEL_WIRELESS_COLUMN_SORT, &str_b, -1);
+
+        /* special case blank entries to the bottom */
+        if (g_strcmp0 (str_a, "") == 0) {
+                retval = 1;
+                goto out;
+        }
+        if (g_strcmp0 (str_b, "") == 0) {
+                retval = -1;
+                goto out;
+        }
+
+        retval = g_strcmp0 (str_a, str_b);
+out:
+        g_free (str_a);
+        g_free (str_b);
+
+        return retval;
+}
+
+static GPtrArray *
+get_strongest_unique_aps (const GPtrArray *aps)
+{
+        const GByteArray *ssid;
+        const GByteArray *ssid_tmp;
+        GPtrArray *unique = NULL;
+        gboolean add_ap;
+        guint i;
+        guint j;
+        NMAccessPoint *ap;
+        NMAccessPoint *ap_tmp;
+
+        /* we will have multiple entries for typical hotspots,
+        * just keep the one with the strongest signal
+        */
+        unique = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+        if (aps == NULL)
+                goto out;
+
+        for (i = 0; i < aps->len; i++) {
+                ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i));
+                ssid = nm_access_point_get_ssid (ap);
+                add_ap = TRUE;
+
+                /* get already added list */
+                for (j = 0; j < unique->len; j++) {
+                        ap_tmp = NM_ACCESS_POINT (g_ptr_array_index (unique, j));
+                        ssid_tmp = nm_access_point_get_ssid (ap_tmp);
+
+                        /* is this the same type and data? */
+                        if (nm_utils_same_ssid (ssid, ssid_tmp, TRUE)) {
+                                /* the new access point is stronger */
+                                if (nm_access_point_get_strength (ap) >
+                                    nm_access_point_get_strength (ap_tmp)) {
+                                        g_ptr_array_remove (unique, ap_tmp);
+                                        add_ap = TRUE;
+                                } else {
+                                        add_ap = FALSE;
+                                }
+                                break;
+                        }
+                }
+                if (add_ap) {
+                        g_ptr_array_add (unique, g_object_ref (ap));
+                }
+        }
+
+out:
+        return unique;
+}
+
+static guint
+get_access_point_security (NMAccessPoint *ap)
+{
+        NM80211ApFlags flags;
+        NM80211ApSecurityFlags wpa_flags;
+        NM80211ApSecurityFlags rsn_flags;
+        guint type;
+
+        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);
+
+        if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+            wpa_flags == NM_802_11_AP_SEC_NONE &&
+            rsn_flags == NM_802_11_AP_SEC_NONE)
+                type = NM_AP_SEC_NONE;
+        else if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+                 wpa_flags == NM_802_11_AP_SEC_NONE &&
+                 rsn_flags == NM_802_11_AP_SEC_NONE)
+                type = NM_AP_SEC_WEP;
+        else if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+                 wpa_flags != NM_802_11_AP_SEC_NONE &&
+                 rsn_flags != NM_802_11_AP_SEC_NONE)
+                type = NM_AP_SEC_WPA;
+        else
+                type = NM_AP_SEC_WPA2;
+
+        return type;
+}
+
+static void
+add_access_point (SetupData *setup, NMAccessPoint *ap, NMAccessPoint *active)
+{
+        const GByteArray *ssid;
+        const gchar *ssid_text;
+        const gchar *object_path;
+        GtkTreeIter iter;
+        gboolean activated, activating;
+
+        ssid = nm_access_point_get_ssid (ap);
+        object_path = nm_object_get_path (NM_OBJECT (ap));
+
+        if (ssid == NULL)
+                return;
+        ssid_text = nm_utils_escape_ssid (ssid->data, ssid->len);
+
+        if (active &&
+            nm_utils_same_ssid (ssid, nm_access_point_get_ssid (active), TRUE)) {
+                switch (nm_device_get_state (setup->nm_device))
+                {
+                case NM_DEVICE_STATE_PREPARE:
+                case NM_DEVICE_STATE_CONFIG:
+                case NM_DEVICE_STATE_NEED_AUTH:
+                case NM_DEVICE_STATE_IP_CONFIG:
+                case NM_DEVICE_STATE_SECONDARIES:
+                        activated = FALSE;
+                        activating = TRUE;
+                        break;
+                case NM_DEVICE_STATE_ACTIVATED:
+                        activated = TRUE;
+                        activating = FALSE;
+                        break;
+                default:
+                        activated = FALSE;
+                        activating = FALSE;
+                        break;
+                }
+        } else {
+                activated = FALSE;
+                activating = FALSE;
+        }
+
+        gtk_list_store_append (setup->ap_list, &iter);
+        gtk_list_store_set (setup->ap_list, &iter,
+                            PANEL_WIRELESS_COLUMN_ID, object_path,
+                            PANEL_WIRELESS_COLUMN_TITLE, ssid_text,
+                            PANEL_WIRELESS_COLUMN_SORT, ssid_text,
+                            PANEL_WIRELESS_COLUMN_STRENGTH, nm_access_point_get_strength (ap),
+                            PANEL_WIRELESS_COLUMN_MODE, nm_access_point_get_mode (ap),
+                            PANEL_WIRELESS_COLUMN_SECURITY, get_access_point_security (ap),
+                            PANEL_WIRELESS_COLUMN_ACTIVATING, activating,
+                            PANEL_WIRELESS_COLUMN_ACTIVE, activated,
+                            PANEL_WIRELESS_COLUMN_PULSE, setup->pulse,
+                            -1);
+        if (activating) {
+                GtkTreePath *path;
+                GtkTreeModel *model;
+
+                model = (GtkTreeModel*)setup->ap_list;
+                path = gtk_tree_model_get_path (model, &iter);
+                setup->row = gtk_tree_row_reference_new (model, path);
+                gtk_tree_path_free (path);
+        }
+
+}
+
+static void
+add_access_point_other (SetupData *setup)
+{
+        GtkTreeIter iter;
+
+        gtk_list_store_append (setup->ap_list, &iter);
+        gtk_list_store_set (setup->ap_list, &iter,
+                            PANEL_WIRELESS_COLUMN_ID, "ap-other...",
+                            /* TRANSLATORS: this is when the access point is not listed
+ *                           * in the dropdown (or hidden) and the user has to select
+ *                           * another entry manually */
+
+                            PANEL_WIRELESS_COLUMN_TITLE, C_("Wireless access point", "Other..."),
+                            /* always last */
+                            PANEL_WIRELESS_COLUMN_SORT, "",
+                            PANEL_WIRELESS_COLUMN_STRENGTH, 0,
+                            PANEL_WIRELESS_COLUMN_MODE, NM_802_11_MODE_UNKNOWN,
+                            PANEL_WIRELESS_COLUMN_SECURITY, NM_AP_SEC_UNKNOWN,
+                            PANEL_WIRELESS_COLUMN_ACTIVATING, FALSE,
+                            PANEL_WIRELESS_COLUMN_ACTIVE, FALSE,
+                            PANEL_WIRELESS_COLUMN_PULSE, setup->pulse,
+                            -1);
+}
+
+static void
+select_and_scroll_to_ap (SetupData *setup, NMAccessPoint *ap)
+{
+        GtkTreeModel *model;
+        GtkTreeView *tv;
+        GtkTreeViewColumn *col;
+        GtkTreeSelection *selection;
+        GtkTreeIter iter;
+        GtkTreePath *path;
+        gchar *ssid_target;
+        const GByteArray *ssid;
+        const gchar *ssid_text;
+
+        model = (GtkTreeModel *)setup->ap_list;
+
+        if (!gtk_tree_model_get_iter_first (model, &iter))
+                return;
+
+        tv = OBJ(GtkTreeView*, "network-list");
+        col = OBJ(GtkTreeViewColumn*, "network-list-column");
+        selection = OBJ(GtkTreeSelection*, "network-list-selection");
+
+        ssid = nm_access_point_get_ssid (ap);
+        ssid_text = nm_utils_escape_ssid (ssid->data, ssid->len);
+
+        do {
+                gtk_tree_model_get (model, &iter,
+                                    PANEL_WIRELESS_COLUMN_TITLE, &ssid_target,
+                                    -1);
+                if (g_strcmp0 (ssid_target, ssid_text) == 0) {
+                        g_free (ssid_target);
+                        gtk_tree_selection_select_iter (selection, &iter);
+                        path = gtk_tree_model_get_path (model, &iter);
+                        gtk_tree_view_scroll_to_cell (tv, path, col, FALSE, 0, 0);
+                        gtk_tree_path_free (path);
+                        break;
+                }
+                g_free (ssid_target);
+
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void refresh_wireless_list (SetupData *setup);
+
+static gboolean
+refresh_again (gpointer data)
+{
+        SetupData *setup = data;
+
+        refresh_wireless_list (setup);
+
+        return FALSE;
+}
+
+static void
+refresh_wireless_list (SetupData *setup)
+{
+        NMDeviceState state;
+        NMAccessPoint *active_ap;
+        NMAccessPoint *ap;
+        const GPtrArray *aps;
+        GPtrArray *unique_aps;
+        gint i;
+        GtkWidget *label;
+        GtkWidget *spinner;
+        GtkWidget *swin;
+
+        setup->refreshing = TRUE;
+
+        state = nm_device_get_state (setup->nm_device);
+
+        active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (setup->nm_device));
+
+        g_object_ref (setup->ap_list);
+        gtk_tree_view_set_model (OBJ(GtkTreeView*, "network-list"), NULL);
+        gtk_list_store_clear (setup->ap_list);
+        if (setup->row) {
+                gtk_tree_row_reference_free (setup->row);
+                setup->row = NULL;
+        }
+
+        aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (setup->nm_device));
+
+        swin = WID("network-scrolledwindow");
+        label = WID("no-network-label");
+        spinner = WID("no-network-spinner");
+
+        if (state == NM_DEVICE_STATE_UNMANAGED ||
+            state == NM_DEVICE_STATE_UNAVAILABLE) {
+                gtk_label_set_text (GTK_LABEL (label), _("Network is not available, make sure to turn airplane mode off."));
+                gtk_widget_hide (swin);
+                gtk_widget_hide (spinner);
+                gtk_widget_show (label);
+
+                goto out;
+        }
+        else if (aps == NULL || aps->len == 0) {
+                gtk_label_set_text (GTK_LABEL (label), _("Checking for available wireless networks"));
+                gtk_widget_hide (swin);
+                gtk_widget_show (spinner);
+                gtk_widget_show (label);
+                g_timeout_add_seconds (1, refresh_again, setup);
+
+                goto out;
+        }
+        else {
+                gtk_widget_show (swin);
+                gtk_widget_hide (spinner);
+                gtk_widget_hide (label);
+        }
+
+        unique_aps = get_strongest_unique_aps (aps);
+        for (i = 0; i < unique_aps->len; i++) {
+                ap = NM_ACCESS_POINT (g_ptr_array_index (unique_aps, i));
+                add_access_point (setup, ap, active_ap);
+        }
+        g_ptr_array_unref (unique_aps);
+        add_access_point_other (setup);
+
+out:
+        gtk_tree_view_set_model (OBJ(GtkTreeView*, "network-list"), (GtkTreeModel*)setup->ap_list);
+        g_object_unref (setup->ap_list);
+
+        if (active_ap)
+                select_and_scroll_to_ap (setup, active_ap);
+
+        setup->refreshing = FALSE;
+}
+
+static void
+device_state_changed (NMDevice *device, GParamSpec *pspec, SetupData *setup)
+{
+        refresh_wireless_list (setup);
+}
+
+static void
+connection_activate_cb (NMClient *client,
+                        NMActiveConnection *connection,
+                        GError *error,
+                        gpointer user_data)
+{
+        SetupData *setup = user_data;
+
+        if (connection == NULL) {
+                /* failed to activate */
+                refresh_wireless_list (setup);
+        }
+}
+
+static void
+connection_add_activate_cb (NMClient *client,
+                            NMActiveConnection *connection,
+                            const char *path,
+                            GError *error,
+                            gpointer user_data)
+{
+        connection_activate_cb (client, connection, error, user_data);
+}
+
+static void
+connect_to_hidden_network_cb (GObject *source_object, GAsyncResult *res, gpointer data)
+{
+        SetupData *setup = data;
+        GError *error = NULL;
+        GVariant *result = NULL;
+
+        result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+        if (result == NULL) {
+                g_warning ("failed to connect to hidden network: %s",
+                           error->message);
+                g_error_free (error);
+        }
+
+        refresh_wireless_list (setup);
+}
+
+static void
+connect_to_hidden_network (SetupData *setup)
+{
+        GDBusProxy *proxy;
+        GVariant *res = NULL;
+        GError *error = NULL;
+
+        /* connect to NM applet */
+        proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                               G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+                                               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                               NULL,
+                                               "org.gnome.network_manager_applet",
+                                               "/org/gnome/network_manager_applet",
+                                               "org.gnome.network_manager_applet",
+                                               NULL,
+                                               &error);
+        if (proxy == NULL) {
+                g_warning ("failed to connect to NM applet: %s",
+                           error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        /* try to show the hidden network UI */
+        g_dbus_proxy_call (proxy,
+                           "ConnectToHiddenNetwork",
+                           NULL,
+                           G_DBUS_CALL_FLAGS_NONE,
+                           5000, /* don't wait forever */
+                           NULL,
+                           connect_to_hidden_network_cb,
+                           setup);
+
+out:
+        if (proxy != NULL)
+                g_object_unref (proxy);
+        if (res != NULL)
+                g_variant_unref (res);
+}
+
+static void
+wireless_selection_changed (GtkTreeSelection *selection, SetupData *setup)
+{
+        GtkTreeModel *model;
+        GtkTreeIter iter;
+        gchar *object_path;
+        gchar *ssid_target;
+        GSList *list, *filtered, *l;
+        NMConnection *connection;
+        NMConnection *connection_to_activate;
+        NMSettingWireless *setting;
+        const GByteArray *ssid;
+        const gchar *ssid_tmp;
+
+        if (setup->refreshing)
+                return;
+
+        if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            PANEL_WIRELESS_COLUMN_ID, &object_path,
+                            PANEL_WIRELESS_COLUMN_TITLE, &ssid_target,
+                            -1);
+
+        gtk_list_store_set (setup->ap_list, &iter,
+                            PANEL_WIRELESS_COLUMN_ACTIVATING, TRUE,
+                            -1);
+
+        if (g_strcmp0 (object_path, "ap-other...") == 0) {
+                connect_to_hidden_network (setup);
+                goto out;
+        }
+
+        list = nm_remote_settings_list_connections (setup->nm_settings);
+        filtered = nm_device_filter_connections (setup->nm_device, list);
+
+        connection_to_activate = NULL;
+
+        for (l = filtered; l; l = l->next) {
+                connection = NM_CONNECTION (l->data);
+                setting = nm_connection_get_setting_wireless (connection);
+                if (!NM_IS_SETTING_WIRELESS (setting))
+                        continue;
+
+                ssid = nm_setting_wireless_get_ssid (setting);
+                if (ssid == NULL)
+                        continue;
+                ssid_tmp = nm_utils_escape_ssid (ssid->data, ssid->len);
+                if (g_strcmp0 (ssid_target, ssid_tmp) == 0) {
+                        connection_to_activate = connection;
+                        break;
+                }
+        }
+        g_slist_free (list);
+        g_slist_free (filtered);
+
+        if (connection_to_activate != NULL) {
+                nm_client_activate_connection (setup->nm_client,
+                                               connection_to_activate,
+                                               setup->nm_device, NULL,
+                                               connection_activate_cb, setup);
+                goto out;
+        }
+
+        nm_client_add_and_activate_connection (setup->nm_client,
+                                               NULL,
+                                               setup->nm_device, object_path,
+                                               connection_add_activate_cb, setup);
+
+out:
+        g_free (object_path);
+        g_free (ssid_target);
+
+        refresh_wireless_list (setup);
+}
+
+static void
+connection_state_changed (NMActiveConnection *c, GParamSpec *pspec, SetupData *setup)
+{
+        refresh_wireless_list (setup);
+}
+
+static void
+active_connections_changed (NMClient *client, GParamSpec *pspec, SetupData *setup)
+{
+        const GPtrArray *connections;
+        int i;
+
+        connections = nm_client_get_active_connections (client);
+        for (i = 0; connections && (i < connections->len); i++) {
+                NMActiveConnection *connection;
+
+                connection = g_ptr_array_index (connections, i);
+                if (!g_object_get_data (G_OBJECT (connection), "has-state-changed-handler")) {
+                        g_signal_connect (connection, "notify::state",
+                                          G_CALLBACK (connection_state_changed), setup);
+                        g_object_set_data (G_OBJECT (connection), "has-state-changed-handler", GINT_TO_POINTER (1));
+                }
+        }
+
+        refresh_wireless_list (setup);
+}
+
+static gboolean
+bump_pulse (gpointer data)
+{
+        SetupData *setup = data;
+        GtkTreeIter iter;
+        GtkTreePath *path;
+        GtkTreeModel *model;
+
+        setup->pulse++;
+
+        if (!setup->refreshing &&
+            gtk_tree_row_reference_valid (setup->row)) {
+                model = (GtkTreeModel *)setup->ap_list;
+                path = gtk_tree_row_reference_get_path (setup->row);
+                gtk_tree_model_get_iter (model, &iter, path);
+                gtk_tree_path_free (path);
+                gtk_list_store_set (setup->ap_list, &iter,
+                                    PANEL_WIRELESS_COLUMN_PULSE, setup->pulse,
+                                    -1);
+        }
+
+        return TRUE;
+}
+
+static void
+prepare_network_page (SetupData *setup)
+{
+        GtkTreeViewColumn *col;
+        GtkCellRenderer *cell;
+        GtkTreeSortable *sortable;
+        GtkTreeSelection *selection;
+        const GPtrArray *devices;
+        NMDevice *device;
+        gint i;
+        DBusGConnection *bus;
+        GError *error;
+
+        col = OBJ(GtkTreeViewColumn*, "network-list-column");
+
+        cell = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (col), cell, FALSE);
+        /* black small diamond */
+        g_object_set (cell, "text", "\342\254\251", NULL);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (col), cell,
+                                        "visible", PANEL_WIRELESS_COLUMN_ACTIVE,
+                                        NULL);
+        cell = gtk_cell_renderer_spinner_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (col), cell, FALSE);
+        gtk_cell_area_cell_set (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col)), cell, "align", FALSE, NULL);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (col), cell,
+                                        "active", PANEL_WIRELESS_COLUMN_ACTIVATING,
+                                        "visible", PANEL_WIRELESS_COLUMN_ACTIVATING,
+                                        "pulse", PANEL_WIRELESS_COLUMN_PULSE,
+                                        NULL);
+        g_timeout_add (80, bump_pulse, setup);
+
+        cell = gtk_cell_renderer_text_new ();
+        g_object_set (cell, "width-chars", 45, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (col), cell, TRUE);
+        gtk_cell_area_cell_set (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col)), cell, "align", TRUE, NULL);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (col), cell,
+                                        "text", PANEL_WIRELESS_COLUMN_TITLE,
+                                        NULL);
+
+        cell = panel_cell_renderer_mode_new ();
+        gtk_cell_renderer_set_padding (cell, 4, 0);
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (col), cell, FALSE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (col), cell,
+                                        "mode", PANEL_WIRELESS_COLUMN_MODE,
+                                        NULL);
+
+        cell = panel_cell_renderer_security_new ();
+        gtk_cell_renderer_set_padding (cell, 4, 0);
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (col), cell, FALSE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (col), cell,
+                                        "security", PANEL_WIRELESS_COLUMN_SECURITY,
+                                        NULL);
+
+        cell = panel_cell_renderer_signal_new ();
+        gtk_cell_renderer_set_padding (cell, 4, 0);
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (col), cell, FALSE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (col), cell,
+                                        "signal", PANEL_WIRELESS_COLUMN_STRENGTH,
+                                        NULL);
+
+        setup->ap_list = OBJ(GtkListStore *, "liststore-wireless");
+        sortable = GTK_TREE_SORTABLE (setup->ap_list);
+        gtk_tree_sortable_set_sort_column_id (sortable,
+                                              PANEL_WIRELESS_COLUMN_SORT,
+                                              GTK_SORT_ASCENDING);
+        gtk_tree_sortable_set_sort_func (sortable,
+                                         PANEL_WIRELESS_COLUMN_SORT,
+                                         wireless_sort_cb,
+                                         sortable,
+                                         NULL);
+
+        setup->nm_client = nm_client_new ();
+
+        g_signal_connect (setup->nm_client, "notify::active-connections",
+                          G_CALLBACK (active_connections_changed), setup);
+
+        devices = nm_client_get_devices (setup->nm_client);
+        if (devices) {
+                for (i = 0; i < devices->len; i++) {
+                        device = g_ptr_array_index (devices, i);
+
+                        if (!nm_device_get_managed (device))
+                                continue;
+
+                        if (nm_device_get_device_type (device) == NM_DEVICE_TYPE_WIFI) {
+                                /* FIXME deal with multiple, dynamic devices */
+                                setup->nm_device = device;
+                                g_signal_connect (G_OBJECT (device), "notify::state",
+                                                  G_CALLBACK (device_state_changed), setup);
+                                break;
+                        }
+                }
+        }
+
+        if (setup->nm_device == NULL) {
+                GtkWidget *swin;
+                GtkWidget *label;
+                GtkWidget *spinner;
+
+                swin = WID("network-scrolledwindow");
+                label = WID("no-network-label");
+                spinner = WID("no-network-spinner");
+
+                gtk_widget_hide (swin);
+                gtk_widget_hide (spinner);
+
+                gtk_label_set_text (GTK_LABEL (label), _("No network devices found"));
+                gtk_widget_show (label);
+
+                goto out;
+        }
+
+        error = NULL;
+        bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (!bus) {
+                g_warning ("Error connecting to system D-Bus: %s",
+                           error->message);
+                g_error_free (error);
+        }
+        setup->nm_settings = nm_remote_settings_new (bus);
+
+        selection = OBJ(GtkTreeSelection*, "network-list-selection");
+
+        g_signal_connect (selection, "changed",
+                          G_CALLBACK (wireless_selection_changed), setup);
+
+        refresh_wireless_list (setup);
+
+out: ;
+}
+
+/* --- Account page --- */
+
+static void
+update_account_page_status (SetupData *setup)
+{
+        gtk_assistant_set_page_complete (setup->assistant, WID("account-page"),
+                                         setup->valid_name &&
+                                         setup->valid_username &&
+                                         (setup->valid_password ||
+                                          setup->password_mode == ACT_USER_PASSWORD_MODE_NONE));
+}
+
+static void
+fullname_changed (GtkWidget *w, GParamSpec *pspec, SetupData *setup)
+{
+        setup->valid_name = strlen (gtk_entry_get_text (GTK_ENTRY (w))) > 0;
+        setup->user_data_unsaved = TRUE;
+
+g_print ("fullname changed\n");
+        update_account_page_status (setup);
+}
+
+static void
+username_changed (GtkWidget *w, GParamSpec *pspec, SetupData *setup)
+{
+        setup->valid_username = strlen (gtk_entry_get_text (GTK_ENTRY (w))) > 0;
+        setup->user_data_unsaved = TRUE;
+
+g_print ("username changed\n");
+        update_account_page_status (setup);
+}
+
+static void
+password_check_changed (GtkWidget *w, GParamSpec *pspec, SetupData *setup)
+{
+        GtkWidget *password_entry;
+        GtkWidget *confirm_entry;
+        gboolean need_password;
+
+        need_password = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+
+        if (need_password) {
+                setup->password_mode = ACT_USER_PASSWORD_MODE_REGULAR;
+                setup->valid_password = FALSE;
+        }
+        else {
+                setup->password_mode = ACT_USER_PASSWORD_MODE_NONE;
+                setup->valid_password = TRUE;
+        }
+
+        password_entry = WID("account-password-entry");
+        confirm_entry = WID("account-confirm-entry");
+
+        gtk_entry_set_text (GTK_ENTRY (password_entry), "");
+        gtk_entry_set_text (GTK_ENTRY (confirm_entry), "");
+        gtk_widget_set_sensitive (password_entry, need_password);
+        gtk_widget_set_sensitive (confirm_entry, need_password);
+
+        setup->user_data_unsaved = TRUE;
+        update_account_page_status (setup);
+}
+
+static void
+admin_check_changed (GtkWidget *w, GParamSpec *pspec, SetupData *setup)
+{
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) {
+                setup->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
+        }
+        else {
+                setup->account_type = ACT_USER_ACCOUNT_TYPE_STANDARD;
+        }
+
+        setup->user_data_unsaved = TRUE;
+        update_account_page_status (setup);
+}
+
+static gboolean
+query_tooltip (GtkWidget  *widget,
+               gint        x,
+               gint        y,
+               gboolean    keyboard_mode,
+               GtkTooltip *tooltip,
+               gpointer    user_data)
+{
+        gchar *tip;
+
+        if (GTK_ENTRY_ICON_SECONDARY == gtk_entry_get_icon_at_pos (GTK_ENTRY (widget), x, y)) {
+                tip = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget),
+                                                       GTK_ENTRY_ICON_SECONDARY);
+                gtk_tooltip_set_text (tooltip, tip);
+                g_free (tip);
+
+                return TRUE;
+        }
+        else {
+                return FALSE;
+        }
+}
+
+static void
+icon_released (GtkEntry             *entry,
+              GtkEntryIconPosition  pos,
+              GdkEvent             *event,
+              gpointer              user_data)
+{
+        GtkSettings *settings;
+        gint timeout;
+
+        settings = gtk_widget_get_settings (GTK_WIDGET (entry));
+
+        g_object_get (settings, "gtk-tooltip-timeout", &timeout, NULL);
+        g_object_set (settings, "gtk-tooltip-timeout", 1, NULL);
+        gtk_tooltip_trigger_tooltip_query (gtk_widget_get_display (GTK_WIDGET (entry)));
+        g_object_set (settings, "gtk-tooltip-timeout", timeout, NULL);
+}
+
+static void
+set_entry_validation_error (GtkEntry    *entry,
+                            const gchar *text)
+{
+        g_object_set (entry, "caps-lock-warning", FALSE, NULL);
+        gtk_entry_set_icon_from_stock (entry,
+                                       GTK_ENTRY_ICON_SECONDARY,
+                                       GTK_STOCK_DIALOG_ERROR);
+        gtk_entry_set_icon_activatable (entry,
+                                        GTK_ENTRY_ICON_SECONDARY,
+                                        TRUE);
+        g_signal_connect (entry, "icon-release",
+                          G_CALLBACK (icon_released), FALSE);
+        g_signal_connect (entry, "query-tooltip",
+                          G_CALLBACK (query_tooltip), NULL);
+        g_object_set (entry, "has-tooltip", TRUE, NULL);
+        gtk_entry_set_icon_tooltip_text (entry,
+                                         GTK_ENTRY_ICON_SECONDARY,
+                                         text);
+}
+
+static void
+clear_entry_validation_error (GtkEntry *entry)
+{
+        gboolean warning;
+
+        g_object_get (entry, "caps-lock-warning", &warning, NULL);
+
+        if (warning)
+                return;
+
+        g_object_set (entry, "has-tooltip", FALSE, NULL);
+        gtk_entry_set_icon_from_pixbuf (entry,
+                                        GTK_ENTRY_ICON_SECONDARY,
+                                        NULL);
+        g_object_set (entry, "caps-lock-warning", TRUE, NULL);
+}
+
+#define MIN_PASSWORD_LEN 6
+
+static void
+update_password_entries (SetupData *setup)
+{
+        const gchar *password;
+        const gchar *verify;
+        GtkWidget *password_entry;
+        GtkWidget *confirm_entry;
+
+        password_entry = WID("account-password-entry");
+        confirm_entry = WID("account-confirm-entry");
+        password = gtk_entry_get_text (GTK_ENTRY (password_entry));
+        verify = gtk_entry_get_text (GTK_ENTRY (confirm_entry));
+
+        /* TODO: configurable policies for acceptable passwords */
+        if (strlen (password) < MIN_PASSWORD_LEN) {
+                setup->valid_password = FALSE;
+        }
+        else if (strcmp (password, verify) != 0) {
+                setup->valid_password = FALSE;
+        }
+        else {
+                setup->valid_password = TRUE;
+        }
+}
+
+static void
+password_changed (GtkWidget *w, GParamSpec *pspec, SetupData *setup)
+{
+        update_password_entries (setup);
+
+        setup->user_data_unsaved = TRUE;
+        update_account_page_status (setup);
+}
+
+static void
+confirm_changed (GtkWidget *w, GParamSpec *pspec, SetupData *setup)
+{
+        clear_entry_validation_error (GTK_ENTRY (w));
+        update_password_entries (setup);
+
+        setup->user_data_unsaved = TRUE;
+        update_account_page_status (setup);
+}
+
+static gboolean
+confirm_entry_focus_out (GtkWidget     *entry,
+                         GdkEventFocus *event,
+                         SetupData     *setup)
+{
+        const gchar *password;
+        const gchar *verify;
+        GtkEntry *password_entry;
+        GtkEntry *confirm_entry;
+
+        password_entry = OBJ(GtkEntry*, "account-password-entry");
+        confirm_entry = OBJ(GtkEntry*, "account-confirm-entry");
+        password = gtk_entry_get_text (password_entry);
+        verify = gtk_entry_get_text (confirm_entry);
+
+        if (strlen (password) > 0 && strlen (verify) > 0) {
+                if (strlen (password) < MIN_PASSWORD_LEN) {
+                        set_entry_validation_error (confirm_entry,
+                                                    _("The new password is too short"));
+                }
+                else if (strcmp (password, verify) != 0) {
+                        set_entry_validation_error (confirm_entry,
+                                                    _("Passwords do not match"));
+                }
+                else {
+                        clear_entry_validation_error (confirm_entry);
+                }
+        }
+
+        return FALSE;
+}
+
+/* FIXME: ActUserManager should have this */
+static void
+create_user (SetupData *setup)
+{
+        GDBusConnection *connection;
+        GVariant *result;
+        const gchar *username;
+        const gchar *fullname;
+        GError *error;
+
+        username = gtk_entry_get_text (OBJ(GtkEntry*, "account-username-entry"));
+        fullname = gtk_entry_get_text (OBJ(GtkEntry*, "account-fullname-entry"));
+        connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+
+        error = NULL;
+        result = g_dbus_connection_call_sync (connection,
+                                              "org.freedesktop.Accounts",
+                                              "/org/freedesktop/Accounts",
+                                              "org.freedesktop.Accounts",
+                                              "CreateUser",
+                                              g_variant_new ("(ssi)",
+                                                             username,
+                                                             fullname,
+                                                             setup->account_type),
+                                              NULL,
+                                              G_DBUS_CALL_FLAGS_NONE,
+                                              -1,
+                                              NULL,
+                                              &error);
+        if (result == NULL) {
+                g_warning ("Failed to create user: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        g_variant_unref (result);
+
+        setup->act_user = act_user_manager_get_user (setup->act_client, username);
+
+out:
+        g_object_unref (connection);
+}
+
+static void save_account_data (SetupData *setup);
+
+gulong when_loaded;
+
+static void
+save_when_loaded (ActUser *user, GParamSpec *pspec, SetupData *setup)
+{
+        g_signal_handler_disconnect (user, when_loaded);
+        when_loaded = 0;
+
+        save_account_data (setup);
+}
+
+static void
+save_account_data (SetupData *setup)
+{
+        if (!setup->user_data_unsaved) {
+                g_print ("no unsaved account data\n");
+                return;
+        }
+
+        /* this can happen when going back */
+        if (!setup->valid_name ||
+            !setup->valid_username ||
+            !setup->valid_password) {
+                g_print ("not saving invalid account data\n");
+                return;
+        }
+
+        g_print ("saving username %s, real name %s\n",
+                 gtk_entry_get_text (OBJ (GtkEntry*, "account-username-entry")),
+                 gtk_entry_get_text (OBJ (GtkEntry*, "account-fullname-entry")));
+
+        if (setup->act_user == NULL) {
+                create_user (setup);
+        }
+
+        if (!act_user_is_loaded (setup->act_user)) {
+                if (when_loaded == 0)
+                        when_loaded = g_signal_connect (setup->act_user, "notify::is-loaded",
+                                                        G_CALLBACK (save_when_loaded), setup);
+                return;
+        }
+
+        act_user_set_real_name (setup->act_user,
+                                gtk_entry_get_text (OBJ (GtkEntry*, "account-fullname-entry")));
+        act_user_set_user_name (setup->act_user,
+                                gtk_entry_get_text (OBJ (GtkEntry*, "account-username-entry")));
+        act_user_set_account_type (setup->act_user, setup->account_type);
+        if (setup->password_mode == ACT_USER_PASSWORD_MODE_REGULAR) {
+                act_user_set_password (setup->act_user,
+                                       gtk_entry_get_text (OBJ (GtkEntry*, "account-password-entry")),
+                                       NULL);
+        }
+        else {
+                act_user_set_password_mode (setup->act_user, setup->password_mode);
+        }
+
+        setup->user_data_unsaved = FALSE;
 }
 
 static void
+prepare_account_page (SetupData *setup)
+{
+        GtkWidget *fullname_entry;
+        GtkWidget *username_entry;
+        GtkWidget *password_check;
+        GtkWidget *admin_check;
+        GtkWidget *password_entry;
+        GtkWidget *confirm_entry;
+        gboolean need_password;
+
+        fullname_entry = WID("account-fullname-entry");
+        username_entry = WID("account-username-entry");
+        password_check = WID("account-password-check");
+        admin_check = WID("account-admin-check");
+        password_entry = WID("account-password-entry");
+        confirm_entry = WID("account-confirm-entry");
+
+        setup->act_client = act_user_manager_get_default ();
+
+        setup->valid_name = FALSE;
+        setup->valid_username = FALSE;
+        setup->valid_password = TRUE;
+        setup->password_mode = ACT_USER_PASSWORD_MODE_NONE;
+        setup->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
+        setup->user_data_unsaved = FALSE;
+
+        need_password = setup->password_mode != ACT_USER_PASSWORD_MODE_NONE;
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (password_check), need_password);
+        gtk_widget_set_sensitive (password_entry, need_password);
+        gtk_widget_set_sensitive (confirm_entry, need_password);
+
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (admin_check), setup->account_type == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR);
+
+        g_signal_connect (fullname_entry, "notify::text",
+                          G_CALLBACK (fullname_changed), setup);
+        g_signal_connect (username_entry, "notify::text",
+                          G_CALLBACK (username_changed), setup);
+        g_signal_connect (password_check, "notify::active",
+                           G_CALLBACK (password_check_changed), setup);
+        g_signal_connect (admin_check, "notify::active",
+                          G_CALLBACK (admin_check_changed), setup);
+        g_signal_connect (password_entry, "notify::text",
+                          G_CALLBACK (password_changed), setup);
+        g_signal_connect (confirm_entry, "notify::text",
+                          G_CALLBACK (confirm_changed), setup);
+        g_signal_connect_after (confirm_entry, "focus-out-event",
+                                G_CALLBACK (confirm_entry_focus_out), setup);
+
+        update_account_page_status (setup);
+}
+
+/* --- Other setup --- */
+
+static void
 disable_autostart (void)
 {
         GSettings *settings;
@@ -30,45 +1162,57 @@ close_cb (GtkAssistant *assi, gpointer data)
         gtk_main_quit ();
 }
 
+static void
+prepare_cb (GtkAssistant *assi, GtkWidget *page, SetupData *setup)
+{
+        gtk_assistant_set_page_complete (assi, page, TRUE);
+        save_account_data (setup);
+}
+
+static void
+prepare_assistant (SetupData *setup)
+{
+        setup->assistant = OBJ(GtkAssistant*, "gnome-setup-assistant");
+
+        /* small hack to get rid of cancel button */
+        gtk_assistant_commit (setup->assistant);
+
+        g_signal_connect (G_OBJECT (setup->assistant), "prepare",
+                          G_CALLBACK (prepare_cb), setup);
+        g_signal_connect (G_OBJECT (setup->assistant), "close",
+                          G_CALLBACK (close_cb), NULL);
+
+        prepare_welcome_page (setup);
+        prepare_network_page (setup);
+        prepare_account_page (setup);
+}
+
 int
 main (int argc, char *argv[])
 {
-        GtkBuilder *builder;
-        GtkAssistant *assi;
-        GtkWidget *widget;
+        SetupData *setup;
         GError *error;
         const gchar *filename;
 
+        setup = g_new0 (SetupData, 1);
+
         gtk_init (&argc, &argv);
 
         filename = UIDIR "/setup.ui";
         if (!g_file_test (filename, G_FILE_TEST_EXISTS))
                 filename = "setup.ui";
 
-        builder = gtk_builder_new ();
+        setup->builder = gtk_builder_new ();
         error = NULL;
-        if (!gtk_builder_add_from_file (builder, filename, &error)) {
+        if (!gtk_builder_add_from_file (setup->builder, filename, &error)) {
                 g_error ("%s", error->message);
                 g_error_free (error);
                 exit (1);
         }
 
-        assi = (GtkAssistant *) gtk_builder_get_object (builder, "gnome-setup-assistant");
-
-        gtk_assistant_commit (assi);
-
-        g_signal_connect (G_OBJECT (assi), "prepare",
-                          G_CALLBACK (prepare_cb), NULL);
-        g_signal_connect (G_OBJECT (assi), "close",
-                          G_CALLBACK (close_cb), NULL);
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "welcome-image");
-        filename = UIDIR "/welcome-image.jpg";
-        if (!g_file_test (filename, G_FILE_TEST_EXISTS))
-                filename = "welcome-image.jpg";
-        gtk_image_set_from_file (GTK_IMAGE (widget), filename);
+        prepare_assistant (setup);
 
-        gtk_window_present (GTK_WINDOW (assi));
+        gtk_window_present (GTK_WINDOW (setup->assistant));
 
         gtk_main ();
 
diff --git a/setup/panel-cell-renderer-mode.c b/setup/panel-cell-renderer-mode.c
new file mode 100644
index 0000000..9707c70
--- /dev/null
+++ b/setup/panel-cell-renderer-mode.c
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * 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.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "nm-device.h"
+#include "panel-cell-renderer-mode.h"
+
+enum {
+        PROP_0,
+        PROP_MODE,
+        PROP_LAST
+};
+
+G_DEFINE_TYPE (PanelCellRendererMode, panel_cell_renderer_mode, GTK_TYPE_CELL_RENDERER_PIXBUF)
+
+static gpointer parent_class = NULL;
+
+/**
+ * panel_cell_renderer_mode_get_property:
+ **/
+static void
+panel_cell_renderer_mode_get_property (GObject *object, guint param_id,
+                                       GValue *value, GParamSpec *pspec)
+{
+        PanelCellRendererMode *renderer = PANEL_CELL_RENDERER_MODE (object);
+
+        switch (param_id) {
+        case PROP_MODE:
+                g_value_set_uint (value, renderer->mode);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+                break;
+        }
+}
+
+/**
+ * panel_cell_renderer_set_name:
+ **/
+static void
+panel_cell_renderer_set_name (PanelCellRendererMode *renderer)
+{
+        const gchar *icon_name = NULL;
+
+        if (renderer->mode == NM_802_11_MODE_ADHOC)
+                icon_name = "network-workgroup-symbolic";
+
+        g_object_set (renderer, "icon-name", icon_name, NULL);
+}
+
+/**
+ * panel_cell_renderer_mode_set_property:
+ **/
+static void
+panel_cell_renderer_mode_set_property (GObject *object, guint param_id,
+                                       const GValue *value, GParamSpec *pspec)
+{
+        PanelCellRendererMode *renderer = PANEL_CELL_RENDERER_MODE (object);
+
+        switch (param_id) {
+        case PROP_MODE:
+                renderer->mode = g_value_get_uint (value);
+                panel_cell_renderer_set_name (renderer);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+                break;
+        }
+}
+
+/**
+ * panel_cell_renderer_finalize:
+ **/
+static void
+panel_cell_renderer_finalize (GObject *object)
+{
+        PanelCellRendererMode *renderer;
+        renderer = PANEL_CELL_RENDERER_MODE (object);
+        g_free (renderer->icon_name);
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * panel_cell_renderer_mode_class_init:
+ **/
+static void
+panel_cell_renderer_mode_class_init (PanelCellRendererModeClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+        object_class->finalize = panel_cell_renderer_finalize;
+
+        parent_class = g_type_class_peek_parent (class);
+
+        object_class->get_property = panel_cell_renderer_mode_get_property;
+        object_class->set_property = panel_cell_renderer_mode_set_property;
+
+        g_object_class_install_property (object_class, PROP_MODE,
+                                         g_param_spec_uint ("mode", NULL,
+                                                            NULL,
+                                                            0, G_MAXUINT, 0,
+                                                            G_PARAM_READWRITE));
+}
+
+/**
+ * panel_cell_renderer_mode_init:
+ **/
+static void
+panel_cell_renderer_mode_init (PanelCellRendererMode *renderer)
+{
+        renderer->mode = 0;
+        renderer->icon_name = NULL;
+}
+
+/**
+ * panel_cell_renderer_mode_new:
+ **/
+GtkCellRenderer *
+panel_cell_renderer_mode_new (void)
+{
+        return g_object_new (PANEL_TYPE_CELL_RENDERER_MODE, NULL);
+}
+
diff --git a/setup/panel-cell-renderer-mode.h b/setup/panel-cell-renderer-mode.h
new file mode 100644
index 0000000..3dedea5
--- /dev/null
+++ b/setup/panel-cell-renderer-mode.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * 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 PANEL_CELL_RENDERER_MODE_H
+#define PANEL_CELL_RENDERER_MODE_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define PANEL_TYPE_CELL_RENDERER_MODE           (panel_cell_renderer_mode_get_type())
+#define PANEL_CELL_RENDERER_MODE(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj), PANEL_TYPE_CELL_RENDERER_MODE, PanelCellRendererMode))
+#define PANEL_CELL_RENDERER_MODE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST((cls), PANEL_TYPE_CELL_RENDERER_MODE, PanelCellRendererModeClass))
+#define PANEL_IS_CELL_RENDERER_MODE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE((obj), PANEL_TYPE_CELL_RENDERER_MODE))
+#define PANEL_IS_CELL_RENDERER_MODE_CLASS(cls)  (G_TYPE_CHECK_CLASS_TYPE((cls), PANEL_TYPE_CELL_RENDERER_MODE))
+#define PANEL_CELL_RENDERER_MODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_CELL_RENDERER_MODE, PanelCellRendererModeClass))
+
+G_BEGIN_DECLS
+
+typedef struct _PanelCellRendererMode           PanelCellRendererMode;
+typedef struct _PanelCellRendererModeClass      PanelCellRendererModeClass;
+
+struct _PanelCellRendererMode
+{
+        GtkCellRendererPixbuf    parent;
+        guint                    mode;
+        gchar                   *icon_name;
+};
+
+struct _PanelCellRendererModeClass
+{
+        GtkCellRendererPixbufClass parent_class;
+};
+
+GType            panel_cell_renderer_mode_get_type      (void);
+GtkCellRenderer *panel_cell_renderer_mode_new           (void);
+
+G_END_DECLS
+
+#endif /* PANEL_CELL_RENDERER_MODE_H */
+
diff --git a/setup/panel-cell-renderer-security.c b/setup/panel-cell-renderer-security.c
new file mode 100644
index 0000000..debce36
--- /dev/null
+++ b/setup/panel-cell-renderer-security.c
@@ -0,0 +1,155 @@
+/* -*- Security: C; tab-width: 8; indent-tabs-security: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 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.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "panel-cell-renderer-security.h"
+
+enum {
+        PROP_0,
+        PROP_SECURITY,
+        PROP_LAST
+};
+
+G_DEFINE_TYPE (PanelCellRendererSecurity, panel_cell_renderer_security, GTK_TYPE_CELL_RENDERER_PIXBUF)
+
+static gpointer parent_class = NULL;
+
+/**
+ * panel_cell_renderer_security_get_property:
+ **/
+static void
+panel_cell_renderer_security_get_property (GObject *object, guint param_id,
+                                       GValue *value, GParamSpec *pspec)
+{
+        PanelCellRendererSecurity *renderer = PANEL_CELL_RENDERER_SECURITY (object);
+
+        switch (param_id) {
+        case PROP_SECURITY:
+                g_value_set_uint (value, renderer->security);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+                break;
+        }
+}
+
+/**
+ * panel_cell_renderer_set_name:
+ **/
+static void
+panel_cell_renderer_set_name (PanelCellRendererSecurity *renderer)
+{
+        const gchar *icon_name = NULL;
+
+        if (renderer->security != NM_AP_SEC_UNKNOWN &&
+            renderer->security != NM_AP_SEC_NONE)
+                icon_name = "network-wireless-encrypted-symbolic";
+
+        if (icon_name != NULL) {
+                g_object_set (renderer,
+                              "icon-name", icon_name,
+                              "visible", TRUE,
+                              NULL);
+        } else {
+                g_object_set (renderer,
+                              "icon-name", NULL,
+                              "visible", FALSE,
+                              NULL);
+        }
+}
+
+/**
+ * panel_cell_renderer_security_set_property:
+ **/
+static void
+panel_cell_renderer_security_set_property (GObject *object, guint param_id,
+                                       const GValue *value, GParamSpec *pspec)
+{
+        PanelCellRendererSecurity *renderer = PANEL_CELL_RENDERER_SECURITY (object);
+
+        switch (param_id) {
+        case PROP_SECURITY:
+                renderer->security = g_value_get_uint (value);
+                panel_cell_renderer_set_name (renderer);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+                break;
+        }
+}
+
+/**
+ * panel_cell_renderer_finalize:
+ **/
+static void
+panel_cell_renderer_finalize (GObject *object)
+{
+        PanelCellRendererSecurity *renderer;
+        renderer = PANEL_CELL_RENDERER_SECURITY (object);
+        g_free (renderer->icon_name);
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * panel_cell_renderer_security_class_init:
+ **/
+static void
+panel_cell_renderer_security_class_init (PanelCellRendererSecurityClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+        object_class->finalize = panel_cell_renderer_finalize;
+
+        parent_class = g_type_class_peek_parent (class);
+
+        object_class->get_property = panel_cell_renderer_security_get_property;
+        object_class->set_property = panel_cell_renderer_security_set_property;
+
+        g_object_class_install_property (object_class, PROP_SECURITY,
+                                         g_param_spec_uint ("security", NULL,
+                                                            NULL,
+                                                            0, G_MAXUINT, 0,
+                                                            G_PARAM_READWRITE));
+}
+
+/**
+ * panel_cell_renderer_security_init:
+ **/
+static void
+panel_cell_renderer_security_init (PanelCellRendererSecurity *renderer)
+{
+        renderer->security = 0;
+        renderer->icon_name = NULL;
+}
+
+/**
+ * panel_cell_renderer_security_new:
+ **/
+GtkCellRenderer *
+panel_cell_renderer_security_new (void)
+{
+        return g_object_new (PANEL_TYPE_CELL_RENDERER_SECURITY, NULL);
+}
+
diff --git a/setup/panel-cell-renderer-security.h b/setup/panel-cell-renderer-security.h
new file mode 100644
index 0000000..3630a02
--- /dev/null
+++ b/setup/panel-cell-renderer-security.h
@@ -0,0 +1,66 @@
+/* -*- Security: C; tab-width: 8; indent-tabs-security: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 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 PANEL_CELL_RENDERER_SECURITY_H
+#define PANEL_CELL_RENDERER_SECURITY_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define PANEL_TYPE_CELL_RENDERER_SECURITY           (panel_cell_renderer_security_get_type())
+#define PANEL_CELL_RENDERER_SECURITY(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj), PANEL_TYPE_CELL_RENDERER_SECURITY, PanelCellRendererSecurity))
+#define PANEL_CELL_RENDERER_SECURITY_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST((cls), PANEL_TYPE_CELL_RENDERER_SECURITY, PanelCellRendererSecurityClass))
+#define PANEL_IS_CELL_RENDERER_SECURITY(obj)        (G_TYPE_CHECK_INSTANCE_TYPE((obj), PANEL_TYPE_CELL_RENDERER_SECURITY))
+#define PANEL_IS_CELL_RENDERER_SECURITY_CLASS(cls)  (G_TYPE_CHECK_CLASS_TYPE((cls), PANEL_TYPE_CELL_RENDERER_SECURITY))
+#define PANEL_CELL_RENDERER_SECURITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_CELL_RENDERER_SECURITY, PanelCellRendererSecurityClass))
+
+G_BEGIN_DECLS
+
+typedef struct _PanelCellRendererSecurity           PanelCellRendererSecurity;
+typedef struct _PanelCellRendererSecurityClass      PanelCellRendererSecurityClass;
+
+typedef enum {
+  NM_AP_SEC_UNKNOWN,
+  NM_AP_SEC_NONE,
+  NM_AP_SEC_WEP,
+  NM_AP_SEC_WPA,
+  NM_AP_SEC_WPA2
+} NMAccessPointSecurity;
+
+struct _PanelCellRendererSecurity
+{
+        GtkCellRendererPixbuf    parent;
+        guint                    security;
+        gchar                   *icon_name;
+};
+
+struct _PanelCellRendererSecurityClass
+{
+        GtkCellRendererPixbufClass parent_class;
+};
+
+GType            panel_cell_renderer_security_get_type      (void);
+GtkCellRenderer *panel_cell_renderer_security_new           (void);
+
+G_END_DECLS
+
+#endif /* PANEL_CELL_RENDERER_SECURITY_H */
+
diff --git a/setup/panel-cell-renderer-signal.c b/setup/panel-cell-renderer-signal.c
new file mode 100644
index 0000000..782526e
--- /dev/null
+++ b/setup/panel-cell-renderer-signal.c
@@ -0,0 +1,161 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-signal: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * 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.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "panel-cell-renderer-signal.h"
+
+enum {
+        PROP_0,
+        PROP_SIGNAL,
+        PROP_LAST
+};
+
+G_DEFINE_TYPE (PanelCellRendererSignal, panel_cell_renderer_signal, GTK_TYPE_CELL_RENDERER_PIXBUF)
+
+static gpointer parent_class = NULL;
+
+/**
+ * panel_cell_renderer_signal_get_property:
+ **/
+static void
+panel_cell_renderer_signal_get_property (GObject *object, guint param_id,
+                                       GValue *value, GParamSpec *pspec)
+{
+        PanelCellRendererSignal *renderer = PANEL_CELL_RENDERER_SIGNAL (object);
+
+        switch (param_id) {
+        case PROP_SIGNAL:
+                g_value_set_uint (value, renderer->signal);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+                break;
+        }
+}
+
+/**
+ * panel_cell_renderer_set_name:
+ **/
+static void
+panel_cell_renderer_set_name (PanelCellRendererSignal *renderer)
+{
+        const gchar *icon_name = NULL;
+        GIcon *icon;
+
+        /* the 'Other...' entry */
+        if (renderer->signal == 0) {
+                g_object_set (renderer, "gicon", NULL, NULL);
+                return;
+        }
+
+        if (renderer->signal < 20)
+                icon_name = "network-wireless-signal-none-symbolic";
+        else if (renderer->signal < 40)
+                icon_name = "network-wireless-signal-weak-symbolic";
+        else if (renderer->signal < 50)
+                icon_name = "network-wireless-signal-ok-symbolic";
+        else if (renderer->signal < 80)
+                icon_name = "network-wireless-signal-good-symbolic";
+        else
+                icon_name = "network-wireless-signal-excellent-symbolic";
+
+        icon = g_themed_icon_new_with_default_fallbacks (icon_name);
+        g_object_set (renderer, "gicon", icon, NULL);
+        g_object_unref (icon);
+}
+
+/**
+ * panel_cell_renderer_signal_set_property:
+ **/
+static void
+panel_cell_renderer_signal_set_property (GObject *object, guint param_id,
+                                       const GValue *value, GParamSpec *pspec)
+{
+        PanelCellRendererSignal *renderer = PANEL_CELL_RENDERER_SIGNAL (object);
+
+        switch (param_id) {
+        case PROP_SIGNAL:
+                renderer->signal = g_value_get_uint (value);
+                panel_cell_renderer_set_name (renderer);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+                break;
+        }
+}
+
+/**
+ * panel_cell_renderer_finalize:
+ **/
+static void
+panel_cell_renderer_finalize (GObject *object)
+{
+        PanelCellRendererSignal *renderer;
+        renderer = PANEL_CELL_RENDERER_SIGNAL (object);
+        g_free (renderer->icon_name);
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * panel_cell_renderer_signal_class_init:
+ **/
+static void
+panel_cell_renderer_signal_class_init (PanelCellRendererSignalClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+        object_class->finalize = panel_cell_renderer_finalize;
+
+        parent_class = g_type_class_peek_parent (class);
+
+        object_class->get_property = panel_cell_renderer_signal_get_property;
+        object_class->set_property = panel_cell_renderer_signal_set_property;
+
+        g_object_class_install_property (object_class, PROP_SIGNAL,
+                                         g_param_spec_uint ("signal", NULL,
+                                                            NULL,
+                                                            0, G_MAXUINT, 0,
+                                                            G_PARAM_READWRITE));
+}
+
+/**
+ * panel_cell_renderer_signal_init:
+ **/
+static void
+panel_cell_renderer_signal_init (PanelCellRendererSignal *renderer)
+{
+        renderer->signal = 0;
+        renderer->icon_name = NULL;
+}
+
+/**
+ * panel_cell_renderer_signal_new:
+ **/
+GtkCellRenderer *
+panel_cell_renderer_signal_new (void)
+{
+        return g_object_new (PANEL_TYPE_CELL_RENDERER_SIGNAL, NULL);
+}
+
diff --git a/setup/panel-cell-renderer-signal.h b/setup/panel-cell-renderer-signal.h
new file mode 100644
index 0000000..b2d54db
--- /dev/null
+++ b/setup/panel-cell-renderer-signal.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-signal: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * 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 PANEL_CELL_RENDERER_SIGNAL_H
+#define PANEL_CELL_RENDERER_SIGNAL_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define PANEL_TYPE_CELL_RENDERER_SIGNAL                 (panel_cell_renderer_signal_get_type())
+#define PANEL_CELL_RENDERER_SIGNAL(obj)                 (G_TYPE_CHECK_INSTANCE_CAST((obj), PANEL_TYPE_CELL_RENDERER_SIGNAL, PanelCellRendererSignal))
+#define PANEL_CELL_RENDERER_SIGNAL_CLASS(cls)           (G_TYPE_CHECK_CLASS_CAST((cls), PANEL_TYPE_CELL_RENDERER_SIGNAL, PanelCellRendererSignalClass))
+#define PANEL_IS_CELL_RENDERER_SIGNAL(obj)              (G_TYPE_CHECK_INSTANCE_TYPE((obj), PANEL_TYPE_CELL_RENDERER_SIGNAL))
+#define PANEL_IS_CELL_RENDERER_SIGNAL_CLASS(cls)        (G_TYPE_CHECK_CLASS_TYPE((cls), PANEL_TYPE_CELL_RENDERER_SIGNAL))
+#define PANEL_CELL_RENDERER_SIGNAL_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_CELL_RENDERER_SIGNAL, PanelCellRendererSignalClass))
+
+G_BEGIN_DECLS
+
+typedef struct _PanelCellRendererSignal         PanelCellRendererSignal;
+typedef struct _PanelCellRendererSignalClass    PanelCellRendererSignalClass;
+
+struct _PanelCellRendererSignal
+{
+        GtkCellRendererPixbuf    parent;
+        guint                    signal;
+        gchar                   *icon_name;
+};
+
+struct _PanelCellRendererSignalClass
+{
+        GtkCellRendererPixbufClass parent_class;
+};
+
+GType            panel_cell_renderer_signal_get_type    (void);
+GtkCellRenderer *panel_cell_renderer_signal_new         (void);
+
+G_END_DECLS
+
+#endif /* PANEL_CELL_RENDERER_SIGNAL_H */
+
diff --git a/setup/setup.ui b/setup/setup.ui
index 2eca0d9..0fb95f8 100644
--- a/setup/setup.ui
+++ b/setup/setup.ui
@@ -1,6 +1,19 @@
 <?xml version="1.0"?>
 <interface>
   <requires lib="gtk+" version="3.0"/>
+  <object class="GtkListStore" id="liststore-wireless">
+    <columns>
+      <column type="gchararray"/> <!-- column-name id -->
+      <column type="gchararray"/> <!-- column-name title -->
+      <column type="gchararray"/> <!-- column-name sortable -->
+      <column type="guint"/>      <!-- column-name strength -->
+      <column type="guint"/>      <!-- column-name mode -->
+      <column type="guint"/>      <!-- column-name security -->
+      <column type="gboolean"/>   <!-- column-name activating -->
+      <column type="gboolean"/>   <!-- column-name active -->
+      <column type="guint"/>      <!-- column-name pulse -->
+    </columns>
+  </object>
   <object class="GtkAssistant" id="gnome-setup-assistant">
     <!-- interface-naming-policy toplevel-contextual -->
     <property name="border-width">12</property>
@@ -8,6 +21,7 @@
     <property name="icon_name">preferences-system</property>
     <property name="visible">False</property>
     <property name="deletable">False</property>
+    <property name="resizable">False</property>
     <child>
       <object class="GtkBox" id="welcome-page">
         <property name="visible">True</property>
@@ -19,6 +33,8 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Welcome to GNOME</property>
             <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
               <attribute name="scale" value="1.2"/>
@@ -28,6 +44,8 @@
         <child>
           <object class="GtkImage" id="welcome-image">
             <property name="visible">True</property>
+            <property name="halign">start</property>
+            <property name="valign">start</property>
             <property name="file">welcome-image.jpg</property>
           </object>
         </child>
@@ -36,6 +54,10 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Now let's set up some essentials for your account.</property>
             <property name="halign">start</property>
+            <property name="xalign">0.0</property>
+            <property name="wrap">True</property>
+            <property name="margin-top">12</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
             </attributes>
@@ -48,31 +70,112 @@
       </packing>
     </child>
     <child>
-      <object class="GtkBox" id="network-page">
+      <object class="GtkGrid" id="network-page">
         <property name="visible">True</property>
-        <property name="border_width">12</property>
+        <property name="border-width">12</property>
         <property name="orientation">vertical</property>
-        <property name="spacing">12</property>
         <child>
           <object class="GtkLabel" id="network-title">
             <property name="visible">True</property>
             <property name="label" translatable="yes">Connect to the Network</property>
             <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
               <attribute name="scale" value="1.2"/>
             </attributes>
           </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+            <property name="width">2</property>
+            <property name="height">1</property>
+          </packing>
         </child>
         <child>
           <object class="GtkLabel" id="network-subtitle">
             <property name="visible">True</property>
             <property name="label" translatable="yes">Select a wireless network</property>
+            <property name="margin-bottom">12</property>
             <property name="halign">start</property>
+            <property name="xalign">0.0</property>
+            <property name="wrap">True</property>
             <attributes>
               <attribute name="weight" value="bold"/>
             </attributes>
           </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>
+        <child>
+          <object class="GtkScrolledWindow" id="network-scrolledwindow">
+            <property name="visible">True</property>
+            <property name="halign">fill</property>
+            <property name="valign">fill</property>
+            <property name="margin-bottom">32</property>
+            <property name="margin-right">64</property>
+            <property name="hscrollbar-policy">never</property>
+            <property name="vscrollbar-policy">automatic</property>
+            <property name="shadow-type">in</property>
+            <child>
+              <object class="GtkTreeView" id="network-list">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="model">liststore-wireless</property>
+                <property name="headers-visible">False</property>
+                <property name="search-column">2</property>
+                <property name="show-expanders">False</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="network-list-selection">
+                    <property name="mode">single</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="network-list-column"/>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">2</property>
+            <property name="width">2</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSpinner" id="no-network-spinner">
+            <property name="visible">True</property>
+            <property name="active">True</property>
+            <property name="margin-left">6</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="GtkLabel" id="no-network-label">
+            <property name="visible">True</property>
+            <property name="label">No text</property>
+            <property name="wrap">True</property>
+            <property name="margin-left">6</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>
       </object>
       <packing>
@@ -90,12 +193,165 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Create an Account</property>
             <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
               <attribute name="scale" value="1.2"/>
             </attributes>
           </object>
         </child>
+        <child>
+          <object class="GtkGrid" id="account-grid">
+            <property name="visible">True</property>
+            <property name="row-spacing">6</property>
+            <property name="column-spacing">12</property>
+            <child>
+              <object class="GtkLabel" id="account-fullname-label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Fullname</property>
+                <property name="halign">end</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="GtkEntry" id="account-fullname-entry">
+                <property name="visible">True</property>
+                <property name="halign">start</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="account-username-label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Username</property>
+                <property name="halign">end</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="GtkEntry" id="account-username-entry">
+                <property name="visible">True</property>
+                <property name="halign">start</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="GtkCheckButton" id="account-password-check">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Require a password to use this account</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+
+            </child>
+
+            <child>
+              <object class="GtkLabel" id="account-password-label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Password</property>
+                <property name="halign">end</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="GtkEntry" id="account-password-entry">
+                <property name="visible">True</property>
+                <property name="halign">start</property>
+                <property name="visibility">False</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="account-confirm-password-label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Confirm Password</property>
+                <property name="halign">end</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="GtkEntry" id="account-confirm-entry">
+                <property name="visible">True</property>
+                <property name="halign">start</property>
+                <property name="visibility">False</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="GtkCheckButton" id="account-admin-check">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Act as administrator of this computer</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">5</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+        </child>
       </object>
       <packing>
         <property name="title" translatable="yes">Account</property>
@@ -112,6 +368,8 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Select your Location</property>
             <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
               <attribute name="scale" value="1.2"/>
@@ -134,6 +392,8 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Web Accounts</property>
             <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
               <attribute name="scale" value="1.2"/>
@@ -145,6 +405,8 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Associate your new account with your existing online accounts</property>
             <property name="halign">start</property>
+            <property name="xalign">0.0</property>
+            <property name="wrap">True</property>
             <attributes>
               <attribute name="weight" value="bold"/>
             </attributes>
@@ -166,6 +428,8 @@
             <property name="visible">True</property>
             <property name="label" translatable="yes">Enjoy GNOME !</property>
             <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin-bottom">18</property>
             <attributes>
               <attribute name="weight" value="bold"/>
               <attribute name="scale" value="1.2"/>
@@ -175,12 +439,12 @@
         <child>
           <object class="GtkLabel" id="summary-details">
             <property name="visible">True</property>
+            <property name="xalign">0.0</property>
             <property name="label" translatable="yes">Your new account is ready to use. You may change any of these options at any time in the System Settings.</property>
             <property name="wrap">True</property>
             <property name="halign">start</property>
             <attributes>
               <attribute name="weight" value="bold"/>
-              <attribute name="scale" value="1.2"/>
             </attributes>
           </object>
         </child>



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