[gnome-initial-setup/bin-fanciness: 1/2] Add a new GisPage base class from which all pages inherit



commit 327e7ffd4585b0836633ce9bcd90ea41ee8a188f
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Wed Oct 31 19:05:09 2012 -0400

    Add a new GisPage base class from which all pages inherit
    
    This will help us prevent memory leaks when we destroy old pages
    for locale switches, as well as help out in the future when we
    want to do more with identifying and caring about pages in particular.

 gnome-initial-setup/gis-assistant.c                |  244 ++++------
 gnome-initial-setup/gis-assistant.h                |    4 +-
 gnome-initial-setup/gis-driver.c                   |    8 +
 gnome-initial-setup/gis-driver.h                   |    2 +
 gnome-initial-setup/gis-page.c                     |  213 ++++++++-
 gnome-initial-setup/gis-page.h                     |   43 ++-
 .../pages/account/gis-account-page.c               |  518 ++++++++++++--------
 .../pages/account/gis-account-page.h               |   27 +
 gnome-initial-setup/pages/eulas/gis-eula-pages.c   |  147 +++++--
 gnome-initial-setup/pages/eulas/gis-eula-pages.h   |   28 +
 gnome-initial-setup/pages/goa/gis-goa-page.c       |  131 ++++--
 gnome-initial-setup/pages/goa/gis-goa-page.h       |   25 +
 .../pages/language/gis-language-page.c             |  109 +++--
 .../pages/language/gis-language-page.h             |   27 +
 .../pages/location/gis-location-page.c             |  151 ++++---
 .../pages/location/gis-location-page.h             |   27 +
 .../pages/network/gis-network-page.c               |  261 ++++++----
 .../pages/network/gis-network-page.h               |   25 +
 .../pages/summary/gis-summary-page.c               |  151 ++++---
 .../pages/summary/gis-summary-page.h               |   25 +
 20 files changed, 1441 insertions(+), 725 deletions(-)
---
diff --git a/gnome-initial-setup/gis-assistant.c b/gnome-initial-setup/gis-assistant.c
index d3e2eb1..c48443f 100644
--- a/gnome-initial-setup/gis-assistant.c
+++ b/gnome-initial-setup/gis-assistant.c
@@ -27,6 +27,8 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#include "gis-page.h"
+
 #include "gis-assistant.h"
 #include "gis-assistant-private.h"
 
@@ -50,8 +52,6 @@ enum {
 
 static guint signals[LAST_SIGNAL];
 
-typedef struct _PageData PageData;
-
 struct _GisAssistantPrivate
 {
   GtkWidget *frame;
@@ -61,67 +61,28 @@ struct _GisAssistantPrivate
   GtkWidget *action_area;
 
   GList *pages;
-  PageData *current_page;
+  GisPage *current_page;
 };
 
-struct _PageData
+struct _GisAssistantPagePrivate
 {
   GisAssistant *assistant;
-
-  GtkWidget *widget;
-  gboolean page_complete : 1;
-  gboolean use_arrow_buttons : 1;
-  guint padding : 6;
-
   GList *link;
-  gchar *title;
 };
 
-static PageData *
-get_page_data_for_page (GtkWidget *page)
-{
-  return (PageData *) g_object_get_data (G_OBJECT (page), "gis-assistant-page-data");
-}
-
-static void
-remove_page_data (PageData *page_data)
-{
-  g_object_set_data (G_OBJECT (page_data->widget), "gis-assistant-page-data", NULL);
-}
-
-static void
-free_page_data (PageData *page_data)
-{
-  GisAssistantPrivate *priv = page_data->assistant->priv;
-
-  priv->pages = g_list_delete_link (priv->pages, page_data->link);
-  if (page_data == priv->current_page)
-    priv->current_page = NULL;
-
-  g_free (page_data->title);
-  g_slice_free (PageData, page_data);
-}
-
 static void
 widget_destroyed (GtkWidget *widget,
-                  PageData  *page_data)
-{
-  remove_page_data (page_data);
-}
-
-static PageData *
-create_page_data_for_page (GisAssistant *assistant,
-                           GtkWidget    *page)
+                  GisPage   *page)
 {
-  PageData *page_data = g_slice_new0 (PageData);
-  page_data->widget = page;
-  page_data->assistant = assistant;
+  GisAssistant *assistant = page->assistant_priv->assistant;
+  GisAssistantPrivate *priv = assistant->priv;
 
-  g_signal_connect (page, "destroy", G_CALLBACK (widget_destroyed), page_data);
-  g_object_set_data_full (G_OBJECT (page), "gis-assistant-page-data",
-                          page_data, (GDestroyNotify) free_page_data);
+  priv->pages = g_list_delete_link (priv->pages, page->assistant_priv->link);
+  if (page == priv->current_page)
+    priv->current_page = NULL;
 
-  return page_data;
+  g_slice_free (GisAssistantPagePrivate, page->assistant_priv);
+  page->assistant_priv = NULL;
 }
 
 static void
@@ -140,14 +101,14 @@ gis_assistant_next_page (GisAssistant *assistant)
 
 static void
 gis_assistant_real_next_page (GisAssistant *assistant,
-                              GtkWidget    *leaving_page)
+                              GtkWidget    *widget)
 {
   GisAssistantPrivate *priv = assistant->priv;
-  PageData *next_page;
+  GisPage *next_page;
 
   g_return_if_fail (priv->current_page != NULL);
 
-  next_page = (PageData *) priv->current_page->link->next->data;
+  next_page = GIS_PAGE (priv->current_page->assistant_priv->link->next->data);
   gis_assistant_switch_to (assistant, next_page->widget);
 }
 
@@ -155,36 +116,38 @@ void
 gis_assistant_previous_page (GisAssistant *assistant)
 {
   GisAssistantPrivate *priv = assistant->priv;
-  PageData *prev_page;
+  GisPage *prev_page;
 
   g_return_if_fail (priv->current_page != NULL);
 
-  prev_page = (PageData *) priv->current_page->link->prev->data;
+  prev_page = GIS_PAGE (priv->current_page->assistant_priv->link->prev->data);
   gis_assistant_switch_to (assistant, prev_page->widget);
 }
 
 static void
-update_navigation_buttons (GisAssistant *assistant,
-                           GtkWidget    *page)
+update_navigation_buttons (GisAssistant *assistant)
 {
   GisAssistantPrivate *priv = assistant->priv;
-  PageData *current_page = priv->current_page;
+  GisPage *page = priv->current_page;
+  GisAssistantPagePrivate *page_priv;
   gboolean can_go_backward, can_go_forward, is_last_page;
 
-  if (current_page == NULL)
+  if (page == NULL)
     return;
 
-  can_go_backward = (current_page->link->prev != NULL);
+  page_priv = page->assistant_priv;
+
+  can_go_backward = (page_priv->link->prev != NULL);
   gtk_widget_set_sensitive (priv->back, can_go_backward);
 
-  can_go_forward = gis_assistant_get_page_complete (assistant, page);
+  can_go_forward = gis_page_get_complete (page);
   gtk_widget_set_sensitive (priv->forward, can_go_forward);
 
-  is_last_page = (current_page->link->next == NULL);
+  is_last_page = (page_priv->link->next == NULL);
   gtk_widget_set_visible (priv->back, !is_last_page);
   gtk_widget_set_visible (priv->forward, !is_last_page);
 
-  if (gis_assistant_get_use_arrow_buttons (assistant, page))
+  if (gis_page_get_use_arrow_buttons (page))
     {
       gtk_button_set_label (GTK_BUTTON (priv->forward), "â");
       gtk_button_set_label (GTK_BUTTON (priv->back), "â");
@@ -198,25 +161,46 @@ update_navigation_buttons (GisAssistant *assistant,
 
 static void
 gis_assistant_prepare (GisAssistant *assistant,
-                       GtkWidget    *page)
+                       GtkWidget    *widget)
+{
+  update_navigation_buttons (assistant);
+}
+
+static void
+page_notify (GisPage      *page,
+             GParamSpec   *pspec,
+             GisAssistant *assistant)
 {
-  update_navigation_buttons (assistant, page);
+  if (page != assistant->priv->current_page)
+    return;
+
+  if (strcmp (pspec->name, "title") == 0)
+    g_object_notify_by_pspec (G_OBJECT (assistant), obj_props[PROP_TITLE]);
+  else
+    update_navigation_buttons (assistant);
 }
 
 void
 gis_assistant_add_page (GisAssistant *assistant,
-                        GtkWidget    *page)
+                        GisPage      *page)
 {
   GisAssistantPrivate *priv = assistant->priv;
-  PageData *page_data = create_page_data_for_page (assistant, page);
+  GList *link;
+
+  g_return_if_fail (page->assistant_priv == NULL);
+
+  page->assistant_priv = g_slice_new0 (GisAssistantPagePrivate);
+  page->assistant_priv->assistant = assistant;
+  priv->pages = g_list_append (priv->pages, page);
+  link = page->assistant_priv->link = g_list_last (priv->pages);
 
-  priv->pages = g_list_append (priv->pages, page_data);
-  page_data->link = g_list_last (priv->pages);
+  g_signal_connect (page->widget, "destroy", G_CALLBACK (widget_destroyed), page);
+  g_signal_connect (page, "notify", G_CALLBACK (page_notify), assistant);
 
-  GIS_ASSISTANT_GET_CLASS (assistant)->add_page (assistant, page);
+  GIS_ASSISTANT_GET_CLASS (assistant)->add_page (assistant, page->widget);
 
-  if (priv->current_page->link->next == page_data->link)
-    update_navigation_buttons (assistant, priv->current_page->widget);
+  if (priv->current_page->assistant_priv->link == link->prev)
+    update_navigation_buttons (assistant);
 }
 
 void
@@ -229,9 +213,9 @@ gis_assistant_destroy_all_pages (GisAssistant *assistant)
 
   for (l = priv->pages; l != NULL; l = next)
     {
-      PageData *page_data = l->data;
+      GisPage *page = l->data;
       next = l->next;
-      gtk_widget_destroy (page_data->widget);
+      gtk_widget_destroy (GTK_WIDGET (page));
     }
 
   g_object_thaw_notify (G_OBJECT (assistant));
@@ -253,77 +237,12 @@ go_backward (GtkWidget    *button,
   gis_assistant_previous_page (assistant);
 }
 
-void
-gis_assistant_set_page_complete (GisAssistant *assistant,
-                                 GtkWidget    *page,
-                                 gboolean      complete)
-{
-  GisAssistantPrivate *priv = assistant->priv;
-  PageData *page_data = get_page_data_for_page (page);
-
-  page_data->page_complete = complete;
-
-  if (page_data == priv->current_page)
-    update_navigation_buttons (assistant, page);
-}
-
-gboolean
-gis_assistant_get_page_complete (GisAssistant *assistant,
-                                 GtkWidget    *page)
-{
-  PageData *page_data = get_page_data_for_page (page);
-  return page_data->page_complete;
-}
-
-void
-gis_assistant_set_page_title (GisAssistant *assistant,
-                              GtkWidget    *page,
-                              gchar        *title)
-{
-  GisAssistantPrivate *priv = assistant->priv;
-  PageData *page_data = get_page_data_for_page (page);
-  g_free (page_data->title);
-  page_data->title = g_strdup (title);
-
-  if (page_data == priv->current_page)
-    g_object_notify_by_pspec (G_OBJECT (assistant), obj_props[PROP_TITLE]);
-}
-
-gchar *
-gis_assistant_get_page_title (GisAssistant *assistant,
-                              GtkWidget    *page)
-{
-  PageData *page_data = get_page_data_for_page (page);
-  return page_data->title;
-}
-
-void
-gis_assistant_set_use_arrow_buttons (GisAssistant *assistant,
-                                     GtkWidget    *page,
-                                     gboolean      use_arrow_buttons)
-{
-  GisAssistantPrivate *priv = assistant->priv;
-  PageData *page_data = get_page_data_for_page (page);
-  page_data->use_arrow_buttons = use_arrow_buttons;
-
-  if (page_data == priv->current_page)
-    update_navigation_buttons (assistant, page);
-}
-
-gboolean
-gis_assistant_get_use_arrow_buttons (GisAssistant *assistant,
-                                     GtkWidget    *page)
-{
-  PageData *page_data = get_page_data_for_page (page);
-  return page_data->use_arrow_buttons;
-}
-
 gchar *
 gis_assistant_get_title (GisAssistant *assistant)
 {
   GisAssistantPrivate *priv = assistant->priv;
-  if (priv->current_page != NULL && priv->current_page->title != NULL)
-    return priv->current_page->title;
+  if (priv->current_page != NULL)
+    return gis_page_get_title (priv->current_page);
   else
     return "";
 }
@@ -334,17 +253,34 @@ _gis_assistant_get_frame (GisAssistant *assistant)
   return assistant->priv->frame;
 }
 
