[evolution/account-mgmt: 29/54] Adapt modules/startup-wizard to the new ESource API.



commit e5c4de266cf361ae62b9dfd633ac0b7217f0c997
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Apr 25 15:18:41 2011 -0400

    Adapt modules/startup-wizard to the new ESource API.

 modules/startup-wizard/Makefile.am                 |   21 +-
 modules/startup-wizard/e-mail-config-import-page.c |  380 +++++++++++++
 modules/startup-wizard/e-mail-config-import-page.h |   87 +++
 .../e-mail-config-import-progress-page.c           |  381 +++++++++++++
 .../e-mail-config-import-progress-page.h           |   82 +++
 modules/startup-wizard/e-startup-assistant.c       |  242 +++++++++
 modules/startup-wizard/e-startup-assistant.h       |   64 +++
 modules/startup-wizard/evolution-startup-wizard.c  |  560 +++-----------------
 8 files changed, 1331 insertions(+), 486 deletions(-)
---
diff --git a/modules/startup-wizard/Makefile.am b/modules/startup-wizard/Makefile.am
index ebaec22..e3a9189 100644
--- a/modules/startup-wizard/Makefile.am
+++ b/modules/startup-wizard/Makefile.am
@@ -1,3 +1,5 @@
+NULL =
+
 module_LTLIBRARIES = libevolution-module-startup-wizard.la
 
 libevolution_module_startup_wizard_la_CPPFLAGS =		\
@@ -6,10 +8,18 @@ libevolution_module_startup_wizard_la_CPPFLAGS =		\
 	-I$(top_srcdir)/widgets					\
 	-DG_LOG_DOMAIN=\"evolution-startup-wizard\"		\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)				\
-	$(GNOME_PLATFORM_CFLAGS)
+	$(GNOME_PLATFORM_CFLAGS)				\
+	$(NULL)
 
 libevolution_module_startup_wizard_la_SOURCES =			\
-	evolution-startup-wizard.c
+	evolution-startup-wizard.c				\
+	e-startup-assistant.c					\
+	e-startup-assistant.h					\
+	e-mail-config-import-page.c				\
+	e-mail-config-import-page.h				\
+	e-mail-config-import-progress-page.c			\
+	e-mail-config-import-progress-page.h			\
+	$(NULL)
 
 libevolution_module_startup_wizard_la_LIBADD =			\
 	$(top_builddir)/e-util/libeutil.la			\
@@ -19,10 +29,11 @@ libevolution_module_startup_wizard_la_LIBADD =			\
 	$(top_builddir)/calendar/gui/libevolution-calendar.la	\
 	$(top_builddir)/mail/libevolution-mail.la		\
 	$(top_builddir)/capplet/settings/libevolution-mail-settings.la \
-	$(top_builddir)/libemail-engine/libemail-engine.la \
-	$(top_builddir)/libemail-utils/libemail-utils.la  \
+	$(top_builddir)/libemail-engine/libemail-engine.la	\
+	$(top_builddir)/libemail-utils/libemail-utils.la	\
 	$(EVOLUTION_DATA_SERVER_LIBS)				\
-	$(GNOME_PLATFORM_LIBS)
+	$(GNOME_PLATFORM_LIBS)					\
+	$(NULL)
 
 libevolution_module_startup_wizard_la_LDFLAGS =			\
 	-module -avoid-version $(NO_UNDEFINED)
