[gnome-control-center] color: Use colord-session to calibrate the display



commit 8a353753e0a3b4b3d28c0dbdb81512b3f2c264de
Author: Richard Hughes <richard hughsie com>
Date:   Mon Jan 7 17:30:49 2013 +0000

    color: Use colord-session to calibrate the display
    
    This allows us to match the new mockups from Allan.

 configure.ac                               |    7 +-
 panels/color/Makefile.am                   |    4 +
 panels/color/cc-color-calibrate.c          | 1095 ++++++++++++++++++++++++++++
 panels/color/cc-color-calibrate.h          |   77 ++
 panels/color/cc-color-cell-renderer-text.c |  125 ++++
 panels/color/cc-color-cell-renderer-text.h |   56 ++
 panels/color/cc-color-panel.c              |  459 ++++++++++++
 panels/color/color-calibrate.ui            |  153 ++++
 panels/color/color.gresource.xml           |    3 +
 panels/color/color.ui                      |  792 ++++++++++++++++----
 10 files changed, 2609 insertions(+), 162 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 2aa6558..79c14cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,6 +108,8 @@ LIBWACOM_REQUIRED_VERSION=0.7
 CLUTTER_REQUIRED_VERSION=1.11.3
 GOA_REQUIRED_VERSION=3.5.90
 ACCOUNTSSERVICE_REQUIRED_VERSION=0.6.30
+COLORD_REQUIRED_VERSION=0.1.27
+COLORD_GTK_REQUIRED_VERSION=0.1.24
 
 COMMON_MODULES="gtk+-3.0 >= $GTK_REQUIRED_VERSION
  glib-2.0 >= $GLIB_REQUIRED_VERSION
@@ -144,7 +146,10 @@ PKG_CHECK_MODULES(NOTIFICATIONS_PANEL, $COMMON_MODULES libgnome-menu-3.0)
 PKG_CHECK_MODULES(ONLINE_ACCOUNTS_PANEL, $COMMON_MODULES goa-1.0 goa-backend-1.0 >= $GOA_REQUIRED_VERSION)
 PKG_CHECK_MODULES(POWER_PANEL, $COMMON_MODULES upower-glib >= 0.9.1
                   gnome-settings-daemon >= $GSD_REQUIRED_VERSION)