+static GisPage *
+find_page_for_widget (GisAssistant *assistant,
+                      GtkWidget    *widget)
+{
+  GisAssistantPrivate *priv = assistant->priv;
+  GList *l;
+
+  for (l = priv->pages; l != NULL; l = l->next)
+    {
+      GisPage *page = GIS_PAGE (l->data);
+      if (page->widget == widget)
+        return page;
+    }
+
+  return NULL;
+}
+
 void
 _gis_assistant_current_page_changed (GisAssistant *assistant,
-                                     GtkWidget    *page)
+                                     GtkWidget    *widget)
 {
   GisAssistantPrivate *priv = assistant->priv;
-  PageData *page_data = get_page_data_for_page (page);
+  GisPage *page = find_page_for_widget (assistant, widget);
 
-  if (priv->current_page != page_data) {
-    priv->current_page = page_data;
+  if (priv->current_page != page) {
+    priv->current_page = page;
     g_object_notify_by_pspec (G_OBJECT (assistant), obj_props[PROP_TITLE]);
-    g_signal_emit (assistant, signals[PREPARE], 0, page);
+    g_signal_emit (assistant, signals[PREPARE], 0, page->widget);
   }
 }
 
@@ -410,19 +346,6 @@ gis_assistant_get_property (GObject    *object,
 }
 
 static void
-gis_assistant_finalize (GObject *gobject)
-{
-  GisAssistant *assistant = GIS_ASSISTANT (gobject);
-  GisAssistantPrivate *priv = assistant->priv;
-
-  priv->current_page = NULL;
-
-  g_list_free_full (priv->pages, (GDestroyNotify) remove_page_data);
-
-  G_OBJECT_CLASS (gis_assistant_parent_class)->finalize (gobject);
-}
-
-static void
 gis_assistant_class_init (GisAssistantClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -430,7 +353,6 @@ gis_assistant_class_init (GisAssistantClass *klass)
   g_type_class_add_private (klass, sizeof (GisAssistantPrivate));
 
   gobject_class->get_property = gis_assistant_get_property;
-  gobject_class->finalize = gis_assistant_finalize;
 
   klass->prepare = gis_assistant_prepare;
   klass->next_page = gis_assistant_real_next_page;
diff --git a/gnome-initial-setup/gis-assistant.h b/gnome-initial-setup/gis-assistant.h
index d2dffeb..55cfdaa 100644
--- a/gnome-initial-setup/gis-assistant.h
+++ b/gnome-initial-setup/gis-assistant.h
@@ -26,6 +26,8 @@
 
 #include <glib-object.h>
 
+#include "gis-page.h"
+
 G_BEGIN_DECLS
 
 #define GIS_TYPE_ASSISTANT               (gis_assistant_get_type ())
@@ -60,7 +62,7 @@ struct _GisAssistantClass
 GType gis_assistant_get_type (void);
 
 void      gis_assistant_add_page          (GisAssistant *assistant,
-                                           GtkWidget    *page);
+                                           GisPage      *page);
 
 void      gis_assistant_next_page         (GisAssistant *assistant);
 void      gis_assistant_previous_page     (GisAssistant *assistant);
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index 603b45c..30e77c5 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -120,6 +120,14 @@ gis_driver_get_user_permissions (GisDriver    *driver,
 }
 
 void
+gis_driver_add_page (GisDriver *driver,
+                     GisPage   *page)
+{
+  GisDriverPrivate *priv = driver->priv;
+  gis_assistant_add_page (priv->assistant, page);
+}
+
+void
 gis_driver_locale_changed (GisDriver *driver)
 {
   g_idle_add ((GSourceFunc) rebuild_pages, driver);
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
index dbdde60..f0bbae2 100644
--- a/gnome-initial-setup/gis-driver.h
+++ b/gnome-initial-setup/gis-driver.h
@@ -67,6 +67,8 @@ void gis_driver_set_user_permissions (GisDriver   *driver,
 void gis_driver_get_user_permissions (GisDriver    *driver,
                                       ActUser     **user,
                                       const gchar **password);
+void gis_driver_add_page (GisDriver *driver,
+                          GisPage   *page);
 GisDriver *gis_driver_new (void);
 
 G_END_DECLS
diff --git a/gnome-initial-setup/gis-page.c b/gnome-initial-setup/gis-page.c
index 1a46711..3202bd6 100644
--- a/gnome-initial-setup/gis-page.c
+++ b/gnome-initial-setup/gis-page.c
@@ -22,19 +22,128 @@
  */
 
 #include "config.h"
+
+#include <glib-object.h>
+
 #include "gis-page.h"
 
-#include <string.h>
+G_DEFINE_ABSTRACT_TYPE (GisPage, gis_page, G_TYPE_OBJECT);
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_PAGE, GisPagePrivate))
+
+struct _GisPagePrivate
+{
+  char *title;
+
+  guint complete : 1;
+  guint use_arrow_buttons : 1;
+  guint padding : 6;
+};
+
+enum
+{
+  PROP_0,
+  PROP_DRIVER,
+  PROP_TITLE,
+  PROP_COMPLETE,
+  PROP_USE_ARROW_BUTTONS,
+  PROP_LAST,
+};
+
+static GParamSpec *obj_props[PROP_LAST];
+
+static void
+gis_page_get_property (GObject    *object,
+                       guint       prop_id,
+                       GValue     *value,
+                       GParamSpec *pspec)
+{
+  GisPage *page = GIS_PAGE (object);
+  switch (prop_id)
+    {
+    case PROP_DRIVER:
+      g_value_set_object (value, page->driver);
+      break;
+    case PROP_TITLE:
+      g_value_set_string (value, page->priv->title);
+      break;
+    case PROP_COMPLETE:
+      g_value_set_boolean (value, page->priv->complete);
+      break;
+    case PROP_USE_ARROW_BUTTONS:
+      g_value_set_boolean (value, page->priv->use_arrow_buttons);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gis_page_set_property (GObject      *object,
+                       guint         prop_id,
+                       const GValue *value,
+                       GParamSpec   *pspec)
+{
+  GisPage *page = GIS_PAGE (object);
+  switch (prop_id)
+    {
+    case PROP_DRIVER:
+      page->driver = g_value_dup_object (value);
+      break;
+    case PROP_TITLE:
+      gis_page_set_title (page, (char *) g_value_get_string (value));
+      break;
+    case PROP_COMPLETE:
+      page->priv->complete = g_value_get_boolean (value);
+      break;
+    case PROP_USE_ARROW_BUTTONS:
+      page->priv->use_arrow_buttons = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gis_page_finalize (GObject *object)
+{
+  GisPage *page = GIS_PAGE (object);
+
+  g_free (page->priv->title);
 
-#include <stdlib.h>
+  G_OBJECT_CLASS (gis_page_parent_class)->finalize (object);
+}
 
-GtkBuilder *
-gis_builder (gchar *page_id)
+static void
+gis_page_dispose (GObject *object)
 {
+  GisPage *page = GIS_PAGE (object);
+
+  g_clear_object (&page->driver);
+  g_clear_object (&page->builder);
+  g_clear_object (&page->widget);
+
+  G_OBJECT_CLASS (gis_page_parent_class)->dispose (object);
+}
+
+static GtkBuilder *
+gis_page_real_get_builder (GisPage *page)
+{
+  GisPageClass *klass = GIS_PAGE_GET_CLASS (page);
   GtkBuilder *builder;
-  gchar *resource_path = g_strdup_printf ("/ui/gis-%s-page.ui", page_id);
+  gchar *resource_path;
   GError *error = NULL;
 
+  if (klass->page_id == NULL)
+    {
+      g_warning ("Null page ID. Won't construct builder.");
+      return NULL;
+    }
+
+  resource_path = g_strdup_printf ("/ui/gis-%s-page.ui", klass->page_id);
+
   builder = gtk_builder_new ();
   gtk_builder_add_from_resource (builder, resource_path, &error);
 
@@ -42,8 +151,100 @@ gis_builder (gchar *page_id)
 
   if (error != NULL) {
     g_warning ("Error while loading %s: %s", resource_path, error->message);
-    exit (1);
+    goto err;
   }
 
   return builder;
+ err:
+  g_object_unref (builder);
+  return NULL;
+}
+
+static void
+gis_page_constructed (GObject *object)
+{
+  GisPage *page = GIS_PAGE (object);
+  GisPageClass *klass = GIS_PAGE_GET_CLASS (page);
+
+  page->builder = klass->get_builder (page);
+
+  G_OBJECT_CLASS (gis_page_parent_class)->constructed (object);
+}
+
+static void
+gis_page_class_init (GisPageClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = gis_page_constructed;
+  object_class->dispose = gis_page_dispose;
+  object_class->finalize = gis_page_finalize;
+  object_class->get_property = gis_page_get_property;
+  object_class->set_property = gis_page_set_property;
+
+  klass->get_builder = gis_page_real_get_builder;
+
+  obj_props[PROP_DRIVER] =
+    g_param_spec_object ("driver", "", "", GIS_TYPE_DRIVER,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+  obj_props[PROP_TITLE] =
+    g_param_spec_string ("title", "", "", "",
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+  obj_props[PROP_COMPLETE] =
+    g_param_spec_boolean ("complete", "", "", FALSE,
+                          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+  obj_props[PROP_USE_ARROW_BUTTONS] =
+    g_param_spec_boolean ("use-arrow-buttons", "", "", FALSE,
+                          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class, PROP_LAST, obj_props);
+
+  g_type_class_add_private (object_class, sizeof(GisPagePrivate));
+}
+
+static void
+gis_page_init (GisPage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+char *
+gis_page_get_title (GisPage *page)
+{
+  if (page->priv->title != NULL)
+    return page->priv->title;
+  else
+    return "";
+}
+
+void
+gis_page_set_title (GisPage *page, char *title)
+{
+  g_clear_pointer (&page->priv->title, g_free);
+  page->priv->title = g_strdup (title);
+  g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_TITLE]);
+}
+
+gboolean
+gis_page_get_complete (GisPage *page)
+{
+  return page->priv->complete;
+}
+
+void
+gis_page_set_complete (GisPage *page, gboolean complete)
+{
+  page->priv->complete = complete;
+}
+
+gboolean
+gis_page_get_use_arrow_buttons (GisPage *page)
+{
+  return page->priv->use_arrow_buttons;
+}
+
+void
+gis_page_set_use_arrow_buttons (GisPage *page, gboolean use_arrow_buttons)
+{
+  page->priv->use_arrow_buttons = use_arrow_buttons;
 }
diff --git a/gnome-initial-setup/gis-page.h b/gnome-initial-setup/gis-page.h
index ca3a467..8db99f5 100644
--- a/gnome-initial-setup/gis-page.h
+++ b/gnome-initial-setup/gis-page.h
@@ -26,11 +26,48 @@
 
 #include "gnome-initial-setup.h"
 
-#include <act/act-user-manager.h>
-
 G_BEGIN_DECLS
 
-GtkBuilder * gis_builder (gchar *resource);
+#define GIS_TYPE_PAGE               (gis_page_get_type ())
+#define GIS_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_PAGE, GisPage))
+#define GIS_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_PAGE, GisPageClass))
+#define GIS_IS_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_PAGE))
+#define GIS_IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_PAGE))
+#define GIS_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_PAGE, GisPageClass))
+
+typedef struct _GisPage        GisPage;
+typedef struct _GisPageClass   GisPageClass;
+typedef struct _GisPagePrivate GisPagePrivate;
+typedef struct _GisAssistantPagePrivate GisAssistantPagePrivate;
+
+struct _GisPage
+{
+  GObject parent;
+
+  GisDriver *driver;
+  GtkBuilder *builder;
+  GtkWidget *widget;
+
+  GisPagePrivate *priv;
+  GisAssistantPagePrivate *assistant_priv;
+};
+
+struct _GisPageClass
+{
+  GObjectClass parent_class;
+  char *page_id;
+
+  GtkBuilder * (*get_builder) (GisPage *page);
+};
+
+GType gis_page_get_type (void);
+
+char *       gis_page_get_title (GisPage *page);
+void         gis_page_set_title (GisPage *page, char *title);
+gboolean     gis_page_get_complete (GisPage *page);
+void         gis_page_set_complete (GisPage *page, gboolean complete);
+gboolean     gis_page_get_use_arrow_buttons (GisPage *page);
+void         gis_page_set_use_arrow_buttons (GisPage *page, gboolean use_arrow_buttons);
 
 G_END_DECLS
 
diff --git a/gnome-initial-setup/pages/account/gis-account-page.c b/gnome-initial-setup/pages/account/gis-account-page.c
index 38d7612..3b9a867 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.c
+++ b/gnome-initial-setup/pages/account/gis-account-page.c
@@ -42,10 +42,9 @@
 #include <cheese-gtk.h>
 #endif
 
-#define OBJ(type,name) ((type)gtk_builder_get_object(data->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
+G_DEFINE_TYPE (GisAccountPage, gis_account_page, GIS_TYPE_PAGE);
 
-typedef struct _AccountData AccountData;
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_ACCOUNT_PAGE, GisAccountPagePrivate))
 
 typedef enum {
   UM_LOCAL,
@@ -53,11 +52,8 @@ typedef enum {
   NUM_MODES,
 } UmAccountMode;
 
-struct _AccountData {
-  GisDriver *driver;
-  GtkWidget *widget;
-  GtkBuilder *builder;
-
+struct _GisAccountPagePrivate
+{
   ActUser *act_user;
   ActUserManager *act_client;
 
@@ -82,14 +78,17 @@ struct _AccountData {
   gboolean domain_chosen;
 };
 
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE (page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
 static void
-show_error_dialog (AccountData *data,
+show_error_dialog (GisAccountPage *page,
                    const gchar *message,
                    GError *error)
 {
   GtkWidget *dialog;
 
-  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (data->widget)),
+  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_ERROR,
                                    GTK_BUTTONS_CLOSE,
@@ -106,8 +105,9 @@ show_error_dialog (AccountData *data,
 }
 
 static void
-clear_account_page (AccountData *data)
+clear_account_page (GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   GtkWidget *fullname_entry;
   GtkWidget *username_combo;
   GtkWidget *password_check;
@@ -123,19 +123,19 @@ clear_account_page (AccountData *data)
   password_entry = WID("account-password-entry");
   confirm_entry = WID("account-confirm-entry");
 
-  data->valid_name = FALSE;
-  data->valid_username = FALSE;
-  data->valid_password = TRUE;
-  data->password_mode = ACT_USER_PASSWORD_MODE_NONE;
-  data->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
-  data->user_data_unsaved = FALSE;
+  priv->valid_name = FALSE;
+  priv->valid_username = FALSE;
+  priv->valid_password = TRUE;
+  priv->password_mode = ACT_USER_PASSWORD_MODE_NONE;
+  priv->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
+  priv->user_data_unsaved = FALSE;
 
-  need_password = data->password_mode != ACT_USER_PASSWORD_MODE_NONE;
+  need_password = priv->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), data->account_type == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (admin_check), priv->account_type == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR);
 
   gtk_entry_set_text (GTK_ENTRY (fullname_entry), "");
   gtk_list_store_clear (GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (username_combo))));
@@ -144,15 +144,15 @@ clear_account_page (AccountData *data)
 }
 
 static gboolean
-local_validate (AccountData *data)
+local_validate (GisAccountPage *page)
 {
-  return data->valid_name && data->valid_username &&
-    (data->valid_password ||
-     data->password_mode == ACT_USER_PASSWORD_MODE_NONE);
+  GisAccountPagePrivate *priv = page->priv;
+  return priv->valid_name && priv->valid_username &&
+    (priv->valid_password || priv->password_mode == ACT_USER_PASSWORD_MODE_NONE);
 }
 
 static gboolean
-enterprise_validate (AccountData *data)
+enterprise_validate (GisAccountPage *page)
 {
   const gchar *name;
   gboolean valid_name;
@@ -175,58 +175,65 @@ enterprise_validate (AccountData *data)
 }
 
 static gboolean
-page_validate (AccountData *data)
+page_validate (GisAccountPage *page)
 {
-  switch (data->mode) {
+  GisAccountPagePrivate *priv = page->priv;
+  switch (priv->mode) {
   case UM_LOCAL:
-    return local_validate (data);
+    return local_validate (page);
   case UM_ENTERPRISE:
-    return enterprise_validate (data);
+    return enterprise_validate (page);
   default:
     g_assert_not_reached ();
   }
 }
 
 static void
-update_account_page_status (AccountData *data)
+update_account_page_status (GisAccountPage *page)
 {
-  gis_assistant_set_page_complete (gis_driver_get_assistant (data->driver),
-                                   data->widget, page_validate (data));
+  gis_page_set_complete (GIS_PAGE (page), page_validate (page));
 }
 
 static void
-set_mode (AccountData   *data,
-          UmAccountMode  mode)
+set_mode (GisAccountPage *page,
+          UmAccountMode   mode)
 {
-  if (data->mode == mode)
+  GisAccountPagePrivate *priv = page->priv;
+
+  if (priv->mode == mode)
     return;
 
-  data->mode = mode;
+  priv->mode = mode;
   gtk_widget_set_visible (WID ("local-area"), (mode == UM_LOCAL));
   gtk_widget_set_visible (WID ("enterprise-area"), (mode == UM_ENTERPRISE));
   gtk_toggle_button_set_active (OBJ (GtkToggleButton *, "local-button"), (mode == UM_LOCAL));
   gtk_toggle_button_set_active (OBJ (GtkToggleButton *, "enterprise-button"), (mode == UM_ENTERPRISE));
 
-  update_account_page_status (data);
+  update_account_page_status (page);
 }
 
 static void
-set_has_enterprise (AccountData *data,
-                    gboolean     has_enterprise)
+set_has_enterprise (GisAccountPage *page,
+                    gboolean        has_enterprise)
 {
-  if (data->has_enterprise == has_enterprise)
+  GisAccountPagePrivate *priv = page->priv;
+
+  if (priv->has_enterprise == has_enterprise)
     return;
 
-  data->has_enterprise = has_enterprise;
+  priv->has_enterprise = has_enterprise;
   gtk_widget_set_visible (WID ("account-mode"), has_enterprise);
 
   if (!has_enterprise)
-    set_mode (data, UM_LOCAL);
+    set_mode (page, UM_LOCAL);
 }
 
 static void
-fullname_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
+fullname_changed (GtkWidget      *w,
+                  GParamSpec     *pspec,
+                  GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   GtkWidget *combo;
   GtkWidget *entry;
   GtkTreeModel *model;
@@ -240,10 +247,10 @@ fullname_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
 
   gtk_list_store_clear (GTK_LIST_STORE (model));
 
-  data->valid_name = is_valid_name (name);
-  data->user_data_unsaved = TRUE;
+  priv->valid_name = is_valid_name (name);
+  priv->user_data_unsaved = TRUE;
 
-  if (!data->valid_name) {
+  if (!priv->valid_name) {
     gtk_entry_set_text (GTK_ENTRY (entry), "");
     return;
   }
@@ -252,20 +259,22 @@ fullname_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
 
   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
 
-  update_account_page_status (data);
+  update_account_page_status (page);
 }
 
 static void
-username_changed (GtkComboBoxText *combo, AccountData *data)
+username_changed (GtkComboBoxText *combo,
+                  GisAccountPage  *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   const gchar *username;
   gchar *tip;
   GtkWidget *entry;
 
   username = gtk_combo_box_text_get_active_text (combo);
 
-  data->valid_username = is_valid_username (username, &tip);
-  data->user_data_unsaved = TRUE;
+  priv->valid_username = is_valid_username (username, &tip);
+  priv->user_data_unsaved = TRUE;
 
   entry = gtk_bin_get_child (GTK_BIN (combo));
 
@@ -277,12 +286,15 @@ username_changed (GtkComboBoxText *combo, AccountData *data)
     clear_entry_validation_error (GTK_ENTRY (entry));
   }
 
-  update_account_page_status (data);
+  update_account_page_status (page);
 }
 
 static void
-password_check_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
+password_check_changed (GtkWidget      *w,
+                        GParamSpec     *pspec,
+                        GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   GtkWidget *password_entry;
   GtkWidget *confirm_entry;
   gboolean need_password;
@@ -290,12 +302,12 @@ password_check_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
   need_password = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
 
   if (need_password) {
-    data->password_mode = ACT_USER_PASSWORD_MODE_REGULAR;
-    data->valid_password = FALSE;
+    priv->password_mode = ACT_USER_PASSWORD_MODE_REGULAR;
+    priv->valid_password = FALSE;
   }
   else {
-    data->password_mode = ACT_USER_PASSWORD_MODE_NONE;
-    data->valid_password = TRUE;
+    priv->password_mode = ACT_USER_PASSWORD_MODE_NONE;
+    priv->valid_password = TRUE;
   }
 
   password_entry = WID("account-password-entry");
@@ -306,29 +318,34 @@ password_check_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
   gtk_widget_set_sensitive (password_entry, need_password);
   gtk_widget_set_sensitive (confirm_entry, need_password);
 
-  data->user_data_unsaved = TRUE;
-  update_account_page_status (data);
+  priv->user_data_unsaved = TRUE;
+  update_account_page_status (page);
 }
 
 static void
-admin_check_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
+admin_check_changed (GtkWidget      *w,
+                     GParamSpec     *pspec,
+                     GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
+
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) {
-    data->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
+    priv->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
   }
   else {
-    data->account_type = ACT_USER_ACCOUNT_TYPE_STANDARD;
+    priv->account_type = ACT_USER_ACCOUNT_TYPE_STANDARD;
   }
 
-  data->user_data_unsaved = TRUE;
-  update_account_page_status (data);
+  priv->user_data_unsaved = TRUE;
+  update_account_page_status (page);
 }
 
 #define MIN_PASSWORD_LEN 6
 
 static void
-update_password_entries (AccountData *data)
+update_password_entries (GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   const gchar *password;
   const gchar *verify;
   const gchar *username;
@@ -350,42 +367,49 @@ update_password_entries (AccountData *data)
   strength = pw_strength (password, NULL, username, &hint, &long_hint);
 
   if (strength == 0.0) {
-    data->valid_password = FALSE;
-    data->password_reason = long_hint ? long_hint : hint;
+    priv->valid_password = FALSE;
+    priv->password_reason = long_hint ? long_hint : hint;
   }
   else if (strcmp (password, verify) != 0) {
-    data->valid_password = FALSE;
-    data->password_reason = _("Passwords do not match");
+    priv->valid_password = FALSE;
+    priv->password_reason = _("Passwords do not match");
   }
   else {
-    data->valid_password = TRUE;
+    priv->valid_password = TRUE;
   }
 }
 
 static void
-password_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
+password_changed (GtkWidget      *w,
+                  GParamSpec     *pspec,
+                  GisAccountPage *page)
 {
-  update_password_entries (data);
+  GisAccountPagePrivate *priv = page->priv;
+  update_password_entries (page);
 
-  data->user_data_unsaved = TRUE;
-  update_account_page_status (data);
+  priv->user_data_unsaved = TRUE;
+  update_account_page_status (page);
 }
 
 static void
-confirm_changed (GtkWidget *w, GParamSpec *pspec, AccountData *data)
+confirm_changed (GtkWidget      *w,
+                 GParamSpec     *pspec,
+                 GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   clear_entry_validation_error (GTK_ENTRY (w));
-  update_password_entries (data);
+  update_password_entries (page);
 
-  data->user_data_unsaved = TRUE;
-  update_account_page_status (data);
+  priv->user_data_unsaved = TRUE;
+  update_account_page_status (page);
 }
 
 static gboolean
-confirm_entry_focus_out (GtkWidget     *entry,
-                         GdkEventFocus *event,
-                         AccountData     *data)
+confirm_entry_focus_out (GtkWidget      *entry,
+                         GdkEventFocus  *event,
+                         GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   const gchar *password;
   const gchar *verify;
   GtkEntry *password_entry;
@@ -397,9 +421,9 @@ confirm_entry_focus_out (GtkWidget     *entry,
   verify = gtk_entry_get_text (confirm_entry);
 
   if (strlen (password) > 0 && strlen (verify) > 0) {
-    if (!data->valid_password) {
+    if (!priv->valid_password) {
       set_entry_validation_error (confirm_entry,
-                                  data->password_reason);
+                                  priv->password_reason);
     }
     else {
       clear_entry_validation_error (confirm_entry);
@@ -410,19 +434,20 @@ confirm_entry_focus_out (GtkWidget     *entry,
 }
 
 static void
-set_user_avatar (AccountData *data)
+set_user_avatar (GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   GFile *file = NULL;
   GFileIOStream *io_stream = NULL;
   GOutputStream *stream = NULL;
   GError *error = NULL;
 
-  if (data->avatar_filename != NULL) {
-    act_user_set_icon_file (data->act_user, data->avatar_filename);
+  if (priv->avatar_filename != NULL) {
+    act_user_set_icon_file (priv->act_user, priv->avatar_filename);
     return;
   }
 
-  if (data->avatar_pixbuf == NULL) {
+  if (priv->avatar_pixbuf == NULL) {
     return;
   }
 
@@ -431,10 +456,10 @@ set_user_avatar (AccountData *data)
     goto out;
 
   stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
-  if (!gdk_pixbuf_save_to_stream (data->avatar_pixbuf, stream, "png", NULL, &error, NULL))
+  if (!gdk_pixbuf_save_to_stream (priv->avatar_pixbuf, stream, "png", NULL, &error, NULL))
     goto out;
 
-  act_user_set_icon_file (data->act_user, g_file_get_path (file));
+  act_user_set_icon_file (priv->act_user, g_file_get_path (file));
 
  out:
   if (error != NULL) {
@@ -447,8 +472,9 @@ set_user_avatar (AccountData *data)
 }
 
 static void
-create_user (AccountData *data)
+create_user (GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   const gchar *username;
   const gchar *fullname;
   GError *error;
@@ -458,60 +484,63 @@ create_user (AccountData *data)
 
   error = NULL;
 
-  data->act_user = act_user_manager_create_user (data->act_client, username, fullname, data->account_type, &error);
+  priv->act_user = act_user_manager_create_user (priv->act_client, username, fullname, priv->account_type, &error);
   if (error != NULL) {
     g_warning ("Failed to create user: %s", error->message);
     g_error_free (error);
   }
 
-  set_user_avatar (data);
+  set_user_avatar (page);
 }
 
-static void save_account_data (AccountData *data);
+static void save_account_data (GisAccountPage *page);
 
 static gulong when_loaded;
 
 static void
-save_when_loaded (ActUser *user, GParamSpec *pspec, AccountData *data)
+save_when_loaded (ActUser        *user,
+                  GParamSpec     *pspec,
+                  GisAccountPage *page)
 {
   g_signal_handler_disconnect (user, when_loaded);
   when_loaded = 0;
 
-  save_account_data (data);
+  save_account_data (page);
 }
 
 static void
-local_create_user (AccountData *data)
+local_create_user (GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   const gchar *realname;
   const gchar *username;
   const gchar *password;
 
-  if (!data->user_data_unsaved) {
+  if (!priv->user_data_unsaved) {
     return;
   }
 
   /* this can happen when going back */
-  if (!data->valid_name ||
-      !data->valid_username ||
-      !data->valid_password) {
+  if (!priv->valid_name ||
+      !priv->valid_username ||
+      !priv->valid_password) {
     return;
   }
 
-  if (data->act_user == NULL) {
-    create_user (data);
+  if (priv->act_user == NULL) {
+    create_user (page);
   }
 
-  if (data->act_user == NULL) {
+  if (priv->act_user == NULL) {
     g_warning ("User creation failed");
-    clear_account_page (data);
+    clear_account_page (page);
     return;
   }
 
-  if (!act_user_is_loaded (data->act_user)) {
+  if (!act_user_is_loaded (priv->act_user)) {
     if (when_loaded == 0)
-      when_loaded = g_signal_connect (data->act_user, "notify::is-loaded",
-                                      G_CALLBACK (save_when_loaded), data);
+      when_loaded = g_signal_connect (priv->act_user, "notify::is-loaded",
+                                      G_CALLBACK (save_when_loaded), page);
     return;
   }
 
@@ -519,19 +548,21 @@ local_create_user (AccountData *data)
   username = gtk_combo_box_text_get_active_text (OBJ (GtkComboBoxText*, "account-username-combo"));
   password = gtk_entry_get_text (OBJ (GtkEntry*, "account-password-entry"));
 
-  act_user_set_real_name (data->act_user, realname);
-  act_user_set_user_name (data->act_user, username);
-  act_user_set_account_type (data->act_user, data->account_type);
-  if (data->password_mode == ACT_USER_PASSWORD_MODE_REGULAR) {
-    act_user_set_password (data->act_user, password, NULL);
+  act_user_set_real_name (priv->act_user, realname);
+  act_user_set_user_name (priv->act_user, username);
+  act_user_set_account_type (priv->act_user, priv->account_type);
+  if (priv->password_mode == ACT_USER_PASSWORD_MODE_REGULAR) {
+    act_user_set_password (priv->act_user, password, NULL);
   }
   else {
-    act_user_set_password_mode (data->act_user, data->password_mode);
+    act_user_set_password_mode (priv->act_user, priv->password_mode);
   }
 
-  gis_driver_set_user_permissions (data->driver, data->act_user, password);
+  gis_driver_set_user_permissions (GIS_PAGE (page)->driver,
+                                   priv->act_user,
+                                   password);
 
-  data->user_data_unsaved = FALSE;
+  priv->user_data_unsaved = FALSE;
 }
 
 static void
@@ -539,7 +570,9 @@ on_permit_user_login (GObject *source,
                       GAsyncResult *result,
                       gpointer user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
+  GisAccountPagePrivate *priv = page->priv;
+
   UmRealmCommon *common;
   GError *error = NULL;
   gchar *login;
@@ -558,18 +591,18 @@ on_permit_user_login (GObject *source,
 
     g_debug ("Caching remote user: %s", login);
 
-    data->act_user = act_user_manager_cache_user (data->act_client, login, NULL);
+    priv->act_user = act_user_manager_cache_user (priv->act_client, login, NULL);
 
     g_free (login);
   } else {
-    show_error_dialog (data, _("Failed to register account"), error);
+    show_error_dialog (page, _("Failed to register account"), error);
     g_message ("Couldn't permit logins on account: %s", error->message);
     g_error_free (error);
   }
 }
 
 static void
-enterprise_permit_user_login (AccountData *data, UmRealmObject *realm)
+enterprise_permit_user_login (GisAccountPage *page, UmRealmObject *realm)
 {
   UmRealmCommon *common;
   gchar *login;
@@ -593,7 +626,7 @@ enterprise_permit_user_login (AccountData *data, UmRealmObject *realm)
                                             add, remove, options,
                                             NULL,
                                             on_permit_user_login,
-                                            data);
+                                            page);
 
   g_object_unref (common);
   g_free (login);
@@ -604,7 +637,7 @@ on_realm_joined (GObject *source,
                  GAsyncResult *result,
                  gpointer user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
   UmRealmObject *realm = UM_REALM_OBJECT (source);
   GError *error = NULL;
 
@@ -613,7 +646,7 @@ on_realm_joined (GObject *source,
   /* Yay, joined the domain, register the user locally */
   if (error == NULL) {
     g_debug ("Joining realm completed successfully");
-    enterprise_permit_user_login (data, realm);
+    enterprise_permit_user_login (page, realm);
 
     /* Credential failure while joining domain, prompt for admin creds */
   } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN) ||
@@ -625,7 +658,7 @@ on_realm_joined (GObject *source,
 
     /* Other failure */
   } else {
-    show_error_dialog (data, _("Failed to join domain"), error);
+    show_error_dialog (page, _("Failed to join domain"), error);
     g_message ("Failed to join the domain: %s", error->message);
   }
 
@@ -637,7 +670,7 @@ on_realm_login (GObject *source,
                 GAsyncResult *result,
                 gpointer user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
   UmRealmObject *realm = UM_REALM_OBJECT (source);
   GError *error = NULL;
   GBytes *creds;
@@ -648,7 +681,7 @@ on_realm_login (GObject *source,
     /* Already joined to the domain, just register this user */
     if (um_realm_is_configured (realm)) {
       g_debug ("Already joined to this realm");
-      enterprise_permit_user_login (data, realm);
+      enterprise_permit_user_login (page, realm);
 
       /* Join the domain, try using the user's creds */
     } else if (!um_realm_join_as_user (realm,
@@ -656,7 +689,7 @@ on_realm_login (GObject *source,
                                        gtk_entry_get_text (OBJ (GtkEntry *, "enterprise-password")),
                                        creds, NULL,
                                        on_realm_joined,
-                                       data)) {
+                                       page)) {
 
       /* If we can't do user auth, try to authenticate as admin */
       g_debug ("Cannot join with user credentials");
@@ -680,7 +713,7 @@ on_realm_login (GObject *source,
 
     /* Other login failure */
   } else {
-    show_error_dialog (data, _("Failed to log into domain"), error);
+    show_error_dialog (page, _("Failed to log into domain"), error);
     g_message ("Couldn't log in as user: %s", error->message);
   }
 
@@ -688,7 +721,7 @@ on_realm_login (GObject *source,
 }
 
 static void
-enterprise_check_login (AccountData *data, UmRealmObject *realm)
+enterprise_check_login (GisAccountPage *page, UmRealmObject *realm)
 {
   g_assert (realm);
 
@@ -697,7 +730,7 @@ enterprise_check_login (AccountData *data, UmRealmObject *realm)
                   gtk_entry_get_text (OBJ (GtkEntry *, "enterprise-password")),
                   NULL,
                   on_realm_login,
-                  data);
+                  page);
 }
 
 static void
@@ -705,11 +738,12 @@ on_realm_discover_input (GObject *source,
                          GAsyncResult *result,
                          gpointer user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
+  GisAccountPagePrivate *priv = page->priv;
   GError *error = NULL;
   GList *realms;
 
-  realms = um_realm_manager_discover_finish (data->realm_manager,
+  realms = um_realm_manager_discover_finish (priv->realm_manager,
                                              result, &error);
 
   /* Found a realm, log user into domain */
@@ -717,7 +751,7 @@ on_realm_discover_input (GObject *source,
     UmRealmObject *realm;
     g_assert (realms != NULL);
     realm = g_object_ref (realms->data);
-    enterprise_check_login (data, realm);
+    enterprise_check_login (page, realm);
     g_list_free_full (realms, g_object_unref);
 
   } else {
@@ -731,8 +765,9 @@ on_realm_discover_input (GObject *source,
 }
 
 static void
-enterprise_add_user (AccountData *data)
+enterprise_add_user (GisAccountPage *page)
 {
+  GisAccountPagePrivate *priv = page->priv;
   UmRealmObject *realm;
   GtkTreeIter iter;
   GtkComboBox *domain = OBJ(GtkComboBox*, "enterprise-domain");
@@ -741,27 +776,28 @@ enterprise_add_user (AccountData *data)
   if (gtk_combo_box_get_active_iter (domain, &iter)) {
     gtk_tree_model_get (gtk_combo_box_get_model (domain),
                         &iter, 1, &realm, -1);
-    enterprise_check_login (data, realm);
+    enterprise_check_login (page, realm);
 
     /* Something the user typed, we need to discover realm */
   } else {
-    um_realm_manager_discover (data->realm_manager,
+    um_realm_manager_discover (priv->realm_manager,
                                gtk_entry_get_text (OBJ (GtkEntry*, "enterprise-domain-entry")),
                                NULL,
                                on_realm_discover_input,
-                               data);
+                               priv);
   }
 }
 
 static void
-save_account_data (AccountData *data)
+save_account_data (GisAccountPage *page)
 {
-  switch (data->mode) {
+  GisAccountPagePrivate *priv = page->priv;
+  switch (priv->mode) {
   case UM_LOCAL:
-    local_create_user (data);
+    local_create_user (page);
     break;
   case UM_ENTERPRISE:
-    enterprise_add_user (data);
+    enterprise_add_user (page);
     break;
   default:
     g_assert_not_reached ();
@@ -773,24 +809,25 @@ avatar_callback (GdkPixbuf   *pixbuf,
                  const gchar *filename,
                  gpointer     user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
+  GisAccountPagePrivate *priv = page->priv;
   GtkWidget *image;
   GdkPixbuf *tmp;
 
-  g_clear_object (&data->avatar_pixbuf);
-  g_free (data->avatar_filename);
-  data->avatar_filename = NULL;
+  g_clear_object (&priv->avatar_pixbuf);
+  g_free (priv->avatar_filename);
+  priv->avatar_filename = NULL;
 
   image = WID("local-account-avatar-image");
 
   if (pixbuf) {
-    data->avatar_pixbuf = g_object_ref (pixbuf);
+    priv->avatar_pixbuf = g_object_ref (pixbuf);
     tmp = gdk_pixbuf_scale_simple (pixbuf, 64, 64, GDK_INTERP_BILINEAR);
     gtk_image_set_from_pixbuf (GTK_IMAGE (image), tmp);
     g_object_unref (tmp);
   }
   else if (filename) {
-    data->avatar_filename = g_strdup (filename);
+    priv->avatar_filename = g_strdup (filename);
     tmp = gdk_pixbuf_new_from_file_at_size (filename, 64, 64, NULL);
     gtk_image_set_from_pixbuf (GTK_IMAGE (image), tmp);
     g_object_unref (tmp);
@@ -802,9 +839,10 @@ avatar_callback (GdkPixbuf   *pixbuf,
 }
 
 static void
-enterprise_add_realm (AccountData *data,
-                      UmRealmObject *realm)
+enterprise_add_realm (GisAccountPage *page,
+                      UmRealmObject  *realm)
 {
+  GisAccountPagePrivate *priv = page->priv;
   GtkTreeIter iter;
   UmRealmCommon *common;
   GtkComboBox *domain = OBJ(GtkComboBox*, "enterprise-domain");
@@ -821,7 +859,7 @@ enterprise_add_realm (AccountData *data,
                       1, realm,
                       -1);
 
-  if (!data->domain_chosen && um_realm_is_configured (realm))
+  if (!priv->domain_chosen && um_realm_is_configured (realm))
     gtk_combo_box_set_active_iter (domain, &iter);
 
   g_object_unref (common);
@@ -832,8 +870,8 @@ on_manager_realm_added (UmRealmManager  *manager,
                         UmRealmObject   *realm,
                         gpointer         user_data)
 {
-  AccountData *data = user_data;
-  enterprise_add_realm (data, realm);
+  GisAccountPage *page = user_data;
+  enterprise_add_realm (page, realm);
 }
 
 static void
@@ -841,12 +879,13 @@ on_realm_manager_created (GObject *source,
                           GAsyncResult *result,
                           gpointer user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
+  GisAccountPagePrivate *priv = page->priv;
   GError *error = NULL;
   GList *realms, *l;
 
-  g_clear_object (&data->realm_manager);
-  data->realm_manager = um_realm_manager_new_finish (result, &error);
+  g_clear_object (&priv->realm_manager);
+  priv->realm_manager = um_realm_manager_new_finish (result, &error);
 
   if (error != NULL) {
     g_warning ("Couldn't contact realmd service: %s", error->message);
@@ -855,17 +894,17 @@ on_realm_manager_created (GObject *source,
   }
 
   /* Lookup all the realm objects */
-  realms = um_realm_manager_get_realms (data->realm_manager);
+  realms = um_realm_manager_get_realms (priv->realm_manager);
   for (l = realms; l != NULL; l = g_list_next (l))
-    enterprise_add_realm (data, l->data);
+    enterprise_add_realm (page, l->data);
 
   g_list_free (realms);
-  g_signal_connect (data->realm_manager, "realm-added",
-                    G_CALLBACK (on_manager_realm_added), data);
+  g_signal_connect (priv->realm_manager, "realm-added",
+                    G_CALLBACK (on_manager_realm_added), page);
 
   /* When no realms try to discover a sensible default, triggers realm-added signal */
-  um_realm_manager_discover (data->realm_manager, "", NULL, NULL, NULL);
-  set_has_enterprise (data, TRUE);
+  um_realm_manager_discover (priv->realm_manager, "", NULL, NULL, NULL);
+  set_has_enterprise (page, TRUE);
 }
 
 static void
@@ -874,8 +913,8 @@ on_realmd_appeared (GDBusConnection *connection,
                     const gchar *name_owner,
                     gpointer user_data)
 {
-  AccountData *data = user_data;
-  um_realm_manager_new (NULL, on_realm_manager_created, data);
+  GisAccountPage *page = user_data;
+  um_realm_manager_new (NULL, on_realm_manager_created, page);
 }
 
 static void
@@ -883,25 +922,26 @@ on_realmd_disappeared (GDBusConnection *unused1,
                        const gchar *unused2,
                        gpointer user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
+  GisAccountPagePrivate *priv = page->priv;
 
-  if (data->realm_manager != NULL) {
-    g_signal_handlers_disconnect_by_func (data->realm_manager,
+  if (priv->realm_manager != NULL) {
+    g_signal_handlers_disconnect_by_func (priv->realm_manager,
                                           on_manager_realm_added,
-                                          data);
-    g_clear_object (&data->realm_manager);
+                                          page);
+    g_clear_object (&priv->realm_manager);
   }
 
-  set_has_enterprise (data, FALSE);
+  set_has_enterprise (page, FALSE);
 }
 
 static void
 on_domain_changed (GtkComboBox *widget,
                    gpointer user_data)
 {
-  AccountData *data = user_data;
-  data->domain_chosen = TRUE;
-  update_account_page_status (data);
+  GisAccountPage *page = user_data;
+  page->priv->domain_chosen = TRUE;
+  update_account_page_status (page);
   clear_entry_validation_error (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget))));
 }
 
@@ -909,8 +949,8 @@ static void
 on_entry_changed (GtkEditable *editable,
                   gpointer user_data)
 {
-  AccountData *data = user_data;
-  update_account_page_status (data);
+  GisAccountPage *page = user_data;
+  update_account_page_status (page);
   clear_entry_validation_error (GTK_ENTRY (editable));
 }
 
@@ -918,9 +958,9 @@ static void
 on_local_toggle (GtkToggleButton *toggle,
                  gpointer         user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
   if (gtk_toggle_button_get_active (toggle)) {
-    set_mode (data, UM_LOCAL);
+    set_mode (page, UM_LOCAL);
   }
 }
 
@@ -928,22 +968,28 @@ static void
 on_enterprise_toggle (GtkToggleButton *toggle,
                       gpointer         user_data)
 {
-  AccountData *data = user_data;
+  GisAccountPage *page = user_data;
   if (gtk_toggle_button_get_active (toggle)) {
-    set_mode (data, UM_ENTERPRISE);
+    set_mode (page, UM_ENTERPRISE);
   }
 }
 
 static void
-next_page_cb (GisAssistant *assistant, GtkWidget *page, AccountData *data)
+next_page_cb (GisAssistant *assistant,
+              GisPage      *which_page,
+              GisPage      *this_page)
 {
-  if (page == data->widget)
-    save_account_data (data);
+  if (which_page == this_page)
+    save_account_data (GIS_ACCOUNT_PAGE (this_page));
 }
 
-void
-gis_prepare_account_page (GisDriver *driver)
+static void
+gis_account_page_constructed (GObject *object)
 {
+  GisAccountPage *page = GIS_ACCOUNT_PAGE (object);
+  GisAccountPagePrivate *priv = page->priv;
+  GisAssistant *assistant = gis_driver_get_assistant (GIS_PAGE (page)->driver);
+
   GtkWidget *fullname_entry;
   GtkWidget *username_combo;
   GtkWidget *password_check;
@@ -951,18 +997,15 @@ gis_prepare_account_page (GisDriver *driver)
   GtkWidget *password_entry;
   GtkWidget *confirm_entry;
   GtkWidget *local_account_avatar_button;
-  AccountData *data = g_slice_new0 (AccountData);
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
-  data->driver = driver;
-  data->builder = gis_builder (PAGE_ID);
-  data->widget = WID("account-page");
 
-  gtk_widget_show (data->widget);
+  G_OBJECT_CLASS (gis_account_page_parent_class)->constructed (object);
+
+  GIS_PAGE (page)->widget = WID ("account-page");
 
-  data->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
+  priv->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
                                          G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
                                          on_realmd_appeared, on_realmd_disappeared,
-                                         data, NULL);
+                                         page, NULL);
 
   fullname_entry = WID("account-fullname-entry");
   username_combo = WID("account-username-combo");
@@ -971,47 +1014,100 @@ gis_prepare_account_page (GisDriver *driver)
   password_entry = WID("account-password-entry");
   confirm_entry = WID("account-confirm-entry");
   local_account_avatar_button = WID("local-account-avatar-button");
-  data->photo_dialog = (GtkWidget *)um_photo_dialog_new (local_account_avatar_button,
+  priv->photo_dialog = (GtkWidget *)um_photo_dialog_new (local_account_avatar_button,
                                                          avatar_callback,
-                                                         data);
+                                                         page);
 
   g_signal_connect (fullname_entry, "notify::text",
-                    G_CALLBACK (fullname_changed), data);
+                    G_CALLBACK (fullname_changed), page);
   g_signal_connect (username_combo, "changed",
-                    G_CALLBACK (username_changed), data);
+                    G_CALLBACK (username_changed), page);
   g_signal_connect (password_check, "notify::active",
-                    G_CALLBACK (password_check_changed), data);
+                    G_CALLBACK (password_check_changed), page);
   g_signal_connect (admin_check, "notify::active",
-                    G_CALLBACK (admin_check_changed), data);
+                    G_CALLBACK (admin_check_changed), page);
   g_signal_connect (password_entry, "notify::text",
-                    G_CALLBACK (password_changed), data);
+                    G_CALLBACK (password_changed), page);
   g_signal_connect (confirm_entry, "notify::text",
-                    G_CALLBACK (confirm_changed), data);
+                    G_CALLBACK (confirm_changed), page);
   g_signal_connect_after (confirm_entry, "focus-out-event",
-                          G_CALLBACK (confirm_entry_focus_out), data);
+                          G_CALLBACK (confirm_entry_focus_out), page);
 
   g_signal_connect (WID("enterprise-domain"), "changed",
-                    G_CALLBACK (on_domain_changed), data);
+                    G_CALLBACK (on_domain_changed), page);
   g_signal_connect (WID("enterprise-login"), "changed",
-                    G_CALLBACK (on_entry_changed), data);
+                    G_CALLBACK (on_entry_changed), page);
   g_signal_connect (WID("local-button"), "toggled",
-                    G_CALLBACK (on_local_toggle), data);
+                    G_CALLBACK (on_local_toggle), page);
   g_signal_connect (WID("enterprise-button"), "toggled",
-                    G_CALLBACK (on_enterprise_toggle), data);
+                    G_CALLBACK (on_enterprise_toggle), page);
 
-  data->act_client = act_user_manager_get_default ();
+  priv->act_client = act_user_manager_get_default ();
 
-  gis_assistant_add_page (assistant, data->widget);
-  gis_assistant_set_page_title (assistant, data->widget, _("Login"));
+  g_signal_connect (assistant, "next-page", G_CALLBACK (next_page_cb), page);
 
-  g_signal_connect (assistant, "next-page", G_CALLBACK (next_page_cb), data);
+  clear_account_page (page);
+  update_account_page_status (page);
 
-  clear_account_page (data);
-  update_account_page_status (data);
-
-  data->has_enterprise = FALSE;
+  priv->has_enterprise = FALSE;
 
   /* force a refresh by setting to an invalid value */
-  data->mode = NUM_MODES;
-  set_mode (data, UM_LOCAL);
+  priv->mode = NUM_MODES;
+  set_mode (page, UM_LOCAL);
+
+  gis_page_set_title (GIS_PAGE (page), _("Login"));
+}
+
+static void
+gis_account_page_dispose (GObject *object)
+{
+  GisAccountPage *page = GIS_ACCOUNT_PAGE (object);
+  GisAccountPagePrivate *priv = page->priv;
+
+  g_clear_object (&priv->act_user);
+  g_clear_object (&priv->act_client);
+  g_clear_object (&priv->realm_manager);
+  g_clear_object (&priv->avatar_pixbuf);
+
+  G_OBJECT_CLASS (gis_account_page_parent_class)->dispose (object);
+}
+
+static void
+gis_account_page_finalize (GObject *object)
+{
+  GisAccountPage *page = GIS_ACCOUNT_PAGE (object);
+  GisAccountPagePrivate *priv = page->priv;
+
+  g_clear_pointer (&priv->avatar_filename, g_free);
+
+  G_OBJECT_CLASS (gis_account_page_parent_class)->finalize (object);
+}
+
+static void
+gis_account_page_class_init (GisAccountPageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  object_class->constructed = gis_account_page_constructed;
+  object_class->dispose = gis_account_page_dispose;
+  object_class->finalize = gis_account_page_finalize;
+
+  g_type_class_add_private (object_class, sizeof(GisAccountPagePrivate));
+}
+
+static void
+gis_account_page_init (GisAccountPage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+void
+gis_prepare_account_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_ACCOUNT_PAGE,
+                                     "driver", driver,
+                                     NULL));
 }
diff --git a/gnome-initial-setup/pages/account/gis-account-page.h b/gnome-initial-setup/pages/account/gis-account-page.h
index 8091e16..496da21 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.h
+++ b/gnome-initial-setup/pages/account/gis-account-page.h
@@ -24,10 +24,37 @@
 #ifndef __GIS_ACCOUNT_PAGE_H__
 #define __GIS_ACCOUNT_PAGE_H__
 
+#include <glib-object.h>
+
 #include "gnome-initial-setup.h"
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_ACCOUNT_PAGE               (gis_account_page_get_type ())
+#define GIS_ACCOUNT_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_ACCOUNT_PAGE, GisAccountPage))
+#define GIS_ACCOUNT_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_ACCOUNT_PAGE, GisAccountPageClass))
+#define GIS_IS_ACCOUNT_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_ACCOUNT_PAGE))
+#define GIS_IS_ACCOUNT_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_ACCOUNT_PAGE))
+#define GIS_ACCOUNT_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_ACCOUNT_PAGE, GisAccountPageClass))
+
+typedef struct _GisAccountPage        GisAccountPage;
+typedef struct _GisAccountPageClass   GisAccountPageClass;
+typedef struct _GisAccountPagePrivate GisAccountPagePrivate;
+
+struct _GisAccountPage
+{
+  GisPage parent;
+
+  GisAccountPagePrivate *priv;
+};
+
+struct _GisAccountPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_account_page_get_type (void);
+
 void gis_prepare_account_page (GisDriver *driver);
 
 G_END_DECLS
diff --git a/gnome-initial-setup/pages/eulas/gis-eula-pages.c b/gnome-initial-setup/pages/eulas/gis-eula-pages.c
index c807e70..eae1853 100644
--- a/gnome-initial-setup/pages/eulas/gis-eula-pages.c
+++ b/gnome-initial-setup/pages/eulas/gis-eula-pages.c
@@ -29,14 +29,15 @@
 
 #include <glib/gi18n.h>
 #include <gio/gio.h>
-
 #include <gtk/gtk.h>
 
-typedef struct _EulaPage EulaPage;
+G_DEFINE_TYPE (GisEulaPage, gis_eula_page, GIS_TYPE_PAGE);
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_EULA_PAGE, GisEulaPagePrivate))
 
-struct _EulaPage {
-  GisDriver *driver;
-  GtkWidget *widget;
+struct _GisEulaPagePrivate
+{
+  GFile *eula;
 
   GtkWidget *text_view;
   GtkWidget *checkbox;
@@ -46,6 +47,15 @@ struct _EulaPage {
   gboolean require_scroll;
 };
 
+enum
+{
+  PROP_0,
+  PROP_EULA,
+  PROP_LAST,
+};
+
+static GParamSpec *obj_props[PROP_LAST];
+
 static GtkTextBuffer *
 build_eula_text_buffer_pango_markup (GFile   *file,
                                      GError **error_out)
@@ -147,16 +157,18 @@ build_eula_text_view (GFile *eula)
 }
 
 static gboolean
-get_page_complete (EulaPage *page)
+get_page_complete (GisEulaPage *page)
 {
-  if (page->require_checkbox) {
-    GtkToggleButton *checkbox = GTK_TOGGLE_BUTTON (page->checkbox);
+  GisEulaPagePrivate *priv = page->priv;
+
+  if (priv->require_checkbox) {
+    GtkToggleButton *checkbox = GTK_TOGGLE_BUTTON (priv->checkbox);
     if (!gtk_toggle_button_get_active (checkbox))
       return FALSE;
   }
 
-  if (page->require_scroll) {
-    GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (page->scrolled_window);
+  if (priv->require_scroll) {
+    GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (priv->scrolled_window);
     GtkAdjustment *vadjust = gtk_scrolled_window_get_vadjustment (scrolled_window);
     gdouble value, upper;
 
@@ -171,10 +183,9 @@ get_page_complete (EulaPage *page)
 }
 
 static void
-sync_page_complete (EulaPage *page)
+sync_page_complete (GisEulaPage *page)
 {
-  gis_assistant_set_page_complete (gis_driver_get_assistant (page->driver),
-                                   page->widget, get_page_complete (page));
+  gis_page_set_complete (GIS_PAGE (page), get_page_complete (page));
 }
 
 static void
@@ -205,18 +216,21 @@ get_config (GFile    *eula,
 }
 
 static void
-build_eula_page (GisDriver *driver,
-                 GFile     *eula)
+gis_eula_page_constructed (GObject *object)
 {
+  GisEulaPage *page = GIS_EULA_PAGE (object);
+  GisEulaPagePrivate *priv = page->priv;
   GtkWidget *text_view;
   GtkWidget *vbox;
   GtkWidget *scrolled_window;
-  EulaPage *page;
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
 
   gboolean require_checkbox = TRUE;
   gboolean require_scroll = FALSE;
 
+  GFile *eula = priv->eula;
+
+  G_OBJECT_CLASS (gis_eula_page_parent_class)->constructed (object);
+
   text_view = build_eula_text_view (eula);
   if (text_view == NULL)
     return;
@@ -228,19 +242,16 @@ build_eula_page (GisDriver *driver,
                                        GTK_SHADOW_ETCHED_IN);
   gtk_widget_set_vexpand (scrolled_window, TRUE);
   gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
-
   gtk_container_add (GTK_CONTAINER (vbox), scrolled_window);
+  GIS_PAGE (page)->widget = vbox;
 
-  page = g_slice_new0 (EulaPage);
-  page->driver = driver;
-  page->widget = vbox;
-  page->text_view = text_view;
-  page->scrolled_window = scrolled_window;
+  priv->text_view = text_view;
+  priv->scrolled_window = scrolled_window;
 
   get_config (eula, &require_checkbox, &require_scroll);
 
-  page->require_checkbox = require_checkbox;
-  page->require_scroll = require_scroll;
+  priv->require_checkbox = require_checkbox;
+  priv->require_scroll = require_scroll;
 
   if (require_checkbox) {
     GtkWidget *checkbox;
@@ -256,7 +267,7 @@ build_eula_page (GisDriver *driver,
                               G_CALLBACK (sync_page_complete),
                               page);
 
-    page->checkbox = checkbox;
+    priv->checkbox = checkbox;
   }
 
   if (require_scroll) {
@@ -270,12 +281,82 @@ build_eula_page (GisDriver *driver,
                               page);
   }
 
-  gis_assistant_add_page (assistant, vbox);
-  gis_assistant_set_page_title (assistant, vbox, _("License Agreements"));
-
+  gis_page_set_title (GIS_PAGE (page), _("License Agreements"));
   sync_page_complete (page);
+}
 
-  gtk_widget_show_all (GTK_WIDGET (vbox));
+
+static void
+gis_eula_page_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  GisEulaPage *page = GIS_EULA_PAGE (object);
+  GisEulaPagePrivate *priv = page->priv;
+  switch (prop_id)
+    {
+    case PROP_EULA:
+      g_value_set_object (value, priv->eula);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gis_eula_page_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  GisEulaPage *page = GIS_EULA_PAGE (object);
+  GisEulaPagePrivate *priv = page->priv;
+  switch (prop_id)
+    {
+    case PROP_EULA:
+      priv->eula = g_value_dup_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gis_eula_page_dispose (GObject *object)
+{
+  GisEulaPage *page = GIS_EULA_PAGE (object);
+  GisEulaPagePrivate *priv = page->priv;
+
+  g_clear_object (&priv->eula);
+
+  G_OBJECT_CLASS (gis_eula_page_parent_class)->dispose (object);
+}
+
+static void
+gis_eula_page_class_init (GisEulaPageClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = gis_eula_page_get_property;
+  object_class->set_property = gis_eula_page_set_property;
+  object_class->constructed = gis_eula_page_constructed;
+  object_class->dispose = gis_eula_page_dispose;
+
+  obj_props[PROP_EULA] =
+    g_param_spec_object ("eula", "", "",
+                         G_TYPE_FILE,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  g_type_class_add_private (object_class, sizeof(GisEulaPagePrivate));
+}
+
+static void
+gis_eula_page_init (GisEulaPage *page)
+{
+  page->priv = GET_PRIVATE (page);
 }
 
 void
@@ -305,7 +386,11 @@ gis_prepare_eula_pages (GisDriver *driver)
 
   while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL) {
     GFile *eula = g_file_get_child (eulas_dir, g_file_info_get_name (info));
-    build_eula_page (driver, eula);
+    gis_driver_add_page (driver,
+                         g_object_new (GIS_TYPE_EULA_PAGE,
+                                       "driver", driver,
+                                       "eula", eula,
+                                       NULL));
     g_object_unref (eula);
   }
 
diff --git a/gnome-initial-setup/pages/eulas/gis-eula-pages.h b/gnome-initial-setup/pages/eulas/gis-eula-pages.h
index 0bbc5df..063f8db 100644
--- a/gnome-initial-setup/pages/eulas/gis-eula-pages.h
+++ b/gnome-initial-setup/pages/eulas/gis-eula-pages.h
@@ -24,12 +24,40 @@
 #ifndef __GIS_EULA_PAGES_H__
 #define __GIS_EULA_PAGES_H__
 
+#include <glib-object.h>
+
 #include "gnome-initial-setup.h"
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_EULA_PAGE               (gis_eula_page_get_type ())
+#define GIS_EULA_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_EULA_PAGE, GisEulaPage))
+#define GIS_EULA_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_EULA_PAGE, GisEulaPageClass))
+#define GIS_IS_EULA_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_EULA_PAGE))
+#define GIS_IS_EULA_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_EULA_PAGE))
+#define GIS_EULA_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_EULA_PAGE, GisEulaPageClass))
+
+typedef struct _GisEulaPage        GisEulaPage;
+typedef struct _GisEulaPageClass   GisEulaPageClass;
+typedef struct _GisEulaPagePrivate GisEulaPagePrivate;
+
+struct _GisEulaPage
+{
+  GisPage parent;
+
+  GisEulaPagePrivate *priv;
+};
+
+struct _GisEulaPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_eula_page_get_type (void);
+
 void gis_prepare_eula_pages (GisDriver *driver);
 
 G_END_DECLS
 
 #endif /* __GIS_EULA_PAGES_H__ */
+
diff --git a/gnome-initial-setup/pages/goa/gis-goa-page.c b/gnome-initial-setup/pages/goa/gis-goa-page.c
index df846e4..249288b 100644
--- a/gnome-initial-setup/pages/goa/gis-goa-page.c
+++ b/gnome-initial-setup/pages/goa/gis-goa-page.c
@@ -38,25 +38,23 @@
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 
-#define OBJ(type,name) ((type)gtk_builder_get_object(data->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
-
-typedef struct _GoaData GoaData;
+G_DEFINE_TYPE (GisGoaPage, gis_goa_page, GIS_TYPE_PAGE);
 
-struct _GoaData {
-  GisDriver *driver;
-  GtkWidget *widget;
-  GtkBuilder *builder;
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_GOA_PAGE, GisGoaPagePrivate))
 
-  /* online data */
+struct _GisGoaPagePrivate {
   GoaClient *goa_client;
 };
 
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE(page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
 static void
 show_online_account_dialog (GtkButton *button,
                             gpointer   user_data)
 {
-  GoaData *data = user_data;
+  GisGoaPage *page = GIS_GOA_PAGE (user_data);
+  GisGoaPagePrivate *priv = page->priv;
   GtkWindow *parent;
   GtkWidget *dialog;
   gint response;
@@ -67,9 +65,9 @@ show_online_account_dialog (GtkButton *button,
 
   providers = NULL;
 
-  parent = GTK_WINDOW (gtk_widget_get_toplevel (data->widget));
+  parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page)));
 
-  dialog = goa_panel_add_account_dialog_new (data->goa_client);
+  dialog = goa_panel_add_account_dialog_new (priv->goa_client);
   gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
 
   providers = goa_provider_get_all ();
@@ -122,14 +120,14 @@ remove_account_cb (GoaAccount   *account,
                    GAsyncResult *res,
                    gpointer      user_data)
 {
-  GoaData *data = user_data;
+  GisGoaPage *page = GIS_GOA_PAGE (user_data);
   GError *error;
 
   error = NULL;
   if (!goa_account_call_remove_finish (account, res, &error))
     {
       GtkWidget *dialog;
-      dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (data->widget)),
+      dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
                                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_MESSAGE_ERROR,
                                        GTK_BUTTONS_CLOSE,
@@ -148,14 +146,14 @@ remove_account_cb (GoaAccount   *account,
 static void
 confirm_remove_account (GtkButton *button, gpointer user_data)
 {
-  GoaData *data = user_data;
+  GisGoaPage *page = GIS_GOA_PAGE (user_data);
   GtkWidget *dialog;
   GoaObject *object;
   gint response;
 
   object = g_object_get_data (G_OBJECT (button), "goa-object");
 
-  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (data->widget)),
+  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_QUESTION,
                                    GTK_BUTTONS_CANCEL,
@@ -172,13 +170,13 @@ confirm_remove_account (GtkButton *button, gpointer user_data)
       goa_account_call_remove (goa_object_peek_account (object),
                                NULL, /* GCancellable */
                                (GAsyncReadyCallback) remove_account_cb,
-                               data);
+                               page);
     }
 }
 
 
 static void
-add_account_to_list (GoaData *data, GoaObject *object)
+add_account_to_list (GisGoaPage *page, GoaObject *object)
 {
   GtkWidget *list;
   GtkWidget *box;
@@ -216,7 +214,7 @@ add_account_to_list (GoaData *data, GoaObject *object)
                           g_object_ref (object), g_object_unref);
 
   g_signal_connect (button, "clicked",
-                    G_CALLBACK (confirm_remove_account), data);
+                    G_CALLBACK (confirm_remove_account), page);
 
   gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
   gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
@@ -228,7 +226,7 @@ add_account_to_list (GoaData *data, GoaObject *object)
 }
 
 static void
-remove_account_from_list (GoaData *data, GoaObject *object)
+remove_account_from_list (GisGoaPage *page, GoaObject *object)
 {
   GtkWidget *list;
   GList *children, *l;
@@ -259,16 +257,17 @@ remove_account_from_list (GoaData *data, GoaObject *object)
 }
 
 static void
-populate_account_list (GoaData *data)
+populate_account_list (GisGoaPage *page)
 {
+  GisGoaPagePrivate *priv = page->priv;
   GList *accounts, *l;
   GoaObject *object;
 
-  accounts = goa_client_get_accounts (data->goa_client);
+  accounts = goa_client_get_accounts (priv->goa_client);
   for (l = accounts; l; l = l->next)
     {
       object = GOA_OBJECT (l->data);
-      add_account_to_list (data, object);
+      add_account_to_list (page, object);
     }
 
   g_list_free_full (accounts, (GDestroyNotify) g_object_unref);
@@ -277,54 +276,94 @@ populate_account_list (GoaData *data)
 static void
 goa_account_added (GoaClient *client, GoaObject *object, gpointer user_data)
 {
-  GoaData *data = user_data;
+  GisGoaPage *page = GIS_GOA_PAGE (user_data);
 
   g_debug ("Online account added");
 
-  add_account_to_list (data, object);
+  add_account_to_list (page, object);
 }
 
 static void
 goa_account_removed (GoaClient *client, GoaObject *object, gpointer user_data)
 {
-  GoaData *data = user_data;
+  GisGoaPage *page = GIS_GOA_PAGE (user_data);
 
   g_debug ("Online account removed");
 
-  remove_account_from_list (data, object);
+  remove_account_from_list (page, object);
 }
 
-void
-gis_prepare_goa_page (GisDriver *driver)
+static void
+gis_goa_page_constructed (GObject *object)
 {
+  GisGoaPage *page = GIS_GOA_PAGE (object);
+  GisGoaPagePrivate *priv = page->priv;
   GtkWidget *button;
   GError *error = NULL;
-  GoaData *data = g_slice_new0 (GoaData);
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
-  data->driver = driver;
-  data->builder = gis_builder (PAGE_ID);
-  data->widget = WID ("goa-page");
-  data->goa_client = goa_client_new_sync (NULL, &error);
-
-  if (data->goa_client == NULL)
+
+  G_OBJECT_CLASS (gis_goa_page_parent_class)->constructed (object);
+
+  GIS_PAGE (page)->widget = WID ("goa-page");
+
+  priv->goa_client = goa_client_new_sync (NULL, &error);
+
+  if (priv->goa_client == NULL)
     {
        g_error ("Failed to get a GoaClient: %s", error->message);
        g_error_free (error);
        return;
     }
 
-  populate_account_list (data);
+  populate_account_list (page);
 
   button = WID("online-add-button");
   g_signal_connect (button, "clicked",
-                    G_CALLBACK (show_online_account_dialog), data);
+                    G_CALLBACK (show_online_account_dialog), page);
+
+  g_signal_connect (priv->goa_client, "account-added",
+                    G_CALLBACK (goa_account_added), page);
+  g_signal_connect (priv->goa_client, "account-removed",
+                    G_CALLBACK (goa_account_removed), page);
+
+  gis_page_set_title (GIS_PAGE (page), _("Online Accounts"));
+  gis_page_set_complete (GIS_PAGE (page), TRUE);
+}
+
+static void
+gis_goa_page_dispose (GObject *object)
+{
+  GisGoaPage *page = GIS_GOA_PAGE (object);
+  GisGoaPagePrivate *priv = page->priv;
+
+  g_clear_object (&priv->goa_client);
+
+  G_OBJECT_CLASS (gis_goa_page_parent_class)->dispose (object);
+}
 
-  g_signal_connect (data->goa_client, "account-added",
-                    G_CALLBACK (goa_account_added), data);
-  g_signal_connect (data->goa_client, "account-removed",
-                    G_CALLBACK (goa_account_removed), data);
+static void
+gis_goa_page_class_init (GisGoaPageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  object_class->constructed = gis_goa_page_constructed;
+  object_class->dispose = gis_goa_page_dispose;
+  
+  g_type_class_add_private (object_class, sizeof(GisGoaPagePrivate));
+}
 
-  gis_assistant_add_page (assistant, data->widget);
-  gis_assistant_set_page_complete (assistant, data->widget, TRUE);
-  gis_assistant_set_page_title (assistant, data->widget, _("Online Accounts"));
+static void
+gis_goa_page_init (GisGoaPage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+void
+gis_prepare_goa_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_GOA_PAGE,
+                                     "driver", driver,
+                                     NULL));
 }
diff --git a/gnome-initial-setup/pages/goa/gis-goa-page.h b/gnome-initial-setup/pages/goa/gis-goa-page.h
index 92bbce1..6824c16 100644
--- a/gnome-initial-setup/pages/goa/gis-goa-page.h
+++ b/gnome-initial-setup/pages/goa/gis-goa-page.h
@@ -28,6 +28,31 @@
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_GOA_PAGE               (gis_goa_page_get_type ())
+#define GIS_GOA_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_GOA_PAGE, GisGoaPage))
+#define GIS_GOA_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_GOA_PAGE, GisGoaPageClass))
+#define GIS_IS_GOA_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_GOA_PAGE))
+#define GIS_IS_GOA_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_GOA_PAGE))
+#define GIS_GOA_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_GOA_PAGE, GisGoaPageClass))
+
+typedef struct _GisGoaPage        GisGoaPage;
+typedef struct _GisGoaPageClass   GisGoaPageClass;
+typedef struct _GisGoaPagePrivate GisGoaPagePrivate;
+
+struct _GisGoaPage
+{
+  GisPage parent;
+
+  GisGoaPagePrivate *priv;
+};
+
+struct _GisGoaPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_goa_page_get_type (void);
+
 void gis_prepare_goa_page (GisDriver *driver);
 
 G_END_DECLS
diff --git a/gnome-initial-setup/pages/language/gis-language-page.c b/gnome-initial-setup/pages/language/gis-language-page.c
index 2a55ded..9cce748 100644
--- a/gnome-initial-setup/pages/language/gis-language-page.c
+++ b/gnome-initial-setup/pages/language/gis-language-page.c
@@ -37,21 +37,13 @@
 #include "cc-common-language.h"
 #include "gdm-languages.h"
 
-#define OBJ(type,name) ((type)gtk_builder_get_object(data->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
+#include <glib-object.h>
 
-typedef struct _LanguageData LanguageData;
+#include "gis-language-page.h"
 
-struct _LanguageData {
-  GisDriver *driver;
-  GtkWidget *widget;
-  GtkBuilder *builder;
+G_DEFINE_TYPE (GisLanguagePage, gis_language_page, GIS_TYPE_PAGE);
 
-  GtkWidget *show_all;
-  GtkWidget *page;
-  GtkWidget *filter_entry;
-  GtkTreeModel *liststore;
-};
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_LANGUAGE_PAGE, GisLanguagePagePrivate))
 
 enum {
   COL_LOCALE_ID,
@@ -60,14 +52,25 @@ enum {
   NUM_COLS,
 };
 
+struct _GisLanguagePagePrivate
+{
+  GtkWidget *show_all;
+  GtkWidget *page;
+  GtkWidget *filter_entry;
+  GtkTreeModel *liststore;
+};
+
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE (page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
 static void
-set_locale_id (LanguageData *data,
-               gchar        *new_locale_id)
+set_locale_id (GisLanguagePage *page,
+               gchar           *new_locale_id)
 {
   gchar *old_locale_id = cc_common_language_get_current_language ();
   if (g_strcmp0 (old_locale_id, new_locale_id) != 0) {
     setlocale (LC_MESSAGES, new_locale_id);
-    gis_driver_locale_changed (data->driver);
+    gis_driver_locale_changed (GIS_PAGE (page)->driver);
   }
   g_free (old_locale_id);
 }
@@ -209,7 +212,7 @@ language_visible (GtkTreeModel *model,
 {
   gchar *locale_name;
   const gchar *filter_contents;
-  LanguageData *data = user_data;
+  GisLanguagePage *page = user_data;
   gboolean visible = TRUE;
   gboolean is_extra;
 
@@ -218,14 +221,14 @@ language_visible (GtkTreeModel *model,
                       COL_IS_EXTRA, &is_extra,
                       -1);
 
-  filter_contents = gtk_entry_get_text (GTK_ENTRY (data->filter_entry));
+  filter_contents = gtk_entry_get_text (GTK_ENTRY (page->priv->filter_entry));
   if (*filter_contents && strcasestr (locale_name, filter_contents) == NULL)
     {
       visible = FALSE;
       goto out;
     }
 
-  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->show_all)) && !is_extra)
+  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->priv->show_all)) && !is_extra)
     {
       visible = FALSE;
       goto out;
@@ -238,7 +241,7 @@ language_visible (GtkTreeModel *model,
 
 static void
 selection_changed (GtkTreeSelection *selection,
-                   LanguageData     *data)
+                   GisLanguagePage  *page)
 {
   GtkTreeModel *model;
   GtkTreeIter iter;
@@ -251,31 +254,30 @@ selection_changed (GtkTreeSelection *selection,
                       COL_LOCALE_ID, &new_locale_id,
                       -1);
 
-  set_locale_id (data, new_locale_id);
+  set_locale_id (page, new_locale_id);
 }
 
-void
-gis_prepare_language_page (GisDriver *driver)
+static void
+gis_language_page_constructed (GObject *object)
 {
-  LanguageData *data;
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
+  GisLanguagePage *page = GIS_LANGUAGE_PAGE (object);
+  GisLanguagePagePrivate *priv = page->priv;
   GtkListStore *liststore;
   GtkTreeModel *filter;
   GtkTreeView *treeview;
 
-  data = g_slice_new0 (LanguageData);
-  data->driver = driver;
-  data->builder = gis_builder (PAGE_ID);
-  data->widget = WID ("language-page");
+  G_OBJECT_CLASS (gis_language_page_parent_class)->constructed (object);
+
+  GIS_PAGE (page)->widget = WID ("language-page");
 
   liststore = gtk_list_store_new (NUM_COLS,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_BOOLEAN);
 
-  data->show_all = WID ("language-show-all");
-  data->filter_entry = WID ("language-filter-entry");
-  data->liststore = GTK_TREE_MODEL (liststore);
+  priv->show_all = WID ("language-show-all");
+  priv->filter_entry = WID ("language-filter-entry");
+  priv->liststore = GTK_TREE_MODEL (liststore);
   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (liststore),
                                            sort_languages, NULL, NULL);
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore),
@@ -286,26 +288,51 @@ gis_prepare_language_page (GisDriver *driver)
 
   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (liststore), NULL);
   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
-                                          language_visible, data, NULL);
+                                          language_visible, page, NULL);
   gtk_tree_view_set_model (treeview, filter);
 
-  add_all_languages (GTK_LIST_STORE (data->liststore));
+  add_all_languages (GTK_LIST_STORE (priv->liststore));
 
-  g_signal_connect_swapped (data->show_all, "toggled",
+  g_signal_connect_swapped (priv->show_all, "toggled",
                             G_CALLBACK (gtk_tree_model_filter_refilter),
                             filter);
 
-  g_signal_connect_swapped (data->filter_entry, "changed",
+  g_signal_connect_swapped (priv->filter_entry, "changed",
                             G_CALLBACK (gtk_tree_model_filter_refilter),
                             filter);
 
   g_signal_connect (gtk_tree_view_get_selection (treeview), "changed",
-                    G_CALLBACK (selection_changed), data);
+                    G_CALLBACK (selection_changed), page);
+  select_current_locale (treeview);
 
-  gis_assistant_add_page (assistant, data->widget);
-  gis_assistant_set_use_arrow_buttons (assistant, data->widget, TRUE);
-  gis_assistant_set_page_complete (assistant, data->widget, TRUE);
+  gis_page_set_complete (GIS_PAGE (page), TRUE);
+  gis_page_set_use_arrow_buttons (GIS_PAGE (page), TRUE);
+  gis_page_set_title (GIS_PAGE (page), _("Welcome"));
+}
 
-  gis_assistant_set_page_title (assistant, data->widget, _("Welcome"));
-  select_current_locale (treeview);
+static void
+gis_language_page_class_init (GisLanguagePageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  object_class->constructed = gis_language_page_constructed;
+
+  g_type_class_add_private (object_class, sizeof(GisLanguagePagePrivate));
+}
+
+static void
+gis_language_page_init (GisLanguagePage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+void
+gis_prepare_language_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_LANGUAGE_PAGE,
+                                     "driver", driver,
+                                     NULL));
 }
diff --git a/gnome-initial-setup/pages/language/gis-language-page.h b/gnome-initial-setup/pages/language/gis-language-page.h
index 878655a..c2695ad 100644
--- a/gnome-initial-setup/pages/language/gis-language-page.h
+++ b/gnome-initial-setup/pages/language/gis-language-page.h
@@ -24,10 +24,37 @@
 #ifndef __GIS_LANGUAGE_PAGE_H__
 #define __GIS_LANGUAGE_PAGE_H__
 
+#include <glib-object.h>
+
 #include "gnome-initial-setup.h"
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_LANGUAGE_PAGE               (gis_language_page_get_type ())
+#define GIS_LANGUAGE_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_LANGUAGE_PAGE, GisLanguagePage))
+#define GIS_LANGUAGE_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_LANGUAGE_PAGE, GisLanguagePageClass))
+#define GIS_IS_LANGUAGE_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_LANGUAGE_PAGE))
+#define GIS_IS_LANGUAGE_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_LANGUAGE_PAGE))
+#define GIS_LANGUAGE_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_LANGUAGE_PAGE, GisLanguagePageClass))
+
+typedef struct _GisLanguagePage        GisLanguagePage;
+typedef struct _GisLanguagePageClass   GisLanguagePageClass;
+typedef struct _GisLanguagePagePrivate GisLanguagePagePrivate;
+
+struct _GisLanguagePage
+{
+  GisPage parent;
+
+  GisLanguagePagePrivate *priv;
+};
+
+struct _GisLanguagePageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_language_page_get_type (void);
+
 void gis_prepare_language_page (GisDriver *driver);
 
 G_END_DECLS
diff --git a/gnome-initial-setup/pages/location/gis-location-page.c b/gnome-initial-setup/pages/location/gis-location-page.c
index 30bff22..0161ea9 100644
--- a/gnome-initial-setup/pages/location/gis-location-page.c
+++ b/gnome-initial-setup/pages/location/gis-location-page.c
@@ -45,32 +45,30 @@
 
 #define DEFAULT_TZ "Europe/London"
 
-#define OBJ(type,name) ((type)gtk_builder_get_object(data->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
-
-typedef struct _LocationData LocationData;
+G_DEFINE_TYPE (GisLocationPage, gis_location_page, GIS_TYPE_PAGE);
 
-struct _LocationData {
-  GisDriver *driver;
-  GtkWidget *widget;
-  GtkBuilder *builder;
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_LOCATION_PAGE, GisLocationPagePrivate))
 
-  /* location data */
+struct _GisLocationPagePrivate
+{
   CcTimezoneMap *map;
   TzLocation *current_location;
   Timedate1 *dtm;
 };
 
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE (page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
 static void
 set_timezone_cb (GObject      *source,
                  GAsyncResult *res,
                  gpointer      user_data)
 {
-  LocationData *data = user_data;
+  GisLocationPage *page = user_data;
   GError *error;
 
   error = NULL;
-  if (!timedate1_call_set_timezone_finish (data->dtm,
+  if (!timedate1_call_set_timezone_finish (page->priv->dtm,
                                            res,
                                            &error)) {
     /* TODO: display any error in a user friendly way */
@@ -81,21 +79,23 @@ set_timezone_cb (GObject      *source,
 
 
 static void
-queue_set_timezone (LocationData *data)
+queue_set_timezone (GisLocationPage *page)
 {
+  GisLocationPagePrivate *priv = page->priv;
+
   /* for now just do it */
-  if (data->current_location) {
-    timedate1_call_set_timezone (data->dtm,
-                                 data->current_location->zone,
+  if (priv->current_location) {
+    timedate1_call_set_timezone (priv->dtm,
+                                 priv->current_location->zone,
                                  TRUE,
                                  NULL,
                                  set_timezone_cb,
-                                 data);
+                                 page);
   }
 }
 
 static void
-update_timezone (LocationData *data)
+update_timezone (GisLocationPage *page)
 {
   GString *str;
   gchar *location;
@@ -103,7 +103,7 @@ update_timezone (LocationData *data)
   gchar *c;
 
   str = g_string_new ("");
-  for (c = data->current_location->zone; *c; c++) {
+  for (c = page->priv->current_location->zone; *c; c++) {
     switch (*c) {
     case '_':
       g_string_append_c (str, ' ');
@@ -130,21 +130,21 @@ update_timezone (LocationData *data)
 }
 
 static void
-location_changed_cb (CcTimezoneMap *map,
-                     TzLocation    *location,
-                     LocationData  *data)
+location_changed_cb (CcTimezoneMap   *map,
+                     TzLocation      *location,
+                     GisLocationPage *page)
 {
   g_debug ("location changed to %s/%s", location->country, location->zone);
 
-  data->current_location = location;
+  page->priv->current_location = location;
 
-  update_timezone (data);
+  update_timezone (page);
 
-  queue_set_timezone (data);
+  queue_set_timezone (page);
 }
 
 static void
-set_location_from_gweather_location (LocationData     *data,
+set_location_from_gweather_location (GisLocationPage  *page,
                                      GWeatherLocation *gloc)
 {
   GWeatherTimezone *zone = gweather_location_get_timezone (gloc);
@@ -164,7 +164,7 @@ set_location_from_gweather_location (LocationData     *data,
       name = id;
     }
     gtk_label_set_label (label, name);
-    cc_timezone_map_set_timezone (data->map, id);
+    cc_timezone_map_set_timezone (page->priv->map, id);
   }
 
   if (city != NULL) {
@@ -178,7 +178,7 @@ set_location_from_gweather_location (LocationData     *data,
 }
 
 static void
-location_changed (GObject *object, GParamSpec *param, LocationData *data)
+location_changed (GObject *object, GParamSpec *param, GisLocationPage *page)
 {
   GWeatherLocationEntry *entry = GWEATHER_LOCATION_ENTRY (object);
   GWeatherLocation *gloc;
@@ -187,7 +187,7 @@ location_changed (GObject *object, GParamSpec *param, LocationData *data)
   if (gloc == NULL)
     return;
 
-  set_location_from_gweather_location (data, gloc);
+  set_location_from_gweather_location (page, gloc);
 
   gweather_location_unref (gloc);
 }
@@ -204,7 +204,7 @@ position_callback (GeocluePosition      *pos,
 		   double                altitude,
 		   GeoclueAccuracy      *accuracy,
 		   GError               *error,
-		   LocationData         *data)
+		   GisLocationPage      *page)
 {
   if (error) {
     g_printerr ("Error getting position: %s\n", error->message);
@@ -213,7 +213,7 @@ position_callback (GeocluePosition      *pos,
     if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
         fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
       GWeatherLocation *city = gweather_location_find_nearest_city (latitude, longitude);
-      set_location_from_gweather_location (data, city);
+      set_location_from_gweather_location (page, city);
     } else {
       g_print ("Position not available.\n");
     }
@@ -221,8 +221,8 @@ position_callback (GeocluePosition      *pos,
 }
 
 static void
-determine_location (GtkWidget    *widget,
-                    LocationData *data)
+determine_location (GtkWidget       *widget,
+                    GisLocationPage *page)
 {
   GeoclueMaster *master;
   GeoclueMasterClient *client;
@@ -250,7 +250,7 @@ determine_location (GtkWidget    *widget,
 
   geoclue_position_get_position_async (position,
                                        (GeocluePositionCallback) position_callback,
-                                       data);
+                                       page);
 
  out:
   g_clear_error (&error);
@@ -259,37 +259,36 @@ determine_location (GtkWidget    *widget,
 }
 #endif
 
-void
-gis_prepare_location_page (GisDriver *driver)
+static void
+gis_location_page_constructed (GObject *object)
 {
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
+  GisLocationPage *page = GIS_LOCATION_PAGE (object);
+  GisLocationPagePrivate *priv = page->priv;
   GtkWidget *frame, *map, *entry;
   GWeatherLocation *world;
   GError *error;
   const gchar *timezone;
-  LocationData *data;
 
-  data = g_slice_new0 (LocationData);
-  data->driver = driver;
-  data->builder = gis_builder (PAGE_ID);
-  data->widget = WID ("location-page");
+  G_OBJECT_CLASS (gis_location_page_parent_class)->constructed (object);
+
+  GIS_PAGE (page)->widget = WID ("location-page");
 
   frame = WID("location-map-frame");
 
   error = NULL;
-  data->dtm = timedate1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+  priv->dtm = timedate1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
                                                 G_DBUS_PROXY_FLAGS_NONE,
                                                 "org.freedesktop.timedate1",
                                                 "/org/freedesktop/timedate1",
                                                 NULL,
                                                 &error);
-  if (data->dtm == NULL) {
+  if (priv->dtm == NULL) {
     g_error ("Failed to create proxy for timedated: %s", error->message);
     exit (1);
   }
 
-  data->map = cc_timezone_map_new ();
-  map = (GtkWidget *)data->map;
+  priv->map = cc_timezone_map_new ();
+  map = GTK_WIDGET (priv->map);
   gtk_widget_set_hexpand (map, TRUE);
   gtk_widget_set_vexpand (map, TRUE);
   gtk_widget_set_halign (map, GTK_ALIGN_FILL);
@@ -311,33 +310,71 @@ gis_prepare_location_page (GisDriver *driver)
   gtk_grid_attach (GTK_GRID (frame), entry, 0, 1, 2, 1);
 #endif
 
-  timezone = timedate1_get_timezone (data->dtm);
+  timezone = timedate1_get_timezone (priv->dtm);
 
-  if (!cc_timezone_map_set_timezone (data->map, timezone)) {
+  if (!cc_timezone_map_set_timezone (priv->map, timezone)) {
     g_warning ("Timezone '%s' is unhandled, setting %s as default", timezone, DEFAULT_TZ);
-    cc_timezone_map_set_timezone (data->map, DEFAULT_TZ);
+    cc_timezone_map_set_timezone (priv->map, DEFAULT_TZ);
   }
   else {
     g_debug ("System timezone is '%s'", timezone);
   }
 
-  data->current_location = cc_timezone_map_get_location (data->map);
-  update_timezone (data);
- 
+  priv->current_location = cc_timezone_map_get_location (priv->map);
+  update_timezone (page);
+
   g_signal_connect (G_OBJECT (entry), "notify::location",
-                    G_CALLBACK (location_changed), data);
+                    G_CALLBACK (location_changed), page);
 
   g_signal_connect (map, "location-changed",
-                    G_CALLBACK (location_changed_cb), data);
+                    G_CALLBACK (location_changed_cb), page);
 
 #if WANT_GEOCLUE
   g_signal_connect (WID ("location-auto-button"), "clicked",
-                    G_CALLBACK (determine_location), data);
+                    G_CALLBACK (determine_location), page);
 #else
   gtk_widget_hide (WID ("location-auto-button"));
 #endif
 
-  gis_assistant_add_page (assistant, data->widget);
-  gis_assistant_set_page_title (assistant, data->widget, _("Location"));
-  gis_assistant_set_page_complete (assistant, data->widget, TRUE);
+  gis_page_set_title (GIS_PAGE (page), _("Location"));
+  gis_page_set_complete (GIS_PAGE (page), TRUE);
+}
+
+static void
+gis_location_page_dispose (GObject *object)
+{
+  GisLocationPage *page = GIS_LOCATION_PAGE (object);
+  GisLocationPagePrivate *priv = page->priv;
+
+  g_clear_object (&priv->dtm);
+
+  G_OBJECT_CLASS (gis_location_page_parent_class)->dispose (object);
+}
+
+static void
+gis_location_page_class_init (GisLocationPageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  object_class->constructed = gis_location_page_constructed;
+  object_class->dispose = gis_location_page_dispose;
+  
+  g_type_class_add_private (object_class, sizeof(GisLocationPagePrivate));
+}
+
+static void
+gis_location_page_init (GisLocationPage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+void
+gis_prepare_location_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_LOCATION_PAGE,
+                                     "driver", driver,
+                                     NULL));
 }
diff --git a/gnome-initial-setup/pages/location/gis-location-page.h b/gnome-initial-setup/pages/location/gis-location-page.h
index 50a20be..eb78ee1 100644
--- a/gnome-initial-setup/pages/location/gis-location-page.h
+++ b/gnome-initial-setup/pages/location/gis-location-page.h
@@ -24,10 +24,37 @@
 #ifndef __GIS_LOCATION_PAGE_H__
 #define __GIS_LOCATION_PAGE_H__
 
+#include <glib-object.h>
+
 #include "gnome-initial-setup.h"
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_LOCATION_PAGE               (gis_location_page_get_type ())
+#define GIS_LOCATION_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_LOCATION_PAGE, GisLocationPage))
+#define GIS_LOCATION_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_LOCATION_PAGE, GisLocationPageClass))
+#define GIS_IS_LOCATION_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_LOCATION_PAGE))
+#define GIS_IS_LOCATION_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_LOCATION_PAGE))
+#define GIS_LOCATION_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_LOCATION_PAGE, GisLocationPageClass))
+
+typedef struct _GisLocationPage        GisLocationPage;
+typedef struct _GisLocationPageClass   GisLocationPageClass;
+typedef struct _GisLocationPagePrivate GisLocationPagePrivate;
+
+struct _GisLocationPage
+{
+  GisPage parent;
+
+  GisLocationPagePrivate *priv;
+};
+
+struct _GisLocationPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_location_page_get_type (void);
+
 void gis_prepare_location_page (GisDriver *driver);
 
 G_END_DECLS
diff --git a/gnome-initial-setup/pages/network/gis-network-page.c b/gnome-initial-setup/pages/network/gis-network-page.c
index ec4c244..e87a4fd 100644
--- a/gnome-initial-setup/pages/network/gis-network-page.c
+++ b/gnome-initial-setup/pages/network/gis-network-page.c
@@ -43,17 +43,11 @@
 #include "panel-cell-renderer-mode.h"
 #include "panel-cell-renderer-security.h"
 
-typedef struct _NetworkData NetworkData;
+G_DEFINE_TYPE (GisNetworkPage, gis_network_page, GIS_TYPE_PAGE);
 
-#define OBJ(type,name) ((type)gtk_builder_get_object(data->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
-
-struct _NetworkData {
-  GisDriver *driver;
-  GtkWidget *widget;
-  GtkBuilder *builder;
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_NETWORK_PAGE, GisNetworkPagePrivate))
 
-  /* network data */
+struct _GisNetworkPagePrivate {
   NMClient *nm_client;
   NMRemoteSettings *nm_settings;
   NMDevice *nm_device;
@@ -64,6 +58,9 @@ struct _NetworkData {
   guint pulse;
 };
 
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE(page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
 enum {
   PANEL_WIRELESS_COLUMN_ID,
   PANEL_WIRELESS_COLUMN_TITLE,
@@ -159,30 +156,32 @@ get_access_point_security (NMAccessPoint *ap)
 static gboolean
 bump_pulse (gpointer user_data)
 {
-  NetworkData *data = user_data;
+  GisNetworkPage *page = user_data;
+  GisNetworkPagePrivate *priv = page->priv;
   GtkTreeIter iter;
   GtkTreePath *path;
   GtkTreeModel *model;
 
-  data->pulse++;
+  priv->pulse++;
 
-  if (data->refreshing || !gtk_tree_row_reference_valid (data->row))
+  if (priv->refreshing || !gtk_tree_row_reference_valid (priv->row))
     return FALSE;
 
-  model = (GtkTreeModel *)data->ap_list;
-  path = gtk_tree_row_reference_get_path (data->row);
+  model = (GtkTreeModel *)priv->ap_list;
+  path = gtk_tree_row_reference_get_path (priv->row);
   gtk_tree_model_get_iter (model, &iter, path);
   gtk_tree_path_free (path);
-  gtk_list_store_set (data->ap_list, &iter,
-                      PANEL_WIRELESS_COLUMN_PULSE, data->pulse,
+  gtk_list_store_set (priv->ap_list, &iter,
+                      PANEL_WIRELESS_COLUMN_PULSE, priv->pulse,
                       -1);
 
   return TRUE;
 }
 
 static void
-add_access_point (NetworkData *data, NMAccessPoint *ap, NMAccessPoint *active)
+add_access_point (GisNetworkPage *page, NMAccessPoint *ap, NMAccessPoint *active)
 {
+  GisNetworkPagePrivate *priv = page->priv;
   const GByteArray *ssid;
   const gchar *ssid_text;
   const gchar *object_path;
@@ -198,7 +197,7 @@ add_access_point (NetworkData *data, NMAccessPoint *ap, NMAccessPoint *active)
 
   if (active &&
       nm_utils_same_ssid (ssid, nm_access_point_get_ssid (active), TRUE)) {
-    switch (nm_device_get_state (data->nm_device))
+    switch (nm_device_get_state (priv->nm_device))
       {
       case NM_DEVICE_STATE_PREPARE:
       case NM_DEVICE_STATE_CONFIG:
@@ -222,8 +221,8 @@ add_access_point (NetworkData *data, NMAccessPoint *ap, NMAccessPoint *active)
     activating = FALSE;
   }
 
-  gtk_list_store_append (data->ap_list, &iter);
-  gtk_list_store_set (data->ap_list, &iter,
+  gtk_list_store_append (priv->ap_list, &iter);
+  gtk_list_store_set (priv->ap_list, &iter,
                       PANEL_WIRELESS_COLUMN_ID, object_path,
                       PANEL_WIRELESS_COLUMN_TITLE, ssid_text,
                       PANEL_WIRELESS_COLUMN_STRENGTH, nm_access_point_get_strength (ap),
@@ -231,29 +230,29 @@ add_access_point (NetworkData *data, NMAccessPoint *ap, NMAccessPoint *active)
                       PANEL_WIRELESS_COLUMN_SECURITY, get_access_point_security (ap),
                       PANEL_WIRELESS_COLUMN_ACTIVATING, activating,
                       PANEL_WIRELESS_COLUMN_ACTIVE, activated,
-                      PANEL_WIRELESS_COLUMN_PULSE, data->pulse,
+                      PANEL_WIRELESS_COLUMN_PULSE, priv->pulse,
                       -1);
   if (activating) {
     GtkTreePath *path;
     GtkTreeModel *model;
 
-    model = (GtkTreeModel*)data->ap_list;
+    model = (GtkTreeModel*)priv->ap_list;
     path = gtk_tree_model_get_path (model, &iter);
-    data->row = gtk_tree_row_reference_new (model, path);
+    priv->row = gtk_tree_row_reference_new (model, path);
     gtk_tree_path_free (path);
 
-    g_timeout_add (80, bump_pulse, data);
+    g_timeout_add (80, bump_pulse, page);
   }
-
 }
 
 static void
-add_access_point_other (NetworkData *data)
+add_access_point_other (GisNetworkPage *page)
 {
+  GisNetworkPagePrivate *priv = page->priv;
   GtkTreeIter iter;
 
-  gtk_list_store_append (data->ap_list, &iter);
-  gtk_list_store_set (data->ap_list, &iter,
+  gtk_list_store_append (priv->ap_list, &iter);
+  gtk_list_store_set (priv->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
@@ -266,13 +265,14 @@ add_access_point_other (NetworkData *data)
                       PANEL_WIRELESS_COLUMN_SECURITY, NM_AP_SEC_UNKNOWN,
                       PANEL_WIRELESS_COLUMN_ACTIVATING, FALSE,
                       PANEL_WIRELESS_COLUMN_ACTIVE, FALSE,
-                      PANEL_WIRELESS_COLUMN_PULSE, data->pulse,
+                      PANEL_WIRELESS_COLUMN_PULSE, priv->pulse,
                       -1);
 }
 
 static void
-select_and_scroll_to_ap (NetworkData *data, NMAccessPoint *ap)
+select_and_scroll_to_ap (GisNetworkPage *page, NMAccessPoint *ap)
 {
+  GisNetworkPagePrivate *priv = page->priv;
   GtkTreeModel *model;
   GtkTreeView *tv;
   GtkTreeViewColumn *col;
@@ -283,7 +283,7 @@ select_and_scroll_to_ap (NetworkData *data, NMAccessPoint *ap)
   const GByteArray *ssid;
   const gchar *ssid_text;
 
-  model = (GtkTreeModel *)data->ap_list;
+  model = (GtkTreeModel *)priv->ap_list;
 
   if (!gtk_tree_model_get_iter_first (model, &iter))
     return;
@@ -312,21 +312,20 @@ select_and_scroll_to_ap (NetworkData *data, NMAccessPoint *ap)
   } while (gtk_tree_model_iter_next (model, &iter));
 }
 
-static void refresh_wireless_list (NetworkData *data);
+static void refresh_wireless_list (GisNetworkPage *page);
 
 static gboolean
 refresh_again (gpointer user_data)
 {
-  NetworkData *data = user_data;
-
-  refresh_wireless_list (data);
-
+  GisNetworkPage *page = GIS_NETWORK_PAGE (user_data);
+  refresh_wireless_list (page);
   return FALSE;
 }
 
 static void
-refresh_without_device (NetworkData *data)
+refresh_without_device (GisNetworkPage *page)
 {
+  GisNetworkPagePrivate *priv = page->priv;
   GtkWidget *label;
   GtkWidget *spinner;
   GtkWidget *swin;
@@ -335,10 +334,9 @@ refresh_without_device (NetworkData *data)
   label = WID("no-network-label");
   spinner = WID("no-network-spinner");
 
-  if (nm_client_get_state (data->nm_client) == NM_STATE_CONNECTED_GLOBAL)
-    /* advance page */
-    gis_assistant_next_page (gis_driver_get_assistant (data->driver));
-  if (data->nm_device != NULL)
+  if (nm_client_get_state (priv->nm_client) == NM_STATE_CONNECTED_GLOBAL)
+    ; /* XXX - don't construct page */
+  else if (priv->nm_device != NULL)
     gtk_label_set_text (GTK_LABEL (label), _("Network is not available."));
   else
     gtk_label_set_text (GTK_LABEL (label), _("No network devices found."));
@@ -349,8 +347,9 @@ refresh_without_device (NetworkData *data)
 }
 
 static void
-refresh_wireless_list (NetworkData *data)
+refresh_wireless_list (GisNetworkPage *page)
 {
+  GisNetworkPagePrivate *priv = page->priv;
   NMDeviceState state = NM_DEVICE_STATE_UNAVAILABLE;
   NMAccessPoint *active_ap = NULL;
   NMAccessPoint *ap;
@@ -361,21 +360,21 @@ refresh_wireless_list (NetworkData *data)
   GtkWidget *spinner;
   GtkWidget *swin;
 
-  data->refreshing = TRUE;
+  priv->refreshing = TRUE;
 
-  if (NM_IS_DEVICE_WIFI (data->nm_device)) {
-    state = nm_device_get_state (data->nm_device);
+  if (NM_IS_DEVICE_WIFI (priv->nm_device)) {
+    state = nm_device_get_state (priv->nm_device);
 
-    active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (data->nm_device));
+    active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (priv->nm_device));
 
     gtk_tree_view_set_model (OBJ(GtkTreeView*, "network-list"), NULL);
-    gtk_list_store_clear (data->ap_list);
-    if (data->row) {
-      gtk_tree_row_reference_free (data->row);
-      data->row = NULL;
+    gtk_list_store_clear (priv->ap_list);
+    if (priv->row) {
+      gtk_tree_row_reference_free (priv->row);
+      priv->row = NULL;
     }
 
-    aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (data->nm_device));
+    aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (priv->nm_device));
   }
 
   swin = WID("network-scrolledwindow");
@@ -384,7 +383,7 @@ refresh_wireless_list (NetworkData *data)
 
   if (state == NM_DEVICE_STATE_UNMANAGED ||
       state == NM_DEVICE_STATE_UNAVAILABLE) {
-    refresh_without_device (data);
+    refresh_without_device (page);
     goto out;
   }
   else if (aps == NULL || aps->len == 0) {
@@ -392,7 +391,7 @@ refresh_wireless_list (NetworkData *data)
     gtk_widget_hide (swin);
     gtk_widget_show (spinner);
     gtk_widget_show (label);
-    g_timeout_add_seconds (1, refresh_again, data);
+    g_timeout_add_seconds (1, refresh_again, page);
 
     goto out;
   }
@@ -405,24 +404,27 @@ refresh_wireless_list (NetworkData *data)
   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 (data, ap, active_ap);
+    add_access_point (page, ap, active_ap);
   }
   g_ptr_array_unref (unique_aps);
-  add_access_point_other (data);
+  add_access_point_other (page);
 
  out:
-  gtk_tree_view_set_model (OBJ(GtkTreeView*, "network-list"), (GtkTreeModel*)data->ap_list);
+  gtk_tree_view_set_model (OBJ(GtkTreeView*, "network-list"), (GtkTreeModel*)priv->ap_list);
 
   if (active_ap)
-    select_and_scroll_to_ap (data, active_ap);
+    select_and_scroll_to_ap (page, active_ap);
 
-  data->refreshing = FALSE;
+  priv->refreshing = FALSE;
 }
 
 static void
-device_state_changed (NMDevice *device, GParamSpec *pspec, NetworkData *data)
+device_state_changed (NMDevice   *device,
+                      GParamSpec *pspec,
+                      gpointer    user_data)
 {
-  refresh_wireless_list (data);
+  GisNetworkPage *page = GIS_NETWORK_PAGE (user_data);
+  refresh_wireless_list (page);
 }
 
 static void
@@ -431,11 +433,11 @@ connection_activate_cb (NMClient *client,
                         GError *error,
                         gpointer user_data)
 {
-  NetworkData *data = user_data;
+  GisNetworkPage *page = GIS_NETWORK_PAGE (user_data);
 
   if (connection == NULL) {
     /* failed to activate */
-    refresh_wireless_list (data);
+    refresh_wireless_list (page);
   }
 }
 
@@ -452,7 +454,7 @@ connection_add_activate_cb (NMClient *client,
 static void
 connect_to_hidden_network_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
-  NetworkData *data = user_data;
+  GisNetworkPage *page = GIS_NETWORK_PAGE (user_data);
   GError *error = NULL;
   GVariant *result = NULL;
 
@@ -463,11 +465,11 @@ connect_to_hidden_network_cb (GObject *source_object, GAsyncResult *res, gpointe
     g_error_free (error);
   }
 
-  refresh_wireless_list (data);
+  refresh_wireless_list (page);
 }
 
 static void
-connect_to_hidden_network (NetworkData *data)
+connect_to_hidden_network (GisNetworkPage *page)
 {
   GDBusProxy *proxy;
   GVariant *res = NULL;
@@ -498,7 +500,7 @@ connect_to_hidden_network (NetworkData *data)
                      5000, /* don't wait forever */
                      NULL,
                      connect_to_hidden_network_cb,
-                     data);
+                     page);
 
  out:
   if (proxy != NULL)
@@ -508,8 +510,9 @@ connect_to_hidden_network (NetworkData *data)
 }
 
 static void
-wireless_selection_changed (GtkTreeSelection *selection, NetworkData *data)
+wireless_selection_changed (GtkTreeSelection *selection, GisNetworkPage *page)
 {
+  GisNetworkPagePrivate *priv = page->priv;
   GtkTreeModel *model;
   GtkTreeIter iter;
   gchar *object_path;
@@ -521,7 +524,7 @@ wireless_selection_changed (GtkTreeSelection *selection, NetworkData *data)
   const GByteArray *ssid;
   const gchar *ssid_tmp;
 
-  if (data->refreshing)
+  if (priv->refreshing)
     return;
 
   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
@@ -532,17 +535,17 @@ wireless_selection_changed (GtkTreeSelection *selection, NetworkData *data)
                       PANEL_WIRELESS_COLUMN_TITLE, &ssid_target,
                       -1);
 
-  gtk_list_store_set (data->ap_list, &iter,
+  gtk_list_store_set (priv->ap_list, &iter,
                       PANEL_WIRELESS_COLUMN_ACTIVATING, TRUE,
                       -1);
 
   if (g_strcmp0 (object_path, "ap-other...") == 0) {
-    connect_to_hidden_network (data);
+    connect_to_hidden_network (page);
     goto out;
   }
 
-  list = nm_remote_settings_list_connections (data->nm_settings);
-  filtered = nm_device_filter_connections (data->nm_device, list);
+  list = nm_remote_settings_list_connections (priv->nm_settings);
+  filtered = nm_device_filter_connections (priv->nm_device, list);
 
   connection_to_activate = NULL;
 
@@ -565,33 +568,33 @@ wireless_selection_changed (GtkTreeSelection *selection, NetworkData *data)
   g_slist_free (filtered);
 
   if (connection_to_activate != NULL) {
-    nm_client_activate_connection (data->nm_client,
+    nm_client_activate_connection (priv->nm_client,
                                    connection_to_activate,
-                                   data->nm_device, NULL,
-                                   connection_activate_cb, data);
+                                   priv->nm_device, NULL,
+                                   connection_activate_cb, page);
     goto out;
   }
 
-  nm_client_add_and_activate_connection (data->nm_client,
+  nm_client_add_and_activate_connection (priv->nm_client,
                                          NULL,
-                                         data->nm_device, object_path,
-                                         connection_add_activate_cb, data);
+                                         priv->nm_device, object_path,
+                                         connection_add_activate_cb, page);
 
  out:
   g_free (object_path);
   g_free (ssid_target);
 
-  refresh_wireless_list (data);
+  refresh_wireless_list (page);
 }
 
 static void
-connection_state_changed (NMActiveConnection *c, GParamSpec *pspec, NetworkData *data)
+connection_state_changed (NMActiveConnection *c, GParamSpec *pspec, GisNetworkPage *page)
 {
-  refresh_wireless_list (data);
+  refresh_wireless_list (page);
 }
 
 static void
-active_connections_changed (NMClient *client, GParamSpec *pspec, NetworkData *data)
+active_connections_changed (NMClient *client, GParamSpec *pspec, GisNetworkPage *page)
 {
   const GPtrArray *connections;
   guint i;
@@ -603,17 +606,19 @@ active_connections_changed (NMClient *client, GParamSpec *pspec, NetworkData *da
     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), data);
+                        G_CALLBACK (connection_state_changed), page);
       g_object_set_data (G_OBJECT (connection), "has-state-changed-handler", GINT_TO_POINTER (1));
     }
   }
 
-  refresh_wireless_list (data);
+  refresh_wireless_list (page);
 }
 
-void
-gis_prepare_network_page (GisDriver *driver)
+static void
+gis_network_page_constructed (GObject *object)
 {
+  GisNetworkPage *page = GIS_NETWORK_PAGE (object);
+  GisNetworkPagePrivate *priv = page->priv;
   GtkTreeViewColumn *col;
   GtkCellRenderer *cell;
   GtkTreeSortable *sortable;
@@ -623,12 +628,10 @@ gis_prepare_network_page (GisDriver *driver)
   guint i;
   DBusGConnection *bus;
   GError *error;
-  NetworkData *data = g_slice_new0 (NetworkData);
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
 
-  data->driver = driver;
-  data->builder = gis_builder (PAGE_ID);
-  data->widget = WID ("network-page");
+  G_OBJECT_CLASS (gis_network_page_parent_class)->constructed (object);
+
+  GIS_PAGE (page)->widget = WID ("network-page");
 
   col = OBJ(GtkTreeViewColumn*, "network-list-column");
 
@@ -677,18 +680,18 @@ gis_prepare_network_page (GisDriver *driver)
                                   "security", PANEL_WIRELESS_COLUMN_SECURITY,
                                   NULL);
 
-  data->ap_list = g_object_ref (OBJ(GtkListStore *, "liststore-wireless"));
-  sortable = GTK_TREE_SORTABLE (data->ap_list);
+  priv->ap_list = g_object_ref (OBJ(GtkListStore *, "liststore-wireless"));
+  sortable = GTK_TREE_SORTABLE (priv->ap_list);
   gtk_tree_sortable_set_sort_column_id (sortable,
                                         PANEL_WIRELESS_COLUMN_STRENGTH,
                                         GTK_SORT_DESCENDING);
 
-  data->nm_client = nm_client_new ();
+  priv->nm_client = nm_client_new ();
 
-  g_signal_connect (data->nm_client, "notify::active-connections",
-                    G_CALLBACK (active_connections_changed), data);
+  g_signal_connect (priv->nm_client, "notify::active-connections",
+                    G_CALLBACK (active_connections_changed), page);
 
-  devices = nm_client_get_devices (data->nm_client);
+  devices = nm_client_get_devices (priv->nm_client);
   if (devices) {
     for (i = 0; i < devices->len; i++) {
       device = g_ptr_array_index (devices, i);
@@ -698,16 +701,17 @@ gis_prepare_network_page (GisDriver *driver)
 
       if (nm_device_get_device_type (device) == NM_DEVICE_TYPE_WIFI) {
         /* FIXME deal with multiple, dynamic devices */
-        data->nm_device = device;
+        priv->nm_device = device;
         g_signal_connect (G_OBJECT (device), "notify::state",
-                          G_CALLBACK (device_state_changed), data);
+                          G_CALLBACK (device_state_changed), page);
         break;
       }
     }
   }
 
-  if (data->nm_device == NULL) {
-    refresh_without_device (data);
+  if (priv->nm_device == NULL) {
+    /* XXX */
+    refresh_without_device (page);
     goto out;
   }
 
@@ -718,18 +722,59 @@ gis_prepare_network_page (GisDriver *driver)
                error->message);
     g_error_free (error);
   }
-  data->nm_settings = nm_remote_settings_new (bus);
+  priv->nm_settings = nm_remote_settings_new (bus);
 
   selection = OBJ(GtkTreeSelection*, "network-list-selection");
 
   g_signal_connect (selection, "changed",
-                    G_CALLBACK (wireless_selection_changed), data);
+                    G_CALLBACK (wireless_selection_changed), page);
 
-  refresh_wireless_list (data);
-
-  gis_assistant_add_page (assistant, data->widget);
-  gis_assistant_set_page_title (assistant, data->widget, _("Network"));
-  gis_assistant_set_page_complete (assistant, data->widget, TRUE);
+  refresh_wireless_list (page);
 
+  gis_page_set_title (GIS_PAGE (page), _("Network"));
+  gis_page_set_complete (GIS_PAGE (page), TRUE);
  out: ;
 }
+
+static void
+gis_network_page_dispose (GObject *object)
+{
+  GisNetworkPage *page = GIS_NETWORK_PAGE (object);
+  GisNetworkPagePrivate *priv = page->priv;
+
+  g_clear_object (&priv->nm_client);
+  g_clear_object (&priv->nm_settings);
+  g_clear_object (&priv->nm_device);
+  g_clear_object (&priv->ap_list);
+  g_clear_pointer (&priv->row, gtk_tree_row_reference_free);
+
+  G_OBJECT_CLASS (gis_network_page_parent_class)->dispose (object);
+}
+
+static void
+gis_network_page_class_init (GisNetworkPageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  object_class->constructed = gis_network_page_constructed;
+  object_class->dispose = gis_network_page_dispose;
+
+  g_type_class_add_private (object_class, sizeof(GisNetworkPagePrivate));
+}
+
+static void
+gis_network_page_init (GisNetworkPage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+void
+gis_prepare_network_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_NETWORK_PAGE,
+                                     "driver", driver,
+                                     NULL));
+}
diff --git a/gnome-initial-setup/pages/network/gis-network-page.h b/gnome-initial-setup/pages/network/gis-network-page.h
index 86975d1..89e74d2 100644
--- a/gnome-initial-setup/pages/network/gis-network-page.h
+++ b/gnome-initial-setup/pages/network/gis-network-page.h
@@ -28,6 +28,31 @@
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_NETWORK_PAGE               (gis_network_page_get_type ())
+#define GIS_NETWORK_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_NETWORK_PAGE, GisNetworkPage))
+#define GIS_NETWORK_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_NETWORK_PAGE, GisNetworkPageClass))
+#define GIS_IS_NETWORK_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_NETWORK_PAGE))
+#define GIS_IS_NETWORK_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_NETWORK_PAGE))
+#define GIS_NETWORK_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_NETWORK_PAGE, GisNetworkPageClass))
+
+typedef struct _GisNetworkPage        GisNetworkPage;
+typedef struct _GisNetworkPageClass   GisNetworkPageClass;
+typedef struct _GisNetworkPagePrivate GisNetworkPagePrivate;
+
+struct _GisNetworkPage
+{
+  GisPage parent;
+
+  GisNetworkPagePrivate *priv;
+};
+
+struct _GisNetworkPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_network_page_get_type (void);
+
 void gis_prepare_network_page (GisDriver *driver);
 
 G_END_DECLS
diff --git a/gnome-initial-setup/pages/summary/gis-summary-page.c b/gnome-initial-setup/pages/summary/gis-summary-page.c
index eb969c9..09ee1df 100644
--- a/gnome-initial-setup/pages/summary/gis-summary-page.c
+++ b/gnome-initial-setup/pages/summary/gis-summary-page.c
@@ -36,24 +36,22 @@
 
 #include <gdm/gdm-client.h>
 
-#define OBJ(type,name) ((type)gtk_builder_get_object(data->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
-
 #define SERVICE_NAME "gdm-password"
 
 #define SKELETON_PATH "/gnome-initial-setup/skeleton"
 
-typedef struct _SummaryData SummaryData;
+G_DEFINE_TYPE (GisSummaryPage, gis_summary_page, GIS_TYPE_PAGE);
 
-struct _SummaryData {
-  GisDriver *driver;
-  GtkWidget *widget;
-  GtkBuilder *builder;
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIS_TYPE_SUMMARY_PAGE, GisSummaryPagePrivate))
 
