[gnome-color-manager] Remove the preferences window and replace it with a calibration wizard



commit d4479b231aca3480af1911ee8d557a618316ad0d
Author: Richard Hughes <richard hughsie com>
Date:   Fri May 20 20:54:45 2011 +0100

    Remove the preferences window and replace it with a calibration wizard
    
    The UI panel has moved to gnome-control-center, and so we don't need to
    duplicate the UI here.

 contrib/gnome-color-manager.spec.in                |    2 +-
 data/Makefile.am                                   |    9 +-
 ...m-prefs.desktop.in => gcm-calibrate.desktop.in} |    0
 data/gcm-calibrate.ui                              |  938 ----------
 data/gcm-prefs.ui                                  |  775 ---------
 po/POTFILES.in                                     |   19 +-
 src/.gitignore                                     |    2 +-
 src/Makefile.am                                    |   14 +-
 src/gcm-calibrate-argyll.c                         |  602 +++----
 src/gcm-calibrate-dialog.c                         |  856 ---------
 src/gcm-calibrate-dialog.h                         |   95 -
 src/gcm-calibrate-main.c                           | 1817 ++++++++++++++++++++
 src/gcm-calibrate-native.c                         |   63 +-
 src/gcm-calibrate.c                                |  680 ++------
 src/gcm-calibrate.h                                |   59 +-
 src/gcm-self-test.c                                |   55 -
 16 files changed, 2286 insertions(+), 3700 deletions(-)
---
diff --git a/contrib/gnome-color-manager.spec.in b/contrib/gnome-color-manager.spec.in
index f251589..cf73bae 100644
--- a/contrib/gnome-color-manager.spec.in
+++ b/contrib/gnome-color-manager.spec.in
@@ -62,7 +62,7 @@ make %{?_smp_mflags}
 %install
 make install DESTDIR=$RPM_BUILD_ROOT
 
-for i in gcm-prefs gcm-import ; do
+for i in gcm-calibrate gcm-import ; do
   desktop-file-install --delete-original                                \
     --dir=$RPM_BUILD_ROOT%{_datadir}/applications/                      \
     $RPM_BUILD_ROOT%{_datadir}/applications/$i.desktop
diff --git a/data/Makefile.am b/data/Makefile.am
index f1d6f62..069783d 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -9,7 +9,7 @@ desktopdir = $(datadir)/applications
 desktop_in_files =					\
 	gcm-viewer.desktop.in				\
 	gcm-picker.desktop.in				\
-	gcm-prefs.desktop.in				\
+	gcm-calibrate.desktop.in			\
 	gcm-import.desktop.in
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
@@ -26,14 +26,11 @@ $(service_DATA): $(service_in_files) Makefile
 	@sed -e "s|\ servicedir\@|$(bindir)|" $< > $@
 
 pkgdata_DATA =						\
-	gcm-calibrate.ui				\
 	gcm-spawn.ui					\
 	gcm-picker.ui					\
-	gcm-viewer.ui					\
-	gcm-prefs.ui
+	gcm-viewer.ui
 
 EXTRA_DIST =						\
-	$(gsettings_SCHEMAS)				\
 	$(service_in_files)				\
 	$(autostart_in_files)				\
 	$(desktop_in_files)				\
@@ -45,7 +42,7 @@ clean-local :
 DISTCLEANFILES =					\
 	org.gnome.ColorManager.service			\
 	gcm-session.desktop				\
-	gcm-prefs.desktop				\
+	gcm-calibrate.desktop				\
 	gcm-picker.desktop				\
 	gcm-viewer.desktop				\
 	gcm-import.desktop
diff --git a/data/gcm-prefs.desktop.in b/data/gcm-calibrate.desktop.in
similarity index 100%
rename from data/gcm-prefs.desktop.in
rename to data/gcm-calibrate.desktop.in
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0fa143a..2421556 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,29 +1,24 @@
-data/gcm-session.desktop.in
+data/gcm-calibrate.desktop.in
 data/gcm-import.desktop.in
-data/gcm-prefs.desktop.in
 data/gcm-picker.desktop.in
+data/gcm-session.desktop.in
 data/gcm-viewer.desktop.in
 data/gcm-viewer.ui
-data/org.gnome.color-manager.gschema.xml
-data/org.gnome.settings-daemon.plugins.color.gschema.xml
-src/gcm-debug.c
-src/gcm-profile.c
-src/gcm-prefs.c
 src/gcm-calibrate-argyll.c
 src/gcm-calibrate.c
-src/gcm-calibrate-dialog.c
-src/gcm-calibrate-manual.c
+src/gcm-calibrate-main.c
 src/gcm-calibrate-native.c
 src/gcm-cell-renderer-profile-date.c
 src/gcm-cell-renderer-profile-text.c
-src/gcm-list-store-profiles.c
+src/gcm-debug.c
 src/gcm-import.c
 src/gcm-inspect.c
+src/gcm-list-store-profiles.c
 src/gcm-picker.c
+src/gcm-prefs.c
+src/gcm-profile.c
 src/gcm-session.c
 src/gcm-utils.c
 src/gcm-viewer.c
-[type: gettext/glade]data/gcm-calibrate.ui
 [type: gettext/glade]data/gcm-picker.ui
-[type: gettext/glade]data/gcm-prefs.ui
 [type: gettext/glade]data/gcm-spawn.ui
diff --git a/src/.gitignore b/src/.gitignore
index e4c3d7b..c1e7b72 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -7,7 +7,7 @@
 .deps
 gcm-import
 gcm-viewer
-gcm-prefs
+gcm-calibrate
 gcm-picker
 gcm-inspect
 gcm-session
diff --git a/src/Makefile.am b/src/Makefile.am
index 43e406f..0913751 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -72,7 +72,7 @@ libgcmshared_a_CFLAGS =					\
 bin_PROGRAMS =						\
 	gcm-inspect					\
 	gcm-viewer					\
-	gcm-prefs					\
+	gcm-calibrate					\
 	gcm-session					\
 	gcm-picker					\
 	gcm-import
@@ -84,14 +84,12 @@ gcm_helper_exiv_LDADD = $(EXIV_LIBS) $(GLIB_LIBS)
 gcm_helper_exiv_CXXFLAGS = -Wall
 endif
 
-gcm_prefs_SOURCES =					\
+gcm_calibrate_SOURCES =					\
 	gcm-brightness.c				\
 	gcm-brightness.h				\
 	gcm-calibrate-argyll.c				\
 	gcm-calibrate-argyll.h				\
 	gcm-calibrate.c					\
-	gcm-calibrate-dialog.c				\
-	gcm-calibrate-dialog.h				\
 	gcm-calibrate.h					\
 	gcm-calibrate-native.c				\
 	gcm-calibrate-native.h				\
@@ -105,9 +103,9 @@ gcm_prefs_SOURCES =					\
 	gcm-list-store-profiles.h			\
 	gcm-sample-window.c				\
 	gcm-sample-window.h				\
-	gcm-prefs.c
+	gcm-calibrate-main.c
 
-gcm_prefs_LDADD =					\
+gcm_calibrate_LDADD =					\
 	libgcmshared.a					\
 	$(CANBERRA_LIBS)				\
 	$(COLORD_LIBS)					\
@@ -121,7 +119,7 @@ gcm_prefs_LDADD =					\
 	$(XORG_LIBS)					\
 	-lm
 
-gcm_prefs_CFLAGS =					\
+gcm_calibrate_CFLAGS =					\
 	$(WARNINGFLAGS_C)
 
 gcm_inspect_SOURCES =					\
@@ -229,8 +227,6 @@ gcm_self_test_SOURCES =					\
 	gcm-calibrate-argyll.c				\
 	gcm-calibrate-argyll.h				\
 	gcm-calibrate.c					\
-	gcm-calibrate-dialog.c				\
-	gcm-calibrate-dialog.h				\
 	gcm-calibrate.h					\
 	gcm-calibrate-native.c				\
 	gcm-calibrate-native.h				\
diff --git a/src/gcm-calibrate-argyll.c b/src/gcm-calibrate-argyll.c
index b0cf05a..8f0475a 100644
--- a/src/gcm-calibrate-argyll.c
+++ b/src/gcm-calibrate-argyll.c
@@ -38,7 +38,6 @@
 #include "gcm-utils.h"
 #include "gcm-x11-screen.h"
 #include "gcm-print.h"
-#include "gcm-calibrate-dialog.h"
 
 #define FIXED_ARGYLL
 
@@ -63,10 +62,8 @@ typedef enum {
  **/
 struct _GcmCalibrateArgyllPrivate
 {
-	guint				 display;
 	GMainLoop			*loop;
 	GtkWidget			*terminal;
-	GcmCalibrateDialog		*calibrate_dialog;
 	pid_t				 child_pid;
 	GtkResponseType			 response;
 	GcmX11Screen			*screen;
@@ -75,6 +72,7 @@ struct _GcmCalibrateArgyllPrivate
 	gboolean			 already_on_window;
 	gboolean			 done_calibrate;
 	GcmCalibrateArgyllState		 state;
+	CdDevice			*device;
 	GcmPrint			*print;
 	const gchar			*argyllcms_ok;
 	gboolean			 done_spot_read;
@@ -282,10 +280,10 @@ out:
 static gchar
 gcm_calibrate_argyll_get_display_kind (GcmCalibrateArgyll *calibrate_argyll)
 {
-	GcmCalibrateDeviceKind device_kind;
+	GcmCalibrateDisplayKind device_kind;
 
 	g_object_get (calibrate_argyll,
-		      "calibrate-device-kind", &device_kind,
+		      "display-kind", &device_kind,
 		      NULL);
 
 	if (device_kind == GCM_CALIBRATE_DEVICE_KIND_LCD)
@@ -407,14 +405,12 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	GcmX11Output *output;
 	GPtrArray *array = NULL;
 	gchar *basename = NULL;
-	gchar *output_name = NULL;
-	const gchar *title;
-	const gchar *message;
+	const gchar *output_name;
+	guint display;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
 		      "basename", &basename,
-		      "output-name", &output_name,
 		      NULL);
 
 	/* get correct name of the command */
@@ -425,8 +421,10 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	}
 
 	/* match up the output name with the device number defined by dispcal */
-	priv->display = gcm_calibrate_argyll_get_display (output_name, error);
-	if (priv->display == G_MAXUINT) {
+	output_name = cd_device_get_metadata_item (priv->device,
+						   CD_DEVICE_METADATA_XRANDR_NAME);
+	display = gcm_calibrate_argyll_get_display (output_name, error);
+	if (display == G_MAXUINT) {
 		ret = FALSE;
 		goto out;
 	}
@@ -442,15 +440,12 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	kind = gcm_calibrate_argyll_get_display_kind (calibrate_argyll);
 
 	/* TRANSLATORS: title, default paramters needed to calibrate_argyll */
-	title = _("Getting default parameters");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Getting default parameters"));
 
 	/* TRANSLATORS: dialog message */
-	message = _("This pre-calibrates the screen by sending colored and gray patches to your screen and measuring them with the hardware device.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("This pre-calibrates the screen by sending colored and gray patches to your screen and measuring them with the hardware device."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -462,9 +457,9 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	g_ptr_array_add (array, g_strdup ("-v"));
 	g_ptr_array_add (array, g_strdup ("-ql"));
 	g_ptr_array_add (array, g_strdup ("-m"));
-	g_ptr_array_add (array, g_strdup_printf ("-d%i", priv->display));
+	g_ptr_array_add (array, g_strdup_printf ("-d%i", display));
 	g_ptr_array_add (array, g_strdup_printf ("-y%c", kind));
-	g_ptr_array_add (array, g_strdup ("-p 0.5,0.5,1.2"));
+	g_ptr_array_add (array, g_strdup ("-P 0.5,0.5,1.2"));
 	g_ptr_array_add (array, g_strdup (basename));
 	argv = gcm_utils_ptr_array_to_strv (array);
 	gcm_calibrate_argyll_debug_argv (command, argv);
@@ -482,7 +477,7 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 		g_set_error_literal (error,
 				     GCM_CALIBRATE_ERROR,
 				     GCM_CALIBRATE_ERROR_USER_ABORT,
-				     "calibration was cancelled");
+				     "Calibration was cancelled");
 		ret = FALSE;
 		goto out;
 	}
@@ -493,7 +488,7 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 		g_set_error (error,
 			     GCM_CALIBRATE_ERROR,
 			     GCM_CALIBRATE_ERROR_INTERNAL,
-			     "command failed to run successfully: %s", vte_text);
+			     "Command failed to run successfully: %s", vte_text);
 		g_free (vte_text);
 		ret = FALSE;
 		goto out;
@@ -503,7 +498,6 @@ out:
 	if (array != NULL)
 		g_ptr_array_unref (array);
 	g_free (basename);
-	g_free (output_name);
 	g_free (command);
 	g_strfreev (argv);
 	return ret;