-PKG_CHECK_MODULES(COLOR_PANEL, $COMMON_MODULES colord >= 0.1.8)
+PKG_CHECK_MODULES(COLOR_PANEL, $COMMON_MODULES
+                  colord >= $COLORD_REQUIRED_VERSION
+                  colord-gtk >= $COLORD_GTK_REQUIRED_VERSION
+                  gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
 PKG_CHECK_MODULES(PRINTERS_PANEL, $COMMON_MODULES
                   polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
 PKG_CHECK_MODULES(PRIVACY_PANEL, $COMMON_MODULES)
diff --git a/panels/color/Makefile.am b/panels/color/Makefile.am
index c6706ba..8cfa6e3 100644
--- a/panels/color/Makefile.am
+++ b/panels/color/Makefile.am
@@ -17,6 +17,10 @@ BUILT_SOURCES =			\
 
 libcolor_la_SOURCES =		\
 	$(BUILT_SOURCES)	\
+	cc-color-calibrate.c		\
+	cc-color-calibrate.h		\
+	cc-color-cell-renderer-text.c	\
+	cc-color-cell-renderer-text.h	\
 	cc-color-panel.c	\
 	cc-color-panel.h
 
diff --git a/panels/color/cc-color-calibrate.c b/panels/color/cc-color-calibrate.c
new file mode 100644
index 0000000..3932d82
--- /dev/null
+++ b/panels/color/cc-color-calibrate.c
@@ -0,0 +1,1095 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 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 <colord-gtk.h>
+#include <gio/gunixfdlist.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <math.h>
+#include <colord-session/cd-session.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-rr.h>
+
+#include "cc-color-calibrate.h"
+
+#define CC_COLOR_CALIBRATE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_COLOR_CALIBRATE, CcColorCalibratePrivate))
+
+#define CALIBRATE_WINDOW_OPACITY 0.9
+
+struct _CcColorCalibratePrivate
+{
+  CdDevice        *device;
+  CdSensorCap      device_kind;
+  CdSensor        *sensor;
+  gchar           *title;
+  GDBusProxy      *proxy_helper;
+  GDBusProxy      *proxy_inhibit;
+  GMainLoop       *loop;
+  GnomeRROutput   *output;
+  GnomeRRScreen   *x11_screen;
+  GtkBuilder      *builder;
+  GtkWidget       *sample_widget;
+  guint            gamma_size;
+  CdProfileQuality quality;
+  guint            target_whitepoint;   /* in Kelvin */
+  gint             inhibit_fd;
+};
+
+#define CD_SESSION_ERROR   cc_color_calibrate_error_quark()
+
+G_DEFINE_TYPE (CcColorCalibrate, cc_color_calibrate, G_TYPE_OBJECT)
+
+static GQuark
+cc_color_calibrate_error_quark (void)
+{
+  static GQuark quark = 0;
+  if (!quark)
+    quark = g_quark_from_static_string ("CcColorCalibrateError");
+  return quark;
+}
+
+void
+cc_color_calibrate_set_kind (CcColorCalibrate *calibrate,
+                             CdSensorCap kind)
+{
+  g_return_if_fail (CC_IS_COLOR_CALIB (calibrate));
+  g_return_if_fail (kind != CD_SENSOR_CAP_UNKNOWN);
+  calibrate->priv->device_kind = kind;
+}
+
+void
+cc_color_calibrate_set_temperature (CcColorCalibrate *calibrate,
+                                    guint temperature)
+{
+  g_return_if_fail (CC_IS_COLOR_CALIB (calibrate));
+  g_return_if_fail (temperature < 10000);
+  calibrate->priv->target_whitepoint = temperature;
+}
+
+void
+cc_color_calibrate_set_quality (CcColorCalibrate *calibrate,
+                                CdProfileQuality quality)
+{
+  g_return_if_fail (CC_IS_COLOR_CALIB (calibrate));
+  calibrate->priv->quality = quality;
+}
+
+CdProfileQuality
+cc_color_calibrate_get_quality (CcColorCalibrate *calibrate)
+{
+  g_return_val_if_fail (CC_IS_COLOR_CALIB (calibrate), 0);
+  return calibrate->priv->quality;
+}
+
+void
+cc_color_calibrate_set_device (CcColorCalibrate *calibrate,
+                               CdDevice *device)
+{
+  g_return_if_fail (CC_IS_COLOR_CALIB (calibrate));
+  g_return_if_fail (CD_IS_DEVICE (device));
+  if (calibrate->priv->device != NULL)
+        g_object_unref (calibrate->priv->device);
+  calibrate->priv->device = g_object_ref (device);
+}
+
+void
+cc_color_calibrate_set_sensor (CcColorCalibrate *calibrate,
+                               CdSensor *sensor)
+{
+  g_return_if_fail (CC_IS_COLOR_CALIB (calibrate));
+  g_return_if_fail (CD_IS_SENSOR (sensor));
+  if (calibrate->priv->sensor != NULL)
+        g_object_unref (calibrate->priv->sensor);
+  calibrate->priv->sensor = g_object_ref (sensor);
+}
+
+void
+cc_color_calibrate_set_title (CcColorCalibrate *calibrate,
+                              const gchar *title)
+{
+  g_return_if_fail (CC_IS_COLOR_CALIB (calibrate));
+  g_return_if_fail (title != NULL);
+  g_free (calibrate->priv->title);
+  calibrate->priv->title = g_strdup (title);
+}
+
+
+static guint
+_gnome_rr_output_get_gamma_size (GnomeRROutput *output)
+{
+  GnomeRRCrtc *crtc;
+  gint len = 0;
+
+  crtc = gnome_rr_output_get_crtc (output);
+  if (crtc == NULL)
+    return 0;
+  gnome_rr_crtc_get_gamma (crtc,
+                           &len,
+                           NULL, NULL, NULL);
+  return (guint) len;
+}
+
+static gboolean
+cc_color_calibrate_calib_setup_screen (CcColorCalibrate *calibrate,
+                                       const gchar *name,
+                                       GError **error)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  gboolean ret = TRUE;
+
+  /* get screen */
+  priv->x11_screen = gnome_rr_screen_new (gdk_screen_get_default (), error);
+  if (priv->x11_screen == NULL)
+    {
+      ret = FALSE;
+      goto out;
+    }
+
+  /* get the output */
+  priv->output = gnome_rr_screen_get_output_by_name (priv->x11_screen,
+                                                     name);
+  if (priv->output == NULL)
+    {
+      ret = FALSE;
+      g_set_error_literal (error,
+                           CD_SESSION_ERROR,
+                           CD_SESSION_ERROR_INTERNAL,
+                           "failed to get output");
+      goto out;
+    }
+
+  /* create a lookup table */
+  priv->gamma_size = _gnome_rr_output_get_gamma_size (priv->output);
+  if (priv->gamma_size == 0)
+    {
+      ret = FALSE;
+      g_set_error_literal (error,
+                           CD_SESSION_ERROR,
+                           CD_SESSION_ERROR_INTERNAL,
+                           "gamma size is zero");
+    }
+out:
+  return ret;
+}
+
+/**
+ * cc_color_calibrate_calib_set_output_gamma:
+ *
+ * Handle this here rather than in gnome-settings-daemon for two reasons:
+ *
+ *  - We don't want to create a profile each time the video card gamma
+ *    table is created, as that would mean ~15 DBus requests each time
+ *    we get UpdateGamma from the session helper.
+ *
+ *  - We only have 100ms to process the request before the next update
+ *    could be scheduled.
+ **/
+static gboolean
+cc_color_calibrate_calib_set_output_gamma (CcColorCalibrate *calibrate,
+                                           GPtrArray *array,
+                                           GError **error)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  CdColorRGB *p1;
+  CdColorRGB *p2;
+  CdColorRGB result;
+  gboolean ret = TRUE;
+  gdouble mix;
+  GnomeRRCrtc *crtc;
+  guint16 *blue = NULL;
+  guint16 *green = NULL;
+  guint16 *red = NULL;
+  guint i;
+
+  /* no length? */
+  if (array->len == 0)
+    {
+      ret = FALSE;
+      g_set_error_literal (error,
+                           CD_SESSION_ERROR,
+                           CD_SESSION_ERROR_INTERNAL,
+                           "no data in the CLUT array");
+      goto out;
+    }
+
+  /* convert to a type X understands of the right size */
+  red = g_new (guint16, priv->gamma_size);
+  green = g_new (guint16, priv->gamma_size);
+  blue = g_new (guint16, priv->gamma_size);
+  cd_color_rgb_set (&result, 1.0, 1.0, 1.0);
+  for (i = 0; i < priv->gamma_size; i++)
+    {
+      mix = (gdouble) (array->len - 1) /
+            (gdouble) (priv->gamma_size - 1) *
+            (gdouble) i;
+      p1 = g_ptr_array_index (array, (guint) floor (mix));
+      p2 = g_ptr_array_index (array, (guint) ceil (mix));
+      cd_color_rgb_interpolate (p1,
+                                p2,
+                                mix - (gint) mix,
+                                &result);
+      red[i] = result.R * 0xffff;
+      green[i] = result.G * 0xffff;
+      blue[i] = result.B * 0xffff;
+    }
+
+  /* send to LUT */
+  crtc = gnome_rr_output_get_crtc (priv->output);
+  if (crtc == NULL)
+    {
+      ret = FALSE;
+      g_set_error (error,
+                   CD_SESSION_ERROR,
+                   CD_SESSION_ERROR_INTERNAL,
+                   "failed to get ctrc for %s",
+                   gnome_rr_output_get_name (priv->output));
+      goto out;
+    }
+  gnome_rr_crtc_set_gamma (crtc, priv->gamma_size,
+                           red, green, blue);
+out:
+  g_free (red);
+  g_free (green);
+  g_free (blue);
+  return ret;
+}
+
+static void
+cc_color_calibrate_property_changed_cb (GDBusProxy *proxy,
+                                        GVariant *changed_properties,
+                                        GStrv invalidated_properties,
+                                        CcColorCalibrate *calibrate)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  gboolean ret;
+  GtkWidget *widget;
+  guint value;
+
+  ret = g_variant_lookup (changed_properties,
+                          "Progress",
+                          "u", &value);
+  if (ret)
+    {
+      widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                                   "progressbar_status"));
+      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget),
+                                     value / 100.0f);
+    }
+}
+
+static void
+cc_color_calibrate_interaction_required (CcColorCalibrate *calibrate,
+                                         CdSessionInteraction code,
+                                         const gchar *message,
+                                         const gchar *image_path)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  const gchar *message_transl;
+  gboolean show_button_start = FALSE;
+  GdkPixbuf *pixbuf;
+  GtkImage *img;
+  GtkLabel *label;
+  GtkWidget *widget;
+
+  /* the client helper does not ship an icon for this */
+  if (code == CD_SESSION_INTERACTION_SHUT_LAPTOP_LID)
+    image_path = "preferences-color-symbolic";
+
+  /* set image */
+  img = GTK_IMAGE (gtk_builder_get_object (priv->builder,
+                                           "image_status"));
+  if (image_path != NULL && image_path[0] != '\0')
+    {
+      g_debug ("showing image %s", image_path);
+      pixbuf = gdk_pixbuf_new_from_file_at_size (image_path,
+                                                 400, 400,
+                                                 NULL);
+      if (pixbuf != NULL)
+        {
+          gtk_image_set_from_pixbuf (img, pixbuf);
+          g_object_unref (pixbuf);
+        }
+      gtk_widget_set_visible (GTK_WIDGET (img), TRUE);
+      gtk_widget_set_visible (GTK_WIDGET (priv->sample_widget), FALSE);
+    }
+  else
+    {
+      g_debug ("hiding image");
+      gtk_widget_set_visible (GTK_WIDGET (img), FALSE);
+      gtk_widget_set_visible (GTK_WIDGET (priv->sample_widget), TRUE);
+    }
+
+  /* set new status */
+  switch (code)
+    {
+    case CD_SESSION_INTERACTION_ATTACH_TO_SCREEN:
+      show_button_start = TRUE;
+      /* TRANSLATORS: The user has to attach the sensor to the screen */
+      message_transl = _("Place your calibration device over the square and press 'Start'");
+      break;
+    case CD_SESSION_INTERACTION_MOVE_TO_CALIBRATION:
+      /* TRANSLATORS: Some calibration devices need the user to move a
+       * dial or switch manually. We also show a picture showing them
+       * what to do... */
+      message_transl = _("Move your calibration device to the calibrate position and press 'Continue'");
+      break;
+    case CD_SESSION_INTERACTION_MOVE_TO_SURFACE:
+      /* TRANSLATORS: Some calibration devices need the user to move a
+       * dial or switch manually. We also show a picture showing them
+       * what to do... */
+      message_transl = _("Move your calibration device to the surface position and press 'Continue'");
+      break;
+    case CD_SESSION_INTERACTION_SHUT_LAPTOP_LID:
+      /* TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor
+       * is built into the palmrest and we need to fullscreen the
+       * sample widget and shut the lid. */
+      message_transl = _("Shut the laptop lid");
+      break;
+    default:
+      message_transl = message;
+      break;
+    }
+  label = GTK_LABEL (gtk_builder_get_object (priv->builder,
+                                             "label_status"));
+  gtk_label_set_label (label, message_transl);
+
+  /* show the correct button */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_start"));
+  gtk_widget_set_visible (widget, show_button_start);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_resume"));
+  gtk_widget_set_visible (widget, !show_button_start);
+}
+
+static const gchar *
+cc_color_calibrate_get_error_translation (CdSessionError code)
+{
+  const gchar *str = NULL;
+  switch (code)
+    {
+      case CD_SESSION_ERROR_FAILED_TO_FIND_DEVICE:
+      case CD_SESSION_ERROR_FAILED_TO_FIND_SENSOR:
+      case CD_SESSION_ERROR_INTERNAL:
+      case CD_SESSION_ERROR_INVALID_VALUE:
+        /* TRANSLATORS: We suck, the calibation failed and we have no
+         * good idea why or any suggestions */
+        str = _("An internal error occurred that could not be recovered.");
+        break;
+      case CD_SESSION_ERROR_FAILED_TO_FIND_TOOL:
+        /* TRANSLATORS: Some required-at-runtime tools were not
+         * installed, which should only affect insane distros */
+        str = _("Tools required for calibration are not installed.");
+        break;
+      case CD_SESSION_ERROR_FAILED_TO_GENERATE_PROFILE:
+      case CD_SESSION_ERROR_FAILED_TO_OPEN_PROFILE:
+      case CD_SESSION_ERROR_FAILED_TO_SAVE_PROFILE:
+        /* TRANSLATORS: The profile failed for some reason */
+        str = _("The profile could not be generated.");
+        break;
+      case CD_SESSION_ERROR_FAILED_TO_GET_WHITEPOINT:
+        /* TRANSLATORS: The user specified a whitepoint that was
+         * unobtainable with the hardware they've got -- see
+         * https://en.wikipedia.org/wiki/White_point for details */
+        str = _("The target whitepoint was not obtainable.");
+        break;
+      default:
+        break;
+    }
+  return str;
+}
+
+static void
+cc_color_calibrate_finished (CcColorCalibrate *calibrate,
+                             CdSessionError code,
+                             const gchar *error_fallback)
+{
+  GtkWidget *widget;
+  GString *str;
+  const gchar *tmp;
+  CcColorCalibratePrivate *priv = calibrate->priv;
+
+  /* show correct buttons */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_cancel"));
+  gtk_widget_set_visible (widget, FALSE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_start"));
+  gtk_widget_set_visible (widget, FALSE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_resume"));
+  gtk_widget_set_visible (widget, FALSE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_done"));
+  gtk_widget_set_visible (widget, TRUE);
+
+  str = g_string_new ("");
+  if (code == CD_SESSION_ERROR_NONE)
+    {
+      g_debug ("calibration succeeded");
+      /* TRANSLATORS: the display calibration process is finished */
+      g_string_append (str, _("Complete!"));
+    }
+  else
+    {
+      g_warning ("calibration failed with code %i: %s",
+                 code, error_fallback);
+      /* TRANSLATORS: the display calibration failed, and we also show
+       * the translated (or untranslated) error string after this */
+      g_string_append (str, _("Calibration failed!"));
+      g_string_append (str, "\n\n");
+      tmp = cc_color_calibrate_get_error_translation (code);
+      g_string_append (str, tmp != NULL ? tmp : error_fallback);
+    }
+  g_string_append (str, "\n");
+  /* TRANSLATORS: The user can now remove the sensor from the screen */
+  g_string_append (str, _("You can remove the calibration device."));
+
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "label_status"));
+  gtk_label_set_label (GTK_LABEL (widget), str->str);
+  g_string_free (str, TRUE);
+}
+
+static void
+cc_color_calibrate_signal_cb (GDBusProxy *proxy,
+                              const gchar *sender_name,
+                              const gchar *signal_name,
+                              GVariant *parameters,
+                              CcColorCalibrate *calibrate)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  CdColorRGB color;
+  CdColorRGB *color_tmp;
+  CdSessionInteraction code;
+  const gchar *image;
+  const gchar *message;
+  const gchar *str;
+  gboolean ret;
+  GError *error = NULL;
+  GPtrArray *array = NULL;
+  GtkImage *img;
+  GtkLabel *label;
+  GVariantIter *iter;
+
+  if (g_strcmp0 (signal_name, "Finished") == 0)
+    {
+      g_variant_get (parameters, "(u&s)",
+                     &code,
+                     &str);
+      cc_color_calibrate_finished (calibrate, code, str);
+      goto out;
+    }
+  if (g_strcmp0 (signal_name, "UpdateSample") == 0)
+    {
+      g_variant_get (parameters, "(ddd)",
+                     &color.R,
+                     &color.G,
+                     &color.B);
+      img = GTK_IMAGE (gtk_builder_get_object (priv->builder,
+                                               "image_status"));
+      gtk_widget_set_visible (GTK_WIDGET (img), FALSE);
+      gtk_widget_set_visible (GTK_WIDGET (priv->sample_widget), TRUE);
+      cd_sample_widget_set_color (CD_SAMPLE_WIDGET (priv->sample_widget),
+                                  &color);
+
+      /* for Lenovo W700 and W520 laptops we almost fullscreen the
+       * sample widget as the device is actually embedded in the
+       * palmrest! */
+      if (cd_sensor_get_embedded (priv->sensor))
+        {
+          g_debug ("Making sample window larger for embedded sensor");
+          gtk_widget_set_size_request (priv->sample_widget, 1000, 600);
+        }
+
+      /* set the generic label too */
+      label = GTK_LABEL (gtk_builder_get_object (priv->builder,
+                                                 "label_status"));
+      /* TRANSLATORS: The user has to be careful not to knock the
+       * display off the screen (although we do cope if this is
+       * detected early enough) */
+      gtk_label_set_label (label, _("Do not disturb the calibration device while in progress"));
+      goto out;
+    }
+  if (g_strcmp0 (signal_name, "InteractionRequired") == 0)
+    {
+      g_variant_get (parameters, "(u&s&s)",
+                     &code,
+                     &message,
+                     &image);
+      g_debug ("Interaction required type %i: %s",
+               code, message);
+      cc_color_calibrate_interaction_required (calibrate,
+                                               code,
+                                               message,
+                                               image);
+      goto out;
+    }
+  if (g_strcmp0 (signal_name, "UpdateGamma") == 0)
+    {
+      g_variant_get (parameters,
+                     "(a(ddd))",
+                     &iter);
+      array = g_ptr_array_new_with_free_func (g_free);
+      while (g_variant_iter_loop (iter, "(ddd)",
+                                  &color.R,
+                                  &color.G,
+                                  &color.B))
+        {
+          color_tmp = cd_color_rgb_new ();
+          cd_color_rgb_copy (&color, color_tmp);
+          g_ptr_array_add (array, color_tmp);
+        }
+      g_variant_iter_free (iter);
+      ret = cc_color_calibrate_calib_set_output_gamma (calibrate,
+                                                       array,
+                                                       &error);
+      if (!ret)
+        {
+          g_warning ("failed to update gamma: %s",
+                     error->message);
+          g_error_free (error);
+          goto out;
+        }
+      goto out;
+    }
+  g_warning ("got unknown signal %s", signal_name);
+out:
+  return;
+}
+
+static void
+cc_color_calibrate_cancel (CcColorCalibrate *calibrate)
+{
+  GVariant *retval;
+  GError *error = NULL;
+
+  /* cancel the calibration to ensure the helper quits */
+  retval = g_dbus_proxy_call_sync (calibrate->priv->proxy_helper,
+                                   "Cancel",
+                                   NULL,
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1,
+                                   NULL,
+                                   &error);
+  if (retval == NULL)
+    {
+      g_warning ("Failed to send Cancel: %s", error->message);
+      g_error_free (error);
+    }
+
+  /* return */
+  g_main_loop_quit (calibrate->priv->loop);
+  if (retval != NULL)
+    g_variant_unref (retval);
+}
+
+static gboolean
+cc_color_calibrate_move_and_resize_window (GtkWindow *window,
+                                           CdDevice *device,
+                                           GError **error)
+{
+  const gchar *xrandr_name;
+  gboolean ret = TRUE;
+  gchar *plug_name;
+  GdkRectangle rect;
+  GdkScreen *screen;
+  gint i;
+  gint monitor_num = -1;
+  gint num_monitors;
+
+  /* find the monitor num of the device output */
+  screen = gdk_screen_get_default ();
+  num_monitors = gdk_screen_get_n_monitors (screen);
+  xrandr_name = cd_device_get_metadata_item (device,
+                                             CD_DEVICE_METADATA_XRANDR_NAME);
+  for (i = 0; i < num_monitors; i++)
+    {
+      plug_name = gdk_screen_get_monitor_plug_name (screen, i);
+      if (g_strcmp0 (plug_name, xrandr_name) == 0)
+        monitor_num = i;
+      g_free (plug_name);
+    }
+  if (monitor_num == -1)
+    {
+      ret = FALSE;
+      g_set_error (error,
+                   CD_SESSION_ERROR,
+                   CD_SESSION_ERROR_INTERNAL,
+                   "failed to find output %s",
+                   xrandr_name);
+      goto out;
+    }
+
+  /* move the window, and set it to the right size */
+  gdk_screen_get_monitor_geometry (screen, monitor_num, &rect);
+  gtk_window_move (window, rect.x, rect.y);
+  gtk_window_resize (window, rect.width, rect.height);
+  g_debug ("Setting window to %ix%i with size %ix%i",
+           rect.x, rect.y, rect.width, rect.height);
+out:
+  return ret;
+}
+
+static void
+cc_color_calibrate_window_realize_cb (GtkWidget *widget,
+                                      CcColorCalibrate *calibrate)
+{
+  gtk_window_fullscreen (GTK_WINDOW (widget));
+  gtk_window_maximize (GTK_WINDOW (widget));
+}
+
+static gboolean
+cc_color_calibrate_window_state_cb (GtkWidget *widget,
+                                    GdkEvent *event,
+                                    CcColorCalibrate *calibrate)
+{
+  gboolean ret;
+  GError *error = NULL;
+  GdkEventWindowState *event_state = (GdkEventWindowState *) event;
+  GtkWindow *window = GTK_WINDOW (widget);
+
+  /* check event */
+  if (event->type != GDK_WINDOW_STATE)
+    return TRUE;
+
+  /* did the user do alt-tab? */
+  if (event_state->changed_mask == GDK_WINDOW_STATE_FOCUSED &&
+      event_state->new_window_state & GDK_WINDOW_STATE_FULLSCREEN &&
+      (event_state->new_window_state & GDK_WINDOW_STATE_FOCUSED) == 0)
+    {
+      g_debug("unfocussed calibration invalid");
+      cc_color_calibrate_cancel (calibrate);
+    }
+  if (event_state->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)
+    return TRUE;
+
+  /* resize to the correct screen */
+  ret = cc_color_calibrate_move_and_resize_window (window,
+                                                   calibrate->priv->device,
+                                                   &error);
+  if (!ret)
+    {
+      g_warning ("Failed to resize window: %s", error->message);
+      g_error_free (error);
+    }
+  return TRUE;
+}
+
+static void
+cc_color_calibrate_button_done_cb (GtkWidget *widget,
+                                   CcColorCalibrate *calibrate)
+{
+  g_main_loop_quit (calibrate->priv->loop);
+}
+
+static void
+cc_color_calibrate_button_start_cb (GtkWidget *widget,
+                                    CcColorCalibrate *calibrate)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  GError *error = NULL;
+  GVariant *retval;
+
+  /* set correct buttons */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_start"));
+  gtk_widget_set_visible (widget, FALSE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_resume"));
+  gtk_widget_set_visible (widget, FALSE);
+
+  /* continue */
+  retval = g_dbus_proxy_call_sync (calibrate->priv->proxy_helper,
+                                   "Resume",
+                                   NULL,
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1,
+                                   NULL,
+                                   &error);
+  if (retval == NULL)
+    {
+      g_warning ("Failed to send Resume: %s", error->message);
+      g_error_free (error);
+    }
+  if (retval != NULL)
+    g_variant_unref (retval);
+}
+
+static void
+cc_color_calibrate_button_cancel_cb (GtkWidget *widget,
+                                     CcColorCalibrate *calibrate)
+{
+  cc_color_calibrate_cancel (calibrate);
+}
+
+static gboolean
+cc_color_calibrate_alpha_window_draw (GtkWidget *widget, cairo_t *cr)
+{
+  if (gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)) &&
+      gtk_widget_is_composited (widget))
+    {
+      /* transparent */
+      cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, CALIBRATE_WINDOW_OPACITY);
+    }
+  else
+    {
+      /* opaque black */
+      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    }
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_paint (cr);
+  return FALSE;
+}
+
+static void
+cc_color_calibrate_alpha_screen_changed_cb (GtkWindow *window,
+                                            GdkScreen *old_screen,
+                                            gpointer user_data)
+{
+  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
+  GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
+  if (visual == NULL)
+    visual = gdk_screen_get_system_visual (screen);
+  gtk_widget_set_visual (GTK_WIDGET (window), visual);
+}
+
+static void
+cc_color_calibrate_uninhibit (CcColorCalibrate *calibrate)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  if (priv->inhibit_fd != -1)
+    {
+      close (priv->inhibit_fd);
+      priv->inhibit_fd = -1;
+    }
+}
+
+static void
+cc_color_calibrate_inhibit (CcColorCalibrate *calibrate)
+{
+  GError *error = NULL;
+  gint idx;
+  GUnixFDList *fd_list = NULL;
+  GVariant *retval;
+  CcColorCalibratePrivate *priv = calibrate->priv;
+
+  /* tell logind to basically disallow everything */
+  retval = g_dbus_proxy_call_with_unix_fd_list_sync (priv->proxy_inhibit,
+                                                     "Inhibit",
+                                                     g_variant_new ("(ssss)",
+                                                                    "shutdown:"
+                                                                    "sleep:"
+                                                                    "idle:"
+                                                                    "handle-lid-switch",
+                                                                    "Display Calibrator",
+                                                                    "Display calibration in progress",
+                                                                    "block"),
+                                                     G_DBUS_CALL_FLAGS_NONE,
+                                                     -1,
+                                                     NULL,
+                                                     &fd_list,
+                                                     NULL,
+                                                     &error);
+  if (retval == NULL)
+    {
+      g_warning ("Failed to send Inhibit: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+  g_variant_get (retval, "(h)", &idx);
+  priv->inhibit_fd = g_unix_fd_list_get (fd_list, idx, &error);
+  if (priv->inhibit_fd == -1)
+    {
+      g_warning ("Failed to receive system inhibitor fd: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+  g_debug ("System inhibitor fd is %d", priv->inhibit_fd);
+out:
+  if (fd_list != NULL)
+    g_object_unref (fd_list);
+  if (retval != NULL)
+    g_variant_unref (retval);
+}
+
+gboolean
+cc_color_calibrate_setup (CcColorCalibrate *calibrate,
+                          GError **error)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (CC_IS_COLOR_CALIB (calibrate), FALSE);
+ 
+  /* use logind to disable system state idle */
+  priv->proxy_inhibit = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+                                                       G_DBUS_PROXY_FLAGS_NONE,
+                                                       NULL,
+                                                       "org.freedesktop.login1",
+                                                       "/org/freedesktop/login1",
+                                                       "org.freedesktop.login1.Manager",
+                                                       NULL,
+                                                       error);
+  if (priv->proxy_inhibit == NULL)
+    {
+      ret = FALSE;
+      goto out;
+    }
+
+  /* start the calibration session daemon */
+  priv->proxy_helper = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                      G_DBUS_PROXY_FLAGS_NONE,
+                                                      NULL,
+                                                      CD_SESSION_DBUS_SERVICE,
+                                                      CD_SESSION_DBUS_PATH,
+                                                      CD_SESSION_DBUS_INTERFACE_DISPLAY,
+                                                      NULL,
+                                                      error);
+  if (priv->proxy_helper == NULL)
+    {
+      ret = FALSE;
+      goto out;
+    }
+  g_signal_connect (priv->proxy_helper,
+                    "g-properties-changed",
+                    G_CALLBACK (cc_color_calibrate_property_changed_cb),
+                    calibrate);
+  g_signal_connect (priv->proxy_helper,
+                    "g-signal",
+                    G_CALLBACK (cc_color_calibrate_signal_cb),
+                    calibrate);
+out:
+  return ret;
+}
+
+gboolean
+cc_color_calibrate_start (CcColorCalibrate *calibrate,
+                          GtkWindow *parent,
+                          GError **error)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  const gchar *name;
+  gboolean ret;
+  GtkWidget *widget;
+  GtkWindow *window;
+  GVariantBuilder builder;
+  GVariant *retval = NULL;
+
+  g_return_val_if_fail (CC_IS_COLOR_CALIB (calibrate), FALSE);
+
+  /* get screen */
+  name = cd_device_get_metadata_item (priv->device,
+                                      CD_DEVICE_METADATA_XRANDR_NAME);
+  ret = cc_color_calibrate_calib_setup_screen (calibrate, name, error);
+  if (!ret)
+    goto out;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+  g_variant_builder_add (&builder,
+                         "{sv}",
+                         "Quality",
+                         g_variant_new_uint32 (priv->quality));
+  g_variant_builder_add (&builder,
+                         "{sv}",
+                         "Whitepoint",
+                         g_variant_new_uint32 (priv->target_whitepoint));
+  g_variant_builder_add (&builder,
+                         "{sv}",
+                         "Title",
+                         g_variant_new_string (priv->title));
+  g_variant_builder_add (&builder,
+                         "{sv}",
+                         "DeviceKind",
+                         g_variant_new_uint32 (priv->device_kind));
+  retval = g_dbus_proxy_call_sync (priv->proxy_helper,
+                                   "Start",
+                                   g_variant_new ("(ssa{sv})",
+                                                  cd_device_get_id (priv->device),
+                                                  cd_sensor_get_id (priv->sensor),
+                                                  &builder),
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1,
+                                   NULL,
+                                   error);
+  if (retval == NULL)
+    {
+      ret = FALSE;
+      goto out;
+    }
+
+  /* set this above our parent */
+  window = GTK_WINDOW (gtk_builder_get_object (priv->builder,
+                                               "dialog_calibrate"));
+  gtk_window_set_modal (window, TRUE);
+  gtk_widget_show (GTK_WIDGET (window));
+
+  /* show correct buttons */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_cancel"));
+  gtk_widget_set_visible (widget, TRUE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_start"));
+  gtk_widget_set_visible (widget, TRUE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_resume"));
+  gtk_widget_set_visible (widget, FALSE);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_done"));
+  gtk_widget_set_visible (widget, FALSE);
+
+  /* stop the computer from auto-suspending or turning off the screen */
+  cc_color_calibrate_inhibit (calibrate);
+
+  g_main_loop_run (priv->loop);
+
+  gtk_widget_hide (GTK_WIDGET (window));
+
+  /* we can go idle now */
+  cc_color_calibrate_uninhibit (calibrate);
+out:
+  if (retval != NULL)
+    g_variant_unref (retval);
+  return ret;
+}
+
+static gboolean
+cc_color_calibrate_delete_event_cb (GtkWidget *widget,
+                                    GdkEvent *event,
+                                    CcColorCalibrate *calibrate)
+{
+  /* do not destroy the window */
+  cc_color_calibrate_cancel (calibrate);
+  return TRUE;
+}
+
+static void
+cc_color_calibrate_finalize (GObject *object)
+{
+  CcColorCalibrate *calibrate = CC_COLOR_CALIBRATE (object);
+  CcColorCalibratePrivate *priv = calibrate->priv;
+
+  g_clear_object (&priv->device);
+  g_clear_object (&priv->proxy_helper);
+  g_clear_object (&priv->proxy_inhibit);
+  g_clear_object (&priv->sensor);
+  g_clear_object (&priv->x11_screen);
+  g_free (priv->title);
+  g_main_loop_unref (priv->loop);
+
+  G_OBJECT_CLASS (cc_color_calibrate_parent_class)->finalize (object);
+}
+
+static void
+cc_color_calibrate_class_init (CcColorCalibrateClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = cc_color_calibrate_finalize;
+
+  g_type_class_add_private (klass, sizeof (CcColorCalibratePrivate));
+}
+
+static void
+cc_color_calibrate_init (CcColorCalibrate *calibrate)
+{
+  CcColorCalibratePrivate *priv = calibrate->priv;
+  GError *error = NULL;
+  gint retval;
+  GtkBox *box;
+  GtkWidget *widget;
+  GtkWindow *window;
+
+  calibrate->priv = priv = CC_COLOR_CALIBRATE_GET_PRIVATE (calibrate);
+  calibrate->priv->loop = g_main_loop_new (NULL, FALSE);
+  calibrate->priv->sample_widget = cd_sample_widget_new ();
+  calibrate->priv->inhibit_fd = -1;
+
+  /* load UI */
+  priv->builder = gtk_builder_new ();
+  retval = gtk_builder_add_from_resource (priv->builder,
+                                          "/org/gnome/control-center/color/color-calibrate.ui",
+                                          &error);
+  if (retval == 0)
+    {
+      g_warning ("Could not load interface: %s", error->message);
+      g_error_free (error);
+    }
+
+  /* add sample widget */
+  box = GTK_BOX (gtk_builder_get_object (priv->builder,
+                 "vbox_status"));
+  priv->sample_widget = cd_sample_widget_new ();
+  gtk_widget_set_size_request (priv->sample_widget, 400, 400);
+  gtk_box_pack_start (box, priv->sample_widget, FALSE, FALSE, 0);
+  gtk_box_reorder_child (box, priv->sample_widget, 0);
+  gtk_widget_set_vexpand (priv->sample_widget, FALSE);
+  gtk_widget_set_hexpand (priv->sample_widget, FALSE);
+
+  /* get default: FIXME: get from colord */
+  calibrate->priv->target_whitepoint = 6500;
+
+  /* connect to buttons */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_start"));
+  g_signal_connect (widget, "clicked",
+                    G_CALLBACK (cc_color_calibrate_button_start_cb), calibrate);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_resume"));
+  g_signal_connect (widget, "clicked",
+                    G_CALLBACK (cc_color_calibrate_button_start_cb), calibrate);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_done"));
+  g_signal_connect (widget, "clicked",
+                    G_CALLBACK (cc_color_calibrate_button_done_cb), calibrate);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "button_cancel"));
+  g_signal_connect (widget, "clicked",
+                    G_CALLBACK (cc_color_calibrate_button_cancel_cb), calibrate);
+  gtk_widget_show (widget);
+
+  /* setup the specialist calibration window */
+  window = GTK_WINDOW (gtk_builder_get_object (priv->builder,
+                                               "dialog_calibrate"));
+  g_signal_connect (window, "draw",
+                    G_CALLBACK (cc_color_calibrate_alpha_window_draw), calibrate);
+  g_signal_connect (window, "realize",
+                    G_CALLBACK (cc_color_calibrate_window_realize_cb), calibrate);
+  g_signal_connect (window, "window-state-event",
+                    G_CALLBACK (cc_color_calibrate_window_state_cb), calibrate);
+  g_signal_connect (window, "delete-event",
+                    G_CALLBACK (cc_color_calibrate_delete_event_cb), calibrate);
+  gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
+  gtk_window_set_keep_above (window, TRUE);
+  cc_color_calibrate_alpha_screen_changed_cb (GTK_WINDOW (window), NULL, calibrate);
+  g_signal_connect (window, "screen-changed",
+                    G_CALLBACK (cc_color_calibrate_alpha_screen_changed_cb), calibrate);
+}
+
+CcColorCalibrate *
+cc_color_calibrate_new (void)
+{
+  CcColorCalibrate *calibrate;
+  calibrate = g_object_new (CC_TYPE_COLOR_CALIBRATE, NULL);
+  return CC_COLOR_CALIBRATE (calibrate);
+}
diff --git a/panels/color/cc-color-calibrate.h b/panels/color/cc-color-calibrate.h
new file mode 100644
index 0000000..965efe4
--- /dev/null
+++ b/panels/color/cc-color-calibrate.h
@@ -0,0 +1,77 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CC_COLOR_CALIBRATE_H
+#define __CC_COLOR_CALIBRATE_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <colord.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_CALIBRATE         (cc_color_calibrate_get_type ())
+#define CC_COLOR_CALIBRATE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_COLOR_CALIBRATE, CcColorCalibrate))
+#define CC_COLOR_CALIBRATE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_COLOR_CALIBRATE, CcColorCalibrateClass))
+#define CC_IS_COLOR_CALIB(o)            (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_COLOR_CALIBRATE))
+#define CC_IS_COLOR_CALIB_CLASS(k)      (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_COLOR_CALIBRATE))
+#define CC_COLOR_CALIBRATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_COLOR_CALIBRATE, CcColorCalibrateClass))
+
+typedef struct _CcColorCalibratePrivate         CcColorCalibratePrivate;
+typedef struct _CcColorCalibrate                CcColorCalibrate;
+typedef struct _CcColorCalibrateClass           CcColorCalibrateClass;
+
+struct _CcColorCalibrate
+{
+  GObject                  parent;
+  CcColorCalibratePrivate *priv;
+};
+
+struct _CcColorCalibrateClass
+{
+  GObjectClass             parent_class;
+};
+
+CcColorCalibrate *cc_color_calibrate_new    (void);
+GType     cc_color_calibrate_get_type       (void);
+void      cc_color_calibrate_set_kind       (CcColorCalibrate *calibrate,
+                                             CdSensorCap       kind);
+void      cc_color_calibrate_set_temperature (CcColorCalibrate *calibrate,
+                                             guint             temperature);
+void      cc_color_calibrate_set_quality    (CcColorCalibrate *calibrate,
+                                             CdProfileQuality  quality);
+CdProfileQuality cc_color_calibrate_get_quality (CcColorCalibrate *calibrate);
+void      cc_color_calibrate_set_device     (CcColorCalibrate *calibrate,
+                                             CdDevice         *device);
+void      cc_color_calibrate_set_sensor     (CcColorCalibrate *calibrate,
+                                             CdSensor         *sensor);
+void      cc_color_calibrate_set_title      (CcColorCalibrate *calibrate,
+                                             const gchar      *title);
+gboolean  cc_color_calibrate_start          (CcColorCalibrate *calibrate,
+                                             GtkWindow        *parent,
+                                             GError          **error);
+gboolean  cc_color_calibrate_setup          (CcColorCalibrate *calibrate,
+                                             GError          **error);
+
+G_END_DECLS
+
+#endif /* __CC_COLOR_CALIBRATE_H */
+
diff --git a/panels/color/cc-color-cell-renderer-text.c b/panels/color/cc-color-cell-renderer-text.c
new file mode 100644
index 0000000..265eeff
--- /dev/null
+++ b/panels/color/cc-color-cell-renderer-text.c
@@ -0,0 +1,125 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 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 <gtk/gtk.h>
+
+#include "cc-color-cell-renderer-text.h"
+
+enum {
+  PROP_0,
+  PROP_IS_DIM_LABEL,
+  PROP_LAST
+};
+
+G_DEFINE_TYPE (CcColorCellRendererText, cc_color_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT)
+
+static gpointer parent_class = NULL;
+
+static void
+cc_color_cell_renderer_text_get_property (GObject *object, guint param_id,
+                                          GValue *value, GParamSpec *pspec)
+{
+  CcColorCellRendererText *renderer = CC_COLOR_CELL_RENDERER_TEXT (object);
+
+  switch (param_id)
+    {
+      case PROP_IS_DIM_LABEL:
+        g_value_set_boolean (value, renderer->is_dim_label);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+        break;
+    }
+}
+
+static void
+cc_color_cell_renderer_text_set_property (GObject *object, guint param_id,
+                                          const GValue *value, GParamSpec *pspec)
+{
+  CcColorCellRendererText *renderer = CC_COLOR_CELL_RENDERER_TEXT (object);
+
+  switch (param_id)
+    {
+      case PROP_IS_DIM_LABEL:
+        renderer->is_dim_label = g_value_get_boolean (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+        break;
+    }
+}
+
+static void
+cc_color_cell_renderer_render (GtkCellRenderer      *cell,
+                               cairo_t              *cr,
+                               GtkWidget            *widget,
+                               const GdkRectangle   *background_area,
+                               const GdkRectangle   *cell_area,
+                               GtkCellRendererState  flags)
+{
+  CcColorCellRendererText *renderer;
+  GtkStyleContext *context;
+
+  renderer = CC_COLOR_CELL_RENDERER_TEXT (cell);
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_save (context);
+  if (renderer->is_dim_label)
+    gtk_style_context_add_class (context, "dim-label");
+  else
+    gtk_style_context_remove_class (context, "dim-label");
+  GTK_CELL_RENDERER_CLASS (parent_class)->render (cell, cr, widget,
+                                                  background_area,
+                                                  cell_area, flags);
+  gtk_style_context_restore (context);
+}
+
+static void
+cc_color_cell_renderer_text_class_init (CcColorCellRendererTextClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkCellRendererClass *object_class_gcr = GTK_CELL_RENDERER_CLASS (class);
+  object_class_gcr->render = cc_color_cell_renderer_render;
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->get_property = cc_color_cell_renderer_text_get_property;
+  object_class->set_property = cc_color_cell_renderer_text_set_property;
+
+  g_object_class_install_property (object_class, PROP_IS_DIM_LABEL,
+                                   g_param_spec_boolean ("is-dim-label",
+                                                         NULL, NULL,
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));
+}
+
+static void
+cc_color_cell_renderer_text_init (CcColorCellRendererText *renderer)
+{
+  renderer->is_dim_label = FALSE;
+}
+
+GtkCellRenderer *
+cc_color_cell_renderer_text_new (void)
+{
+  return g_object_new (CC_COLOR_TYPE_CELL_RENDERER_TEXT, NULL);
+}
diff --git a/panels/color/cc-color-cell-renderer-text.h b/panels/color/cc-color-cell-renderer-text.h
new file mode 100644
index 0000000..b79d3ca
--- /dev/null
+++ b/panels/color/cc-color-cell-renderer-text.h
@@ -0,0 +1,56 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CC_COLOR_CELL_RENDERER_TEXT_H
+#define CC_COLOR_CELL_RENDERER_TEXT_H
+
+#include <gtk/gtk.h>
+
+#define CC_COLOR_TYPE_CELL_RENDERER_TEXT                (cc_color_cell_renderer_text_get_type())
+#define CC_COLOR_CELL_RENDERER_TEXT(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), CC_COLOR_TYPE_CELL_RENDERER_TEXT, CcColorCellRendererText))
+#define CC_COLOR_CELL_RENDERER_TEXT_CLASS(cls)          (G_TYPE_CHECK_CLASS_CAST((cls), CC_COLOR_TYPE_CELL_RENDERER_TEXT, CcColorCellRendererTextClass))
+#define CC_COLOR_IS_CELL_RENDERER_TEXT(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), CC_COLOR_TYPE_CELL_RENDERER_TEXT))
+#define CC_COLOR_IS_CELL_RENDERER_TEXT_CLASS(cls)       (G_TYPE_CHECK_CLASS_TYPE((cls), CC_COLOR_TYPE_CELL_RENDERER_TEXT))
+#define CC_COLOR_CELL_RENDERER_TEXT_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), CC_COLOR_TYPE_CELL_RENDERER_TEXT, CcColorCellRendererTextClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CcColorCellRendererText         CcColorCellRendererText;
+typedef struct _CcColorCellRendererTextClass    CcColorCellRendererTextClass;
+
+struct _CcColorCellRendererText
+{
+  GtkCellRendererText      parent;
+  gboolean                 is_dim_label;
+};
+
+struct _CcColorCellRendererTextClass
+{
+  GtkCellRendererTextClass parent_class;
+};
+
+GType            cc_color_cell_renderer_text_get_type           (void);
+GtkCellRenderer *cc_color_cell_renderer_text_new                (void);
+
+G_END_DECLS
+
+#endif /* CC_COLOR_CELL_RENDERER_TEXT_H */
+
diff --git a/panels/color/cc-color-panel.c b/panels/color/cc-color-panel.c
index 5178905..010103c 100644
--- a/panels/color/cc-color-panel.c
+++ b/panels/color/cc-color-panel.c
@@ -26,6 +26,8 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 
+#include "cc-color-calibrate.h"
+#include "cc-color-cell-renderer-text.h"
 #include "cc-color-panel.h"
 #include "cc-color-resources.h"
 
@@ -47,6 +49,7 @@ struct _CcColorPanelPrivate
   GtkBuilder    *builder;
   GtkTreeStore  *list_store_devices;
   GtkWidget     *main_window;
+  CcColorCalibrate *calibrate;
 };
 
 enum {
@@ -72,6 +75,29 @@ enum {
   GCM_PREFS_COMBO_COLUMN_NUM_COLUMNS
 };
 
+/* for the GtkListStores */
+enum {
+  COLUMN_CALIB_KIND_DESCRIPTION,
+  COLUMN_CALIB_KIND_CAP_VALUE,
+  COLUMN_CALIB_KIND_LAST
+};
+enum {
+  COLUMN_CALIB_QUALITY_DESCRIPTION,
+  COLUMN_CALIB_QUALITY_APPROX_TIME,
+  COLUMN_CALIB_QUALITY_VALUE,
+  COLUMN_CALIB_QUALITY_LAST
+};
+enum {
+  COLUMN_CALIB_SENSOR_OBJECT,
+  COLUMN_CALIB_SENSOR_DESCRIPTION,
+  COLUMN_CALIB_SENSOR_LAST
+};
+enum {
+  COLUMN_CALIB_TEMP_DESCRIPTION,
+  COLUMN_CALIB_TEMP_VALUE_K,
+  COLUMN_CALIB_TEMP_LAST
+};
+
 #define GCM_SETTINGS_SCHEMA                             "org.gnome.settings-daemon.plugins.color"
 #define GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD      "recalibrate-printer-threshold"
 #define GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD      "recalibrate-display-threshold"
@@ -258,6 +284,308 @@ gcm_prefs_file_chooser_get_icc_profile (CcColorPanel *prefs)
 }
 
 static void