+struct _GisSummaryPagePrivate {
   ActUser *user_account;
   const gchar *user_password;
 };
 
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE(page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
 static gboolean
 connect_to_gdm (GdmGreeter      **greeter,
                 GdmUserVerifier **user_verifier)
@@ -120,17 +118,19 @@ copy_file_to_tmpfs (const char *dest_base,
 }
 
 static char *
-get_skeleton_dir (SummaryData *data)
+get_skeleton_dir (GisSummaryPage *page)
 {
-  uid_t uid = act_user_get_uid (data->user_account);
+  GisSummaryPagePrivate *priv = page->priv;
+  uid_t uid = act_user_get_uid (priv->user_account);
   return g_strdup_printf ("/run/user/%d" SKELETON_PATH, uid);
 }
 
 static void
-copy_files_to_tmpfs (SummaryData *data)
+copy_files_to_tmpfs (GisSummaryPage *page)
 {
-  const char *user = act_user_get_user_name (data->user_account);
-  char *dest = get_skeleton_dir (data);
+  GisSummaryPagePrivate *priv = page->priv;
+  const char *user = act_user_get_user_name (priv->user_account);
+  char *dest = get_skeleton_dir (page);
   GError *error = NULL;
 
   if (!pkinstall (user, "--directory", dest, &error)) {
@@ -153,7 +153,7 @@ copy_files_to_tmpfs (SummaryData *data)
 }
 
 static void
-request_info_query (SummaryData     *data,
+request_info_query (GisSummaryPage  *page,
                     GdmUserVerifier *user_verifier,
                     const char      *question,
                     gboolean         is_secret)
@@ -168,7 +168,7 @@ static void
 on_info (GdmUserVerifier *user_verifier,
          const char      *service_name,
          const char      *info,
-         SummaryData     *data)
+         GisSummaryPage  *page)
 {
   g_debug ("PAM module info: %s\n", info);
 }
@@ -177,7 +177,7 @@ static void
 on_problem (GdmUserVerifier *user_verifier,
             const char      *service_name,
             const char      *problem,
-            SummaryData     *data)
+            GisSummaryPage  *page)
 {
   g_warning ("PAM module error: %s\n", problem);
 }
@@ -186,45 +186,47 @@ static void
 on_info_query (GdmUserVerifier *user_verifier,
                const char      *service_name,
                const char      *question,
-               SummaryData     *data)
+               GisSummaryPage  *page)
 {
-  request_info_query (data, user_verifier, question, FALSE);
+  request_info_query (page, user_verifier, question, FALSE);
 }
 
 static void
 on_secret_info_query (GdmUserVerifier *user_verifier,
                       const char      *service_name,
                       const char      *question,
-                      SummaryData     *data)
+                      GisSummaryPage  *page)
 {
-  gboolean should_send_password = data->user_password != NULL;
+  GisSummaryPagePrivate *priv = page->priv;
+  gboolean should_send_password = priv->user_password != NULL;
 
   g_debug ("PAM module secret info query: %s\n", question);
   if (should_send_password) {
     g_debug ("sending password\n");
     gdm_user_verifier_call_answer_query (user_verifier,
                                          service_name,
-                                         data->user_password,
+                                         priv->user_password,
                                          NULL, NULL, NULL);
-    g_clear_pointer (&data->user_password, (GDestroyNotify) g_free);
+    g_clear_pointer (&priv->user_password, (GDestroyNotify) g_free);
   } else {
-    request_info_query (data, user_verifier, question, TRUE);
+    request_info_query (page, user_verifier, question, TRUE);
   }
 }
 
 static void