@@ -521,8 +515,6 @@ gcm_calibrate_argyll_display_read_chart (GcmCalibrateArgyll *calibrate_argyll, G
 	gchar **argv = NULL;
 	GPtrArray *array = NULL;
 	gchar *basename = NULL;
-	const gchar *title;
-	const gchar *message;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
@@ -537,14 +529,11 @@ gcm_calibrate_argyll_display_read_chart (GcmCalibrateArgyll *calibrate_argyll, G
 	}
 
 	/* TRANSLATORS: title, patches are specific colours used in calibration */
-	title = _("Reading the patches");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Reading the patches"));
 	/* TRANSLATORS: dialog message */
-	message = _("Reading the patches using the color measuring instrument.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Reading the patches using the color measuring instrument."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -611,8 +600,6 @@ gcm_calibrate_argyll_display_generate_patches (GcmCalibrateArgyll *calibrate_arg
 	gchar **argv = NULL;
 	GPtrArray *array = NULL;
 	gchar *basename = NULL;
-	const gchar *title;
-	const gchar *message;
 	CdDeviceKind device_kind;
 
 	/* get shared data */
@@ -629,14 +616,11 @@ gcm_calibrate_argyll_display_generate_patches (GcmCalibrateArgyll *calibrate_arg
 	}
 
 	/* TRANSLATORS: title, patches are specific colours used in calibration */
-	title = _("Generating the patches");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Generating the patches"));
 	/* TRANSLATORS: dialog message */
-	message = _("Generating the patches that will be measured with the color instrument.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Generating the patches that will be measured with the color instrument."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -719,8 +703,8 @@ gcm_calibrate_argyll_display_draw_and_measure (GcmCalibrateArgyll *calibrate_arg
 	gchar **argv = NULL;
 	GPtrArray *array = NULL;
 	gchar *basename = NULL;
-	const gchar *title;
-	const gchar *message;
+	const gchar *output_name;
+	guint display;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
@@ -734,18 +718,24 @@ gcm_calibrate_argyll_display_draw_and_measure (GcmCalibrateArgyll *calibrate_arg
 		goto out;
 	}
 
+	/* match up the output name with the device number defined by dispcal */
+	output_name = cd_device_get_metadata_item (priv->device,
+						   CD_DEVICE_METADATA_XRANDR_NAME);
+	display = gcm_calibrate_argyll_get_display (output_name, error);
+	if (display == G_MAXUINT) {
+		ret = FALSE;
+		goto out;
+	}
+
 	/* get l-cd or c-rt */
 	kind = gcm_calibrate_argyll_get_display_kind (calibrate_argyll);
 
 	/* TRANSLATORS: title, drawing means painting to the screen */
-	title = _("Drawing the patches");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Drawing the patches"));
 	/* TRANSLATORS: dialog message */
-	message = _("Drawing the generated patches to the screen, which will then be measured by the hardware device.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Drawing the generated patches to the screen, which will then be measured by the hardware device."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -755,7 +745,7 @@ gcm_calibrate_argyll_display_draw_and_measure (GcmCalibrateArgyll *calibrate_arg
 	g_ptr_array_add (array, g_strdup (command));
 #endif
 	g_ptr_array_add (array, g_strdup ("-v"));
-	g_ptr_array_add (array, g_strdup_printf ("-d%i", priv->display));
+	g_ptr_array_add (array, g_strdup_printf ("-d%i", display));
 	g_ptr_array_add (array, g_strdup_printf ("-y%c", kind));
 	g_ptr_array_add (array, g_strdup ("-k"));
 	g_ptr_array_add (array, g_strdup_printf ("%s.cal", basename));
@@ -818,8 +808,6 @@ gcm_calibrate_argyll_display_generate_profile (GcmCalibrateArgyll *calibrate_arg
 	gchar *command = NULL;
 	gchar *basename = NULL;
 	GPtrArray *array = NULL;
-	const gchar *title;
-	const gchar *message;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
@@ -840,14 +828,11 @@ gcm_calibrate_argyll_display_generate_profile (GcmCalibrateArgyll *calibrate_arg
 	}
 
 	/* TRANSLATORS: title, a profile is a ICC file */
-	title = _("Generating the profile");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Generating the profile"));
 	/* TRANSLATORS: dialog message */
-	message = _("Generating the ICC color profile that can be used with this screen.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Generating the ICC color profile that can be used with this screen."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -962,11 +947,8 @@ gcm_calibrate_argyll_device_copy (GcmCalibrateArgyll *calibrate_argyll, GError *
 	GFile *dest_source = NULL;
 	GFile *dest_reference = NULL;
 	const gchar *working_path;
-	const gchar *title;
-	const gchar *message;
 	const gchar *filename_tmp;
 	GcmCalibrateReferenceKind reference_kind;
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
@@ -978,14 +960,11 @@ gcm_calibrate_argyll_device_copy (GcmCalibrateArgyll *calibrate_argyll, GError *
 	working_path = gcm_calibrate_get_working_path (GCM_CALIBRATE (calibrate_argyll));
 
 	/* TRANSLATORS: title, a profile is a ICC file */
-	title = _("Copying files");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Copying files"));
 	/* TRANSLATORS: dialog message */
-	message = _("Copying source image, chart data and CIE reference values.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Copying source image, chart data and CIE reference values."));
 
 	/* build filenames */
 	filename = g_strdup_printf ("%s.tif", basename);
@@ -1046,8 +1025,6 @@ gcm_calibrate_argyll_device_measure (GcmCalibrateArgyll *calibrate_argyll, GErro
 	gchar *filename = NULL;
 	gchar *command = NULL;
 	gchar *basename = NULL;
-	const gchar *title;
-	const gchar *message;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
@@ -1055,14 +1032,11 @@ gcm_calibrate_argyll_device_measure (GcmCalibrateArgyll *calibrate_argyll, GErro
 		      NULL);
 
 	/* TRANSLATORS: title, drawing means painting to the screen */
-	title = _("Measuring the patches");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Measuring the patches"));
 	/* TRANSLATORS: dialog message */
-	message = _("Detecting the reference patches and measuring them.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Detecting the reference patches and measuring them."));
 
 	/* get correct name of the command */
 	command = gcm_calibrate_argyll_get_tool_filename ("scanin", error);
@@ -1144,8 +1118,6 @@ gcm_calibrate_argyll_device_generate_profile (GcmCalibrateArgyll *calibrate_argy
 	gchar *description = NULL;
 	gchar *manufacturer = NULL;
 	gchar *model = NULL;
-	const gchar *title;
-	const gchar *message;
 	GcmCalibrateReferenceKind reference_kind;
 
 	/* get shared data */
@@ -1168,14 +1140,11 @@ gcm_calibrate_argyll_device_generate_profile (GcmCalibrateArgyll *calibrate_argy
 	}
 
 	/* TRANSLATORS: title, a profile is a ICC file */
-	title = _("Generating the profile");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Generating the profile"));
 	/* TRANSLATORS: dialog message */
-	message = _("Generating the ICC color profile that can be used with this device.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Generating the ICC color profile that can be used with this device."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -1348,28 +1317,33 @@ gcm_calibrate_argyll_remove_temp_files (GcmCalibrateArgyll *calibrate_argyll, GE
  * gcm_calibrate_argyll_display:
  **/
 static gboolean
-gcm_calibrate_argyll_display (GcmCalibrate *calibrate, CdSensor *sensor, GtkWindow *window, GError **error)
+gcm_calibrate_argyll_display (GcmCalibrate *calibrate, CdDevice *device, CdSensor *sensor, GtkWindow *window, GError **error)
 {
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 	gboolean ret;
-	const gchar *title;
-	const gchar *message;
-
-	/* set modal windows up correctly */
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
 
-	/* TRANSLATORS: title, hardware refers to a calibration device */
-	title = _("Set up display");
+	priv->device = g_object_ref (device);
 
-	/* TRANSLATORS: dialog message */
-	message = _("Setting up display device for useâ?¦");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
+{
+	GtkWidget *vbox;
+	GtkWidget *expander;
+
+	/* pack terminal into expander */
+	expander = gtk_expander_new (NULL);
+	gtk_container_add (GTK_CONTAINER (expander),
+			   calibrate_argyll->priv->terminal);
+	gtk_expander_set_expanded (GTK_EXPANDER (expander), TRUE);
+
+	/* pack the expander in the content area */
+	vbox = gcm_calibrate_get_content_widget (GCM_CALIBRATE (calibrate_argyll));
+	gtk_box_pack_start (GTK_BOX (vbox),
+			    expander,
+			    FALSE, FALSE, 0);
+
+	/* show both */
+	gtk_widget_show_all (expander);
+}
 
 	/* step 1 */
 	ret = gcm_calibrate_argyll_display_neutralise (calibrate_argyll, error);
@@ -1415,8 +1389,6 @@ gcm_calibrate_argyll_spotread_read_chart (GcmCalibrateArgyll *calibrate_argyll,
 	gchar *command = NULL;
 	gchar **argv = NULL;
 	GPtrArray *array = NULL;
-	const gchar *title;
-	const gchar *message;
 
 	/* get correct name of the command */
 	command = gcm_calibrate_argyll_get_tool_filename ("spotread", error);
@@ -1426,14 +1398,11 @@ gcm_calibrate_argyll_spotread_read_chart (GcmCalibrateArgyll *calibrate_argyll,
 	}
 
 	/* TRANSLATORS: title, setting up the photospectromiter */
-	title = _("Setting up device");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Setting up device"));
 	/* TRANSLATORS: dialog message */
-	message = _("Setting up the device to read a spot colorâ?¦");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Setting up the device to read a spot colorâ?¦"));
 
 	/* reset flag so we exit after the single spotread */
 	priv->done_spot_read = FALSE;
@@ -1493,16 +1462,11 @@ out:
  * gcm_calibrate_argyll_spotread:
  **/
 static gboolean
-gcm_calibrate_argyll_spotread (GcmCalibrate *calibrate, CdSensor *sensor, GtkWindow *window, GError **error)
+gcm_calibrate_argyll_spotread (GcmCalibrate *calibrate, CdDevice *device, CdSensor *sensor, GtkWindow *window, GError **error)
 {
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 	gboolean ret;
 
-	/* set modal windows up correctly */
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-
 	/* step 3 */
 	ret = gcm_calibrate_argyll_spotread_read_chart (calibrate_argyll, error);
 	if (!ret)
@@ -1517,6 +1481,67 @@ out:
 }
 
 /**
+ * gcm_calibrate_argyll_interaction:
+ **/
+static void
+gcm_calibrate_argyll_interaction (GcmCalibrate *calibrate, GtkResponseType response)
+{
+	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
+	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
+
+	/* save our state */
+	priv->response = response;
+
+	/* ok */
+	if (response == GTK_RESPONSE_OK) {
+
+		/* send input if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
+			g_debug ("sending '%s' to argyll", priv->argyllcms_ok);
+#ifdef HAVE_VTE
+			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), priv->argyllcms_ok, 1);
+#endif
+			gcm_calibrate_pop (calibrate);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
+
+		/* clear loop if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
+			g_main_loop_quit (priv->loop);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
+
+		goto out;
+	}
+
+	/* cancel */
+	if (response == GTK_RESPONSE_CANCEL) {
+
+		/* send input if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
+			g_debug ("sending 'Q' to argyll");
+#ifdef HAVE_VTE
+			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), "Q", 1);
+#endif
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
+
+		/* clear loop if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
+			g_main_loop_quit (priv->loop);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
+
+		/* stop loop */
+		if (g_main_loop_is_running (priv->loop))
+			g_main_loop_quit (priv->loop);
+		goto out;
+	}
+out:
+	return;
+}
+
+/**
  * gcm_calibrate_argyll_get_sensor_target:
  **/
 static const gchar *
@@ -1557,8 +1582,6 @@ gcm_calibrate_argyll_display_generate_targets (GcmCalibrateArgyll *calibrate_arg
 	gchar **argv = NULL;
 	GPtrArray *array = NULL;
 	gchar *basename = NULL;
-	const gchar *title;
-	const gchar *message;
 	CdSensorKind sensor_kind;
 
 	/* get shared data */
@@ -1575,15 +1598,12 @@ gcm_calibrate_argyll_display_generate_targets (GcmCalibrateArgyll *calibrate_arg
 	}
 
 	/* TRANSLATORS: title, patches are specific colors used in calibration */
-	title = _("Printing patches");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Printing patches"));
 
 	/* TRANSLATORS: dialog message */
-	message = _("Rendering the patches for the selected paper and ink.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Rendering the patches for the selected paper and ink."));
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -1850,7 +1870,7 @@ out:
  * gcm_calibrate_argyll_printer:
  **/
 static gboolean
-gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdSensor *sensor, GtkWindow *window, GError **error)
+gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdDevice *device, CdSensor *sensor, GtkWindow *window, GError **error)
 {
 	gboolean ret;
 	gchar *cmdline = NULL;
@@ -1858,10 +1878,7 @@ gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 	const gchar *working_path;
 	gchar *basename = NULL;
 	GtkPaperSize *paper_size;
-	const gchar *title;
-	const gchar *message;
 	gdouble width, height;
-	GtkResponseType response;
 	GcmCalibratePrintKind print_kind;
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
@@ -1873,10 +1890,6 @@ gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 		      NULL);
 	working_path = gcm_calibrate_get_working_path (GCM_CALIBRATE (calibrate_argyll));
 
-	/* set modal windows up correctly */
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-
 	/* step 1 */
 	if (print_kind == GCM_CALIBRATE_PRINT_KIND_LOCAL ||
 	    print_kind == GCM_CALIBRATE_PRINT_KIND_GENERATE) {
@@ -1887,7 +1900,6 @@ gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 
 	/* print */
 	if (print_kind == GCM_CALIBRATE_PRINT_KIND_LOCAL) {
-		window = gcm_calibrate_dialog_get_window (priv->calibrate_dialog);
 		ret = gcm_print_with_render_callback (priv->print, window, (GcmPrintRenderCb) gcm_calibrate_argyll_render_cb, calibrate, error);
 		if (!ret)
 			goto out;
@@ -1920,26 +1932,13 @@ gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 	/* wait */
 	if (print_kind == GCM_CALIBRATE_PRINT_KIND_LOCAL) {
 		/* TRANSLATORS: title, patches are specific colours used in calibration */
-		title = _("Wait for the ink to dry");
+		gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+					 _("Wait for the ink to dry"));
 
 		/* TRANSLATORS: dialog message */
-		message = _("Please wait a few minutes for the ink to dry. Profiling damp ink will produce a poor profile and may damage your color measuring instrument.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("Please wait a few minutes for the ink to dry. Profiling damp ink will produce a poor profile and may damage your color measuring instrument."));
 
-		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, "clock.svg");
-		response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-		if (response != GTK_RESPONSE_OK) {
-			gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-			g_set_error_literal (error,
-					     GCM_CALIBRATE_ERROR,
-					     GCM_CALIBRATE_ERROR_USER_ABORT,
-					     "user did not wait for ink to dry");
-			ret = FALSE;
-			goto out;
-		}
 	}
 
 	/* we need to read the ti2 file to set the device used for calibration */
@@ -1947,7 +1946,6 @@ gcm_calibrate_argyll_printer (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 		filename = g_strdup_printf ("%s/%s.ti2", working_path, basename);
 		ret = g_file_test (filename, G_FILE_TEST_EXISTS);
 		if (!ret) {
-			gcm_calibrate_dialog_hide (priv->calibrate_dialog);
 			g_set_error (error,
 				     GCM_CALIBRATE_ERROR,
 				     GCM_CALIBRATE_ERROR_NO_DATA,
@@ -2091,28 +2089,19 @@ out:
  * gcm_calibrate_argyll_device:
  **/
 static gboolean
-gcm_calibrate_argyll_device (GcmCalibrate *calibrate, CdSensor *sensor, GtkWindow *window, GError **error)
+gcm_calibrate_argyll_device (GcmCalibrate *calibrate, CdDevice *device, CdSensor *sensor, GtkWindow *window, GError **error)
 {
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 	gboolean ret;
-	const gchar *title;
-	const gchar *message;
-
-	/* set modal windows up correctly */
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
 
 	/* TRANSLATORS: title, instrument refers to a calibration device */
-	title = _("Set up instrument");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Set up instrument"));
 
 	/* TRANSLATORS: dialog message */
-	message = _("Setting up the instrument for useâ?¦");
+	gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Setting up the instrument for useâ?¦"));
 
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 
 	/* step 1 */
 	ret = gcm_calibrate_argyll_device_copy (calibrate_argyll, error);
@@ -2188,8 +2177,6 @@ gcm_calibrate_argyll_timeout_cb (GcmCalibrateArgyll *calibrate_argyll)
 static void
 gcm_calibrate_argyll_interaction_attach (GcmCalibrateArgyll *calibrate_argyll)
 {
-	const gchar *title;
-	const gchar *message;
 	const gchar *filename;
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
@@ -2199,38 +2186,32 @@ gcm_calibrate_argyll_interaction_attach (GcmCalibrateArgyll *calibrate_argyll)
 		priv->keypress_id = g_timeout_add_seconds (1,
 							   (GSourceFunc) gcm_calibrate_argyll_timeout_cb,
 							   calibrate_argyll);
-#if GLIB_CHECK_VERSION(2,25,8)
 		g_source_set_name_by_id (priv->keypress_id, "[GcmCalibrateArgyll] keypress faker");
-#endif
 		goto out;
 	}
 
 	/* TRANSLATORS: title, instrument is a hardware color calibration sensor */
-	title = _("Please attach instrument");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Please attach instrument"));
 
 	/* get the image, if we have one */
 	filename = gcm_calibrate_argyll_get_sensor_image_attach (calibrate_argyll);
+	gcm_calibrate_set_image (GCM_CALIBRATE (calibrate_argyll), filename);
 
 	/* different messages with or without image */
 	if (filename != NULL) {
 		/* TRANSLATORS: dialog message, ask user to attach device, and there's an example image */
-		message = _("Please attach the measuring instrument to the center of the screen on the gray square like the image below.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Please attach the measuring instrument to the center of the screen on the gray square like the image below."));
 	} else {
 		/* TRANSLATORS: dialog message, ask user to attach device */
-		message = _("Please attach the measuring instrument to the center of the screen on the gray square.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Please attach the measuring instrument to the center of the screen on the gray square."));
 	}
 
 	/* block for a response */
-	g_debug ("blocking waiting for user input: %s", title);
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, filename);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-
-	/* TRANSLATORS: button text */
-	gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Continue"));
+	g_debug ("blocking waiting for user input");
+	gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Continue"));
 
 	/* set state */
 	priv->argyllcms_ok = " ";
@@ -2241,7 +2222,7 @@ gcm_calibrate_argyll_interaction_attach (GcmCalibrateArgyll *calibrate_argyll)
 			 CA_PROP_EVENT_ID, "dialog-information",
 			 /* TRANSLATORS: this is the application name for libcanberra */
 			 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
-			 CA_PROP_EVENT_DESCRIPTION, message, NULL);
+			 CA_PROP_EVENT_DESCRIPTION, "interaction required", NULL);
 
 	/* save as we know the device is on the screen now */
 	priv->already_on_window = TRUE;
@@ -2255,43 +2236,36 @@ out:
 static void
 gcm_calibrate_argyll_interaction_calibrate (GcmCalibrateArgyll *calibrate_argyll)
 {
-	const gchar *title;
-	const gchar *message;
 	const gchar *filename;
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
 	/* TRANSLATORS: title, instrument is a hardware color calibration sensor */
-	title = _("Please configure instrument");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Please configure instrument"));
 
 	/* block for a response */
-	g_debug ("blocking waiting for user input: %s", title);
+	g_debug ("blocking waiting for user input");
 
 	/* get the image, if we have one */
 	filename = gcm_calibrate_argyll_get_sensor_image_calibrate (calibrate_argyll);
 
 	if (filename != NULL) {
 		/* TRANSLATORS: this is when the user has to change a setting on the sensor, and we're showing a picture */
-		message = _("Please set the measuring instrument to calibration mode like the image below.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Please set the measuring instrument to calibration mode like the image below."));
 	} else {
 		/* TRANSLATORS: this is when the user has to change a setting on the sensor */
-		message = _("Please set the measuring instrument to calibration mode.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Please set the measuring instrument to calibration mode."));
 	}
 
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, filename);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-
-	/* TRANSLATORS: button text */
-	gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Continue"));
 
 	/* play sound from the naming spec */
 	ca_context_play (ca_gtk_context_get (), 0,
 			 CA_PROP_EVENT_ID, "dialog-information",
 			 /* TRANSLATORS: this is the application name for libcanberra */
 			 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
-			 CA_PROP_EVENT_DESCRIPTION, message, NULL);
+			 CA_PROP_EVENT_DESCRIPTION, "setup calibration tool", NULL);
 
 	/* assume it's no longer on the window */
 	priv->already_on_window = FALSE;
@@ -2302,6 +2276,7 @@ gcm_calibrate_argyll_interaction_calibrate (GcmCalibrateArgyll *calibrate_argyll
 	/* set state */
 	priv->argyllcms_ok = " ";
 	priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
+	gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Continue"));
 }
 
 /**
@@ -2310,43 +2285,36 @@ gcm_calibrate_argyll_interaction_calibrate (GcmCalibrateArgyll *calibrate_argyll
 static void
 gcm_calibrate_argyll_interaction_surface (GcmCalibrateArgyll *calibrate_argyll)
 {
-	const gchar *title;
-	const gchar *message;
 	const gchar *filename;
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
 	/* TRANSLATORS: title, instrument is a hardware color calibration sensor */
-	title = _("Please configure instrument");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Please configure instrument"));
 
 	/* block for a response */
-	g_debug ("blocking waiting for user input: %s", title);
+	g_debug ("blocking waiting for user input");
 
 	/* get the image, if we have one */
 	filename = gcm_calibrate_argyll_get_sensor_image_screen (calibrate_argyll);
 
 	if (filename != NULL) {
 		/* TRANSLATORS: this is when the user has to change a setting on the sensor, and we're showing a picture */
-		message = _("Please set the measuring instrument to screen mode like the image below.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Please set the measuring instrument to screen mode like the image below."));
 	} else {
 		/* TRANSLATORS: this is when the user has to change a setting on the sensor */
-		message = _("Please set the measuring instrument to screen mode.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("Please set the measuring instrument to screen mode."));
 	}
 
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, filename);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-
-	/* TRANSLATORS: button text */
-	gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Continue"));
 
 	/* play sound from the naming spec */
 	ca_context_play (ca_gtk_context_get (), 0,
 			 CA_PROP_EVENT_ID, "dialog-information",
 			 /* TRANSLATORS: this is the application name for libcanberra */
 			 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
-			 CA_PROP_EVENT_DESCRIPTION, message, NULL);
+			 CA_PROP_EVENT_DESCRIPTION, "correct hardware state", NULL);
 
 	/* assume it's no longer on the window */
 	priv->already_on_window = FALSE;
@@ -2354,6 +2322,7 @@ gcm_calibrate_argyll_interaction_surface (GcmCalibrateArgyll *calibrate_argyll)
 	/* set state */
 	priv->argyllcms_ok = " ";
 	priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
+	gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Continue"));
 }
 
 /**
@@ -2364,9 +2333,7 @@ gcm_calibrate_argyll_interaction_surface (GcmCalibrateArgyll *calibrate_argyll)
 static gboolean
 gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, const gchar *line)
 {
-	const gchar *title;
 	gchar *title_str = NULL;
-	const gchar *message;
 	GString *string = NULL;
 	gchar *found;
 	gchar **split = NULL;
@@ -2400,29 +2367,25 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 	/* something went wrong with a measurement */
 	if (g_strstr_len (line, -1, "Measurement misread") != NULL) {
 		/* TRANSLATORS: title, the calibration failed */
-		title = _("Calibration error");
+		gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+					 _("Calibration error"));
 
 		/* TRANSLATORS: message, the sample was not read correctly */
-		message = _("The sample could not be read at this time.");
-
-		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("The sample could not be read at this time."));
 
-		/* TRANSLATORS: button text */
-		gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Try again"));
 
 		/* set state */
 		priv->argyllcms_ok = " ";
 		priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
+		gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Retry"));
 
 		/* play sound from the naming spec */
 		ca_context_play (ca_gtk_context_get (), 0,
 				 CA_PROP_EVENT_ID, "dialog-warning",
 				 /* TRANSLATORS: this is the application name for libcanberra */
 				 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
-				 CA_PROP_EVENT_DESCRIPTION, message, NULL);
+				 CA_PROP_EVENT_DESCRIPTION, "unspecified error", NULL);
 		goto out;
 	}
 
@@ -2459,7 +2422,6 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 			      "xyz", xyz,
 			      NULL);
 		priv->done_spot_read = TRUE;
-		gcm_calibrate_dialog_response (priv->calibrate_dialog, GTK_RESPONSE_CANCEL);
 		cd_color_xyz_free (xyz);
 		goto out;
 	}
@@ -2469,29 +2431,31 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 	if (found != NULL) {
 
 		/* TRANSLATORS: title, the calibration failed */
-		title = _("Calibration error");
+		gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+					 _("Calibration error"));
 
 		if (g_strstr_len (line, -1, "No PLD firmware pattern is available") != NULL) {
 			/* TRANSLATORS: message, no firmware is available */
-			message = _("No firmware is installed for this instrument.");
+			gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("No firmware is installed for this instrument."));
 		} else if (g_strstr_len (line, -1, "Pattern match wasn't good enough") != NULL) {
 			/* TRANSLATORS: message, the image wasn't good enough */
-			message = _("The pattern match wasn't good enough. Ensure you have the correct type of target selected.");
+			gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("The pattern match wasn't good enough. Ensure you have the correct type of target selected."));
 		} else if (g_strstr_len (line, -1, "Aprox. fwd matrix unexpectedly singular") != NULL ||
 			   g_strstr_len (line, -1, "Inverting aprox. fwd matrix failed") != NULL) {
 			/* TRANSLATORS: message, the sensor got no readings */
-			message = _("The measuring instrument got no valid readings. Please ensure the aperture is fully open.");
+			gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("The measuring instrument got no valid readings. Please ensure the aperture is fully open."));
 		} else if (g_strstr_len (line, -1, "Device or resource busy") != NULL) {
 			/* TRANSLATORS: message, the colorimeter has got confused */
-			message = _("The measuring instrument is busy and is not starting up. Please remove the USB plug and re-insert before trying to use this device.");
+			gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   _("The measuring instrument is busy and is not starting up. Please remove the USB plug and re-insert before trying to use this device."));
 		} else {
-			message = found + 8;
+			gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+				   found + 8);
 		}
 