+gcm_prefs_calib_cancel_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+  widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                               "assistant_calib"));
+  gtk_widget_hide (widget);
+}
+
+static gboolean
+gcm_prefs_calib_delayed_complete_cb (gpointer user_data)
+{
+  CcColorPanel *panel = CC_COLOR_PANEL (user_data);
+  GtkAssistant *assistant;
+  GtkWidget *widget;
+
+  assistant = GTK_ASSISTANT (gtk_builder_get_object (panel->priv->builder,
+                                                     "assistant_calib"));
+  widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
+                                               "box_calib_brightness"));
+  gtk_assistant_set_page_complete (assistant, widget, TRUE);
+  return FALSE;
+}
+
+static void
+gcm_prefs_calib_prepare_cb (GtkAssistant *assistant,
+                            GtkWidget    *page,
+                            CcColorPanel *panel)
+{
+  GtkWidget *widget;
+
+  /* give the user the indication they should actually manually set the
+   * desired brightness rather than clicking blindly by delaying the
+   * "Next" button deliberately for a second or so */
+  widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
+                                               "box_calib_brightness"));
+  if (widget == page)
+  {
+    g_timeout_add_seconds (1, gcm_prefs_calib_delayed_complete_cb, panel);
+    return;
+  }
+
+  /* disable the brightness page as we don't want to show a 'Finished'
+   * button if the user goes back at any point */
+  gtk_assistant_set_page_complete (assistant, widget, FALSE);
+}
+
+static void
+gcm_prefs_calib_apply_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+  gboolean ret;
+  GError *error = NULL;
+  GtkWindow *window = NULL;
+
+  /* setup the calibration object with items that can fail */
+  ret = cc_color_calibrate_setup (prefs->priv->calibrate,
+                                  &error);
+  if (!ret)
+    {
+      g_warning ("failed to setup calibrate: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* actually start the calibration */
+  window = GTK_WINDOW (gtk_builder_get_object (prefs->priv->builder,
+                                               "assistant_calib"));
+  ret = cc_color_calibrate_start (prefs->priv->calibrate,
+                                  window,
+                                  &error);
+  if (!ret)
+    {
+      g_warning ("failed to start calibrate: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+out:
+  if (window != NULL)
+    gtk_widget_hide (GTK_WIDGET (window));
+}
+
+static gboolean
+gcm_prefs_calib_delete_event_cb (GtkWidget *widget,
+                                 GdkEvent *event,
+                                 CcColorPanel *prefs)
+{
+  /* do not destroy the window */
+  gcm_prefs_calib_cancel_cb (widget, prefs);
+  return TRUE;
+}
+
+static void
+gcm_prefs_calib_temp_treeview_clicked_cb (GtkTreeSelection *selection,
+                                          CcColorPanel *prefs)
+{
+  CcColorPanelPrivate *priv = prefs->priv;
+  gboolean ret;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkWidget *widget;
+  guint target_whitepoint;
+  GtkAssistant *assistant;
+
+  /* check to see if anything is selected */
+  ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+  assistant = GTK_ASSISTANT (gtk_builder_get_object (prefs->priv->builder,
+                                                     "assistant_calib"));
+  widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                               "box_calib_temp"));
+  gtk_assistant_set_page_complete (assistant, widget, ret);
+  if (!ret)
+    return;
+
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_CALIB_TEMP_VALUE_K, &target_whitepoint,
+                      -1);
+  cc_color_calibrate_set_temperature (priv->calibrate, target_whitepoint);
+}
+
+static void
+gcm_prefs_calib_kind_treeview_clicked_cb (GtkTreeSelection *selection,
+                                          CcColorPanel *prefs)
+{
+  CcColorPanelPrivate *priv = prefs->priv;
+  CdSensorCap device_kind;
+  gboolean ret;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkWidget *widget;
+  GtkAssistant *assistant;
+
+  /* check to see if anything is selected */
+  ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+  assistant = GTK_ASSISTANT (gtk_builder_get_object (prefs->priv->builder,
+                                                     "assistant_calib"));
+  widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                               "box_calib_kind"));
+  gtk_assistant_set_page_complete (assistant, widget, ret);
+  if (!ret)
+    return;
+
+  /* save the values if we have a selection */
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_CALIB_KIND_CAP_VALUE, &device_kind,
+                      -1);
+  cc_color_calibrate_set_kind (priv->calibrate, device_kind);
+}
+
+static void
+gcm_prefs_calib_quality_treeview_clicked_cb (GtkTreeSelection *selection,
+                                             CcColorPanel *prefs)
+{
+  CcColorPanelPrivate *priv = prefs->priv;
+  CdProfileQuality quality;
+  gboolean ret;
+  GtkAssistant *assistant;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkWidget *widget;
+
+  /* check to see if anything is selected */
+  ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+  assistant = GTK_ASSISTANT (gtk_builder_get_object (prefs->priv->builder,
+                                                     "assistant_calib"));
+  widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                               "box_calib_quality"));
+  gtk_assistant_set_page_complete (assistant, widget, ret);
+  if (!ret)
+    return;
+
+  /* save the values if we have a selection */
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_CALIB_QUALITY_VALUE, &quality,
+                      -1);
+  cc_color_calibrate_set_quality (priv->calibrate, quality);
+}
+
+static void
+gcm_prefs_calib_sensor_treeview_clicked_cb (GtkTreeSelection *selection,
+                                             CcColorPanel *prefs)
+{
+  CcColorPanelPrivate *priv = prefs->priv;
+  gboolean ret;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkWidget *widget;
+  CdSensor *sensor;
+  GtkAssistant *assistant;
+
+  /* check to see if anything is selected */
+  ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+  assistant = GTK_ASSISTANT (gtk_builder_get_object (prefs->priv->builder,
+                                                     "assistant_calib"));
+  widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                               "box_calib_sensor"));
+  gtk_assistant_set_page_complete (assistant, widget, ret);
+  if (!ret)
+    return;
+
+  /* save the values if we have a selection */
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_CALIB_SENSOR_OBJECT, &sensor,
+                      -1);
+  cc_color_calibrate_set_sensor (priv->calibrate, sensor);
+  g_object_unref (sensor);
+}
+
+static void
+gcm_prefs_calibrate_display (CcColorPanel *prefs)
+{
+  CcColorPanelPrivate *priv = prefs->priv;
+  CdSensor *sensor_tmp;
+  const gchar *tmp;
+  GtkListStore *liststore;
+  GtkTreeIter iter;
+  GtkWidget *page;
+  GtkWidget *widget;
+  guint i;
+
+  /* set target device */
+  cc_color_calibrate_set_device (priv->calibrate, priv->current_device);
+
+  /* add sensors to list */
+  liststore = GTK_LIST_STORE (gtk_builder_get_object (priv->builder,
+                                                      "liststore_calib_sensor"));
+  gtk_list_store_clear (liststore);
+  page = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                             "box_calib_sensor"));
+  if (priv->sensors->len > 1)
+    {
+      for (i = 0; i < priv->sensors->len; i++)
+        {
+          sensor_tmp = g_ptr_array_index (priv->sensors, i);
+          gtk_list_store_append (liststore, &iter);
+          gtk_list_store_set (liststore, &iter,
+                              COLUMN_CALIB_SENSOR_OBJECT, sensor_tmp,
+                              COLUMN_CALIB_SENSOR_DESCRIPTION, cd_sensor_get_model (sensor_tmp),
+                              -1);
+        }
+      gtk_widget_set_visible (page, TRUE);
+    }
+  else
+    {
+      sensor_tmp = g_ptr_array_index (priv->sensors, 0);
+      cc_color_calibrate_set_sensor (priv->calibrate, sensor_tmp);
+      gtk_widget_set_visible (page, FALSE);
+    }
+
+  /* set default profile title */
+  tmp = cd_device_get_model (priv->current_device);
+  if (tmp == NULL)
+    tmp = cd_device_get_vendor (priv->current_device);
+  if (tmp == NULL)
+    tmp = _("Screen");
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "entry_calib_title"));
+  gtk_entry_set_text (GTK_ENTRY (widget), tmp);
+  cc_color_calibrate_set_title (priv->calibrate, tmp);
+
+  /* set the display whitepoint to D65 by default */
+  //FIXME?
+
+  /* show ui */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "assistant_calib"));
+  gtk_window_set_transient_for (GTK_WINDOW (widget),
+                                GTK_WINDOW (priv->main_window));
+  gtk_widget_show (widget);
+}
+
+static gboolean
+gcm_prefs_calib_treeview_realize_idle_cb (gpointer user_data)
+{
+  GtkWidget *widget = GTK_WIDGET (user_data);
+  GtkTreeSelection *selection;
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+  gtk_tree_selection_unselect_all (selection);
+  return FALSE;
+}
+
+static void
+gcm_prefs_calib_treeview_realize_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+  g_idle_add (gcm_prefs_calib_treeview_realize_idle_cb, widget);
+}
+
+static void
+gcm_prefs_title_entry_changed_cb (GtkWidget *widget,
+                                  GParamSpec *param_spec,
+                                  CcColorPanel *prefs)
+{
+  GtkAssistant *assistant;
+  GtkWidget *page;
+  const gchar *value;
+
+  assistant = GTK_ASSISTANT (gtk_builder_get_object (prefs->priv->builder,
+                                                     "assistant_calib"));
+  page = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
+                                             "box_calib_title"));
+  value = gtk_entry_get_text (GTK_ENTRY (widget));
+  gtk_assistant_set_page_complete (assistant, page, value[0] != '\0');
+}
+
+static void
 gcm_prefs_calibrate_cb (GtkWidget *widget, CcColorPanel *prefs)
 {
   gboolean ret;
@@ -266,6 +594,13 @@ gcm_prefs_calibrate_cb (GtkWidget *widget, CcColorPanel *prefs)
   GPtrArray *argv;
   CcColorPanelPrivate *priv = prefs->priv;
 
+  /* use the new-style calibration helper */
+  if (cd_device_get_kind (priv->current_device) == CD_DEVICE_KIND_DISPLAY)
+    {
+      gcm_prefs_calibrate_display (prefs);
+      return;
+    }
+
   /* get xid */
   xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (priv->main_window)));
 