-on_session_opened (GdmGreeter  *greeter,
-                   const char  *service_name,
-                   SummaryData *data)
+on_session_opened (GdmGreeter     *greeter,
+                   const char     *service_name,
+                   GisSummaryPage *page)
 {
-  copy_files_to_tmpfs (data);
+  copy_files_to_tmpfs (page);
   gdm_greeter_call_start_session_when_ready_sync (greeter, service_name,
                                                   TRUE, NULL, NULL);
 }
 
 static void
-log_user_in (SummaryData *data)
+log_user_in (GisSummaryPage *page)
 {
+  GisSummaryPagePrivate *priv = page->priv;
   GError *error = NULL;
   GdmGreeter *greeter;
   GdmUserVerifier *user_verifier;
@@ -240,20 +242,20 @@ log_user_in (SummaryData *data)
   }
 
   g_signal_connect (user_verifier, "info",
-                    G_CALLBACK (on_info), data);
+                    G_CALLBACK (on_info), page);
   g_signal_connect (user_verifier, "problem",
-                    G_CALLBACK (on_problem), data);
+                    G_CALLBACK (on_problem), page);
   g_signal_connect (user_verifier, "info-query",
-                    G_CALLBACK (on_info_query), data);
+                    G_CALLBACK (on_info_query), page);
   g_signal_connect (user_verifier, "secret-info-query",
-                    G_CALLBACK (on_secret_info_query), data);
+                    G_CALLBACK (on_secret_info_query), page);
 
   g_signal_connect (greeter, "session-opened",
-                    G_CALLBACK (on_session_opened), data);
+                    G_CALLBACK (on_session_opened), page);
 
   gdm_user_verifier_call_begin_verification_for_user_sync (user_verifier,
                                                            SERVICE_NAME,
-                                                           act_user_get_user_name (data->user_account),
+                                                           act_user_get_user_name (priv->user_account),
                                                            NULL, &error);
 
   if (error != NULL) {
@@ -263,19 +265,19 @@ log_user_in (SummaryData *data)
 }
 
 static void