-		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 		g_debug ("VTE: error: %s", found+8);
 
@@ -2503,7 +2467,7 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 				 CA_PROP_EVENT_ID, "dialog-warning",
 				 /* TRANSLATORS: this is the application name for libcanberra */
 				 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
-				 CA_PROP_EVENT_DESCRIPTION, message, NULL);
+				 CA_PROP_EVENT_DESCRIPTION, "hardware error", NULL);
 
 		/* wait until finished */
 		g_main_loop_run (priv->loop);
@@ -2513,7 +2477,7 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 	/* all done */
 	found = g_strstr_len (line, -1, "(All rows read)");
 	if (found != NULL) {
-		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, "scan-target-good.svg");
+		gcm_calibrate_set_image (GCM_CALIBRATE (calibrate_argyll), "scan-target-good.svg");
 		vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), "d", 1);
 		goto out;
 	}
@@ -2521,30 +2485,24 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 	/* reading strip */
 	if (g_str_has_prefix (line, "Strip read failed due to misread")) {
 		/* TRANSLATORS: dialog title */
-		title = _("Reading target");
+		gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+					 _("Reading target"));
 
 		/* TRANSLATORS: message, no firmware is available */
-		message = _("Failed to read the strip correctly.");
-
-		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, "scan-target-bad.svg");
-
-		/* TRANSLATORS: button text */
-		gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Retry"));
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("Failed to read the strip correctly."));
 
 		/* set state */
 		priv->argyllcms_ok = " ";
 		priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
+		gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Retry"));
 
 		/* play sound from the naming spec */
 		ca_context_play (ca_gtk_context_get (), 0,
 				 CA_PROP_EVENT_ID, "dialog-warning",
 				 /* TRANSLATORS: this is the application name for libcanberra */
 				 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
-				 CA_PROP_EVENT_DESCRIPTION, message, NULL);
+				 CA_PROP_EVENT_DESCRIPTION, "failed to read strip", NULL);
 		goto out;
 	}
 
@@ -2568,18 +2526,15 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 		g_string_append (string, _("If you've really measured the right one, it's okay, it could just be unusual paper."));
 		g_string_append (string, "\n\n");
 
-		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title_str, string->str);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, "scan-target-bad.svg");
+g_debug ("title=%s, message=%s", title_str, string->str);
 
-		/* TRANSLATORS: button */
-		gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Use anyway"));
+		/* push new messages into the UI */
+		gcm_calibrate_set_image (GCM_CALIBRATE (calibrate_argyll), "scan-target-bad.svg");
 
 		/* set state */
 		priv->argyllcms_ok = "\n";
 		priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
+		gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Retry"));
 		goto out;
 	}
 
@@ -2587,7 +2542,6 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 	if (g_str_has_prefix (line, "Place instrument on spot to be measured")) {
 		if (!priv->done_spot_read)
 			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), " ", 1);
-		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
 		goto out;
 	}
 
@@ -2595,22 +2549,17 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 	if (g_str_has_prefix (line, "Spot read failed due to misread")) {
 
 		/* TRANSLATORS: title, the calibration failed */
-		title = _("Device Error");
+		gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+					 _("Device Error"));
 
 		/* TRANSLATORS: message, the sample was not read correctly */
-		message = _("The device could not measure the color spot correctly.");
-
-		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-
-		/* TRANSLATORS: button */
-		gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Retry"));
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("The device could not measure the color spot correctly."));
 
 		/* set state */
 		priv->argyllcms_ok = " ";
 		priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
+		gcm_calibrate_interaction_required (GCM_CALIBRATE (calibrate_argyll), _("Retry"));
 		goto out;
 	}
 
@@ -2638,10 +2587,7 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 		g_string_append (string, _("If you make a mistake just release the switch and you'll get a chance to try again."));
 
 		/* push new messages into the UI */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title_str, string->str);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, "scan-target.svg");
+		gcm_calibrate_set_image (GCM_CALIBRATE (calibrate_argyll), "scan-target.svg");
 		goto out;
 	}
 
@@ -2710,118 +2656,48 @@ gcm_calibrate_argyll_cursor_moved_cb (VteTerminal *terminal, GcmCalibrateArgyll
 #endif
 
 /**
- * gcm_calibrate_argyll_response_cb:
- **/
-static void
-gcm_calibrate_argyll_response_cb (GtkWidget *widget, GtkResponseType response, GcmCalibrateArgyll *calibrate_argyll)
-{
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
-
-	/* save our state */
-	priv->response = response;
-
-	/* ok */
-	if (response == GTK_RESPONSE_OK) {
-
-		/* send input if waiting */
-		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
-			g_debug ("sending '%s' to argyll", priv->argyllcms_ok);
-#ifdef HAVE_VTE
-			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), priv->argyllcms_ok, 1);
-#endif
-			gcm_calibrate_dialog_pop (priv->calibrate_dialog);
-			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
-		}
-
-		/* clear loop if waiting */
-		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
-			g_main_loop_quit (priv->loop);
-			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
-		}
-
-		goto out;
-	}
-
-	/* cancel */
-	if (response == GTK_RESPONSE_CANCEL) {
-
-		/* send input if waiting */
-		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
-			g_debug ("sending 'Q' to argyll");
-#ifdef HAVE_VTE
-			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), "Q", 1);
-#endif
-			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
-		}
-
-		/* clear loop if waiting */
-		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
-			g_main_loop_quit (priv->loop);
-			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
-		}
-
-		/* hide the window */
-		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-
-		/* stop loop */
-		if (g_main_loop_is_running (priv->loop))
-			g_main_loop_quit (priv->loop);
-		goto out;
-	}
-out:
-	return;
-}
-
-/**
  * gcm_calibrate_argyll_status_changed_cb:
  **/
 static void
 gcm_calibrate_argyll_status_changed_cb (GcmPrint *print, GtkPrintStatus status, GcmCalibrateArgyll *calibrate_argyll)
 {
-	const gchar *title;
-	const gchar *message = NULL;
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
-
 	/* TRANSLATORS: title, printing reference files to media */
-	title = _("Printing");
+	gcm_calibrate_set_title (GCM_CALIBRATE (calibrate_argyll),
+				 _("Printing"));
 
 	switch (status) {
 	case GTK_PRINT_STATUS_INITIAL:
 	case GTK_PRINT_STATUS_PREPARING:
 	case GTK_PRINT_STATUS_GENERATING_DATA:
 		/* TRANSLATORS: dialog message */
-		message = _("Preparing the data for the printer.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("Preparing the data for the printer."));
 		break;
 	case GTK_PRINT_STATUS_SENDING_DATA:
 	case GTK_PRINT_STATUS_PENDING:
 	case GTK_PRINT_STATUS_PENDING_ISSUE:
 		/* TRANSLATORS: dialog message */
-		message = _("Sending the targets to the printer.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("Sending the targets to the printer."));
 		break;
 	case GTK_PRINT_STATUS_PRINTING:
 		/* TRANSLATORS: dialog message */
-		message = _("Printing the targets...");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("Printing the targets..."));
 		break;
 	case GTK_PRINT_STATUS_FINISHED:
 		/* TRANSLATORS: dialog message */
-		message = _("The printing has finished.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("The printing has finished."));
 		break;
 	case GTK_PRINT_STATUS_FINISHED_ABORTED:
 		/* TRANSLATORS: dialog message */
-		message = _("The print was aborted.");
+		gcm_calibrate_set_message (GCM_CALIBRATE (calibrate_argyll),
+					   _("The print was aborted."));
 		break;
 	default:
 		break;
 	}
-
-	/* not a translated message */
-	if (message == NULL)
-		return;
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 }
 
 /**
@@ -2839,6 +2715,7 @@ gcm_calibrate_argyll_class_init (GcmCalibrateArgyllClass *klass)
 	parent_class->calibrate_device = gcm_calibrate_argyll_device;
 	parent_class->calibrate_printer = gcm_calibrate_argyll_printer;
 	parent_class->calibrate_spotread = gcm_calibrate_argyll_spotread;
+	parent_class->interaction = gcm_calibrate_argyll_interaction;
 
 	g_type_class_add_private (klass, sizeof (GcmCalibrateArgyllPrivate));
 }
@@ -2860,9 +2737,6 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 	calibrate_argyll->priv->print = gcm_print_new ();
 	g_signal_connect (calibrate_argyll->priv->print, "status-changed",
 			  G_CALLBACK (gcm_calibrate_argyll_status_changed_cb), calibrate_argyll);
-	calibrate_argyll->priv->calibrate_dialog = gcm_calibrate_dialog_new ();
-	g_signal_connect (calibrate_argyll->priv->calibrate_dialog, "response",
-			  G_CALLBACK (gcm_calibrate_argyll_response_cb), calibrate_argyll);
 
 	/* get screen */
 	calibrate_argyll->priv->screen = gcm_x11_screen_new ();
@@ -2876,8 +2750,6 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 			  G_CALLBACK (gcm_calibrate_argyll_exit_cb), calibrate_argyll);
 	g_signal_connect (calibrate_argyll->priv->terminal, "cursor-moved",
 			  G_CALLBACK (gcm_calibrate_argyll_cursor_moved_cb), calibrate_argyll);
-	gcm_calibrate_dialog_pack_details (calibrate_argyll->priv->calibrate_dialog,
-					   calibrate_argyll->priv->terminal);
 #endif
 }
 
@@ -2909,15 +2781,11 @@ gcm_calibrate_argyll_finalize (GObject *object)
 					      calibrate_argyll);
 #endif
 
-	/* hide */
-	gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-
 	if (priv->keypress_id != 0)
 		g_source_remove (priv->keypress_id);
 
 	g_main_loop_unref (priv->loop);
 	g_object_unref (priv->screen);
-	g_object_unref (priv->calibrate_dialog);
 	g_object_unref (priv->print);
 
 	G_OBJECT_CLASS (gcm_calibrate_argyll_parent_class)->finalize (object);