@@ -2079,6 +2414,7 @@ cc_color_panel_dispose (GObject *object)
   g_clear_object (&priv->builder);
   g_clear_object (&priv->client);
   g_clear_object (&priv->current_device);
+  g_clear_object (&priv->calibrate);
   g_clear_pointer (&priv->sensors, g_ptr_array_unref);
 
   G_OBJECT_CLASS (cc_color_panel_parent_class)->dispose (object);
@@ -2111,8 +2447,10 @@ cc_color_panel_init (CcColorPanel *prefs)
 {
   CcColorPanelPrivate *priv;
   GError *error = NULL;
+  GtkCellRenderer *renderer;
   GtkStyleContext *context;
   GtkTreeSelection *selection;
+  GtkTreeViewColumn *column;
   GtkWidget *widget;
 
   priv = prefs->priv = COLOR_PANEL_PRIVATE (prefs);
@@ -2132,6 +2470,9 @@ cc_color_panel_init (CcColorPanel *prefs)
 
   priv->cancellable = g_cancellable_new ();
 
+  /* can do native display calibration using colord-session */
+  priv->calibrate = cc_color_calibrate_new ();
+
   /* setup defaults */
   priv->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
 
@@ -2254,6 +2595,124 @@ cc_color_panel_init (CcColorPanel *prefs)
   g_signal_connect (widget, "clicked",
                     G_CALLBACK (gcm_prefs_button_assign_import_cb), prefs);
 
+  /* setup the calibration helper */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "assistant_calib"));
+  g_signal_connect (widget, "delete-event",
+                    G_CALLBACK (gcm_prefs_calib_delete_event_cb),
+                    prefs);
+  g_signal_connect (widget, "apply",
+                    G_CALLBACK (gcm_prefs_calib_apply_cb),
+                    prefs);
+  g_signal_connect (widget, "cancel",
+                    G_CALLBACK (gcm_prefs_calib_cancel_cb),
+                    prefs);
+  g_signal_connect (widget, "prepare",
+                    G_CALLBACK (gcm_prefs_calib_prepare_cb),
+                    prefs);
+
+  /* setup the calibration helper ::TreeView */
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "treeview_calib_quality"));
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+  g_signal_connect (selection, "changed",
+                    G_CALLBACK (gcm_prefs_calib_quality_treeview_clicked_cb),
+                    prefs);
+  column = gtk_tree_view_column_new ();
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (renderer,
+                "xpad", 9,
+                "ypad", 9,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute (column, renderer,
+                                      "markup", COLUMN_CALIB_QUALITY_DESCRIPTION);
+  gtk_tree_view_column_set_expand (column, TRUE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
+                               GTK_TREE_VIEW_COLUMN (column));
+  column = gtk_tree_view_column_new ();
+  renderer = cc_color_cell_renderer_text_new ();
+  g_object_set (renderer,
+                "xpad", 9,
+                "ypad", 9,
+                "is-dim-label", TRUE,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute (column, renderer,
+                                      "markup", COLUMN_CALIB_QUALITY_APPROX_TIME);
+  gtk_tree_view_column_set_expand (column, FALSE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
+                               GTK_TREE_VIEW_COLUMN (column));
+  g_signal_connect (widget, "realize",
+                    G_CALLBACK (gcm_prefs_calib_treeview_realize_cb), prefs);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "treeview_calib_sensor"));
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+  g_signal_connect (selection, "changed",
+                    G_CALLBACK (gcm_prefs_calib_sensor_treeview_clicked_cb),
+                    prefs);
+  column = gtk_tree_view_column_new ();
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (renderer,
+                "xpad", 9,
+                "ypad", 9,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute (column, renderer,
+                                      "markup", COLUMN_CALIB_SENSOR_DESCRIPTION);
+  gtk_tree_view_column_set_expand (column, TRUE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
+                               GTK_TREE_VIEW_COLUMN (column));
+  g_signal_connect (widget, "realize",
+                    G_CALLBACK (gcm_prefs_calib_treeview_realize_cb), prefs);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "treeview_calib_kind"));
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+  g_signal_connect (selection, "changed",
+                    G_CALLBACK (gcm_prefs_calib_kind_treeview_clicked_cb),
+                    prefs);
+  column = gtk_tree_view_column_new ();
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (renderer,
+                "xpad", 9,
+                "ypad", 9,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute (column, renderer,
+                                      "markup", COLUMN_CALIB_KIND_DESCRIPTION);
+  gtk_tree_view_column_set_expand (column, TRUE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
+                               GTK_TREE_VIEW_COLUMN (column));
+  g_signal_connect (widget, "realize",
+                    G_CALLBACK (gcm_prefs_calib_treeview_realize_cb), prefs);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "treeview_calib_temp"));
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+  g_signal_connect (selection, "changed",
+                    G_CALLBACK (gcm_prefs_calib_temp_treeview_clicked_cb),
+                    prefs);
+  column = gtk_tree_view_column_new ();
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (renderer,
+                "xpad", 9,
+                "ypad", 9,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_add_attribute (column, renderer,
+                                      "markup", COLUMN_CALIB_TEMP_DESCRIPTION);
+  gtk_tree_view_column_set_expand (column, TRUE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
+                               GTK_TREE_VIEW_COLUMN (column));
+  g_signal_connect (widget, "realize",
+                    G_CALLBACK (gcm_prefs_calib_treeview_realize_cb), prefs);
+  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+                                               "entry_calib_title"));
+  g_signal_connect (widget, "notify::text",
+        G_CALLBACK (gcm_prefs_title_entry_changed_cb), prefs);
+
   /* use a device client array */
   priv->client = cd_client_new ();
   g_signal_connect_object (priv->client, "device-added",
diff --git a/panels/color/color-calibrate.ui b/panels/color/color-calibrate.ui
new file mode 100644
index 0000000..efab918
--- /dev/null
+++ b/panels/color/color-calibrate.ui
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="dialog_calibrate">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">Display Calibration</property>
+    <property name="hide_titlebar_when_maximized">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="deletable">False</property>
+    <property name="has_resize_grip">False</property>
+    <style>
+      <class name="osd"/>
+    </style>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox4">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button_cancel">
+                <property name="label" translatable="yes">Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_start">
+                <property name="label" translatable="yes" comments="This starts the calibration process">Start</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_resume">
+                <property name="label" translatable="yes" comments="This resumes the calibration process">Resume</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_done">
+                <property name="label" translatable="yes" comments="This button returns the user back to the color control panel">Done</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="vbox_status">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">15</property>
+            <child>
+              <object class="GtkImage" id="image_status">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="yalign">1</property>
+                <property name="pixel_size">200</property>
+                <property name="icon_name">address-book-new</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_status">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="yalign">0</property>
+                <property name="label">Do not disturb the calibration device while in progress</property>
+                <property name="justify">center</property>
+                <property name="wrap">True</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                  <attribute name="foreground" value="#ffffffffffff"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_status">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="padding">25</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">button_cancel</action-widget>
+      <action-widget response="0">button_start</action-widget>
+      <action-widget response="0">button_resume</action-widget>
+      <action-widget response="0">button_done</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkSizeGroup" id="sizegroup_sample"/>
+</interface>
diff --git a/panels/color/color.gresource.xml b/panels/color/color.gresource.xml
index 0dda0e5..4952786 100644
--- a/panels/color/color.gresource.xml
+++ b/panels/color/color.gresource.xml
@@ -3,4 +3,7 @@
   <gresource prefix="/org/gnome/control-center/color">
     <file preprocess="xml-stripblanks">color.ui</file>
   </gresource>
+  <gresource prefix="/org/gnome/control-center/color">
+    <file preprocess="xml-stripblanks">color-calibrate.ui</file>
+  </gresource>
 </gresources>
diff --git a/panels/color/color.ui b/panels/color/color.ui
index 5b51e70..0aaa847 100644
--- a/panels/color/color.ui
+++ b/panels/color/color.ui
@@ -1,46 +1,82 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkWindow" id="dialog_prefs">
+  <object class="GtkAssistant" id="assistant_calib">
     <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <property name="title" translatable="yes">Color</property>
-    <property name="window_position">center</property>
-    <property name="icon_name">preferences-system</property>
+    <property name="title" translatable="yes">Screen Calibration</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="transient_for">dialog_prefs</property>
     <child>
-      <object class="GtkBox" id="dialog-vbox1">
+      <object class="GtkBox" id="box_calib_quality">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="border_width">15</property>
         <property name="orientation">vertical</property>
-        <property name="spacing">12</property>
-        <property name="margin-left">6</property>
-        <property name="margin-right">6</property>
-        <property name="margin-top">6</property>
-        <property name="margin-bottom">6</property>
+        <property name="spacing">9</property>
         <child>
-          <object class="GtkHBox" id="hbox3">
+          <object class="GtkLabel" id="label_calib_quality_message">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="spacing">9</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Calibration will produce a profile that you can use to color manage your screen. The longer you spend on calibration, the better the quality of the color profile.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_calib_quality_message2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">You will not be able to use your computer while calibration takes place.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box_label_calib_quality_header">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_top">12</property>
             <child>
-              <object class="GtkLabel" id="label_intro">
+              <object class="GtkLabel" id="label_calib_quality_header">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="xalign">0</property>
-                <property name="label" translatable="yes">Each device needs an up to date color profile to be color managed.</property>
-                <property name="wrap">True</property>
+                <property name="xpad">6</property>
+                <property name="label" translatable="yes" comments="This is the approximate time it takes to calibrate the display.">Quality</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="label_padding">
+              <object class="GtkLabel" id="label_calib_quality_approx_time">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="xpad">6</property>
+                <property name="label" translatable="yes" comments="This is the approximate time it takes to calibrate the display.">Approximate Time</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
               </object>
               <packing>
                 <property name="expand">True</property>
@@ -48,171 +84,186 @@
                 <property name="position">1</property>
               </packing>
             </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow_calib_quality">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
             <child>
-              <object class="GtkLinkButton" id="linkbutton_help">
-                <property name="label" translatable="yes">Learn more</property>
+              <object class="GtkTreeView" id="treeview_calib_quality">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="has_tooltip">True</property>
-                <property name="tooltip_text" translatable="yes">Learn more about color management</property>
-                <property name="relief">none</property>
-                <property name="xalign">0.50999999046325684</property>
-                <property name="uri">help:gnome-help/color-whyimportant</property>
-                <accessibility>
-                  <relation type="labelled-by" target="label_intro"/>
-                </accessibility>
+                <property name="model">liststore_calib_quality</property>
+                <property name="headers_visible">False</property>
+                <property name="search_column">0</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection3"/>
+                </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
           </packing>
         </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Calibration Quality</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box_calib_kind">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">9</property>
         <child>
-          <object class="GtkVBox" id="vbox3">
+          <object class="GtkLabel" id="label_calib_kind_message">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Select the type of display that is connected.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow_calib_kind">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow_devices">
+              <object class="GtkTreeView" id="treeview_calib_kind">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkTreeView" id="treeview_devices">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <child internal-child="selection">
-                      <object class="GtkTreeSelection" id="treeview-selection"/>
-                    </child>
-                  </object>
+                <property name="model">liststore_calib_kind</property>
+                <property name="headers_visible">False</property>
+                <property name="search_column">0</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection5"/>
                 </child>
               </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
             </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Display Type</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box_calib_sensor">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">9</property>
+        <child>
+          <object class="GtkLabel" id="label_calib_sensor_message">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Select the sensor device you want to use for calibration.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow_calib_sensor">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
             <child>
-              <object class="GtkToolbar" id="toolbar_devices">
+              <object class="GtkTreeView" id="treeview_calib_sensor">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="show_arrow">False</property>
-                <property name="icon_size">1</property>
-                <child>
-                  <object class="GtkToolItem" id="left_button_group">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkBox" id="left_button_group_box">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <object class="GtkButton" id="toolbutton_device_default">
-                            <property name="label" translatable="yes">Set for all users</property>
-                            <property name="can_focus">False</property>
-                            <property name="receives_default">False</property>
-                            <property name="has_tooltip">True</property>
-                            <property name="tooltip_text" translatable="yes">Set this profile for all users on this computer</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                  </packing>
+                <property name="can_focus">True</property>
+                <property name="model">liststore_calib_sensor</property>
+                <property name="headers_visible">False</property>
+                <property name="search_column">1</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection4"/>
                 </child>
-                <child>
-                  <object class="GtkToolItem" id="right_button_group">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkBox" id="right_button_group_box">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <object class="GtkButton" id="toolbutton_profile_add">
-                            <property name="label" translatable="yes">Add profile</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="toolbutton_device_calibrate">
-                            <property name="label" translatable="yes">Calibrateâ</property>
-                            <property name="can_focus">False</property>
-                            <property name="receives_default">False</property>
-                            <property name="has_tooltip">True</property>
-                            <property name="tooltip_text" translatable="yes">Calibrate the device</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="toolbutton_profile_remove">
-                            <property name="label" translatable="yes">Remove profile</property>
-                            <property name="can_focus">False</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="toolbutton_profile_view">
-                            <property name="label" translatable="yes">View details</property>
-                            <property name="can_focus">False</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                  </packing>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Calibration Device</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box_calib_temp">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">9</property>
+        <child>
+          <object class="GtkLabel" id="label_calib_temp_message">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Select a display target white point. Most displays should be calibrated to a D65 illuminant.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow_calib_temp">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="treeview_calib_temp">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">liststore_calib_temp</property>
+                <property name="headers_visible">False</property>
+                <property name="search_column">0</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection6"/>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
           <packing>
@@ -222,6 +273,115 @@
           </packing>
         </child>
       </object>
+      <packing>
+        <property name="title" translatable="yes">Profile Whitepoint</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box_calib_brightness">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">9</property>
+        <child>
+          <object class="GtkLabel" id="label_calib_brightness_message1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Please set the display to a brightness that is typical for you. Color management will be most accurate at this brightness level.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_calib_brightness_message2">
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Alternatively, you can use the brightness level used with one of the other profiles for this device.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Display Brightness</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box_calib_title">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">9</property>
+        <child>
+          <object class="GtkLabel" id="label_calib_title_message">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">You can use a color profile on different computers, or even create profiles for different lighting conditions.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_calib_title_header">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="xpad">6</property>
+            <property name="label" translatable="yes">Profile Name:</property>
+            <property name="wrap">True</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="entry_calib_title">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">â</property>
+            <property name="truncate_multiline">True</property>
+            <property name="invisible_char_set">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+        <property name="title" translatable="yes">Profile Name</property>
+      </packing>
+    </child>
+    <child internal-child="action_area">
+      <object class="GtkBox" id="assistant-action_area1">
+        <property name="can_focus">False</property>
+        <property name="halign">end</property>
+        <property name="spacing">6</property>
+      </object>
     </child>
   </object>
   <object class="GtkDialog" id="dialog_assign">
@@ -611,6 +771,225 @@
       <action-widget response="0">button_virtual_add</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkWindow" id="dialog_prefs">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">Color</property>
+    <property name="window_position">center</property>
+    <property name="icon_name">preferences-system</property>
+    <child>
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">15</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkHBox" id="hbox3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">9</property>
+            <child>
+              <object class="GtkLabel" id="label_intro">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Each device needs an up to date color profile to be color managed.</property>
+                <property name="wrap">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_padding">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLinkButton" id="linkbutton_help">
+                <property name="label" translatable="yes">Learn more</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="has_tooltip">True</property>
+                <property name="tooltip_text" translatable="yes">Learn more about color management</property>
+                <property name="relief">none</property>
+                <property name="xalign">0.50999999046325684</property>
+                <property name="uri">help:gnome-help/color-whyimportant</property>
+                <accessibility>
+                  <relation type="labelled-by" target="label_intro"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="vbox3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow_devices">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview_devices">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection" id="treeview-selection"/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolbar" id="toolbar_devices">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="show_arrow">False</property>
+                <property name="icon_size">1</property>
+                <child>
+                  <object class="GtkToolItem" id="left_button_group">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="left_button_group_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="toolbutton_device_default">
+                            <property name="label" translatable="yes">Set for all users</property>
+                            <property name="can_focus">False</property>
+                            <property name="receives_default">False</property>
+                            <property name="has_tooltip">True</property>
+                            <property name="tooltip_text" translatable="yes">Set this profile for all users on this computer</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolItem" id="right_button_group">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="right_button_group_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="toolbutton_profile_add">
+                            <property name="label" translatable="yes">Add profile</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="toolbutton_device_calibrate">
+                            <property name="label" translatable="yes">Calibrateâ</property>
+                            <property name="can_focus">False</property>
+                            <property name="receives_default">False</property>
+                            <property name="has_tooltip">True</property>
+                            <property name="tooltip_text" translatable="yes">Calibrate the device</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="toolbutton_profile_remove">
+                            <property name="label" translatable="yes">Remove profile</property>
+                            <property name="can_focus">False</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="toolbutton_profile_view">
+                            <property name="label" translatable="yes">View details</property>
+                            <property name="can_focus">False</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
   <object class="GtkListStore" id="liststore_assign">
     <columns>
       <!-- column-name title -->
@@ -623,6 +1002,97 @@
       <column type="gchararray"/>
     </columns>
   </object>
+  <object class="GtkListStore" id="liststore_calib_kind">
+    <columns>
+      <!-- column-name display_kind -->
+      <column type="gchararray"/>
+      <!-- column-name kind -->
+      <column type="guint"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">LCD</col>
+        <col id="1" translatable="yes">1</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">LED</col>
+        <col id="1" translatable="yes">8</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">CRT</col>
+        <col id="1" translatable="yes">2</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Projector</col>
+        <col id="1" translatable="yes">5</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="liststore_calib_quality">
+    <columns>
+      <!-- column-name quality -->
+      <column type="gchararray"/>
+      <!-- column-name approx_time -->
+      <column type="gchararray"/>
+      <!-- column-name value -->
+      <column type="guint"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">High</col>
+        <col id="1" translatable="yes">40 minutes</col>
+        <col id="2" translatable="yes">2</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Medium</col>
+        <col id="1" translatable="yes">30 minutes</col>
+        <col id="2" translatable="yes">1</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Low</col>
+        <col id="1" translatable="yes">15 minutes</col>
+        <col id="2" translatable="yes">0</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="liststore_calib_sensor">
+    <columns>
+      <!-- column-name sensor -->
+      <column type="GObject"/>
+      <!-- column-name sensor_desc -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="liststore_calib_temp">
+    <columns>
+      <!-- column-name temp_desc -->
+      <column type="gchararray"/>
+      <!-- column-name temp_value -->
+      <column type="guint"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Native to display</col>
+        <col id="1">0</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">D50 (Printing and publishing)</col>
+        <col id="1">5000</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">D55</col>
+        <col id="1">5500</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">D65 (Photography and graphics)</col>
+        <col id="1">6500</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">D75</col>
+        <col id="1">7500</col>
+      </row>
+    </data>
+  </object>
   <object class="GtkSizeGroup" id="sizegroup_assign">
     <widgets>
       <widget name="label_assign_warning"/>



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