-byebye (SummaryData *data)
+byebye (GisSummaryPage *page)
 {
-  log_user_in (data);
+  log_user_in (page);
 }
 
 static void
-byebye_cb (GtkButton *button, SummaryData *data)
+byebye_cb (GtkButton *button, GisSummaryPage *page)
 {
-  byebye (data);
+  byebye (page);
 }
 
 static void
-tour_cb (GtkButton *button, SummaryData *data)
+tour_cb (GtkButton *button, GisSummaryPage *page)
 {
   gchar *file;
 
@@ -283,22 +285,25 @@ tour_cb (GtkButton *button, SummaryData *data)
   file = g_build_filename (g_get_user_config_dir (), "run-welcome-tour", NULL);
   g_file_set_contents (file, "yes", -1, NULL);
   g_free (file);
-  byebye (data);
+  byebye (page);
 }
 
 static void
-prepare_cb (GisAssistant *assistant, GtkWidget *page, SummaryData *data)
+prepare_cb (GisAssistant   *assistant,
+            GtkWidget      *widget,
+            GisSummaryPage *page)
 {
-  if (page == data->widget)
+  if (GIS_PAGE (page)->widget == widget)
     {
-      gis_driver_get_user_permissions (data->driver,
-                                       &data->user_account,
-                                       &data->user_password);
+      GisSummaryPagePrivate *priv = page->priv;
+      gis_driver_get_user_permissions (GIS_PAGE (page)->driver,
+                                       &priv->user_account,
+                                       &priv->user_password);
     }
 }
 
 static GtkBuilder *