diff --git a/src/gcm-calibrate-main.c b/src/gcm-calibrate-main.c
new file mode 100644
index 0000000..0c6add3
--- /dev/null
+++ b/src/gcm-calibrate-main.c
@@ -0,0 +1,1817 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009-2011 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <glib/gstdio.h>
+#include <locale.h>
+#include <canberra-gtk.h>
+#include <colord.h>
+
+#include "gcm-utils.h"
+#include "gcm-debug.h"
+#include "gcm-brightness.h"
+#include "gcm-calibrate.h"
+#include "gcm-calibrate-argyll.h"
+
+typedef enum {
+	GCM_CALIBRATE_PAGE_INTRO,
+	GCM_CALIBRATE_PAGE_DISPLAY_KIND,
+	GCM_CALIBRATE_PAGE_DISPLAY_CONFIG,
+	GCM_CALIBRATE_PAGE_INSTALL_ARGYLLCMS,
+	GCM_CALIBRATE_PAGE_INSTALL_TARGETS,
+	GCM_CALIBRATE_PAGE_PRINT_KIND,
+	GCM_CALIBRATE_PAGE_TARGET_KIND,
+	GCM_CALIBRATE_PAGE_SENSOR,
+	GCM_CALIBRATE_PAGE_ACTION,
+	GCM_CALIBRATE_PAGE_FAILURE,
+	GCM_CALIBRATE_PAGE_LAST
+} GcmCalibratePage;
+
+typedef struct {
+	GtkApplication	*application;
+	CdClient	*client;
+	GcmCalibrate	*calibrate;
+	CdDevice	*device;
+	CdDeviceKind	 device_kind;
+	GCancellable	*cancellable;
+	CdSensor	*sensor;
+	gchar		*device_id;
+	guint		 xid;
+	GtkWindow	*main_window;
+	GPtrArray	*pages;
+	GcmBrightness	*brightness;
+	guint		 old_brightness;
+	gboolean	 internal_lcd;
+	GtkWidget	*reference_preview;
+	GtkWidget	*action_title;
+	GtkWidget	*action_message;
+	GtkWidget	*action_image;
+	GtkWidget	*interaction_button;
+	GtkWidget	*abort_button;
+	GcmCalibrateDisplayKind		 display_kind;
+	GcmCalibrateReferenceKind	 reference_kind;
+	GcmCalibratePrintKind		 print_kind;
+	GcmCalibratePrecision		 precision;
+	GcmCalibratePage		 current_page;
+} GcmCalibratePriv;
+
+/**
+ * gcm_window_set_parent_xid:
+ **/
+static void
+gcm_window_set_parent_xid (GtkWindow *window, guint32 xid)
+{
+	GdkDisplay *display;
+	GdkWindow *parent_window;
+	GdkWindow *our_window;
+
+	display = gdk_display_get_default ();
+	parent_window = gdk_x11_window_foreign_new_for_display (display, xid);
+	if (parent_window == NULL) {
+		g_warning ("failed to get parent window");
+		return;
+	}
+	our_window = gtk_widget_get_window (GTK_WIDGET (window));
+	if (our_window == NULL) {
+		g_warning ("failed to get our window");
+		return;
+	}
+
+	/* set this above our parent */
+	gtk_window_set_modal (window, TRUE);
+	gdk_window_set_transient_for (our_window, parent_window);
+	gtk_window_set_title (window, "");
+}
+
+/**
+ * gcm_calib_activate_cb:
+ **/
+static void
+gcm_calib_activate_cb (GApplication *application, GcmCalibratePriv *calib)
+{
+	gtk_window_present (calib->main_window);
+}
+
+static void
+gcm_calib_confirm_quit_cb (GtkDialog *dialog,
+			   gint response_id,
+			   GcmCalibratePriv *calib)
+{
+	if (response_id != GTK_RESPONSE_CLOSE) {
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		return;
+	}
+	g_application_release (G_APPLICATION (calib->application));
+}
+
+/**
+ * gcm_calib_confirm_quit:
+ **/
+static void
+gcm_calib_confirm_quit (GcmCalibratePriv *calib)
+{
+	GtkWidget *dialog;
+
+	/* do not ask for confirmation on the initial page */
+	if (calib->current_page == GCM_CALIBRATE_PAGE_INTRO)
+		g_application_release (G_APPLICATION (calib->application));
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (calib->main_window),
+					 GTK_DIALOG_MODAL,
+					 GTK_MESSAGE_QUESTION,
+					 GTK_BUTTONS_NONE,
+					 "%s", _("Calibration is not complete"));
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+						  "%s",
+						  _("Are you sure you want to cancel the calibration?"));
+	/* TRANSLATORS: button text */
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       _("Continue calibration"),
+			       GTK_RESPONSE_CANCEL);
+	/* TRANSLATORS: button text */
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       _("Cancel and close"),
+			       GTK_RESPONSE_CLOSE);
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (gcm_calib_confirm_quit_cb),
+			  calib);
+	gtk_widget_show (dialog);
+}
+
+/**
+ * gcm_calib_delete_event_cb:
+ **/
+static gboolean
+gcm_calib_delete_event_cb (GtkWidget *widget, GdkEvent *event, GcmCalibratePriv *calib)
+{
+	gcm_calib_confirm_quit (calib);
+	return FALSE;
+}
+
+/**
+ * gcm_calib_assistant_cancel_cb:
+ **/
+static void
+gcm_calib_assistant_cancel_cb (GtkAssistant *assistant, GcmCalibratePriv *calib)
+{
+	gcm_calib_confirm_quit (calib);
+}
+
+/**
+ * gcm_calib_assistant_close_cb:
+ **/
+static void
+gcm_calib_assistant_close_cb (GtkAssistant *assistant, GcmCalibratePriv *calib)
+{
+	g_application_release (G_APPLICATION (calib->application));
+}
+
+/**
+ * gcm_calib_device_inihibit:
+ **/
+static void
+gcm_calib_device_inihibit (GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	GError *error = NULL;
+
+	/* invalid */
+	if (calib->device == NULL)
+		return;
+
+	/* mark device to be profiled in colord */
+	ret = cd_device_profiling_inhibit_sync (calib->device,
+						calib->cancellable,
+						&error);
+	if (!ret) {
+		g_warning ("failed to inhibit device: %s",
+			   error->message);
+		g_clear_error (&error);
+	}
+
+	/* set the brightness to max */
+	if (calib->device_kind == CD_DEVICE_KIND_DISPLAY &&
+	    calib->internal_lcd) {
+		ret = gcm_brightness_get_percentage (calib->brightness,
+						     &calib->old_brightness,
+						     &error);
+		if (!ret) {
+			g_warning ("failed to get brightness: %s",
+				   error->message);
+			g_clear_error (&error);
+		}
+		ret = gcm_brightness_set_percentage (calib->brightness,
+						     100,
+						     &error);
+		if (!ret) {
+			g_warning ("failed to set brightness: %s",
+				   error->message);
+			g_error_free (error);
+		}
+	}
+}
+
+/**
+ * gcm_calib_device_uninihibit:
+ **/
+static void
+gcm_calib_device_uninihibit (GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	GError *error = NULL;
+
+	/* invalid */
+	if (calib->device == NULL)
+		return;
+
+	/* mark device to be profiled in colord */
+	ret = cd_device_profiling_uninhibit_sync (calib->device,
+						  calib->cancellable,
+						  &error);
+	if (!ret) {
+		g_warning ("failed to uninhibit device: %s",
+			   error->message);
+		g_clear_error (&error);
+	}
+
+	/* reset the brightness to what it was before */
+	if (calib->device_kind == CD_DEVICE_KIND_DISPLAY &&
+	    calib->old_brightness != G_MAXUINT &&
+	    calib->internal_lcd) {
+		ret = gcm_brightness_set_percentage (calib->brightness,
+						     calib->old_brightness,
+						     &error);
+		if (!ret) {
+			g_warning ("failed to set brightness: %s",
+				   error->message);
+			g_error_free (error);
+		}
+	}
+}
+
+/**
+ * gcm_calib_play_sound:
+ **/
+static void
+gcm_calib_play_sound (GcmCalibratePriv *calib)
+{
+	/* play sound from the naming spec */
+	ca_context_play (ca_gtk_context_get (), 0,
+			 CA_PROP_EVENT_ID, "complete",
+			 /* TRANSLATORS: this is the application name for libcanberra */
+			 CA_PROP_APPLICATION_NAME, _("GNOME Color Manager"),
+			 /* TRANSLATORS: this is the sound description */
+			 CA_PROP_EVENT_DESCRIPTION, _("Profiling completed"),
+			 NULL);
+}
+
+
+/**
+ * gcm_calib_get_vbox_for_page:
+ **/
+static GtkWidget *
+gcm_calib_get_vbox_for_page (GcmCalibratePriv *calib,
+			     GcmCalibratePage page)
+{
+	guint i;
+	GtkWidget *tmp;
+	GcmCalibratePage page_tmp;
+
+	for (i=0; i<calib->pages->len; i++) {
+		tmp = g_ptr_array_index (calib->pages, i);
+		page_tmp = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tmp),
+								"GcmCalibrateMain::Index"));
+		if (page_tmp == page)
+			return tmp;
+	}
+	return NULL;
+}
+
+static gboolean
+gcm_calib_start_idle_cb (gpointer user_data)
+{
+	CdProfile *profile = NULL;
+	const gchar *filename;
+	gboolean ret;
+	gchar *destination = NULL;
+	gchar *filename_dest = NULL;
+	GError *error = NULL;
+	GFile *dest = NULL;
+	GFile *file = NULL;
+	GtkWidget *vbox;
+	GcmCalibratePriv *calib = (GcmCalibratePriv *) user_data;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	g_object_set (calib->calibrate,
+		      "display-kind", calib->display_kind,
+		      "precision", calib->precision,
+		      NULL);
+
+	/* actuall do the action */
+	ret = gcm_calibrate_display (calib->calibrate,
+				     calib->device,
+				     calib->main_window,
+				     &error);
+	if (!ret) {
+		gcm_calibrate_set_title (calib->calibrate, _("Failed to calibrate"));
+		gcm_calibrate_set_message (calib->calibrate, error->message);
+		gcm_calibrate_set_image (calib->calibrate, NULL);
+
+		g_warning ("failed to calibrate: %s",
+			   error->message);
+		g_error_free (error);
+
+		/* mark this box as the end */
+		vbox = gcm_calib_get_vbox_for_page (calib, GCM_CALIBRATE_PAGE_ACTION);
+		gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_SUMMARY);
+		goto out;
+	}
+
+	/* get profile */
+	filename = gcm_calibrate_get_filename_result (calib->calibrate);
+	if (filename == NULL) {
+		g_warning ("failed to get filename from calibration");
+		goto out;
+	}
+
+	/* copy the ICC file to the proper location */
+	file = g_file_new_for_path (filename);
+	dest = gcm_utils_get_profile_destination (file);
+	ret = gcm_utils_mkdir_and_copy (file, dest, &error);
+	if (!ret) {
+		g_warning ("failed to calibrate: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* add the new profile as the default */
+	filename_dest = g_file_get_path (dest);
+	profile = cd_client_find_profile_by_filename_sync (calib->client,
+							   filename_dest,
+							   calib->cancellable,
+							   &error);
+	if (profile == NULL) {
+		g_warning ("failed to find calibration profile: %s",
+			   error->message);
+		g_error_free (error);
+		goto out;
+	}
+	ret = cd_device_add_profile_sync (calib->device,
+					  CD_DEVICE_RELATION_HARD,
+					  profile,
+					  calib->cancellable,
+					  &error);
+	if (!ret) {
+		g_warning ("failed to add %s to %s: %s",
+			   cd_profile_get_object_path (profile),
+			   cd_device_get_object_path (calib->device),
+			   error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* remove temporary file */
+	g_unlink (filename);
+
+out:
+	g_free (destination);
+	g_free (filename_dest);
+	if (profile != NULL)
+		g_object_unref (profile);
+	if (file != NULL)
+		g_object_unref (file);
+	if (dest != NULL)
+		g_object_unref (dest);
+	return FALSE;
+}
+
+/**
+ * gcm_calib_assistant_prepare_cb:
+ **/
+static gboolean
+gcm_calib_assistant_prepare_cb (GtkAssistant *assistant, GtkWidget *page_widget, GcmCalibratePriv *calib)
+{
+	calib->current_page = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (page_widget),
+								   "GcmCalibrateMain::Index"));
+	switch (calib->current_page) {
+	case GCM_CALIBRATE_PAGE_INTRO:
+		g_debug ("now intro page");
+		gcm_calib_device_inihibit (calib);
+		break;
+	case GCM_CALIBRATE_PAGE_LAST:
+		g_debug ("now last page");
+		gcm_calib_device_uninihibit (calib);
+		gcm_calib_play_sound (calib);
+		break;
+	case GCM_CALIBRATE_PAGE_ACTION:
+		g_debug ("lights! camera! action!");
+		g_idle_add (gcm_calib_start_idle_cb, calib);
+		break;
+	default:
+		break;
+	}
+
+	/* use the default on each page */
+	switch (calib->current_page) {
+	case GCM_CALIBRATE_PAGE_INSTALL_ARGYLLCMS:
+	case GCM_CALIBRATE_PAGE_ACTION:
+	case GCM_CALIBRATE_PAGE_SENSOR:
+		break;
+	default:
+		gtk_assistant_set_page_complete (assistant, page_widget, TRUE);
+		break;
+	}
+	return FALSE;
+}
+
+/**
+ * gcm_calib_add_page_title:
+ **/
+static GtkWidget *
+gcm_calib_add_page_title (GcmCalibratePriv *calib, const gchar *text)
+{
+	GtkWidget *label;
+	GtkWidget *hbox;
+	GtkWidget *vbox;
+	gchar *markup;
+
+	markup = g_strdup_printf ("<span size=\"large\" font_weight=\"bold\">%s</span>", text);
+	label = gtk_label_new (NULL);
+	gtk_label_set_markup (GTK_LABEL (label), markup);
+
+	/* make left aligned */
+	hbox = gtk_hbox_new (FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+
+	/* header */
+	vbox = gtk_vbox_new (FALSE, 20);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+	g_free (markup);
+	return vbox;
+}
+
+static gboolean
+gcm_calib_label_activate_link_cb (GtkLabel *label,
+				  gchar *uri,
+				  GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	GError *error = NULL;
+	ret = g_spawn_command_line_async (BINDIR "/gnome-control-center color", &error);
+	if (!ret) {
+		g_warning ("failed to launch the control center: %s",
+			   error->message);
+		g_error_free (error);
+	}
+	return ret;
+}
+
+/**
+ * gcm_calib_add_page_para:
+ **/
+static GtkWidget *
+gcm_calib_add_page_para (GtkWidget *vbox, const gchar *text)
+{
+	GtkWidget *label;
+	GtkWidget *hbox;
+
+	label = gtk_label_new (NULL);
+	g_signal_connect (label, "activate-link",
+			  G_CALLBACK (gcm_calib_label_activate_link_cb),
+			  NULL);
+	gtk_label_set_markup (GTK_LABEL (label), text);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+//	gtk_label_set_max_width_chars (GTK_LABEL (label), 120);
+//	gtk_label_set_width_chars (GTK_LABEL (label), 120);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.0f);
+
+	/* make left aligned */
+	hbox = gtk_hbox_new (FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+	return label;
+}
+
+/**
+ * gcm_calib_add_page_bullet:
+ **/
+static void
+gcm_calib_add_page_bullet (GtkWidget *vbox, const gchar *text)
+{
+	gchar *markup;
+	markup = g_strdup_printf ("â?¢ %s", text);
+	gcm_calib_add_page_para (vbox, markup);
+	g_free (markup);
+}
+
+/**
+ * gcm_calib_setup_page_intro:
+ **/
+static void
+gcm_calib_setup_page_intro (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is intro page text */
+	switch (calib->device_kind) {
+	case CD_DEVICE_KIND_CAMERA:
+	case CD_DEVICE_KIND_WEBCAM:
+		/* TRANSLATORS: this is the page title */
+		vbox = gcm_calib_add_page_title (calib, _("Calibrate your camera"));
+		break;
+	case CD_DEVICE_KIND_DISPLAY:
+		/* TRANSLATORS: this is the page title */
+		vbox = gcm_calib_add_page_title (calib, _("Calibrate your display"));
+		break;
+	case CD_DEVICE_KIND_PRINTER:
+		/* TRANSLATORS: this is the page title */
+		vbox = gcm_calib_add_page_title (calib, _("Calibrate your printer"));
+		break;
+	default:
+		/* TRANSLATORS: this is the page title */
+		vbox = gcm_calib_add_page_title (calib, _("Calibrate your device"));
+		break;
+	}
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	switch (calib->device_kind) {
+	case CD_DEVICE_KIND_DISPLAY:
+		/* TRANSLATORS: this is the final intro page text */
+		gcm_calib_add_page_para (content, _("Any existing screen correction will be temporarily turned off and the brightness set to maximum."));
+		break;
+	default:
+		break;
+	}
+
+	/* TRANSLATORS: this is the final intro page text */
+	gcm_calib_add_page_para (content, _("You can cancel this process at any stage by pressing the cancel button."));
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_INTRO);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Introduction"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_INTRO));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+/**
+ * gcm_calib_setup_page_summary:
+ **/
+static void
+gcm_calib_setup_page_summary (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *image;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("All done!"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	switch (calib->device_kind) {
+	case CD_DEVICE_KIND_CAMERA:
+	case CD_DEVICE_KIND_WEBCAM:
+		/* TRANSLATORS: this is the final summary */
+		gcm_calib_add_page_para (content, _("The camera has been calibrated successfully."));
+		break;
+	case CD_DEVICE_KIND_DISPLAY:
+		/* TRANSLATORS: this is the final summary */
+		gcm_calib_add_page_para (content, _("The display has been calibrated successfully."));
+		gcm_calib_add_page_para (content, _("You may notice the screen is a slightly different color."));
+		break;
+	case CD_DEVICE_KIND_PRINTER:
+		/* TRANSLATORS: this is the final summary */
+		gcm_calib_add_page_para (content, _("The printer has been calibrated successfully."));
+		gcm_calib_add_page_para (content, _("Docments printed from this device will be color managed."));
+		break;
+	default:
+		/* TRANSLATORS: this is the final summary */
+		gcm_calib_add_page_para (content, _("The device has been calibrated successfully."));
+		break;
+	}
+
+	/* only display the backlink if not launched from the control center itself */
+	if (calib->xid == 0) {
+		/* TRANSLATORS: this is the final summary */
+		gcm_calib_add_page_para (content, _("To view details about the new profile or to undo the calibration visit the <a href=\"control-center://color\">control center</a>."));
+	}
+	/* add image for success */
+	image = gtk_image_new ();
+	gtk_image_set_from_icon_name (GTK_IMAGE (image), "face-smile", GTK_ICON_SIZE_DIALOG);
+	gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_SUMMARY);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Summary"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_LAST));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+static void
+gcm_calib_interaction_continue_cb (GtkButton *button, GcmCalibratePriv *calib)
+{
+	gcm_calibrate_interaction (calib->calibrate, GTK_RESPONSE_OK);
+	gtk_widget_hide (calib->interaction_button);
+	gtk_widget_hide (calib->abort_button);
+}
+
+static void
+gcm_calib_interaction_abort_cb (GtkButton *button, GcmCalibratePriv *calib)
+{
+	gcm_calibrate_interaction (calib->calibrate, GTK_RESPONSE_CANCEL);
+	gtk_widget_hide (calib->interaction_button);
+	gtk_widget_hide (calib->abort_button);
+}
+
+/**
+ * gcm_calib_setup_page_action:
+ **/
+static void
+gcm_calib_setup_page_action (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GList *list;
+	GList *list2;
+	GtkWidget *hbox;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Performing calibration"));
+
+	/* grab title */
+	list = gtk_container_get_children (GTK_CONTAINER (vbox));
+	list2 = gtk_container_get_children (GTK_CONTAINER (list->data));
+	calib->action_title = list2->data;
+	g_list_free (list);
+	g_list_free (list2);
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	calib->action_message = gcm_calib_add_page_para (content, _("Calibration is about to start"));
+
+	/* add image for success */
+	calib->action_image = gtk_image_new ();
+	gtk_image_set_from_icon_name (GTK_IMAGE (calib->action_image), "face-frown", GTK_ICON_SIZE_DIALOG);
+	gtk_box_pack_start (GTK_BOX (vbox), calib->action_image, FALSE, FALSE, 0);
+
+	/* add button for interaction */
+	hbox = gtk_hbox_new (FALSE, 6);
+	calib->interaction_button = gtk_button_new_with_label ("Hello dave");
+	g_signal_connect (calib->interaction_button, "clicked",
+			  G_CALLBACK (gcm_calib_interaction_continue_cb), calib);
+	gtk_box_pack_start (GTK_BOX (hbox), calib->interaction_button, FALSE, FALSE, 0);
+
+	/* add button for interaction */
+	calib->abort_button = gtk_button_new_with_label ("Abort");
+	g_signal_connect (calib->abort_button, "clicked",
+			  G_CALLBACK (gcm_calib_interaction_abort_cb), calib);
+	gtk_box_pack_start (GTK_BOX (hbox), calib->abort_button, FALSE, FALSE, 0);
+
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+	/* add content widget */
+	gcm_calibrate_set_content_widget (calib->calibrate, content);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_PROGRESS);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Action"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	gtk_assistant_commit (assistant);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_ACTION));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+	gtk_widget_hide (calib->action_image);
+	gtk_widget_hide (calib->interaction_button);
+	gtk_widget_hide (calib->abort_button);
+}
+
+/**
+ * gcm_calib_setup_page_display_configure_wait:
+ **/
+static void
+gcm_calib_setup_page_display_configure_wait (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: dialog message, preface */
+	vbox = gcm_calib_add_page_title (calib, _("Calibration checklist"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, _("Before calibrating the display, it is recommended to configure your display with the following settings to get optimal results."));
+
+	/* TRANSLATORS: dialog message, preface */
+if(0)	gcm_calib_add_page_para (content, _("You may want to consult the owner's manual for your display on how to achieve these settings."));
+
+	/* TRANSLATORS: dialog message, bullet item */
+if(0)	gcm_calib_add_page_bullet (content, _("Reset your display to the factory defaults."));
+
+	/* TRANSLATORS: dialog message, bullet item */
+if(0)	gcm_calib_add_page_bullet (content, _("Disable dynamic contrast if your display has this feature."));
+
+	/* TRANSLATORS: dialog message, bullet item */
+if(0)	gcm_calib_add_page_bullet (content, _("Configure your display with custom color settings and ensure the RGB channels are set to the same values."));
+
+	/* TRANSLATORS: dialog message, addition to bullet item */
+if(0)	gcm_calib_add_page_para (content, _("If custom color is not available then use a 6500K color temperature."));
+
+	/* TRANSLATORS: dialog message, bullet item */
+if(0)	gcm_calib_add_page_bullet (content, _("Adjust the display brightness to a comfortable level for prolonged viewing."));
+
+	gcm_calib_add_page_para (content, "");
+
+	/* TRANSLATORS: dialog message, suffix */
+	gcm_calib_add_page_para (content, _("For best results, the display should have been powered for at least 15 minutes before starting the calibration."));
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Check Settings"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_DISPLAY_CONFIG));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+/**
+ * gcm_calib_button_clicked_install_argyllcms_cb:
+ **/
+static void
+gcm_calib_button_clicked_install_argyllcms_cb (GtkButton *button, GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	GtkWidget *vbox;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	ret = gcm_utils_install_package (GCM_PREFS_PACKAGE_NAME_ARGYLLCMS,
+					 calib->main_window);
+	/* we can continue now */
+	if (TRUE || ret) {
+		vbox = gcm_calib_get_vbox_for_page (calib,
+						    GCM_CALIBRATE_PAGE_INSTALL_ARGYLLCMS);
+		gtk_assistant_set_page_complete (assistant, vbox, TRUE);
+		gtk_assistant_next_page (assistant);
+
+		/* we ddn't need to re-install now */
+		gtk_widget_hide (vbox);
+	}
+}
+
+/**
+ * gcm_calib_setup_page_install_argyllcms:
+ **/
+static void
+gcm_calib_setup_page_install_argyllcms (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *button;
+	GString *string;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	string = g_string_new ("");
+
+	/* TRANSLATORS: dialog message saying the argyllcms is not installed */
+	g_string_append_printf (string, "%s\n",
+				_("Calibration and profiling software is not installed."));
+	/* TRANSLATORS: dialog message saying the color targets are not installed */
+	g_string_append_printf (string, "%s",
+				_("These tools are required to build color profiles for devices."));
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("More software is required!"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, string->str);
+
+	button = gtk_button_new_with_label (_("Install required software"));
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (gcm_calib_button_clicked_install_argyllcms_cb),
+			  calib);
+	gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Install Tools"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_INSTALL_ARGYLLCMS));
+	g_string_free (string, TRUE);
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+/**
+ * gcm_calib_button_clicked_install_targets_cb:
+ **/
+static void
+gcm_calib_button_clicked_install_targets_cb (GtkButton *button, GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	GtkWidget *vbox;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	ret = gcm_utils_install_package (GCM_PREFS_PACKAGE_NAME_SHARED_COLOR_TARGETS,
+					 calib->main_window);
+	/* we can continue now */
+	if (ret) {
+		vbox = gcm_calib_get_vbox_for_page (calib,
+						    GCM_CALIBRATE_PAGE_INSTALL_TARGETS);
+		gtk_assistant_next_page (assistant);
+
+		/* we ddn't need to re-install now */
+		gtk_widget_hide (vbox);
+	}
+}
+
+/**
+ * gcm_calib_setup_page_install_targets:
+ **/
+static void
+gcm_calib_setup_page_install_targets (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *button;
+	GString *string;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	string = g_string_new ("");
+
+	/* TRANSLATORS: dialog message saying the color targets are not installed */
+	g_string_append_printf (string, "%s\n", _("Common color target files are not installed on this computer."));
+	/* TRANSLATORS: dialog message saying the color targets are not installed */
+	g_string_append_printf (string, "%s\n\n", _("Color target files are needed to convert the image to a color profile."));
+	/* TRANSLATORS: dialog message, asking if it's okay to install them */
+	g_string_append_printf (string, "%s\n\n", _("Do you want them to be installed?"));
+	/* TRANSLATORS: dialog message, if the user has the target file on a CDROM then there's no need for this package */
+	g_string_append_printf (string, "%s", _("If you already have the correct file, you can skip this step."));
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Optional data files available"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, string->str);
+
+	button = gtk_button_new_with_label (_("Install Now"));
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (gcm_calib_button_clicked_install_targets_cb),
+			  calib);
+	gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Install Targets"));
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_INSTALL_TARGETS));
+	g_string_free (string, TRUE);
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+
+/**
+ * gcm_calib_reference_kind_to_localised_string:
+ **/
+static const gchar *
+gcm_calib_reference_kind_to_localised_string (GcmCalibrateReferenceKind kind)
+{
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DIGITAL_TARGET_3) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("CMP Digital Target 3");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DT_003) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("CMP DT 003");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Color Checker");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_DC) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Color Checker DC");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_SG) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Color Checker SG");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_HUTCHCOLOR) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Hutchcolor");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_I1_RGB_SCAN_1_4) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("i1 RGB Scan 1.4");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_IT8) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("IT8.7/2");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_LASER_SOFT_DC_PRO) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Laser Soft DC Pro");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("QPcard 201");
+	}
+	return NULL;
+}
+
+/**
+ * gcm_calib_reference_kind_to_image_filename:
+ **/
+static const gchar *
+gcm_calib_reference_kind_to_image_filename (GcmCalibrateReferenceKind kind)
+{
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DIGITAL_TARGET_3)
+		return "CMP-DigitalTarget3.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DT_003)
+		return "CMP_DT_003.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER)
+		return "ColorChecker24.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_DC)
+		return "ColorCheckerDC.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_SG)
+		return "ColorCheckerSG.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_HUTCHCOLOR)
+		return NULL;
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_I1_RGB_SCAN_1_4)
+		return "i1_RGB_Scan_14.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_IT8)
+		return "IT872.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_LASER_SOFT_DC_PRO)
+		return "LaserSoftDCPro.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201)
+		return "QPcard_201.png";
+	return NULL;
+}
+
+/**
+ * gcm_calib_reference_kind_combobox_cb:
+ **/
+static void
+gcm_calib_reference_kind_combobox_cb (GtkComboBox *combo_box,
+				      GcmCalibratePriv *calib)
+{
+	const gchar *filename;
+	gchar *path;
+
+	/* not sorted so we can just use the index */
+	calib->reference_kind = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
+	filename = gcm_calib_reference_kind_to_image_filename (calib->reference_kind);
+
+	/* fallback */
+	if (filename == NULL)
+		filename = "unknown.png";
+
+	path = g_build_filename (GCM_DATA, "targets", filename, NULL);
+	gtk_image_set_from_file (GTK_IMAGE (calib->reference_preview), path);
+	g_free (path);
+}
+
+/**
+ * gcm_calib_setup_page_target_kind:
+ **/
+static void
+gcm_calib_setup_page_target_kind (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *combo;
+	GString *string;
+	guint i;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	string = g_string_new ("");
+
+	/* TRANSLATORS: dialog message, preface. A calibration target looks like
+	 * this: http://www.colorreference.de/targets/target.jpg */
+	g_string_append_printf (string, "%s\n", _("Before profiling the device, you have to manually capture an image of a calibration target and save it as a TIFF image file."));
+
+	/* scanner specific options */
+	if (calib->device_kind == CD_DEVICE_KIND_SCANNER) {
+		/* TRANSLATORS: dialog message, preface */
+		g_string_append_printf (string, "%s\n", _("Ensure that the contrast and brightness are not changed and color correction profiles have not been applied."));
+
+		/* TRANSLATORS: dialog message, suffix */
+		g_string_append_printf (string, "%s\n", _("The device sensor should have been cleaned prior to scanning and the output file resolution should be at least 200dpi."));
+	}
+
+	/* camera specific options */
+	if (calib->device_kind == CD_DEVICE_KIND_CAMERA) {
+		/* TRANSLATORS: dialog message, preface */
+		g_string_append_printf (string, "%s\n", _("Ensure that the white-balance has not been modified by the camera and that the lens is clean."));
+	}
+
+	/* TRANSLATORS: this is the message body for the chart selection */
+	g_string_append_printf (string, "\n%s", _("Please select the calibration target type."));
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("What target type do you have?"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, string->str);
+
+	/* pack in a preview image */
+	calib->reference_preview = gtk_image_new ();
+	gtk_box_pack_start (GTK_BOX (vbox), calib->reference_preview, FALSE, FALSE, 0);
+
+	combo = gtk_combo_box_text_new ();
+	for (i=0; i<GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN; i++) {
+		gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+						gcm_calib_reference_kind_to_localised_string (i));
+	}
+	g_signal_connect (combo, "changed",
+			  G_CALLBACK (gcm_calib_reference_kind_combobox_cb),
+			  calib);
+
+	/* use IT8 by default */
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), GCM_CALIBRATE_REFERENCE_KIND_IT8);
+
+	gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Select Target"));
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_TARGET_KIND));
+	g_string_free (string, TRUE);
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+static void
+gcm_calib_display_kind_toggled_cb (GtkToggleButton *togglebutton,
+				   GcmCalibratePriv *calib)
+{
+	if (!gtk_toggle_button_get_active (togglebutton))
+		return;
+	calib->display_kind = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (togglebutton),
+								   "GcmCalib::display-kind"));
+}
+
+/**
+ * gcm_calib_setup_page_display_kind:
+ **/
+static void
+gcm_calib_setup_page_display_kind (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *widget;
+	GSList *list;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Choose your display type"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, _("Select the monitor type that is attached to your computer."));
+
+	widget = gtk_radio_button_new_with_label (NULL, _("LCD"));
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::display-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_DEVICE_KIND_LCD));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_display_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, _("CRT"));
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::display-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_DEVICE_KIND_CRT));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_display_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, _("Plasma"));
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::display-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_DEVICE_KIND_CRT));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_display_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, _("Projector"));
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::display-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_DEVICE_KIND_PROJECTOR));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_display_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Choose Display Type"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_DISPLAY_KIND));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+static void
+gcm_calib_print_kind_toggled_cb (GtkToggleButton *togglebutton,
+				   GcmCalibratePriv *calib)
+{
+	if (!gtk_toggle_button_get_active (togglebutton))
+		return;
+	calib->print_kind = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (togglebutton),
+								   "GcmCalib::print-kind"));
+}
+
+/**
+ * gcm_calib_setup_page_print_kind:
+ **/
+static void
+gcm_calib_setup_page_print_kind (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *widget;
+	GSList *list;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Choose profiling mode"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, _("Please indicate if you want to profile a local printer, generate some test patches, or profile using existing test patches."));
+
+	widget = gtk_radio_button_new_with_label (NULL, "Local printer");
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::print-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PRINT_KIND_LOCAL));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_print_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, "Generate patches for remote printer");
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::print-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PRINT_KIND_GENERATE));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_print_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, "Generate profile from existing test patches");
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::print-kind",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PRINT_KIND_ANALYZE));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_print_kind_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Calibration Mode"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_PRINT_KIND));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+static void
+gcm_calib_precision_toggled_cb (GtkToggleButton *togglebutton,
+				GcmCalibratePriv *calib)
+{
+	if (!gtk_toggle_button_get_active (togglebutton))
+		return;
+	calib->precision = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (togglebutton),
+								"GcmCalib::precision"));
+}
+
+/**
+ * gcm_calib_setup_page_precision:
+ **/
+static void
+gcm_calib_setup_page_precision (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkWidget *widget;
+	GSList *list;
+	gchar **labels;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Choose calibration quality"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, _("Higher quality calibration requires many color samples and more time."));
+
+#if 0
+	/* TRANSLATORS: this is the message body for the chart selection */
+	g_string_append (string, _("A higher precision profile provides higher accuracy in color matching but requires more time for reading the color patches."));
+
+	/* TRANSLATORS: this is the message body for the chart selection */
+	g_string_append_printf (string, "\n%s", _("For a typical workflow, a normal precision profile is sufficient."));
+
+	/* printer specific options */
+	if (calib->device_kind == CD_DEVICE_KIND_PRINTER) {
+		/* TRANSLATORS: dialog message, preface */
+		g_string_append_printf (string, "\n%s", _("The high precision profile also requires more paper and printer ink."));
+	}
+#endif
+
+	labels = g_new0 (gchar *, 4);
+	switch (calib->device_kind) {
+	case CD_DEVICE_KIND_PRINTER:
+		/* TRANSLATORS: radio options for calibration precision */
+		labels[0] = g_strdup_printf (_("Accurate (about %i sheets of paper)"), 20);
+		labels[1] = g_strdup_printf (_("Normal (about %i sheets of paper)"), 10);
+		labels[2] = g_strdup_printf (_("Quick (about %i sheets of paper)"), 4);
+		break;
+	case CD_DEVICE_KIND_DISPLAY:
+		/* TRANSLATORS: radio options for calibration precision */
+		labels[0] = g_strdup_printf (_("Accurate (about %i minutes)"), 20);
+		labels[1] = g_strdup_printf (_("Normal (about %i minutes)"), 10);
+		labels[2] = g_strdup_printf (_("Quick (about %i minutes)"), 4);
+		break;
+	default:
+		/* TRANSLATORS: radio options for calibration precision */
+		labels[0] = g_strdup (_("Accurate"));
+		labels[1] = g_strdup (_("Normal"));
+		labels[2] = g_strdup (_("Quick"));
+		break;
+	}
+
+	widget = gtk_radio_button_new_with_label (NULL, labels[0]);
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::precision",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PRECISION_LONG));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_precision_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, labels[1]);
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::precision",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PRECISION_NORMAL));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_precision_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	widget = gtk_radio_button_new_with_label (list, labels[2]);
+	g_object_set_data (G_OBJECT (widget),
+			   "GcmCalib::precision",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PRECISION_SHORT));
+	g_signal_connect (widget, "toggled",
+			  G_CALLBACK (gcm_calib_precision_toggled_cb), calib);
+	gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Calibration Quality"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_DISPLAY_KIND));
+	g_strfreev (labels);
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+/**
+ * gcm_calib_setup_page_sensor:
+ **/
+static void
+gcm_calib_setup_page_sensor (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Insert sensor hardware"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, _("You need to insert sensor hardware to continue."));
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_CONTENT);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Sensor Check"));
+	gtk_assistant_set_page_complete (assistant, vbox, FALSE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_SENSOR));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+/**
+ * gcm_calib_setup_page_failure:
+ **/
+static void
+gcm_calib_setup_page_failure (GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+	GtkWidget *content;
+	GtkAssistant *assistant = GTK_ASSISTANT (calib->main_window);
+
+	/* TRANSLATORS: this is the page title */
+	vbox = gcm_calib_add_page_title (calib, _("Failed to calibrate"));
+
+	/* main contents */
+	content = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), content, FALSE, FALSE, 0);
+
+	/* TRANSLATORS: this is intro page text */
+	gcm_calib_add_page_para (content, _("The device could not be found. Ensure it is plugged in and turned on."));
+
+	/* add to assistant */
+	gtk_assistant_append_page (assistant, vbox);
+	gtk_assistant_set_page_type (assistant, vbox, GTK_ASSISTANT_PAGE_SUMMARY);
+	/* TRANSLATORS: this is the calibration wizard page title */
+	gtk_assistant_set_page_title (assistant, vbox, _("Summary"));
+	gtk_assistant_set_page_complete (assistant, vbox, TRUE);
+	g_ptr_array_add (calib->pages, vbox);
+	g_object_set_data (G_OBJECT (vbox),
+			   "GcmCalibrateMain::Index",
+			   GUINT_TO_POINTER (GCM_CALIBRATE_PAGE_FAILURE));
+
+	/* show page */
+	gtk_widget_show_all (vbox);
+}
+
+/**
+ * gcm_calib_get_sensors_cb:
+ **/
+static void
+gcm_calib_get_sensors_cb (GObject *object,
+			  GAsyncResult *res,
+			  gpointer user_data)
+{
+	CdClient *client = CD_CLIENT (object);
+	GcmCalibratePriv *calib = (GcmCalibratePriv *) user_data;
+	GError *error = NULL;
+	GPtrArray *sensors;
+	GtkWidget *vbox;
+	gboolean ret;
+
+	/* get the result */
+	sensors = cd_client_get_sensors_finish (client, res, &error);
+	if (sensors == NULL) {
+		g_warning ("failed to get sensors: %s",
+			   error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* hide the sensors screen */
+	if (sensors->len > 0) {
+		calib->sensor = g_object_ref (g_ptr_array_index (sensors, 0));
+
+		ret = cd_sensor_connect_sync (calib->sensor, NULL, &error);
+		if (!ret) {
+			g_warning ("failed to connect to sensor: %s",
+				   error->message);
+			g_error_free (error);
+			goto out;
+		}
+
+		gcm_calibrate_set_sensor (calib->calibrate, calib->sensor);
+		vbox = gcm_calib_get_vbox_for_page (calib,
+						    GCM_CALIBRATE_PAGE_SENSOR);
+		gtk_widget_hide (vbox);
+	}
+out:
+	if (sensors != NULL)
+		g_ptr_array_unref (sensors);
+}
+
+/**
+ * gcm_calib_add_pages:
+ **/
+static void
+gcm_calib_add_pages (GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	const gchar *xrandr_name;
+
+	/* device not found */
+	if (calib->device_kind == CD_DEVICE_KIND_UNKNOWN) {
+		gcm_calib_setup_page_failure (calib);
+		gtk_widget_show_all (GTK_WIDGET (calib->main_window));
+		return;
+	}
+
+	gcm_calib_setup_page_intro (calib);
+
+	if (calib->device_kind == CD_DEVICE_KIND_DISPLAY ||
+	    calib->device_kind == CD_DEVICE_KIND_PRINTER)
+		gcm_calib_setup_page_sensor (calib);
+
+	/* find whether argyllcms is installed using a tool which should exist */
+	ret = g_file_test ("/usr/bin/dispcal", G_FILE_TEST_EXISTS);
+	if (!ret)
+		gcm_calib_setup_page_install_argyllcms (calib);
+
+	xrandr_name = cd_device_get_metadata_item (calib->device,
+						   CD_DEVICE_METADATA_XRANDR_NAME);
+	if (xrandr_name != NULL)
+		calib->internal_lcd = gcm_utils_output_is_lcd_internal (xrandr_name);
+	if (!calib->internal_lcd && calib->device_kind == CD_DEVICE_KIND_DISPLAY)
+		gcm_calib_setup_page_display_configure_wait (calib);
+
+	gcm_calib_setup_page_precision (calib);
+
+	if (calib->device_kind == CD_DEVICE_KIND_DISPLAY) {
+		if (!calib->internal_lcd)
+			gcm_calib_setup_page_display_kind (calib);
+		else
+			calib->display_kind = GCM_CALIBRATE_DEVICE_KIND_LCD;
+	} else if (calib->device_kind == CD_DEVICE_KIND_PRINTER) {
+		gcm_calib_setup_page_print_kind (calib);
+	} else {
+		gcm_calib_setup_page_target_kind (calib);
+		ret = g_file_test ("/usr/share/shared-color-targets", G_FILE_TEST_IS_DIR);
+		if (!ret) 
+			gcm_calib_setup_page_install_targets (calib);
+	}
+
+	gcm_calib_setup_page_action (calib);
+
+	gcm_calib_setup_page_summary (calib);
+
+	/* see if we can hide the sensor check */
+	cd_client_get_sensors (calib->client,
+			       NULL,
+			       gcm_calib_get_sensors_cb,
+			       calib);
+}
+
+/**
+ * gcm_calib_sensor_added_cb:
+ **/
+static void
+gcm_calib_sensor_added_cb (CdClient *client, CdSensor *sensor, GcmCalibratePriv *calib)
+{
+	GtkWidget *vbox;
+
+	g_debug ("sensor inserted");
+	calib->sensor = g_object_ref (sensor);
+	vbox = gcm_calib_get_vbox_for_page (calib,
+					    GCM_CALIBRATE_PAGE_SENSOR);
+	gtk_widget_hide (vbox);
+}
+
+/**
+ * gcm_calib_startup_cb:
+ **/
+static void
+gcm_calib_startup_cb (GApplication *application, GcmCalibratePriv *calib)
+{
+	gboolean ret;
+	GError *error = NULL;
+
+	/* add application specific icons to search path */
+	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+					   GCM_DATA G_DIR_SEPARATOR_S "icons");
+
+	/* connect to colord */
+	calib->client = cd_client_new ();
+	g_signal_connect (calib->client, "sensor-added",
+			  G_CALLBACK (gcm_calib_sensor_added_cb), calib);
+	ret = cd_client_connect_sync (calib->client,
+				      NULL,
+				      &error);
+	if (!ret) {
+		g_warning ("failed to connect to colord: %s",
+			   error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* show main UI */
+	calib->main_window = GTK_WINDOW (gtk_assistant_new ());
+	gtk_window_set_default_size (calib->main_window, 640, 480);
+	gtk_window_set_resizable (calib->main_window, TRUE);
+	gtk_window_set_title (calib->main_window, "");
+	gtk_container_set_border_width (GTK_CONTAINER (calib->main_window), 12);
+	g_signal_connect (calib->main_window, "delete_event",
+			  G_CALLBACK (gcm_calib_delete_event_cb), calib);
+	g_signal_connect (calib->main_window, "close",
+			  G_CALLBACK (gcm_calib_assistant_close_cb), calib);
+	g_signal_connect (calib->main_window, "cancel",
+			  G_CALLBACK (gcm_calib_assistant_cancel_cb), calib);
+	g_signal_connect (calib->main_window, "prepare",
+			  G_CALLBACK (gcm_calib_assistant_prepare_cb), calib);
+	gtk_application_add_window (calib->application,
+				    calib->main_window);
+
+	/* set the parent window if it is specified */
+	if (calib->xid != 0) {
+		g_debug ("Setting xid %i", calib->xid);
+		gcm_window_set_parent_xid (GTK_WINDOW (calib->main_window), calib->xid);
+	}
+
+	/* select a specific profile only */
+	calib->device = cd_client_find_device_sync (calib->client,
+						    calib->device_id,
+						    NULL,
+						    &error);
+	if (calib->device == NULL) {
+		g_warning ("failed to get device %s: %s",
+			   calib->device_id,
+			   error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* connect to the device */
+	ret = cd_device_connect_sync (calib->device,
+				      NULL,
+				      &error);
+	if (!ret) {
+		g_warning ("failed to connect to device: %s",
+			   error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get the device kind */
+	calib->device_kind = cd_device_get_kind (calib->device);
+out:
+	/* add different pages depending on the device kind */
+	gcm_calib_add_pages (calib);
+	gtk_assistant_set_current_page (GTK_ASSISTANT (calib->main_window), 0);
+}
+
+static void
+gcm_calib_title_changed_cb (GcmCalibrate *calibrate,
+			    const gchar *title,
+			    GcmCalibratePriv *calib)
+{
+	gchar *markup;
+
+	markup = g_strdup_printf ("<span size=\"large\" font_weight=\"bold\">%s</span>", title);
+	gtk_label_set_markup (GTK_LABEL (calib->action_title), markup);
+	g_free (markup);
+}
+
+static void
+gcm_calib_message_changed_cb (GcmCalibrate *calibrate,
+			      const gchar *title,
+			      GcmCalibratePriv *calib)
+{
+	gtk_label_set_label (GTK_LABEL (calib->action_message), title);
+}
+
+static void
+gcm_calib_image_changed_cb (GcmCalibrate *calibrate,
+			    const gchar *filename,
+			    GcmCalibratePriv *calib)
+{
+	if (filename != NULL) {
+		gtk_image_set_from_file (GTK_IMAGE (calib->action_image),
+					 filename);
+		gtk_widget_show (calib->action_image);
+	} else {
+		gtk_widget_hide (calib->action_image);
+	}
+}
+
+static void
+gcm_calib_interaction_required_cb (GcmCalibrate *calibrate,
+				   const gchar *button_text,
+				   GcmCalibratePriv *calib)
+{
+	if (button_text != NULL) {
+		gtk_button_set_label (GTK_BUTTON (calib->interaction_button),
+				      button_text);
+		gtk_widget_show (calib->interaction_button);
+		gtk_widget_show (calib->abort_button);
+	} else {
+		gtk_widget_hide (calib->interaction_button);
+		gtk_widget_hide (calib->abort_button);
+	}
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char **argv)
+{
+	gchar *device_id = NULL;
+	GcmCalibratePriv *calib;
+	GOptionContext *context;
+	guint xid = 0;
+	int status = 0;
+
+	const GOptionEntry options[] = {
+		{ "parent-window", 'p', 0, G_OPTION_ARG_INT, &xid,
+		  /* TRANSLATORS: we can make this modal (stay on top of) another window */
+		  _("Set the parent window to make this modal"), NULL },
+		{ "device", 'd', 0, G_OPTION_ARG_STRING, &device_id,
+		  /* TRANSLATORS: show just the one profile, rather than all */
+		  _("Set the specific device to calibrate"), NULL },
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+
+	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	gtk_init (&argc, &argv);
+
+	context = g_option_context_new ("gnome-color-manager calibration tool");
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_add_group (context, gcm_debug_get_option_group ());
+	g_option_context_add_group (context, gtk_get_option_group (TRUE));
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	calib = g_new0 (GcmCalibratePriv, 1);
+	calib->pages = g_ptr_array_new ();
+	calib->xid = xid;
+	calib->device_id = device_id;
+	calib->old_brightness = G_MAXUINT;
+	calib->brightness = gcm_brightness_new ();
+	calib->calibrate = gcm_calibrate_argyll_new ();
+	calib->device_kind = CD_DEVICE_KIND_UNKNOWN;
+	calib->display_kind = GCM_CALIBRATE_DEVICE_KIND_UNKNOWN;
+	g_signal_connect (calib->calibrate, "title-changed",
+			  G_CALLBACK (gcm_calib_title_changed_cb), calib);
+	g_signal_connect (calib->calibrate, "message-changed",
+			  G_CALLBACK (gcm_calib_message_changed_cb), calib);
+	g_signal_connect (calib->calibrate, "image-changed",
+			  G_CALLBACK (gcm_calib_image_changed_cb), calib);
+	g_signal_connect (calib->calibrate, "interaction-required",
+			  G_CALLBACK (gcm_calib_interaction_required_cb), calib);
+
+	/* nothing specified */
+	if (calib->device_id == NULL) {
+		g_print ("did not specify a device ID\n");
+//		calib->device_id = g_strdup ("sysfs-Chicony_Electronics_Co.__Ltd.-Integrated_Camera");
+		calib->device_id = g_strdup ("xrandr-Lenovo Group Limited");
+if(0)		goto out;
+	}
+
+	/* ensure single instance */
+	calib->application = gtk_application_new ("org.gnome.ColorManager.Calibration", 0);
+	g_signal_connect (calib->application, "startup",
+			  G_CALLBACK (gcm_calib_startup_cb), calib);
+	g_signal_connect (calib->application, "activate",
+			  G_CALLBACK (gcm_calib_activate_cb), calib);
+
+	/* wait */
+	status = g_application_run (G_APPLICATION (calib->application), argc, argv);
+
+	g_ptr_array_unref (calib->pages);
+	g_object_unref (calib->application);
+	g_object_unref (calib->brightness);
+	g_object_unref (calib->calibrate);
+	if (calib->client != NULL)
+		g_object_unref (calib->client);
+	if (calib->device_id != NULL)
+		g_free (calib->device_id);
+	if (calib->device != NULL)
+		g_object_unref (calib->device);
+	g_free (calib);
+out:
+	return status;
+}
diff --git a/src/gcm-calibrate-native.c b/src/gcm-calibrate-native.c
index 01ba2b9..10f6043 100644
--- a/src/gcm-calibrate-native.c
+++ b/src/gcm-calibrate-native.c
@@ -29,7 +29,6 @@
 #include <colord.h>
 
 #include "gcm-calibrate-native.h"
-#include "gcm-calibrate-dialog.h"
 #include "gcm-sample-window.h"
 #include "gcm-profile.h"
 
@@ -47,7 +46,6 @@ struct _GcmCalibrateNativePrivate
 	GtkWindow			*sample_window;
 	GMainLoop			*loop;
 	GCancellable			*cancellable;
-	GcmCalibrateDialog		*calibrate_dialog;
 };
 
 G_DEFINE_TYPE (GcmCalibrateNative, gcm_calibrate_native, GCM_TYPE_CALIBRATE)
@@ -580,7 +578,7 @@ out:
  * gcm_calibrate_native_display:
  **/
 static gboolean
-gcm_calibrate_native_display (GcmCalibrate *calibrate, CdSensor *sensor, GtkWindow *window, GError **error)
+gcm_calibrate_native_display (GcmCalibrate *calibrate, CdDevice *device, CdSensor *sensor, GtkWindow *window, GError **error)
 {
 	GcmCalibrateNative *calibrate_native = GCM_CALIBRATE_NATIVE(calibrate);
 	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
@@ -649,18 +647,7 @@ gcm_calibrate_native_display (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 		message = _("Please attach the measuring instrument to the center of the screen on the gray square.");
 	}
 
-	/* block for a response */
-	g_debug ("blocking waiting for user input: %s", title);
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, filename);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, TRUE);
-
-	/* TRANSLATORS: button text */
-	gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Continue"));
+	g_debug ("title=%s, message=%s", title, message);
 
 	/* wait for response */
 //	gtk_window_present (GTK_WINDOW (priv->calibrate_dialog));
@@ -670,21 +657,12 @@ gcm_calibrate_native_display (GcmCalibrate *calibrate, CdSensor *sensor, GtkWind
 	if (g_cancellable_is_cancelled (priv->cancellable))
 		goto out;
 
-	/* set modal windows up correctly */
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-
 	/* TRANSLATORS: title, drawing means painting to the screen */
 	title = _("Drawing the patches");
 
 	/* TRANSLATORS: dialog message */
 	message = _("Drawing the generated patches to the screen, which will then be measured by the hardware device.");
 
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-
 	/* get filenames */
 	basename = gcm_calibrate_get_basename (calibrate);
 	filename_it8 = g_strdup_printf ("%s.it8", basename);
@@ -744,10 +722,10 @@ out:
  * gcm_calibrate_native_spotread:
  **/
 static gboolean
-gcm_calibrate_native_spotread (GcmCalibrate *calibrate, CdSensor *sensor, GtkWindow *window, GError **error)
+gcm_calibrate_native_spotread (GcmCalibrate *calibrate, CdDevice *device, CdSensor *sensor, GtkWindow *window, GError **error)
 {
-	GcmCalibrateNative *calibrate_native = GCM_CALIBRATE_NATIVE(calibrate);
-	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
+//	GcmCalibrateNative *calibrate_native = GCM_CALIBRATE_NATIVE(calibrate);
+//	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
 	gboolean ret = TRUE;
 	const gchar *title;
 	const gchar *message;
@@ -758,35 +736,13 @@ gcm_calibrate_native_spotread (GcmCalibrate *calibrate, CdSensor *sensor, GtkWin
 	message = _("Setting up the device to read a spot colorâ?¦");
 
 	/* push new messages into the UI */
-	gcm_calibrate_dialog_set_move_window (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	g_debug ("title=%s, message=%s", title, message);
 
 //out:
 	return ret;
 }
 
 /**
- * gcm_calibrate_native_response_cb:
- **/
-static void
-gcm_calibrate_native_response_cb (GtkWidget *widget, GtkResponseType response, GcmCalibrateNative *calibrate_native)
-{
-	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
-	if (response == GTK_RESPONSE_OK) {
-		if (g_main_loop_is_running (priv->loop))
-			g_main_loop_quit (priv->loop);
-	}
-	if (response == GTK_RESPONSE_CANCEL) {
-		if (g_main_loop_is_running (priv->loop))
-			g_main_loop_quit (priv->loop);
-		g_cancellable_cancel (priv->cancellable);
-	}
-}
-
-/**
  * gcm_calibrate_native_class_init:
  **/
 static void
@@ -814,11 +770,6 @@ gcm_calibrate_native_init (GcmCalibrateNative *calibrate_native)
 	calibrate_native->priv->loop = g_main_loop_new (NULL, FALSE);
 	calibrate_native->priv->cancellable = g_cancellable_new ();
 
-	/* common dialog */
-	calibrate_native->priv->calibrate_dialog = gcm_calibrate_dialog_new ();
-	g_signal_connect (calibrate_native->priv->calibrate_dialog, "response",
-			  G_CALLBACK (gcm_calibrate_native_response_cb), calibrate_native);
-
 	/* sample window */
 	calibrate_native->priv->sample_window = gcm_sample_window_new ();
 }
@@ -833,8 +784,6 @@ gcm_calibrate_native_finalize (GObject *object)
 	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
 
 	/* hide */
-	gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-	g_object_unref (priv->calibrate_dialog);
 //	g_object_unref (priv->sample_window);
 	g_object_unref (priv->cancellable);
 	g_main_loop_unref (priv->loop);
diff --git a/src/gcm-calibrate.c b/src/gcm-calibrate.c
index 046077b..ab1761d 100644
--- a/src/gcm-calibrate.c
+++ b/src/gcm-calibrate.c
@@ -1,24 +1,3 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2009-2010 Richard Hughes <richard hughsie com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
 #include "config.h"
 
 #include <glib/gi18n.h>
@@ -28,7 +7,6 @@
 #include "gcm-calibrate.h"
 #include "gcm-utils.h"
 #include "gcm-brightness.h"
-#include "gcm-calibrate-dialog.h"
 #include "gcm-exif.h"
 
 static void     gcm_calibrate_finalize	(GObject     *object);
@@ -42,13 +20,11 @@ static void     gcm_calibrate_finalize	(GObject     *object);
  **/
 struct _GcmCalibratePrivate
 {
-	GcmCalibrateReferenceKind	 reference_kind;
-	GcmCalibrateDeviceKind		 calibrate_device_kind;
+	GcmCalibrateDisplayKind		 display_kind;
 	GcmCalibratePrintKind		 print_kind;
 	GcmCalibratePrecision		 precision;
+	GcmCalibrateReferenceKind	 reference_kind;
 	CdSensor			*sensor;
-	CdSensorKind			 sensor_kind;
-	GcmCalibrateDialog		*calibrate_dialog;
 	CdDeviceKind			 device_kind;
 	CdColorXYZ			*xyz;
 	gchar				*output_name;
@@ -62,8 +38,12 @@ struct _GcmCalibratePrivate
 	gchar				*serial;
 	gchar				*device;
 	gchar				*working_path;
+	GtkWidget			*content_widget;
+	GPtrArray			*old_message;
+	GPtrArray			*old_title;
 };
 
+
 enum {
 	PROP_0,
 	PROP_BASENAME,
@@ -73,7 +53,7 @@ enum {
 	PROP_DEVICE,
 	PROP_MANUFACTURER,
 	PROP_REFERENCE_KIND,
-	PROP_CALIBRATE_DEVICE_KIND,
+	PROP_DISPLAY_KIND,
 	PROP_PRINT_KIND,
 	PROP_DEVICE_KIND,
 	PROP_SENSOR_KIND,
@@ -87,8 +67,30 @@ enum {
 	PROP_LAST
 };
 
+enum {
+	SIGNAL_TITLE_CHANGED,
+	SIGNAL_MESSAGE_CHANGED,
+	SIGNAL_IMAGE_CHANGED,
+	SIGNAL_INTERACTION_REQUIRED,
+	SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0 };
+
 G_DEFINE_TYPE (GcmCalibrate, gcm_calibrate, G_TYPE_OBJECT)
 
+void
+gcm_calibrate_set_content_widget (GcmCalibrate *calibrate, GtkWidget *widget)
+{
+	calibrate->priv->content_widget = widget;
+}
+
+GtkWidget *
+gcm_calibrate_get_content_widget (GcmCalibrate *calibrate)
+{
+	return calibrate->priv->content_widget;
+}
+
 /**
  * gcm_calibrate_mkdir_with_parents:
  **/
@@ -307,8 +309,6 @@ gcm_calibrate_set_from_device (GcmCalibrate *calibrate,
 
 	/* do not refcount */
 	calibrate->priv->sensor = sensor;
-	calibrate->priv->sensor_kind = cd_sensor_get_kind (sensor);
-	g_object_notify (G_OBJECT (calibrate), "sensor-kind");
 
 	/* set the proper values */
 	g_object_set (calibrate,
@@ -324,7 +324,7 @@ gcm_calibrate_set_from_device (GcmCalibrate *calibrate,
 
 	/* display specific properties */
 	if (kind == CD_DEVICE_KIND_DISPLAY) {
-		native_device = cd_device_get_metadata_item (device, "XRANDR_name");
+		native_device = cd_device_get_metadata_item (device, CD_DEVICE_METADATA_XRANDR_NAME);
 		if (native_device == NULL) {
 			g_set_error (error,
 				     GCM_CALIBRATE_ERROR,
@@ -388,69 +388,23 @@ out:
 	return ret;
 }
 
-/**
- * gcm_calibrate_get_display_kind:
- **/
-static gboolean
-gcm_calibrate_get_display_kind (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
-{
-	gboolean ret = TRUE;
-	const gchar *title;
-	const gchar *message;
-	GtkResponseType response;
-	GcmCalibratePrivate *priv = calibrate->priv;
-
-	/* TRANSLATORS: title, usually we can tell based on the EDID data or output name */
-	title = _("Could not detect screen type");
-
-	/* TRANSLATORS: dialog message */
-	message = _("Please indicate if the screen you are trying to profile is an LCD, CRT or a projector.");
-
-	/* show the ui */
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_DISPLAY_TYPE, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-	response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-	if (response != GTK_RESPONSE_OK) {
-		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-		g_set_error_literal (error,
-				     GCM_CALIBRATE_ERROR,
-				     GCM_CALIBRATE_ERROR_USER_ABORT,
-				     "user did not choose crt or lcd");
-		ret = FALSE;
-		goto out;
-	}
-
-	/* copy */
-	g_object_get (priv->calibrate_dialog, "device-kind", &priv->calibrate_device_kind, NULL);
-
+#if 0
 	/* can this device support projectors? */
-	if (priv->calibrate_device_kind == GCM_CALIBRATE_DEVICE_KIND_PROJECTOR &&
+	if (priv->display_kind == GCM_CALIBRATE_DEVICE_KIND_PROJECTOR &&
 	    !cd_sensor_has_cap (priv->sensor, CD_SENSOR_CAP_PROJECTOR)) {
 		/* TRANSLATORS: title, the hardware calibration device does not support projectors */
 		title = _("Could not calibrate and profile using this color measuring instrument");
 
 		/* TRANSLATORS: dialog message */
 		message = _("This color measuring instrument is not designed to support calibration and profiling projectors.");
-
-		/* ask the user again */
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-		response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-		if (response != GTK_RESPONSE_OK) {
-			gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-			g_set_error_literal (error,
-					     GCM_CALIBRATE_ERROR,
-					     GCM_CALIBRATE_ERROR_NO_SUPPORT,
-					     "hardware not capable of profiling a projector");
-			ret = FALSE;
-			goto out;
-		}
 	}
-out:
-	return ret;
+#endif
+
+void
+gcm_calibrate_set_sensor (GcmCalibrate *calibrate, CdSensor *sensor)
+{
+	/* do not refcount */
+	calibrate->priv->sensor = sensor;
 }
 
 /**
@@ -478,71 +432,15 @@ gcm_calibrate_set_working_path (GcmCalibrate *calibrate, GError **error)
 }
 
 /**
- * gcm_calibrate_get_precision:
- **/
-static GcmCalibratePrecision
-gcm_calibrate_get_precision (GcmCalibrate *calibrate, GError **error)
-{
-	GcmCalibratePrecision precision = GCM_CALIBRATE_PRECISION_UNKNOWN;
-	const gchar *title;
-	GString *string;
-	GtkResponseType response;
-	GcmCalibratePrivate *priv = calibrate->priv;
-
-	string = g_string_new ("");
-
-	/* TRANSLATORS: dialog title */
-	title = _("Profile Precision");
-
-	/* TRANSLATORS: this is the message body for the chart selection */
-	g_string_append (string, _("A higher precision profile provides higher accuracy in color matching but requires more time for reading the color patches."));
-
-	/* TRANSLATORS: this is the message body for the chart selection */
-	g_string_append_printf (string, "\n%s", _("For a typical workflow, a normal precision profile is sufficient."));
-
-	/* printer specific options */
-	if (priv->device_kind == CD_DEVICE_KIND_PRINTER) {
-		/* TRANSLATORS: dialog message, preface */
-		g_string_append_printf (string, "\n%s", _("The high precision profile also requires more paper and printer ink."));
-	}
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_PRECISION, title, string->str);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-	response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-	if (response != GTK_RESPONSE_OK) {
-		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-		g_set_error_literal (error,
-				     GCM_CALIBRATE_ERROR,
-				     GCM_CALIBRATE_ERROR_USER_ABORT,
-				     "user did not choose precision type and ask is specified in GSettings");
-		goto out;
-	}
-
-	/* copy */
-	g_object_get (priv->calibrate_dialog, "precision", &precision, NULL);
-out:
-	if (string != NULL)
-		g_string_free (string, TRUE);
-	return precision;
-}
-
-/**
  * gcm_calibrate_spotread:
  **/
 gboolean
-gcm_calibrate_spotread (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+gcm_calibrate_spotread (GcmCalibrate *calibrate, CdDevice *device, GtkWindow *window, GError **error)
 {
 	GcmCalibrateClass *klass = GCM_CALIBRATE_GET_CLASS (calibrate);
 	GcmCalibratePrivate *priv = calibrate->priv;
 	gboolean ret;
 
-	/* set the per-profile filename */
-	ret = gcm_calibrate_set_working_path (calibrate, error);
-	if (!ret)
-		goto out;
-
 	/* coldplug source */
 	if (klass->calibrate_spotread == NULL) {
 		ret = FALSE;
@@ -554,43 +452,49 @@ gcm_calibrate_spotread (GcmCalibrate *calibrate, GtkWindow *window, GError **err
 	}
 
 	/* proxy */
-	ret = klass->calibrate_spotread (calibrate, priv->sensor, window, error);
+	ret = klass->calibrate_spotread (calibrate, device, priv->sensor, window, error);
 out:
 	return ret;
 }
 
 /**
+ * gcm_calibrate_interaction:
+ **/
+void
+gcm_calibrate_interaction (GcmCalibrate *calibrate, GtkResponseType response)
+{
+	GcmCalibrateClass *klass = GCM_CALIBRATE_GET_CLASS (calibrate);
+
+	/* coldplug source */
+	if (klass->interaction == NULL)
+		return;
+
+	/* proxy */
+	klass->interaction (calibrate, response);
+}
+
+/**
  * gcm_calibrate_display:
  **/
 gboolean
-gcm_calibrate_display (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+gcm_calibrate_display (GcmCalibrate *calibrate, CdDevice *device, GtkWindow *window, GError **error)
 {
-	GcmCalibrateClass *klass = GCM_CALIBRATE_GET_CLASS (calibrate);
 	gboolean ret = TRUE;
-	const gchar *hardware_device;
-	gboolean ret_tmp;
-	GString *string = NULL;
-	GcmBrightness *brightness = NULL;
-	guint percentage = G_MAXUINT;
-	GtkResponseType response;
-	GError *error_tmp = NULL;
-	gchar *precision = NULL;
+	GcmCalibrateClass *klass = GCM_CALIBRATE_GET_CLASS (calibrate);
 	GcmCalibratePrivate *priv = calibrate->priv;
 
-	/* coldplug source */
-	if (priv->output_name == NULL) {
-		ret = FALSE;
-		g_set_error_literal (error,
-				     GCM_CALIBRATE_ERROR,
-				     GCM_CALIBRATE_ERROR_INTERNAL,
-				     "no output name set");
-		goto out;
+	/* set basename */
+	gcm_calibrate_set_basename (calibrate);
+#if 0
+	const gchar *hardware_device;
+	/* get device, harder */
+	hardware_device = cd_sensor_get_model (priv->sensor);
+	if (hardware_device == NULL) {
+		/* TRANSLATORS: this is the formattted custom profile description.
+		 * "Custom" refers to the fact that it's user generated */
+		hardware_device = _("Custom");
 	}
-
-	/* set the per-profile filename */
-	ret = gcm_calibrate_set_working_path (calibrate, error);
-	if (!ret)
-		goto out;
+#endif
 
 	/* coldplug source */
 	if (klass->calibrate_display == NULL) {
@@ -602,120 +506,9 @@ gcm_calibrate_display (GcmCalibrate *calibrate, GtkWindow *window, GError **erro
 		goto out;
 	}
 
-	/* get device, harder */
-	hardware_device = cd_sensor_get_model (priv->sensor);
-	if (hardware_device == NULL) {
-		/* TRANSLATORS: this is the formattted custom profile description.
-		 * "Custom" refers to the fact that it's user generated */
-		hardware_device = g_strdup (_("Custom"));
-	}
-
-	/* set display specific properties */
-	g_object_set (calibrate,
-		      "device", hardware_device,
-		      NULL);
-
-	/* this wasn't previously set */
-	if (priv->calibrate_device_kind == GCM_CALIBRATE_DEVICE_KIND_UNKNOWN) {
-		ret = gcm_calibrate_get_display_kind (calibrate, window, error);
-		if (!ret)
-			goto out;
-	}
-
-	/* get default precision */
-	priv->precision = gcm_calibrate_get_precision (calibrate, error);
-
-	/* show a warning for external monitors */
-	ret = gcm_utils_output_is_lcd_internal (priv->output_name);
-	if (!ret) {
-		string = g_string_new ("");
-
-		/* TRANSLATORS: dialog message, preface */
-		g_string_append_printf (string, "%s\n", _("Before calibrating the display, it is recommended to configure your display with the following settings to get optimal results."));
-
-		/* TRANSLATORS: dialog message, preface */
-		g_string_append_printf (string, "%s\n\n", _("You may want to consult the owner's manual for your display on how to achieve these settings."));
-
-		/* TRANSLATORS: dialog message, bullet item */
-		g_string_append_printf (string, "â?¢ %s\n", _("Reset your display to the factory defaults."));
-
-		/* TRANSLATORS: dialog message, bullet item */
-		g_string_append_printf (string, "â?¢ %s\n", _("Disable dynamic contrast if your display has this feature."));
-
-		/* TRANSLATORS: dialog message, bullet item */
-		g_string_append_printf (string, "â?¢ %s", _("Configure your display with custom color settings and ensure the RGB channels are set to the same values."));
-
-		/* TRANSLATORS: dialog message, addition to bullet item */
-		g_string_append_printf (string, " %s\n", _("If custom color is not available then use a 6500K color temperature."));
-
-		/* TRANSLATORS: dialog message, bullet item */
-		g_string_append_printf (string, "â?¢ %s\n", _("Adjust the display brightness to a comfortable level for prolonged viewing."));
-
-		/* TRANSLATORS: dialog message, suffix */
-		g_string_append_printf (string, "\n%s\n", _("For best results, the display should have been powered for at least 15 minutes before starting the calibration."));
-
-		/* TRANSLATORS: window title */
-		gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, _("Display setup"), string->str);
-		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-		response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-		if (response != GTK_RESPONSE_OK) {
-			gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-			g_set_error_literal (error,
-					     GCM_CALIBRATE_ERROR,
-					     GCM_CALIBRATE_ERROR_USER_ABORT,
-					     "user did not follow calibration steps");
-			ret = FALSE;
-			goto out;
-		}
-	}
-
-	/* create new helper objects */
-	brightness = gcm_brightness_new ();
-
-	/* if we are an internal LCD, we need to set the brightness to maximum */
-	ret = gcm_utils_output_is_lcd_internal (priv->output_name);
-	if (ret) {
-		/* get the old brightness so we can restore state */
-		ret = gcm_brightness_get_percentage (brightness, &percentage, &error_tmp);
-		if (!ret) {
-			g_warning ("failed to get brightness: %s", error_tmp->message);
-			g_error_free (error_tmp);
-			/* not fatal */
-			error_tmp = NULL;
-		}
-
-		/* set the new brightness */
-		ret = gcm_brightness_set_percentage (brightness, 100, &error_tmp);
-		if (!ret) {
-			g_warning ("failed to set brightness: %s", error_tmp->message);
-			g_error_free (error_tmp);
-			/* not fatal */
-			error_tmp = NULL;
-		}
-	}
-
 	/* proxy */
-	ret = klass->calibrate_display (calibrate, priv->sensor, window, error);
+	ret = klass->calibrate_display (calibrate, device, priv->sensor, window, error);
 out:
-	/* restore brightness */
-	if (percentage != G_MAXUINT) {
-		/* set the new brightness */
-		ret_tmp = gcm_brightness_set_percentage (brightness, percentage, &error_tmp);
-		if (!ret_tmp) {
-			g_warning ("failed to restore brightness: %s", error_tmp->message);
-			g_error_free (error_tmp);
-			/* not fatal */
-			error = NULL;
-		}
-	}
-
-	if (brightness != NULL)
-		g_object_unref (brightness);
-	if (string != NULL)
-		g_string_free (string, TRUE);
-	g_free (precision);
 	return ret;
 }
 
@@ -896,50 +689,17 @@ gcm_calibrate_file_chooser_get_working_path (GcmCalibrate *calibrate, GtkWindow
  * gcm_calibrate_printer:
  **/
 gboolean
-gcm_calibrate_printer (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+gcm_calibrate_printer (GcmCalibrate *calibrate, CdDevice *device, GtkWindow *window, GError **error)
 {
 	gboolean ret = FALSE;
-	const gchar *title;
-	const gchar *message;
 	gchar *ptr;
-	GtkWindow *window_tmp;
-	GtkResponseType response;
+	GtkWindow *window_tmp = NULL;
 	gchar *precision = NULL;
 	GcmCalibrateClass *klass = GCM_CALIBRATE_GET_CLASS (calibrate);
 	GcmCalibratePrivate *priv = calibrate->priv;
 
-	/* TRANSLATORS: title, you can profile all at once, or in steps */
-	title = _("Please choose a profiling mode");
-
-	/* TRANSLATORS: dialog message. Test patches are pages of colored squares
-	 * that are printed with a printer, and then read in with a calibration
-	 * device to create a profile */
-	message = _("Please indicate if you want to profile a local printer, generate some test patches, or profile using existing test patches.");
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_PRINT_MODE, title, message);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-	response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-	if (response != GTK_RESPONSE_OK) {
-		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-		g_set_error_literal (error,
-				     GCM_CALIBRATE_ERROR,
-				     GCM_CALIBRATE_ERROR_USER_ABORT,
-				     "user did not choose print mode");
-		ret = FALSE;
-		goto out;
-	}
-
-	/* get default precision */
-	priv->precision = gcm_calibrate_get_precision (calibrate, error);
-	if (priv->precision == GCM_CALIBRATE_PRECISION_UNKNOWN) {
-		ret = FALSE;
-		goto out;
-	}
-
 	/* copy */
-	g_object_get (priv->calibrate_dialog, "print-kind", &priv->print_kind, NULL);
+	g_object_get (NULL, "print-kind", &priv->print_kind, NULL);
 
 	if (priv->print_kind != GCM_CALIBRATE_PRINT_KIND_ANALYZE) {
 		/* set the per-profile filename */
@@ -953,7 +713,6 @@ gcm_calibrate_printer (GcmCalibrate *calibrate, GtkWindow *window, GError **erro
 		priv->working_path = NULL;
 
 		/* get from the user */
-		window_tmp = gcm_calibrate_dialog_get_window (priv->calibrate_dialog);
 		priv->working_path = gcm_calibrate_file_chooser_get_working_path (calibrate, window_tmp);
 		if (priv->working_path == NULL) {
 			g_set_error_literal (error,
@@ -984,7 +743,7 @@ gcm_calibrate_printer (GcmCalibrate *calibrate, GtkWindow *window, GError **erro
 	}
 
 	/* proxy */
-	ret = klass->calibrate_printer (calibrate, priv->sensor, window, error);
+	ret = klass->calibrate_printer (calibrate, device, priv->sensor, window, error);
 out:
 	g_free (precision);
 	return ret;
@@ -994,119 +753,24 @@ out:
  * gcm_calibrate_device:
  **/
 gboolean
-gcm_calibrate_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+gcm_calibrate_device (GcmCalibrate *calibrate, CdDevice *device, GtkWindow *window, GError **error)
 {
 	gboolean ret = FALSE;
-	gboolean has_shared_targets;
+	gboolean has_shared_targets = TRUE;
 	gchar *reference_image = NULL;
 	gchar *reference_data = NULL;
-	gchar *device = NULL;
+	gchar *device_str = NULL;
 	const gchar *directory;
 	GString *string;
-	GtkResponseType response;
-	GtkWindow *window_tmp;
+	GtkWindow *window_tmp = NULL;
 	gchar *precision = NULL;
-#ifdef HAVE_PACKAGEKIT
-	GtkWidget *dialog;
-#endif
-	const gchar *title;
 	GcmCalibratePrivate *priv = calibrate->priv;
 	GcmCalibrateClass *klass = GCM_CALIBRATE_GET_CLASS (calibrate);
 
 	string = g_string_new ("");
 
-	/* install shared-color-targets package */
-	has_shared_targets = g_file_test ("/usr/share/shared-color-targets", G_FILE_TEST_IS_DIR);
-	if (!has_shared_targets) {
-#ifdef HAVE_PACKAGEKIT
-		/* ask the user to confirm */
-		dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
-						 /* TRANSLATORS: title, usually we can tell based on the EDID data or output name */
-						 _("Install missing files?"));
-
-		/* TRANSLATORS: dialog message saying the color targets are not installed */
-		g_string_append_printf (string, "%s ", _("Common color target files are not installed on this computer."));
-		/* TRANSLATORS: dialog message saying the color targets are not installed */
-		g_string_append_printf (string, "%s\n\n", _("Color target files are needed to convert the image to a color profile."));
-		/* TRANSLATORS: dialog message, asking if it's okay to install them */
-		g_string_append_printf (string, "%s\n\n", _("Do you want them to be installed?"));
-		/* TRANSLATORS: dialog message, if the user has the target file on a CDROM then there's no need for this package */
-		g_string_append_printf (string, "%s", _("If you already have the correct file, you can skip this step."));
-
-		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", string->str);
-		gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
-		/* TRANSLATORS: button, skip installing a package */
-		gtk_dialog_add_button (GTK_DIALOG (dialog), _("Do not install"), GTK_RESPONSE_CANCEL);
-		/* TRANSLATORS: button, install a package */
-		gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_YES);
-		response = gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
-
-		/* only install if the user wanted to */
-		if (response == GTK_RESPONSE_YES)
-			has_shared_targets = gcm_utils_install_package (GCM_PREFS_PACKAGE_NAME_SHARED_COLOR_TARGETS, window);
-#else
-		g_warning ("cannot install: this package was not compiled with --enable-packagekit");
-#endif
-	}
-
-	/* TRANSLATORS: this is the window title for when the user selects the calibration target.
-	 * A calibration target is an accuratly printed grid of colors, for instance:
-	 * the IT 8.7 targets available here: http://www.targets.coloraid.de/ */
-	title = _("Please select a calibration target");
-	g_string_set_size (string, 0);
-
-	/* TRANSLATORS: dialog message, preface. A calibration target looks like
-	 * this: http://www.colorreference.de/targets/target.jpg */
-	g_string_append_printf (string, "%s\n", _("Before profiling the device, you have to manually capture an image of a calibration target and save it as a TIFF image file."));
-
-	/* scanner specific options */
-	if (priv->device_kind == CD_DEVICE_KIND_SCANNER) {
-		/* TRANSLATORS: dialog message, preface */
-		g_string_append_printf (string, "%s\n", _("Ensure that the contrast and brightness are not changed and color correction profiles have not been applied."));
-
-		/* TRANSLATORS: dialog message, suffix */
-		g_string_append_printf (string, "%s\n", _("The device sensor should have been cleaned prior to scanning and the output file resolution should be at least 200dpi."));
-	}
-
-	/* camera specific options */
-	if (priv->device_kind == CD_DEVICE_KIND_CAMERA) {
-		/* TRANSLATORS: dialog message, preface */
-		g_string_append_printf (string, "%s\n", _("Ensure that the white-balance has not been modified by the camera and that the lens is clean."));
-	}
-
-	/* TRANSLATORS: this is the message body for the chart selection */
-	g_string_append_printf (string, "\n%s", _("Please select the calibration target type."));
-
-	/* push new messages into the UI */
-	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
-	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_TARGET_TYPE, title, string->str);
-	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
-	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
-	response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
-	if (response != GTK_RESPONSE_OK) {
-		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
-		g_set_error_literal (error,
-				     GCM_CALIBRATE_ERROR,
-				     GCM_CALIBRATE_ERROR_USER_ABORT,
-				     "user did not choose calibration target type");
-		ret = FALSE;
-		goto out;
-	}
-
-	/* copy */
-	g_object_get (priv->calibrate_dialog, "reference-kind", &priv->reference_kind, NULL);
-
-	/* get default precision */
-	priv->precision = gcm_calibrate_get_precision (calibrate, error);
-	if (priv->precision == GCM_CALIBRATE_PRECISION_UNKNOWN) {
-		ret = FALSE;
-		goto out;
-	}
-
 	/* get scanned image */
 	directory = g_get_home_dir ();
-	window_tmp = gcm_calibrate_dialog_get_window (priv->calibrate_dialog);
 	reference_image = gcm_calibrate_device_get_reference_image (directory, window_tmp);
 	if (reference_image == NULL) {
 		g_set_error_literal (error,
@@ -1135,9 +799,9 @@ gcm_calibrate_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error
 	}
 
 	/* use the ORIGINATOR in the it8 file */
-	device = gcm_calibrate_get_device_for_it8_file (reference_data);
-	if (device == NULL)
-		device = g_strdup ("IT8.7");
+	device_str = gcm_calibrate_get_device_for_it8_file (reference_data);
+	if (device_str == NULL)
+		device_str = g_strdup ("IT8.7");
 
 	/* set the calibration parameters */
 	g_object_set (calibrate,
@@ -1146,11 +810,6 @@ gcm_calibrate_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error
 		      "device", device,
 		      NULL);
 
-	/* set the per-profile filename */
-	ret = gcm_calibrate_set_working_path (calibrate, error);
-	if (!ret)
-		goto out;
-
 	/* coldplug source */
 	if (klass->calibrate_device == NULL) {
 		g_set_error_literal (error,
@@ -1161,17 +820,53 @@ gcm_calibrate_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error
 	}
 
 	/* proxy */
-	ret = klass->calibrate_device (calibrate, priv->sensor, window, error);
+	ret = klass->calibrate_device (calibrate, device, priv->sensor, window, error);
 out:
 	if (string != NULL)
 		g_string_free (string, TRUE);
 	g_free (precision);
-	g_free (device);
+	g_free (device_str);
 	g_free (reference_image);
 	g_free (reference_data);
 	return ret;
 }
 
+void
+gcm_calibrate_set_title (GcmCalibrate *calibrate, const gchar *title)
+{
+	g_signal_emit (calibrate, signals[SIGNAL_TITLE_CHANGED], 0, title);
+	g_ptr_array_add (calibrate->priv->old_title, g_strdup (title));
+}
+
+void
+gcm_calibrate_set_message (GcmCalibrate *calibrate, const gchar *message)
+{
+	g_signal_emit (calibrate, signals[SIGNAL_MESSAGE_CHANGED], 0, message);
+	g_ptr_array_add (calibrate->priv->old_message, g_strdup (message));
+}
+
+void
+gcm_calibrate_set_image (GcmCalibrate *calibrate, const gchar *filename)
+{
+	g_signal_emit (calibrate, signals[SIGNAL_IMAGE_CHANGED], 0, filename);
+}
+
+void
+gcm_calibrate_interaction_required (GcmCalibrate *calibrate, const gchar *button_text)
+{
+	g_signal_emit (calibrate, signals[SIGNAL_INTERACTION_REQUIRED], 0, button_text);
+}
+
+void
+gcm_calibrate_pop (GcmCalibrate *calibrate)
+{
+	const gchar *tmp;
+	tmp = g_ptr_array_index (calibrate->priv->old_title, calibrate->priv->old_title->len - 2);
+	g_signal_emit (calibrate, signals[SIGNAL_TITLE_CHANGED], 0, tmp);
+	tmp = g_ptr_array_index (calibrate->priv->old_message, calibrate->priv->old_message->len - 2);
+	g_signal_emit (calibrate, signals[SIGNAL_MESSAGE_CHANGED], 0, tmp);
+}
+
 /**
  * gcm_calibrate_get_property:
  **/
@@ -1191,11 +886,12 @@ gcm_calibrate_get_property (GObject *object, guint prop_id, GValue *value, GPara
 	case PROP_PRINT_KIND:
 		g_value_set_uint (value, priv->print_kind);
 		break;
-	case PROP_CALIBRATE_DEVICE_KIND:
-		g_value_set_uint (value, priv->calibrate_device_kind);
+	case PROP_DISPLAY_KIND:
+		g_value_set_uint (value, priv->display_kind);
 		break;
 	case PROP_SENSOR_KIND:
-		g_value_set_uint (value, priv->sensor_kind);
+		g_assert (priv->sensor != NULL);
+		g_value_set_uint (value, cd_sensor_get_kind (priv->sensor));
 		break;
 	case PROP_OUTPUT_NAME:
 		g_value_set_string (value, priv->output_name);
@@ -1242,20 +938,6 @@ gcm_calibrate_get_property (GObject *object, guint prop_id, GValue *value, GPara
 	}
 }
 
-/**
- * gcm_calibrate_guess_kind:
- **/
-static void
-gcm_calibrate_guess_kind (GcmCalibrate *calibrate)
-{
-	gboolean ret;
-	GcmCalibratePrivate *priv = calibrate->priv;
-
-	/* guess based on the output name */
-	ret = gcm_utils_output_is_lcd_internal (priv->output_name);
-	if (ret)
-		priv->calibrate_device_kind = GCM_CALIBRATE_DEVICE_KIND_LCD;
-}
 
 /**
  * gcm_calibrate_set_property:
@@ -1270,7 +952,6 @@ gcm_calibrate_set_property (GObject *object, guint prop_id, const GValue *value,
 	case PROP_OUTPUT_NAME:
 		g_free (priv->output_name);
 		priv->output_name = g_strdup (g_value_get_string (value));
-		gcm_calibrate_guess_kind (calibrate);
 		break;
 	case PROP_FILENAME_SOURCE:
 		g_free (priv->filename_source);
@@ -1312,6 +993,12 @@ gcm_calibrate_set_property (GObject *object, guint prop_id, const GValue *value,
 	case PROP_DEVICE_KIND:
 		priv->device_kind = g_value_get_uint (value);
 		break;
+	case PROP_PRECISION:
+		priv->precision = g_value_get_uint (value);
+		break;
+	case PROP_DISPLAY_KIND:
+		priv->display_kind = g_value_get_uint (value);
+		break;
 	case PROP_WORKING_PATH:
 		g_free (priv->working_path);
 		priv->working_path = g_strdup (g_value_get_string (value));
@@ -1339,150 +1026,121 @@ gcm_calibrate_class_init (GcmCalibrateClass *klass)
 	object_class->get_property = gcm_calibrate_get_property;
 	object_class->set_property = gcm_calibrate_set_property;
 
-	/**
-	 * GcmCalibrate:reference-kind:
-	 */
 	pspec = g_param_spec_uint ("reference-kind", NULL, NULL,
 				   0, G_MAXUINT, 0,
 				   G_PARAM_READABLE);
 	g_object_class_install_property (object_class, PROP_REFERENCE_KIND, pspec);
 
-	/**
-	 * GcmCalibrate:calibrate-device-kind:
-	 */
-	pspec = g_param_spec_uint ("calibrate-device-kind", NULL, NULL,
+	pspec = g_param_spec_uint ("display-kind", NULL, NULL,
 				   0, G_MAXUINT, 0,
-				   G_PARAM_READABLE);
-	g_object_class_install_property (object_class, PROP_CALIBRATE_DEVICE_KIND, pspec);
+				   G_PARAM_READWRITE);
+	g_object_class_install_property (object_class, PROP_DISPLAY_KIND, pspec);
 
-	/**
-	 * GcmCalibrate:print-kind:
-	 */
 	pspec = g_param_spec_uint ("print-kind", NULL, NULL,
 				   0, G_MAXUINT, 0,
 				   G_PARAM_READABLE);
 	g_object_class_install_property (object_class, PROP_PRINT_KIND, pspec);
 
-	/**
-	 * GcmCalibrate:device-kind:
-	 */
 	pspec = g_param_spec_uint ("device-kind", NULL, NULL,
 				   0, G_MAXUINT, 0,
 				   G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_DEVICE_KIND, pspec);
 
-	/**
-	 * GcmCalibrate:sensor-kind:
-	 */
 	pspec = g_param_spec_uint ("sensor-kind", NULL, NULL,
 				   0, G_MAXUINT, 0,
 				   G_PARAM_READABLE);
 	g_object_class_install_property (object_class, PROP_SENSOR_KIND, pspec);
 
-	/**
-	 * GcmCalibrate:output-name:
-	 */
 	pspec = g_param_spec_string ("output-name", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_OUTPUT_NAME, pspec);
 
-	/**
-	 * GcmCalibrate:filename-source:
-	 */
 	pspec = g_param_spec_string ("filename-source", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_FILENAME_SOURCE, pspec);
 
-	/**
-	 * GcmCalibrate:filename-reference:
-	 */
 	pspec = g_param_spec_string ("filename-reference", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_FILENAME_REFERENCE, pspec);
 
-	/**
-	 * GcmCalibrate:filename-result:
-	 */
 	pspec = g_param_spec_string ("filename-result", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_FILENAME_RESULT, pspec);
 
-	/**
-	 * GcmCalibrate:basename:
-	 */
 	pspec = g_param_spec_string ("basename", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_BASENAME, pspec);
 
-	/**
-	 * GcmCalibrate:model:
-	 */
 	pspec = g_param_spec_string ("model", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_MODEL, pspec);
 
-	/**
-	 * GcmCalibrate:description:
-	 */
 	pspec = g_param_spec_string ("description", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
 
-	/**
-	 * GcmCalibrate:serial:
-	 */
 	pspec = g_param_spec_string ("serial", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_SERIAL, pspec);
 
-	/**
-	 * GcmCalibrate:device:
-	 */
 	pspec = g_param_spec_string ("device", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_DEVICE, pspec);
 
-	/**
-	 * GcmCalibrate:manufacturer:
-	 */
 	pspec = g_param_spec_string ("manufacturer", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_MANUFACTURER, pspec);
 
-	/**
-	 * GcmCalibrate:working-path:
-	 */
 	pspec = g_param_spec_string ("working-path", NULL, NULL,
 				     NULL,
 				     G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_WORKING_PATH, pspec);
 
-	/**
-	 * GcmCalibrate:precision:
-	 */
 	pspec = g_param_spec_uint ("precision", NULL, NULL,
 				   0, G_MAXUINT, 0,
-				   G_PARAM_READABLE);
+				   G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_PRECISION, pspec);
 
-	/**
-	 * GcmCalibrate:xyz:
-	 */
 	pspec = g_param_spec_boxed ("xyz", NULL, NULL,
 				    CD_TYPE_COLOR_XYZ,
 				    G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_XYZ, pspec);
 
+	signals[SIGNAL_TITLE_CHANGED] =
+		g_signal_new ("title-changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GcmCalibrateClass, title_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1, G_TYPE_STRING);
+	signals[SIGNAL_MESSAGE_CHANGED] =
+		g_signal_new ("message-changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GcmCalibrateClass, message_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1, G_TYPE_STRING);
+	signals[SIGNAL_IMAGE_CHANGED] =
+		g_signal_new ("image-changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GcmCalibrateClass, image_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1, G_TYPE_STRING);
+	signals[SIGNAL_INTERACTION_REQUIRED] =
+		g_signal_new ("interaction-required",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GcmCalibrateClass, interaction_required),
+			      NULL, NULL, g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1, G_TYPE_STRING);
+
 	g_type_class_add_private (klass, sizeof (GcmCalibratePrivate));
 }
 
@@ -1493,26 +1151,16 @@ static void
 gcm_calibrate_init (GcmCalibrate *calibrate)
 {
 	calibrate->priv = GCM_CALIBRATE_GET_PRIVATE (calibrate);
-	calibrate->priv->output_name = NULL;
-	calibrate->priv->filename_source = NULL;
-	calibrate->priv->filename_reference = NULL;
-	calibrate->priv->filename_result = NULL;
-	calibrate->priv->basename = NULL;
-	calibrate->priv->manufacturer = NULL;
-	calibrate->priv->model = NULL;
-	calibrate->priv->description = NULL;
-	calibrate->priv->device = NULL;
-	calibrate->priv->serial = NULL;
 	calibrate->priv->xyz = cd_color_xyz_new ();
-	calibrate->priv->working_path = NULL;
-	calibrate->priv->calibrate_device_kind = GCM_CALIBRATE_DEVICE_KIND_UNKNOWN;
+
 	calibrate->priv->print_kind = GCM_CALIBRATE_PRINT_KIND_UNKNOWN;
 	calibrate->priv->reference_kind = GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN;
 	calibrate->priv->precision = GCM_CALIBRATE_PRECISION_UNKNOWN;
-	calibrate->priv->calibrate_dialog = gcm_calibrate_dialog_new ();
 
 	// FIXME: this has to be per-run specific
 	calibrate->priv->working_path = g_strdup ("/tmp");
+	calibrate->priv->old_title = g_ptr_array_new_with_free_func (g_free);
+	calibrate->priv->old_message = g_ptr_array_new_with_free_func (g_free);
 }
 
 /**
@@ -1536,7 +1184,8 @@ gcm_calibrate_finalize (GObject *object)
 	g_free (priv->serial);
 	g_free (priv->working_path);
 	cd_color_xyz_free (priv->xyz);
-	g_object_unref (priv->calibrate_dialog);
+	g_ptr_array_unref (calibrate->priv->old_title);
+	g_ptr_array_unref (calibrate->priv->old_message);
 
 	G_OBJECT_CLASS (gcm_calibrate_parent_class)->finalize (object);
 }
@@ -1553,4 +1202,3 @@ gcm_calibrate_new (void)
 	calibrate = g_object_new (GCM_TYPE_CALIBRATE, NULL);
 	return GCM_CALIBRATE (calibrate);
 }
-
diff --git a/src/gcm-calibrate.h b/src/gcm-calibrate.h
index 2904814..34ad2fd 100644
--- a/src/gcm-calibrate.h
+++ b/src/gcm-calibrate.h
@@ -50,27 +50,37 @@ struct _GcmCalibrateClass
 	GObjectClass	parent_class;
 	/* vtable */
 	gboolean	 (*calibrate_display)		(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 CdSensor	*sensor,
 							 GtkWindow	*window,
 							 GError		**error);
 	gboolean	 (*calibrate_device)		(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 CdSensor	*sensor,
 							 GtkWindow	*window,
 							 GError		**error);
 	gboolean	 (*calibrate_printer)		(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 CdSensor	*sensor,
 							 GtkWindow	*window,
 							 GError		**error);
 	gboolean	 (*calibrate_spotread)		(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 CdSensor	*sensor,
 							 GtkWindow	*window,
 							 GError		**error);
-	/* padding for future expansion */
-	void (*_gcm_reserved1) (void);
-	void (*_gcm_reserved2) (void);
-	void (*_gcm_reserved3) (void);
-	void (*_gcm_reserved4) (void);
-	void (*_gcm_reserved5) (void);
+	void		 (*interaction)			(GcmCalibrate	*calibrate,
+							 GtkResponseType response);
+
+	/* signal */
+	void		(* title_changed)		(GcmCalibrate	*calibrate,
+							 const gchar	*title);
+	void		(* message_changed)		(GcmCalibrate	*calibrate,
+							 const gchar	*message);
+	void		(* image_changed)		(GcmCalibrate	*calibrate,
+							 const gchar	*filename);
+	void		(* interaction_required)	(GcmCalibrate	*calibrate,
+							 const gchar	*button_text);
 };
 
 typedef enum {
@@ -102,7 +112,7 @@ typedef enum {
 	GCM_CALIBRATE_DEVICE_KIND_LCD,
 	GCM_CALIBRATE_DEVICE_KIND_PROJECTOR,
 	GCM_CALIBRATE_DEVICE_KIND_UNKNOWN
-} GcmCalibrateDeviceKind;
+} GcmCalibrateDisplayKind;
 
 typedef enum {
 	GCM_CALIBRATE_PRINT_KIND_LOCAL,
@@ -120,18 +130,48 @@ typedef enum {
 
 GType		 gcm_calibrate_get_type			(void);
 GcmCalibrate	*gcm_calibrate_new			(void);
+
+/* designed for gcm-calibrate to call */
 gboolean	 gcm_calibrate_display			(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 GtkWindow	*window,
 							 GError		**error);
 gboolean	 gcm_calibrate_device			(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 GtkWindow	*window,
 							 GError		**error);
 gboolean	 gcm_calibrate_printer			(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 GtkWindow	*window,
 							 GError		**error);
 gboolean	 gcm_calibrate_spotread			(GcmCalibrate	*calibrate,
+							 CdDevice	*device,
 							 GtkWindow	*window,
 							 GError		**error);
+void		 gcm_calibrate_set_content_widget	(GcmCalibrate	*calibrate,
+							 GtkWidget	*widget);
+void		 gcm_calibrate_interaction		(GcmCalibrate	*calibrate,
+							 GtkResponseType response);
+
+/* designed for super-classes to call */
+gchar		*gcm_calibrate_get_profile_copyright	(GcmCalibrate	*calibrate);
+gchar		*gcm_calibrate_get_profile_description	(GcmCalibrate	*calibrate);
+gchar		*gcm_calibrate_get_profile_model	(GcmCalibrate	*calibrate);
+gchar		*gcm_calibrate_get_profile_manufacturer	(GcmCalibrate	*calibrate);
+void		 gcm_calibrate_set_sensor		(GcmCalibrate	*calibrate,
+							 CdSensor	*sensor);
+void		 gcm_calibrate_set_title		(GcmCalibrate	*calibrate,
+							 const gchar	*title);
+void		 gcm_calibrate_set_message		(GcmCalibrate	*calibrate,
+							 const gchar	*message);
+void		 gcm_calibrate_set_image		(GcmCalibrate	*calibrate,
+							 const gchar	*filename);
+void		 gcm_calibrate_pop			(GcmCalibrate	*calibrate);
+void		 gcm_calibrate_interaction_required	(GcmCalibrate	*calibrate,
+							 const gchar	*button_text);
+GtkWidget	*gcm_calibrate_get_content_widget	(GcmCalibrate	*calibrate);
+
+/* JUNK */
 gboolean	 gcm_calibrate_set_from_device		(GcmCalibrate	*calibrate,
 							 CdDevice	*device,
 							 CdSensor	*sensor,
@@ -143,11 +183,6 @@ const gchar	*gcm_calibrate_get_filename_result	(GcmCalibrate	*calibrate);
 const gchar	*gcm_calibrate_get_working_path		(GcmCalibrate	*calibrate);
 const gchar	*gcm_calibrate_get_basename		(GcmCalibrate	*calibrate);
 
-gchar		*gcm_calibrate_get_profile_copyright	(GcmCalibrate	*calibrate);
-gchar		*gcm_calibrate_get_profile_description	(GcmCalibrate	*calibrate);
-gchar		*gcm_calibrate_get_profile_model	(GcmCalibrate	*calibrate);
-gchar		*gcm_calibrate_get_profile_manufacturer	(GcmCalibrate	*calibrate);
-
 G_END_DECLS
 
 #endif /* __GCM_CALIBRATE_H */
diff --git a/src/gcm-self-test.c b/src/gcm-self-test.c
index 74ea266..29a2fba 100644
--- a/src/gcm-self-test.c
+++ b/src/gcm-self-test.c
@@ -27,7 +27,6 @@
 #include <stdlib.h>
 
 #include "gcm-brightness.h"
-#include "gcm-calibrate-dialog.h"
 #include "gcm-calibrate.h"
 #include "gcm-calibrate-native.h"
 #include "gcm-cie-widget.h"
@@ -691,58 +690,6 @@ gcm_test_calibrate_func (void)
 }
 
 static void
-gcm_test_calibrate_dialog_func (void)
-{
-	GcmCalibrateDialog *calibrate_dialog;
-	calibrate_dialog = gcm_calibrate_dialog_new ();
-	g_assert (calibrate_dialog != NULL);
-	g_object_unref (calibrate_dialog);
-}
-
-static void
-gcm_test_calibrate_native_func (void)
-{
-	gboolean ret;
-	GError *error = NULL;
-	GcmCalibrate *calibrate;
-	GcmX11Screen *screen;
-//	gchar *contents;
-	gchar *filename = NULL;
-
-	calibrate = gcm_calibrate_native_new ();
-	g_assert (calibrate != NULL);
-
-	g_object_set (calibrate,
-		      "output-name", "LVDS1",
-		      NULL);
-
-	/* set device */
-//	g_object_set (device,
-//		      "native-device", "LVDS1",
-//		      NULL);
-//	ret = gcm_calibrate_set_from_device (calibrate, device, &error);
-//	g_assert_no_error (error);
-//	g_assert (ret);
-
-	/* use a screen */
-	screen = gcm_x11_screen_new ();
-	ret = gcm_x11_screen_assign (screen, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret);
-
-	/* do the calibration */
-	ret = gcm_calibrate_display (calibrate, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret);
-
-	g_unlink (filename);
-//	g_free (contents);
-	g_free (filename);
-	g_object_unref (screen);
-	g_object_unref (calibrate);
-}
-
-static void
 gcm_test_cie_widget_func (void)
 {
 	GtkWidget *widget;
@@ -1091,7 +1038,6 @@ main (int argc, char **argv)
 	g_test_add_func ("/color/calibrate", gcm_test_calibrate_func);
 	g_test_add_func ("/color/exif", gcm_test_exif_func);
 	g_test_add_func ("/color/utils", gcm_test_utils_func);
-	g_test_add_func ("/color/calibrate_dialog", gcm_test_calibrate_dialog_func);
 	g_test_add_func ("/color/hull", gcm_test_hull_func);
 	g_test_add_func ("/color/edid", gcm_test_edid_func);
 	g_test_add_func ("/color/tables", gcm_test_tables_func);
@@ -1103,7 +1049,6 @@ main (int argc, char **argv)
 	if (g_test_thorough ()) {
 		g_test_add_func ("/color/brightness", gcm_test_brightness_func);
 		g_test_add_func ("/color/image", gcm_test_image_func);
-		g_test_add_func ("/color/calibrate_native", gcm_test_calibrate_native_func);
 		g_test_add_func ("/color/trc", gcm_test_trc_widget_func);
 		g_test_add_func ("/color/cie", gcm_test_cie_widget_func);
 		g_test_add_func ("/color/gamma_widget", gcm_test_gamma_widget_func);



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