diff --git a/modules/startup-wizard/e-mail-config-import-page.c b/modules/startup-wizard/e-mail-config-import-page.c
new file mode 100644
index 0000000..8d2ad1f
--- /dev/null
+++ b/modules/startup-wizard/e-mail-config-import-page.c
@@ -0,0 +1,380 @@
+/*
+ * e-mail-config-import-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-import-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <e-util/e-import.h>
+
+#define E_MAIL_CONFIG_IMPORT_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PAGE, EMailConfigImportPagePrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailConfigImportPagePrivate {
+	EImport *import;
+	EImportTarget *import_target;
+	GSList *available_importers;
+};
+
+struct _AsyncContext {
+	EMailConfigImportPage *page;
+	GQueue pending_importers;
+	EActivity *activity;
+	GCancellable *cancellable;
+	gulong cancel_id;
+};
+
+/* Forward Declarations */
+static void	e_mail_config_import_page_interface_init
+					(EMailConfigPageInterface *interface);
+static gboolean	mail_config_import_page_next	(gpointer user_data);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailConfigImportPage,
+	e_mail_config_import_page,
+	GTK_TYPE_BOX,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_import_page_interface_init))
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+	if (async_context->page != NULL)
+		g_object_unref (async_context->page);
+
+	if (async_context->activity != NULL)
+		g_object_unref (async_context->activity);
+
+	if (async_context->cancellable != NULL) {
+		g_cancellable_disconnect (
+			async_context->cancellable,
+			async_context->cancel_id);
+		g_object_unref (async_context->cancellable);
+	}
+
+	g_queue_clear (&async_context->pending_importers);
+
+	g_slice_free (AsyncContext, async_context);
+}
+
+static void
+mail_config_import_page_status (EImport *import,
+                                const gchar *what,
+                                gint percent,
+                                GSimpleAsyncResult *simple)
+{
+	AsyncContext *async_context;
+
+	async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+	e_activity_set_text (async_context->activity, what);
+	e_activity_set_percent (async_context->activity, (gdouble) percent);
+}
+
+static void
+mail_config_import_page_complete (EImport *import,
+                                  GSimpleAsyncResult *simple)
+{
+	/* Schedule the next importer to start. */
+	g_idle_add (mail_config_import_page_next, simple);
+}
+
+static gboolean
+mail_config_import_page_next (gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	AsyncContext *async_context;
+	GCancellable *cancellable;
+	EImportImporter *next_importer;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+	async_context = g_simple_async_result_get_op_res_gpointer (simple);
+	cancellable = async_context->cancellable;
+
+	/* Pop the completed importer and peek at the next one. */
+	g_queue_pop_head (&async_context->pending_importers);
+	next_importer = g_queue_peek_head (&async_context->pending_importers);
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, &error)) {
+		g_simple_async_result_take_error (simple, error);
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+
+	} else if (next_importer != NULL) {
+		e_import_import (
+			async_context->page->priv->import,
+			async_context->page->priv->import_target,
+			next_importer,
+			(EImportStatusFunc) mail_config_import_page_status,
+			(EImportCompleteFunc) mail_config_import_page_complete,
+			simple);
+
+	} else {
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+	}
+
+	return FALSE;
+}
+
+static void
+mail_config_import_page_cancelled (GCancellable *cancellable,
+                                   AsyncContext *async_context)
+{
+	GQueue *pending_importers;
+	EImportImporter *current_importer;
+
+	pending_importers = &async_context->pending_importers;
+	current_importer = g_queue_peek_head (pending_importers);
+	g_return_if_fail (current_importer != NULL);
+
+	e_import_cancel (
+		async_context->page->priv->import,
+		async_context->page->priv->import_target,
+		current_importer);
+}
+
+static void
+mail_config_import_page_dispose (GObject *object)
+{
+	EMailConfigImportPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_IMPORT_PAGE_GET_PRIVATE (object);
+
+	if (priv->import != NULL) {
+		e_import_target_free (
+			priv->import,
+			priv->import_target);
+		g_object_unref (priv->import);
+		priv->import_target = NULL;
+		priv->import = NULL;
+	}
+
+	g_slist_free (priv->available_importers);
+	priv->available_importers = NULL;
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_import_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_import_page_constructed (GObject *object)
+{
+	EMailConfigImportPage *page;
+	GtkWidget *widget;
+	GtkWidget *container;
+	GSList *list, *link;
+	const gchar *text;
+	gint row = 0;
+
+	page = E_MAIL_CONFIG_IMPORT_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_import_page_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 24);
+
+	text = _("Please select the information "
+		 "that you would like to import:");
+	widget = gtk_label_new (text);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 12);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 12);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	list = page->priv->available_importers;
+
+	for (link = list; link != NULL; link = link->next) {
+		EImportImporter *importer = link->data;
+		gchar *from_text;
+
+		widget = e_import_get_widget (
+			page->priv->import,
+			page->priv->import_target, importer);
+		if (widget == NULL)
+			continue;
+		gtk_grid_attach (GTK_GRID (container), widget, 1, row, 1, 1);
+		gtk_widget_show (widget);
+
+		from_text = g_strdup_printf (_("From %s:"), importer->name);
+		widget = gtk_label_new (from_text);
+		gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
+		gtk_grid_attach (GTK_GRID (container), widget, 0, row, 1, 1);
+		gtk_widget_show (widget);
+
+		row++;
+	}
+}
+
+static void
+e_mail_config_import_page_class_init (EMailConfigImportPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigImportPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = mail_config_import_page_dispose;
+	object_class->constructed = mail_config_import_page_constructed;
+}
+
+static void
+e_mail_config_import_page_class_finalize (EMailConfigImportPageClass *class)
+{
+}
+
+static void
+e_mail_config_import_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Importing Files");
+	interface->sort_order = E_MAIL_CONFIG_IMPORT_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_import_page_init (EMailConfigImportPage *page)
+{
+	page->priv = E_MAIL_CONFIG_IMPORT_PAGE_GET_PRIVATE (page);
+
+	page->priv->import =
+		e_import_new ("org.gnome.evolution.shell.importer");
+	page->priv->import_target = (EImportTarget *)
+		e_import_target_new_home (page->priv->import);
+	page->priv->available_importers = e_import_get_importers (
+		page->priv->import, page->priv->import_target);
+}
+
+void
+e_mail_config_import_page_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_import_page_register_type (type_module);
+}
+
+EMailConfigPage *
+e_mail_config_import_page_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_CONFIG_IMPORT_PAGE, NULL);
+}
+
+guint
+e_mail_config_import_page_get_n_importers (EMailConfigImportPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_IMPORT_PAGE (page), 0);
+
+	return g_slist_length (page->priv->available_importers);
+}
+
+void
+e_mail_config_import_page_import (EMailConfigImportPage *page,
+                                  EActivity *activity,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	AsyncContext *async_context;
+	GCancellable *cancellable;
+	EImportImporter *first_importer;
+	GSList *list, *link;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_IMPORT_PAGE (page));
+	g_return_if_fail (E_IS_ACTIVITY (activity));
+
+	cancellable = e_activity_get_cancellable (activity);
+
+	async_context = g_slice_new0 (AsyncContext);
+	async_context->page = g_object_ref (page);
+	async_context->activity = g_object_ref (activity);
+
+	list = page->priv->available_importers;
+
+	for (link = list; link != NULL; link = g_slist_next (link)) {
+		EImportImporter *importer = link->data;
+		g_queue_push_tail (&async_context->pending_importers, importer);
+	}
+
+	if (G_IS_CANCELLABLE (cancellable)) {
+		async_context->cancellable = g_object_ref (cancellable);
+		async_context->cancel_id = g_cancellable_connect (
+			cancellable,
+			G_CALLBACK (mail_config_import_page_cancelled),
+			async_context, (GDestroyNotify) NULL);
+	}
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (page), callback, user_data,
+		e_mail_config_import_page_import);
+
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_context, (GDestroyNotify) async_context_free);
+
+	/* Start the first importer. */
+
+	first_importer = g_queue_peek_head (&async_context->pending_importers);
+
+	if (first_importer != NULL)
+		e_import_import (
+			async_context->page->priv->import,
+			async_context->page->priv->import_target,
+			first_importer,
+			(EImportStatusFunc) mail_config_import_page_status,
+			(EImportCompleteFunc) mail_config_import_page_complete,
+			simple);
+	else
+		g_simple_async_result_complete_in_idle (simple);
+}
+
+gboolean
+e_mail_config_import_page_import_finish (EMailConfigImportPage *page,
+                                         GAsyncResult *result,
+                                         GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (page),
+		e_mail_config_import_page_import), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	/* Assume success unless a GError is set. */
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
diff --git a/modules/startup-wizard/e-mail-config-import-page.h b/modules/startup-wizard/e-mail-config-import-page.h
new file mode 100644
index 0000000..9f37807
--- /dev/null
+++ b/modules/startup-wizard/e-mail-config-import-page.h
@@ -0,0 +1,87 @@
+/*
+ * e-mail-config-import-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_IMPORT_PAGE_H
+#define E_MAIL_CONFIG_IMPORT_PAGE_H
+
+#include <gtk/gtk.h>
+
+#include <e-util/e-activity.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-summary-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_IMPORT_PAGE \
+	(e_mail_config_import_page_get_type ())
+#define E_MAIL_CONFIG_IMPORT_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PAGE, EMailConfigImportPage))
+#define E_MAIL_CONFIG_IMPORT_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_IMPORT_PAGE, EMailConfigImportPageClass))
+#define E_IS_MAIL_CONFIG_IMPORT_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PAGE))
+#define E_IS_MAIL_CONFIG_IMPORT_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_IMPORT_PAGE))
+#define E_MAIL_CONFIG_IMPORT_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PAGE, EMailConfigImportPageClass))
+
+/* Sort the page in terms of the page we want to appear after. */
+#define E_MAIL_CONFIG_IMPORT_PAGE_SORT_ORDER \
+	(E_MAIL_CONFIG_SUMMARY_PAGE_SORT_ORDER + 10)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigImportPage EMailConfigImportPage;
+typedef struct _EMailConfigImportPageClass EMailConfigImportPageClass;
+typedef struct _EMailConfigImportPagePrivate EMailConfigImportPagePrivate;
+
+struct _EMailConfigImportPage {
+	GtkBox parent;
+	EMailConfigImportPagePrivate *priv;
+};
+
+struct _EMailConfigImportPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_import_page_get_type
+						(void) G_GNUC_CONST;
+void		e_mail_config_import_page_type_register
+						(GTypeModule *type_module);
+EMailConfigPage *
+		e_mail_config_import_page_new	(void);
+guint		e_mail_config_import_page_get_n_importers
+						(EMailConfigImportPage *page);
+void		e_mail_config_import_page_import
+						(EMailConfigImportPage *page,
+						 EActivity *activity,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_mail_config_import_page_import_finish
+						(EMailConfigImportPage *page,
+						 GAsyncResult *result,
+						 GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_IMPORT_PAGE_H */
diff --git a/modules/startup-wizard/e-mail-config-import-progress-page.c b/modules/startup-wizard/e-mail-config-import-progress-page.c
new file mode 100644
index 0000000..12a1a7b
--- /dev/null
+++ b/modules/startup-wizard/e-mail-config-import-progress-page.c
@@ -0,0 +1,381 @@
+/*
+ * e-mail-config-import-progress-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-import-progress-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#define E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE, EMailConfigImportProgressPagePrivate))
+
+struct _EMailConfigImportProgressPagePrivate {
+	EActivity *activity;
+	GtkWidget *progress_bar;   /* not referenced */
+	GtkWidget *cancelled_msg;  /* not referenced */
+	GtkWidget *completed_msg;  /* not referenced */
+};
+
+enum {
+	PROP_0,
+	PROP_ACTIVITY
+};
+
+/* Forward Declarations */
+static void	e_mail_config_import_progress_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailConfigImportProgressPage,
+	e_mail_config_import_progress_page,
+	GTK_TYPE_BOX,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_import_progress_page_interface_init))
+
+static gboolean
+mail_config_import_progress_page_is_cancelled (GBinding *binding,
+                                               const GValue *source_value,
+                                               GValue *target_value,
+                                               gpointer unused)
+{
+	EActivityState state;
+	gboolean is_cancelled;
+
+	state = g_value_get_enum (source_value);
+	is_cancelled = (state == E_ACTIVITY_CANCELLED);
+	g_value_set_boolean (target_value, is_cancelled);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_import_progress_page_is_completed (GBinding *binding,
+                                               const GValue *source_value,
+                                               GValue *target_value,
+                                               gpointer unused)
+{
+	EActivityState state;
+	gboolean is_completed;
+
+	state = g_value_get_enum (source_value);
+	is_completed = (state == E_ACTIVITY_COMPLETED);
+	g_value_set_boolean (target_value, is_completed);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_import_progress_page_percent_to_fraction (GBinding *binding,
+                                                      const GValue *source_value,
+                                                      GValue *target_value,
+                                                      gpointer unused)
+{
+	gdouble fraction;
+
+	fraction = g_value_get_double (source_value) / 100.0;
+	g_value_set_double (target_value, CLAMP (fraction, 0.0, 1.0));
+
+	return TRUE;
+}
+
+static void
+mail_config_import_progress_page_set_activity (EMailConfigImportProgressPage *page,
+                                               EActivity *activity)
+{
+	g_return_if_fail (E_IS_ACTIVITY (activity));
+	g_return_if_fail (page->priv->activity == NULL);
+
+	page->priv->activity = g_object_ref (activity);
+}
+
+static void
+mail_config_import_progress_page_set_property (GObject *object,
+                                               guint property_id,
+                                               const GValue *value,
+                                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVITY:
+			mail_config_import_progress_page_set_activity (
+				E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_import_progress_page_get_property (GObject *object,
+                                               guint property_id,
+                                               GValue *value,
+                                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVITY:
+			g_value_set_object (
+				value,
+				e_mail_config_import_progress_page_get_activity (
+				E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_import_progress_page_dispose (GObject *object)
+{
+	EMailConfigImportProgressPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_GET_PRIVATE (object);
+
+	if (priv->activity != NULL) {
+		g_object_unref (priv->activity);
+		priv->activity = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_import_progress_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_import_progress_page_constructed (GObject *object)
+{
+	EMailConfigImportProgressPage *page;
+	GtkSizeGroup *size_group;
+	GtkWidget *container;
+	GtkWidget *widget;
+	EActivity *activity;
+
+	page = E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_import_progress_page_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_CENTER);
+
+	activity = e_mail_config_import_progress_page_get_activity (page);
+
+	/* The activity state affects the "check-complete" result. */
+	g_signal_connect_swapped (
+		activity, "notify::state",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
+	/* Just a spacer. */
+	widget = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_box_pack_start (GTK_BOX (page), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_progress_bar_new ();
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	page->priv->progress_bar = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		activity, "text",
+		widget, "text",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property_full (
+		activity, "percent",
+		widget, "fraction",
+		G_BINDING_SYNC_CREATE,
+		mail_config_import_progress_page_percent_to_fraction,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	widget = gtk_vbox_new (FALSE, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_box_pack_start (GTK_BOX (page), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	page->priv->cancelled_msg = widget;  /* not referenced */
+
+	g_object_bind_property_full (
+		activity, "state",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE,
+		mail_config_import_progress_page_is_cancelled,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	widget = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	page->priv->completed_msg = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_object_bind_property_full (
+		activity, "state",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE,
+		mail_config_import_progress_page_is_completed,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	container = page->priv->cancelled_msg;
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_image_new_from_stock (
+		GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (_("Import cancelled."));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = page->priv->completed_msg;
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_image_new_from_icon_name (
+		"emblem-default", GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new _("Import complete.");
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_object_unref (size_group);
+}
+
+static gboolean
+mail_config_import_progress_page_check_complete (EMailConfigPage *page)
+{
+	EMailConfigImportProgressPagePrivate *priv;
+	gboolean complete;
+
+	priv = E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_GET_PRIVATE (page);
+
+	switch (e_activity_get_state (priv->activity)) {
+		case E_ACTIVITY_CANCELLED:
+		case E_ACTIVITY_COMPLETED:
+			complete = TRUE;
+			break;
+		default:
+			complete = FALSE;
+			break;
+	}
+
+	return complete;
+}
+
+static void
+e_mail_config_import_progress_page_class_init (EMailConfigImportProgressPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigImportProgressPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_import_progress_page_set_property;
+	object_class->get_property = mail_config_import_progress_page_get_property;
+	object_class->dispose = mail_config_import_progress_page_dispose;
+	object_class->constructed = mail_config_import_progress_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACTIVITY,
+		g_param_spec_object (
+			"activity",
+			"Activity",
+			"Import activity",
+			E_TYPE_ACTIVITY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_mail_config_import_progress_page_class_finalize (EMailConfigImportProgressPageClass *class)
+{
+}
+
+static void
+e_mail_config_import_progress_page_interface_init (EMailConfigPageInterface *interface)
+{
+	/* Keep the title identical to EMailConfigImportPage
+	 * so it's only shown once in the assistant sidebar. */
+	interface->title = _("Importing Files");
+	interface->sort_order = E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_SORT_ORDER;
+	interface->page_type = GTK_ASSISTANT_PAGE_PROGRESS;
+	interface->check_complete = mail_config_import_progress_page_check_complete;
+}
+
+static void
+e_mail_config_import_progress_page_init (EMailConfigImportProgressPage *page)
+{
+	page->priv = E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_GET_PRIVATE (page);
+}
+
+void
+e_mail_config_import_progress_page_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_import_progress_page_register_type (type_module);
+}
+
+EMailConfigPage *
+e_mail_config_import_progress_page_new (EActivity *activity)
+{
+	g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE,
+		"activity", activity, NULL);
+}
+
+EActivity *
+e_mail_config_import_progress_page_get_activity (EMailConfigImportProgressPage *page)
+{
+	g_return_val_if_fail (
+		E_IS_MAIL_CONFIG_IMPORT_PROGRESS_PAGE (page), NULL);
+
+	return page->priv->activity;
+}
+
diff --git a/modules/startup-wizard/e-mail-config-import-progress-page.h b/modules/startup-wizard/e-mail-config-import-progress-page.h
new file mode 100644
index 0000000..387e6cc
--- /dev/null
+++ b/modules/startup-wizard/e-mail-config-import-progress-page.h
@@ -0,0 +1,82 @@
+/*
+ * e-mail-config-import-progress-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_H
+#define E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_H
+
+#include <gtk/gtk.h>
+
+#include <e-util/e-activity.h>
+
+#include <mail/e-mail-config-page.h>
+
+#include "e-mail-config-import-page.h"
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE \
+	(e_mail_config_import_progress_page_get_type ())
+#define E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE, EMailConfigImportProgressPage))
+#define E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE, EMailConfigImportProgressPageClass))
+#define E_IS_MAIL_CONFIG_IMPORT_PROGRESS_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE))
+#define E_IS_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE))
+#define E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_IMPORT_PROGRESS_PAGE, EMailConfigImportProgressPageClass))
+
+/* Sort the page in terms of the page we want to appear after. */
+#define E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_SORT_ORDER \
+	(E_MAIL_CONFIG_IMPORT_PAGE_SORT_ORDER + 1)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigImportProgressPage EMailConfigImportProgressPage;
+typedef struct _EMailConfigImportProgressPageClass EMailConfigImportProgressPageClass;
+typedef struct _EMailConfigImportProgressPagePrivate EMailConfigImportProgressPagePrivate;
+
+struct _EMailConfigImportProgressPage {
+	GtkBox parent;
+	EMailConfigImportProgressPagePrivate *priv;
+};
+
+struct _EMailConfigImportProgressPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_import_progress_page_get_type
+					(void) G_GNUC_CONST;
+void		e_mail_config_import_progress_page_type_register
+					(GTypeModule *type_module);
+EMailConfigPage *
+		e_mail_config_import_progress_page_new
+					(EActivity *activity);
+EActivity *
+		e_mail_config_import_progress_page_get_activity
+					(EMailConfigImportProgressPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_IMPORT_PROGRESS_PAGE_H */
+
diff --git a/modules/startup-wizard/e-startup-assistant.c b/modules/startup-wizard/e-startup-assistant.c
new file mode 100644
index 0000000..f29ed69
--- /dev/null
+++ b/modules/startup-wizard/e-startup-assistant.c
@@ -0,0 +1,242 @@
+/*
+ * e-startup-assistant.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-startup-assistant.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <mail/e-mail-config-welcome-page.h>
+
+#include "e-mail-config-import-page.h"
+#include "e-mail-config-import-progress-page.h"
+
+#define E_STARTUP_ASSISTANT_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_STARTUP_ASSISTANT, EStartupAssistantPrivate))
+
+struct _EStartupAssistantPrivate {
+	EActivity *import_activity;
+	EMailConfigImportPage *import_page;
+	EMailConfigImportProgressPage *progress_page;
+};
+
+G_DEFINE_DYNAMIC_TYPE (
+	EStartupAssistant,
+	e_startup_assistant,
+	E_TYPE_MAIL_CONFIG_ASSISTANT)
+
+static void
+startup_assistant_import_done (GObject *source_object,
+                               GAsyncResult *result,
+                               gpointer user_data)
+{
+	EMailConfigImportPage *page;
+	EStartupAssistant *assistant;
+	EActivity *activity;
+	GError *error = NULL;
+
+	page = E_MAIL_CONFIG_IMPORT_PAGE (source_object);
+	assistant = E_STARTUP_ASSISTANT (user_data);
+	activity = assistant->priv->import_activity;
+
+	e_mail_config_import_page_import_finish (page, result, &error);
+
+	if (e_activity_handle_cancellation (activity, error)) {
+		g_error_free (error);
+
+	} else {
+		/* XXX The current EImport API does not allow importers to
+		 *     report errors.  Once we have a better importing API
+		 *     we'll have to figure out how to show import errors,
+		 *     but for now just emit a runtime warning. */
+		if (error != NULL) {
+			g_warning ("%s: %s", G_STRFUNC, error->message);
+			g_error_free (error);
+		}
+
+		e_activity_set_percent (activity, 100.0);
+		e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
+	}
+
+	g_object_unref (assistant);
+}
+
+static void
+startup_assistant_dispose (GObject *object)
+{
+	EStartupAssistantPrivate *priv;
+
+	priv = E_STARTUP_ASSISTANT_GET_PRIVATE (object);
+
+	if (priv->import_activity != NULL) {
+		g_object_unref (priv->import_activity);
+		priv->import_activity = NULL;
+	}
+
+	if (priv->import_page != NULL) {
+		g_object_unref (priv->import_page);
+		priv->import_page = NULL;
+	}
+
+	if (priv->progress_page != NULL) {
+		g_object_unref (priv->progress_page);
+		priv->progress_page = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_startup_assistant_parent_class)->dispose (object);
+}
+
+static void
+startup_assistant_constructed (GObject *object)
+{
+	EStartupAssistant *assistant;
+	EMailConfigPage *page;
+	gint n_pages, ii;
+
+	assistant = E_STARTUP_ASSISTANT (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_startup_assistant_parent_class)->constructed (object);
+
+	/* Note: We exclude this page if there is no application data
+	 *       to import, but we don't know that until we create it. */
+	page = e_mail_config_import_page_new ();
+	if (e_mail_config_import_page_get_n_importers (
+			E_MAIL_CONFIG_IMPORT_PAGE (page)) == 0) {
+		g_object_unref (g_object_ref_sink (page));
+	} else {
+		e_mail_config_assistant_add_page (
+			E_MAIL_CONFIG_ASSISTANT (assistant), page);
+		assistant->priv->import_page = g_object_ref (page);
+
+		/* Obviously we only need an import progress page if
+		 * there's a chance we may be importing something. */
+		page = e_mail_config_import_progress_page_new (
+			assistant->priv->import_activity);
+		e_mail_config_assistant_add_page (
+			E_MAIL_CONFIG_ASSISTANT (assistant), page);
+	}
+
+	/* Additional tweaks. */
+
+	n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (assistant));
+	for (ii = 0; ii < n_pages; ii++) {
+		GtkWidget *nth_page;
+
+		nth_page = gtk_assistant_get_nth_page (
+			GTK_ASSISTANT (assistant), ii);
+
+		if (!E_IS_MAIL_CONFIG_WELCOME_PAGE (nth_page))
+			continue;
+
+		gtk_assistant_set_page_title (
+			GTK_ASSISTANT (assistant), nth_page, _("Welcome"));
+
+		e_mail_config_welcome_page_set_text (
+			E_MAIL_CONFIG_WELCOME_PAGE (nth_page),
+			_("Welcome to Evolution.\n\nThe next few screens will "
+			  "allow Evolution to connect to your email accounts, "
+			  "and to import files from other applications."));
+	}
+}
+
+static void
+startup_assistant_prepare (GtkAssistant *assistant,
+                           GtkWidget *page)
+{
+	EStartupAssistantPrivate *priv;
+
+	priv = E_STARTUP_ASSISTANT_GET_PRIVATE (assistant);
+
+	/* Chain up to parent's prepare() method. */
+	GTK_ASSISTANT_CLASS (e_startup_assistant_parent_class)->
+		prepare (assistant, page);
+
+	if (E_IS_MAIL_CONFIG_IMPORT_PROGRESS_PAGE (page)) {
+		EActivity *activity;
+
+		activity = priv->import_activity;
+		e_activity_set_state (activity, E_ACTIVITY_RUNNING);
+
+		e_mail_config_import_page_import (
+			priv->import_page, activity,
+			startup_assistant_import_done,
+			g_object_ref (assistant));
+	}
+}
+
+static void
+e_startup_assistant_class_init (EStartupAssistantClass *class)
+{
+	GObjectClass *object_class;
+	GtkAssistantClass *assistant_class;
+
+	g_type_class_add_private (class, sizeof (EStartupAssistantPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = startup_assistant_dispose;
+	object_class->constructed = startup_assistant_constructed;
+
+	assistant_class = GTK_ASSISTANT_CLASS (class);
+	assistant_class->prepare = startup_assistant_prepare;
+}
+
+static void
+e_startup_assistant_class_finalize (EStartupAssistantClass *class)
+{
+}
+
+static void
+e_startup_assistant_init (EStartupAssistant *assistant)
+{
+	EActivity *activity;
+	GCancellable *cancellable;
+
+	assistant->priv = E_STARTUP_ASSISTANT_GET_PRIVATE (assistant);
+
+	cancellable = g_cancellable_new ();
+
+	activity = e_activity_new ();
+	e_activity_set_cancellable (activity, cancellable);
+	e_activity_set_state (activity, E_ACTIVITY_WAITING);
+	assistant->priv->import_activity = activity;
+
+	g_object_unref (cancellable);
+}
+
+void
+e_startup_assistant_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_startup_assistant_register_type (type_module);
+}
+
+GtkWidget *
+e_startup_assistant_new (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return g_object_new (
+		E_TYPE_STARTUP_ASSISTANT,
+		"session", session, NULL);
+}
+
diff --git a/modules/startup-wizard/e-startup-assistant.h b/modules/startup-wizard/e-startup-assistant.h
new file mode 100644
index 0000000..f063357
--- /dev/null
+++ b/modules/startup-wizard/e-startup-assistant.h
@@ -0,0 +1,64 @@
+/*
+ * e-startup-assistant.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_STARTUP_ASSISTANT_H
+#define E_STARTUP_ASSISTANT_H
+
+#include <mail/e-mail-config-assistant.h>
+
+/* Standard GObject macros */
+#define E_TYPE_STARTUP_ASSISTANT \
+	(e_startup_assistant_get_type ())
+#define E_STARTUP_ASSISTANT(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_STARTUP_ASSISTANT, EStartupAssistant))
+#define E_STARTUP_ASSISTANT_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_STARTUP_ASSISTANT, EStartupAssistantClass))
+#define E_IS_STARTUP_ASSISTANT(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_STARTUP_ASSISTANT))
+#define E_IS_STARTUP_ASSISTANT_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_STARTUP_ASSISTANT))
+#define E_STARTUP_ASSISTANT_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_STARTUP_ASSISTANT, EStartupAssistantClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EStartupAssistant EStartupAssistant;
+typedef struct _EStartupAssistantClass EStartupAssistantClass;
+typedef struct _EStartupAssistantPrivate EStartupAssistantPrivate;
+
+struct _EStartupAssistant {
+	EMailConfigAssistant parent;
+	EStartupAssistantPrivate *priv;
+};
+
+struct _EStartupAssistantClass {
+	EMailConfigAssistantClass parent_class;
+};
+
+GType		e_startup_assistant_get_type	(void) G_GNUC_CONST;
+void		e_startup_assistant_type_register
+						(GTypeModule *type_module);
+GtkWidget *	e_startup_assistant_new		(EMailSession *session);
+
+#endif /* E_STARTUP_ASSISTANT_H */
+
diff --git a/modules/startup-wizard/evolution-startup-wizard.c b/modules/startup-wizard/evolution-startup-wizard.c
index 7dd1c67..23ffa65 100644
--- a/modules/startup-wizard/evolution-startup-wizard.c
+++ b/modules/startup-wizard/evolution-startup-wizard.c
@@ -22,20 +22,22 @@
 
 #include <glib/gi18n-lib.h>
 #include <libebackend/e-extension.h>
+#include <libedataserver/e-source-mail-account.h>
 
 #include <shell/e-shell.h>
 
 #include <libevolution-utils/e-alert-dialog.h>
 #include <e-util/e-import.h>
 
-#include <libemail-utils/e-account-utils.h>
-
 #include <mail/e-mail-backend.h>
-#include <mail/em-account-editor.h>
+#include <mail/e-mail-config-assistant.h>
+#include <mail/e-mail-config-welcome-page.h>
 
 #include <capplet/settings/mail-capplet-shell.h>
 
-#include <calendar/gui/calendar-config.h>
+#include "e-startup-assistant.h"
+#include "e-mail-config-import-page.h"
+#include "e-mail-config-import-progress-page.h"
 
 /* Standard GObject macros */
 #define E_TYPE_STARTUP_WIZARD \
@@ -49,26 +51,6 @@ typedef struct _EStartupWizardClass EStartupWizardClass;
 
 struct _EStartupWizard {
 	EExtension parent;
-
-	EConfig *config;
-
-	EImport *import;
-	EImportTarget *import_target;
-
-	/* Currently active importer. */
-	EImportImporter *import_importer;
-
-	/* List of available importers. */
-	GSList *import_importers;
-
-	/* List node of the active importer. */
-	GSList *import_iterator;
-
-	gboolean import_cancelled;
-	gint import_progress_page_num;
-	GtkWidget *import_progress_bar;
-	GtkWidget *import_cancelled_msg;
-	GtkWidget *import_completed_msg;
 };
 
 struct _EStartupWizardClass {
@@ -101,444 +83,91 @@ startup_wizard_get_shell (EStartupWizard *extension)
 	return E_SHELL (extensible);
 }
 
-static void
-startup_wizard_import_status (EImport *import,
-                              const gchar *what,
-                              gint percentage,
-                              EStartupWizard *extension)
-{
-	GtkProgressBar *progress_bar;
-	gfloat fraction;
-
-	fraction = (gfloat) (percentage / 100.0);
-	progress_bar = GTK_PROGRESS_BAR (extension->import_progress_bar);
-	gtk_progress_bar_set_fraction (progress_bar, fraction);
-	gtk_progress_bar_set_text (progress_bar, what);
-}
-
-static void
-startup_wizard_import_complete (EImport *import,
-                                EStartupWizard *extension)
-{
-	EConfig *config = extension->config;
-
-	extension->import_importer = NULL;
-	extension->import_iterator = g_slist_next (extension->import_iterator);
-	e_config_target_changed (config, E_CONFIG_TARGET_CHANGED_STATE);
-}
-
-static void
-startup_wizard_tweak_welcome_label (GtkWidget *child)
-{
-	const gchar *welcome_text;
-
-	welcome_text =
-		_("Welcome to Evolution. The next few screens will "
-		  "allow Evolution to connect to your email accounts, "
-		  "and to import files from other applications.");
-
-	if (GTK_IS_LABEL (child))
-		gtk_label_set_text (GTK_LABEL (child), welcome_text);
-}
-
-static gboolean
-startup_wizard_check_progress (EConfig *config,
-                               const gchar *page_id,
-                               EStartupWizard *extension)
-{
-	if (extension->import_cancelled)
-		goto cancelled;
-
-	if (extension->import_iterator == NULL)
-		goto completed;
-
-	gtk_widget_hide (extension->import_cancelled_msg);
-	gtk_widget_hide (extension->import_completed_msg);
-
-	extension->import_importer = extension->import_iterator->data;
-	startup_wizard_import_status (extension->import, "", 0, extension);
-
-	e_import_import (
-		extension->import,
-		extension->import_target,
-		extension->import_importer,
-		(EImportStatusFunc) startup_wizard_import_status,
-		(EImportCompleteFunc) startup_wizard_import_complete,
-		extension);
-
-	return FALSE;
-
-cancelled:
-
-	gtk_widget_show (extension->import_cancelled_msg);
-	startup_wizard_import_status (extension->import, "", 0, extension);
-
-	return TRUE;
-
-completed:
-
-	gtk_widget_show (extension->import_completed_msg);
-	startup_wizard_import_status (extension->import, "", 100, extension);
-
-	return TRUE;
-}
-
-static void
-startup_wizard_config_abort (EConfig *config,
-                             EStartupWizard *extension)
-{
-	GtkAssistant *assistant;
-	gint page_num;
-
-	assistant = GTK_ASSISTANT (config->widget);
-	page_num = gtk_assistant_get_current_page (assistant);
-
-	/* If we're not on the import progress page, terminate. */
-	if (page_num != extension->import_progress_page_num) {
-		startup_wizard_terminate ();
-		g_assert_not_reached ();
-	}
-
-	/* XXX Overloading the cancel button like this is a bit evil,
-	 *     but if we're on the import progress page and the import
-	 *     has already been cancelled, terminate. */
-	if (extension->import_cancelled) {
-		startup_wizard_terminate ();
-		g_assert_not_reached ();
-	}
-
-	if (extension->import_importer) {
-		e_import_cancel (
-			extension->import,
-			extension->import_target,
-			extension->import_importer);
-	} else {
-		startup_wizard_terminate ();
-		g_assert_not_reached ();
-	}
-
-	extension->import_cancelled = TRUE;
-	e_config_target_changed (config, E_CONFIG_TARGET_CHANGED_STATE);
-
-	/* Prevent EConfig from destroying the GtkAssistant. */
-	g_signal_stop_emission_by_name (assistant, "cancel");
-}
-
-static void
-startup_wizard_config_commit (EConfig *config,
-                              EStartupWizard *extension)
+static GtkWidget *
+startup_wizard_new_assistant (EStartupWizard *extension)
 {
 	EShell *shell;
-	EShellSettings *shell_settings;
-	gchar *location;
+	EShellBackend *shell_backend;
+	EMailBackend *backend;
+	EMailSession *session;
 
 	shell = startup_wizard_get_shell (extension);
-	shell_settings = e_shell_get_shell_settings (shell);
-
-	/* Use System Timezone by default. */
-	e_shell_settings_set_boolean (
-		shell_settings, "cal-use-system-timezone", TRUE);
-	location = e_cal_util_get_system_timezone_location ();
-	e_shell_settings_set_string (
-		shell_settings, "cal-timezone-string", location);
-	g_free (location);
-
-	gtk_main_quit ();
-}
-
-static void
-startup_wizard_config_free (EConfig *config,
-                            GSList *items,
-                            EStartupWizard *extension)
-{
-	while (items != NULL) {
-		EConfigItem *config_item = items->data;
-
-		g_free (config_item->path);
-		g_object_unref (config_item->user_data);
-		g_slice_free (EConfigItem, config_item);
-
-		items = g_slist_delete_link (items, items);
-	}
-
-	g_object_unref (extension);
-}
-
-static GtkWidget *
-startup_wizard_importer_page (EConfig *config,
-                              EConfigItem *item,
-                              GtkAssistant *assistant,
-                              GtkWidget *old,
-                              gint position,
-                              EStartupWizard *extension)
-{
-	GtkWidget *container;
-	GtkWidget *widget;
-	GtkWidget *page;
-	GSList *list, *iter;
-	const gchar *title;
-	guint n_importers;
-	gint row = 0;
-
-	list = extension->import_importers;
-	n_importers = g_slist_length (list);
-
-	/* Skip this page if there's nothing to import. */
-	if (n_importers == 0)
-		return NULL;
-
-	page = gtk_vbox_new (FALSE, 12);
-	gtk_container_set_border_width (GTK_CONTAINER (page), 12);
-	gtk_widget_show (page);
-
-	container = page;
-
-	widget = gtk_label_new (
-		_("Please select the information "
-		  "that you would like to import:"));
-	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	widget = gtk_hseparator_new ();
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	widget = gtk_table_new (n_importers, 2, FALSE);
-	gtk_table_set_col_spacings (GTK_TABLE (widget), 12);
-	gtk_table_set_row_spacings (GTK_TABLE (widget), 12);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	for (iter = list; iter != NULL; iter = iter->next) {
-		EImportImporter *importer = iter->data;
-		gchar *text;
-
-		widget = e_import_get_widget (
-			extension->import,
-			extension->import_target, importer);
-		if (widget == NULL)
-			continue;
-		gtk_table_attach (
-			GTK_TABLE (container), widget,
-			1, 2, row, row + 1, GTK_FILL, 0, 0, 0);
-		gtk_widget_show (widget);
-
-		text = g_strdup_printf (_("From %s:"), importer->name);
-		widget = gtk_label_new (text);
-		gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
-		gtk_table_attach (
-			GTK_TABLE (container), widget,
-			0, 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
-		gtk_widget_show (widget);
-
-		row++;
-	}
+	shell_backend = e_shell_get_backend_by_name (shell, "mail");
 
-	title = _("Importing Files");
-	gtk_assistant_insert_page (assistant, page, position);
-	gtk_assistant_set_page_title (assistant, page, title);
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
 
-	return page;
+	/* Note: We subclass EMailConfigAssistant so we can distinguish
+	 *       the first-time account assistant from the normal account
+	 *       assistant.  The backup-restore module relies on this to
+	 *       add a "Restore" page to the first-time assistant only. */
+	return e_startup_assistant_new (session);
 }
 
 static GtkWidget *
-startup_wizard_progress_page (EConfig *config,
-                              EConfigItem *item,
-                              GtkAssistant *assistant,
-                              GtkWidget *old,
-                              gint position,
-                              EStartupWizard *extension)
+startup_wizard_new_capplet (EStartupWizard *extension)
 {
-	GtkSizeGroup *size_group;
-	GtkWidget *container;
-	GtkWidget *widget;
-	GtkWidget *page;
-	const gchar *title;
-	gint page_num;
-
-	/* Skip this page if there's nothing to import. */
-	if (extension->import_importers == NULL)
-		return NULL;
-
-	size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
-
-	page = gtk_vbox_new (FALSE, 12);
-	gtk_container_set_border_width (GTK_CONTAINER (page), 12);
-	gtk_widget_show (page);
-
-	container = page;
-
-	/* Just a spacer. */
-	widget = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
-	gtk_size_group_add_widget (size_group, widget);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	gtk_widget_show (widget);
-
-	widget = gtk_progress_bar_new ();
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	extension->import_progress_bar = widget;
-	gtk_widget_show (widget);
-
-	widget = gtk_vbox_new (FALSE, 12);
-	gtk_size_group_add_widget (size_group, widget);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	widget = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	extension->import_cancelled_msg = widget;
-	gtk_widget_show (widget);
-
-	widget = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	extension->import_completed_msg = widget;
-	gtk_widget_show (widget);
-
-	container = extension->import_cancelled_msg;
-
-	widget = gtk_hbox_new (FALSE, 6);
-	gtk_container_add (GTK_CONTAINER (container), widget);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	widget = gtk_image_new_from_stock (
-		GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	widget = gtk_label_new (
-		_("Import cancelled."));
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	container = extension->import_completed_msg;
-
-	widget = gtk_hbox_new (FALSE, 6);
-	gtk_container_add (GTK_CONTAINER (container), widget);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	widget = gtk_image_new_from_icon_name (
-		"emblem-default", GTK_ICON_SIZE_MENU);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	widget = gtk_label_new (
-		_("Import complete."));
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	title = _("Importing Files");
-	page_num = gtk_assistant_insert_page (assistant, page, position);
-	gtk_assistant_set_page_title (assistant, page, title);
-
-	extension->import_progress_page_num = page_num;
-
-	return page;
+	return mail_capplet_shell_new (0, TRUE, TRUE);
 }
 
-static GtkWidget *
-startup_wizard_new_assistant (EStartupWizard *extension)
+static gboolean
+startup_wizard_have_mail_account (EStartupWizard *extension)
 {
 	EShell *shell;
-	EShellBackend *shell_backend;
-	EMailBackend *backend;
-	EMAccountEditor *emae;
-	EConfig *config;
-	EConfigItem *config_item;
-	GtkWidget *widget;
-	GSList *items = NULL;
+	ESource *source;
+	ESourceRegistry *registry;
+	GList *list, *link;
+	const gchar *extension_name;
+	const gchar *uid;
+	gboolean have_account;
 
 	shell = startup_wizard_get_shell (extension);
-	shell_backend = e_shell_get_backend_by_name (shell, "mail");
-
-	backend = E_MAIL_BACKEND (shell_backend);
-
-	emae = em_account_editor_new (
-		NULL, EMAE_ASSISTANT, backend,
-		"org.gnome.evolution.mail.config.accountWizard");
-
-	config = E_CONFIG (emae->config);
-	extension->config = g_object_ref (config);
 
-	/* Insert the importer page. */
-
-	config_item = g_slice_new0 (EConfigItem);
-	config_item->type = E_CONFIG_PAGE;
-	config_item->path = g_strdup ("60.importers");
-	config_item->factory =
-		(EConfigItemFactoryFunc) startup_wizard_importer_page;
-	config_item->user_data = g_object_ref (extension);
-	items = g_slist_prepend (items, config_item);
-
-	/* Insert the progress page. */
-
-	config_item = g_slice_new0 (EConfigItem);
-	config_item->type = E_CONFIG_PAGE_PROGRESS;
-	config_item->path = g_strdup ("70.progress");
-	config_item->factory =
-		(EConfigItemFactoryFunc) startup_wizard_progress_page;
-	config_item->user_data = g_object_ref (extension);
-	items = g_slist_prepend (items, config_item);
-
-	e_config_add_items (
-		config, items,
-		(EConfigItemsFunc) startup_wizard_config_free,
-		g_object_ref (extension));
-
-	e_config_add_page_check (
-		config, "70.progress", (EConfigCheckFunc)
-		startup_wizard_check_progress, extension);
-
-	g_signal_connect (
-		config, "abort",
-		G_CALLBACK (startup_wizard_config_abort), extension);
-
-	g_signal_connect (
-		config, "commit",
-		G_CALLBACK (startup_wizard_config_commit), extension);
-
-	e_config_create_window (config, NULL, _("Evolution Setup Assistant"));
-
-	/* Additional tweaks.  The window must be created at this point. */
+	registry = e_shell_get_registry (shell);
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	/* Exclude the built-in 'On This Computer' source. */
+	uid = E_MAIL_SESSION_LOCAL_UID;
+	source = e_source_registry_ref_source (registry, uid);
+	link = g_list_find (list, source);
+	if (link != NULL) {
+		/* We have two references to the ESource,
+		 * one from e_source_registry_list_sources()
+		 * and one from e_source_registry_ref_source().
+		 * Drop them both. */
+		g_object_unref (source);
+		g_object_unref (source);
+		list = g_list_delete_link (list, link);
+	}
 
-	widget = e_config_page_get (config, "0.start");
-	gtk_assistant_set_page_title (
-		GTK_ASSISTANT (config->widget), widget, _("Welcome"));
+	/* Exclude the built-in 'Search Folders' source. */
+	uid = E_MAIL_SESSION_VFOLDER_UID;
+	source = e_source_registry_ref_source (registry, uid);
+	link = g_list_find (list, source);
+	if (link != NULL) {
+		/* We have two references to the ESource,
+		 * one from e_source_registry_list_sources()
+		 * and one from e_source_registry_ref_source().
+		 * Drop them both. */
+		g_object_unref (source);
+		g_object_unref (source);
+		list = g_list_delete_link (list, link);
+	}
 
-	/* The welcome page should be a GtkBox with a GtkLabel
-	 * packed inside.  We need to alter the GtkLabel text. */
-	gtk_container_foreach (
-		GTK_CONTAINER (widget),
-		(GtkCallback) startup_wizard_tweak_welcome_label, NULL);
+	have_account = (list != NULL);
 
-	/* Finalize the EMAccountEditor along with the GtkAssistant. */
-	g_object_set_data_full (
-		G_OBJECT (config->window), "AccountEditor",
-		emae, (GDestroyNotify) g_object_unref);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
-	return config->window;
+	return have_account;
 }
 
-static GtkWidget *
-startup_wizard_new_capplet (EStartupWizard *extension)
+static void
+startup_wizard_weak_ref_cb (gpointer data,
+                            GObject *where_the_object_was)
 {
-	GtkWidget *capplet;
-
-	capplet = mail_capplet_shell_new (0, TRUE, TRUE);
-
-	/* g_signal_connect (
-		capplet, "destroy",
-		G_CALLBACK (gtk_main_quit), NULL); */
-
-	return capplet;
+	gtk_main_quit ();
 }
 
 static void
@@ -546,7 +175,6 @@ startup_wizard_run (EStartupWizard *extension)
 {
 	EShell *shell;
 	GtkWidget *window;
-	EAccountList *account_list;
 	const gchar *startup_view;
 	gboolean express_mode;
 
@@ -557,8 +185,7 @@ startup_wizard_run (EStartupWizard *extension)
 	express_mode = e_shell_get_express_mode (shell);
 	startup_view = e_shell_get_startup_view (shell);
 
-	account_list = e_get_account_list ();
-	if (e_list_length (E_LIST (account_list)) > 0)
+	if (startup_wizard_have_mail_account (extension))
 		return;
 
 	if (express_mode && g_strcmp0 (startup_view, "mail") != 0)
@@ -569,17 +196,20 @@ startup_wizard_run (EStartupWizard *extension)
 	else {
 		window = startup_wizard_new_assistant (extension);
 		g_signal_connect (
-			window, "delete-event",
+			window, "cancel",
 			G_CALLBACK (startup_wizard_terminate), NULL);
 	}
 
+	g_object_weak_ref (
+		G_OBJECT (window),
+		startup_wizard_weak_ref_cb, NULL);
+
 	gtk_widget_show (window);
 
 	gtk_main ();
 
-	if (e_list_length (E_LIST (account_list)) <= 0)
+	if (!startup_wizard_have_mail_account (extension))
 		exit (0);
-
 }
 
 static void
@@ -672,38 +302,10 @@ startup_wizard_load_accounts (EStartupWizard *extension)
 }
 
 static void
-startup_wizard_dispose (GObject *object)
-{
-	EStartupWizard *extension;
-
-	extension = E_STARTUP_WIZARD (object);
-
-	if (extension->config != NULL) {
-		g_object_unref (extension->config);
-		extension->config = NULL;
-	}
-
-	if (extension->import != NULL) {
-		e_import_target_free (
-			extension->import,
-			extension->import_target);
-		g_object_unref (extension->import);
-		extension->import_target = NULL;
-		extension->import = NULL;
-	}
-
-	g_slist_free (extension->import_importers);
-	extension->import_importers = NULL;
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (e_startup_wizard_parent_class)->dispose (object);
-}
-
-static void
 startup_wizard_constructed (GObject *object)
 {
-	EStartupWizard *extension;
 	EShell *shell;
+	EStartupWizard *extension;
 
 	extension = E_STARTUP_WIZARD (object);
 	shell = startup_wizard_get_shell (extension);
@@ -723,7 +325,6 @@ e_startup_wizard_class_init (EStartupWizardClass *class)
 	EExtensionClass *extension_class;
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->dispose = startup_wizard_dispose;
 	object_class->constructed = startup_wizard_constructed;
 
 	extension_class = E_EXTENSION_CLASS (class);
@@ -738,22 +339,19 @@ e_startup_wizard_class_finalize (EStartupWizardClass *class)
 static void
 e_startup_wizard_init (EStartupWizard *extension)
 {
-	extension->import =
-		e_import_new ("org.gnome.evolution.shell.importer");
-	extension->import_target = (EImportTarget *)
-		e_import_target_new_home (extension->import);
-	extension->import_importers = e_import_get_importers (
-		extension->import, extension->import_target);
-	extension->import_iterator = extension->import_importers;
 }
 
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
 	e_startup_wizard_register_type (type_module);
+	e_startup_assistant_type_register (type_module);
+	e_mail_config_import_page_type_register (type_module);
+	e_mail_config_import_progress_page_type_register (type_module);
 }
 
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
 }
+



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