-get_builder (void)
+gis_summary_page_get_builder (GisPage *page)
 {
   GtkBuilder *builder = gtk_builder_new ();
 
@@ -327,23 +332,49 @@ get_builder (void)
   return builder;
 }
 
-void
-gis_prepare_summary_page (GisDriver *driver)
+static void
+gis_summary_page_constructed (GObject *object)
 {
-  GisAssistant *assistant = gis_driver_get_assistant (driver);
-  SummaryData *data;
+  GisSummaryPage *page = GIS_SUMMARY_PAGE (object);
+  GisAssistant *assistant = gis_driver_get_assistant (GIS_PAGE (page)->driver);
+
+  G_OBJECT_CLASS (gis_summary_page_parent_class)->constructed (object);
+
+  GIS_PAGE (page)->widget = WID ("summary-page");
 
-  data = g_slice_new0 (SummaryData);
-  data->driver = driver;
-  data->builder = get_builder ();
-  data->widget = WID ("summary-page");
+  g_signal_connect (assistant, "prepare", G_CALLBACK (prepare_cb), page);
 
-  g_signal_connect (assistant, "prepare", G_CALLBACK (prepare_cb), data);
+  g_signal_connect (WID("summary-start-button"), "clicked", G_CALLBACK (byebye_cb), page);
+  g_signal_connect (WID("summary-tour-button"), "clicked", G_CALLBACK (tour_cb), page);
 
-  g_signal_connect (WID("summary-start-button"), "clicked", G_CALLBACK (byebye_cb), data);
-  g_signal_connect (WID("summary-tour-button"), "clicked", G_CALLBACK (tour_cb), data);
+  gis_page_set_title (GIS_PAGE (page), _("Thank You"));
+  gis_page_set_complete (GIS_PAGE (page), TRUE);
+}
 
-  gis_assistant_add_page (assistant, data->widget);
-  gis_assistant_set_page_title (assistant, data->widget, _("Thank You"));
-  gis_assistant_set_page_complete (assistant, data->widget, TRUE);
+static void
+gis_summary_page_class_init (GisSummaryPageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  page_class->get_builder = gis_summary_page_get_builder;
+  object_class->constructed = gis_summary_page_constructed;
+
+  g_type_class_add_private (object_class, sizeof(GisSummaryPagePrivate));
+}
+
+static void
+gis_summary_page_init (GisSummaryPage *page)
+{
+  page->priv = GET_PRIVATE (page);
+}
+
+void
+gis_prepare_summary_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_SUMMARY_PAGE,
+                                     "driver", driver,
+                                     NULL));
 }
diff --git a/gnome-initial-setup/pages/summary/gis-summary-page.h b/gnome-initial-setup/pages/summary/gis-summary-page.h
index 754419b..6e2efee 100644
--- a/gnome-initial-setup/pages/summary/gis-summary-page.h
+++ b/gnome-initial-setup/pages/summary/gis-summary-page.h
@@ -28,6 +28,31 @@
 
 G_BEGIN_DECLS
 
+#define GIS_TYPE_SUMMARY_PAGE               (gis_summary_page_get_type ())
+#define GIS_SUMMARY_PAGE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_SUMMARY_PAGE, GisSummaryPage))
+#define GIS_SUMMARY_PAGE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_SUMMARY_PAGE, GisSummaryPageClass))
+#define GIS_IS_SUMMARY_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_SUMMARY_PAGE))
+#define GIS_IS_SUMMARY_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_SUMMARY_PAGE))
+#define GIS_SUMMARY_PAGE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_SUMMARY_PAGE, GisSummaryPageClass))
+
+typedef struct _GisSummaryPage        GisSummaryPage;
+typedef struct _GisSummaryPageClass   GisSummaryPageClass;
+typedef struct _GisSummaryPagePrivate GisSummaryPagePrivate;
+
+struct _GisSummaryPage
+{
+  GisPage parent;
+
+  GisSummaryPagePrivate *priv;
+};
+
+struct _GisSummaryPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_summary_page_get_type (void);
+
 void gis_prepare_summary_page (GisDriver *driver);
 
 G_END_DECLS



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