[gnome-color-manager] Do all the calibration UI in one place to avoid getting lots of GtkDialogs



commit 3d580588acd48f326d75414e44987f27fb203208
Author: Richard Hughes <richard hughsie com>
Date:   Thu Feb 18 22:22:49 2010 +0000

    Do all the calibration UI in one place to avoid getting lots of GtkDialogs
    
    This also allows us to fix up the UI in the future by adding more descriptions and images.

 data/gcm-calibrate.ui      |  610 ++++++++++++++++++++++++------------
 src/Makefile.am            |    2 +
 src/gcm-calibrate-argyll.c |  338 ++++++--------------
 src/gcm-calibrate-dialog.c |  752 ++++++++++++++++++++++++++++++++++++++++++++
 src/gcm-calibrate-dialog.h |   89 ++++++
 src/gcm-calibrate.c        |  366 +++-------------------
 6 files changed, 1396 insertions(+), 761 deletions(-)
---
diff --git a/data/gcm-calibrate.ui b/data/gcm-calibrate.ui
index 64c4f9d..d4e0c73 100644
--- a/data/gcm-calibrate.ui
+++ b/data/gcm-calibrate.ui
@@ -4,10 +4,13 @@
   <!-- interface-naming-policy project-wide -->
   <object class="GtkDialog" id="dialog_calibrate">
     <property name="border_width">5</property>
-    <property name="title" translatable="yes" comments="window title">Manual calibration wizard</property>
+    <property name="title" translatable="yes" comments="window title">Device Calibration</property>
+    <property name="resizable">False</property>
     <property name="modal">True</property>
     <property name="window_position">center</property>
-    <property name="type_hint">normal</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="icon_name">gnome-color-manager</property>
+    <property name="type_hint">dialog</property>
     <property name="has_separator">False</property>
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox1">
@@ -65,10 +68,10 @@
                     <property name="orientation">vertical</property>
                     <property name="spacing">9</property>
                     <child>
-                      <object class="GtkHBox" id="hbox_text1">
+                      <object class="GtkHBox" id="hbox_message">
                         <property name="visible">True</property>
                         <child>
-                          <object class="GtkLabel" id="label_text1">
+                          <object class="GtkLabel" id="label_message">
                             <property name="visible">True</property>
                             <property name="label">This is a first line of text.</property>
                             <property name="wrap">True</property>
@@ -87,248 +90,485 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkHBox" id="hbox_text2">
+                      <object class="GtkNotebook" id="notebook1">
                         <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="show_border">False</property>
                         <child>
-                          <object class="GtkLabel" id="label_text2">
-                            <property name="visible">True</property>
-                            <property name="label">This is a second line of text.</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>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAspectFrame" id="aspectframe_gamma">
-                        <property name="visible">True</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAspectFrame" id="aspectframe_trc">
-                        <property name="visible">True</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAlignment" id="alignment9">
-                        <property name="visible">True</property>
-                        <property name="left_padding">18</property>
-                        <property name="right_padding">18</property>
-                        <child>
-                          <object class="GtkTable" id="table_adjust">
+                          <object class="GtkVBox" id="vbox_display_type">
                             <property name="visible">True</property>
-                            <property name="n_rows">4</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">6</property>
-                            <property name="row_spacing">6</property>
+                            <property name="border_width">9</property>
+                            <property name="orientation">vertical</property>
                             <child>
-                              <object class="GtkHScale" id="hscale_brightness">
+                              <object class="GtkHBox" id="hbox1">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="restrict_to_fill_level">False</property>
-                                <property name="fill_level">0.5</property>
-                                <property name="draw_value">False</property>
+                                <property name="spacing">6</property>
+                                <property name="homogeneous">True</property>
+                                <child>
+                                  <object class="GtkButton" id="button_lcd">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <child>
+                                      <object class="GtkVBox" id="vbox7">
+                                        <property name="visible">True</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="spacing">6</property>
+                                        <child>
+                                          <object class="GtkImage" id="image1">
+                                            <property name="visible">True</property>
+                                            <property name="pixel_size">150</property>
+                                            <property name="icon_name">lcd</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel" id="label11">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">LCD</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkButton" id="button_crt">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <child>
+                                      <object class="GtkVBox" id="vbox8">
+                                        <property name="visible">True</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="spacing">6</property>
+                                        <child>
+                                          <object class="GtkImage" id="image2">
+                                            <property name="visible">True</property>
+                                            <property name="pixel_size">150</property>
+                                            <property name="icon_name">crt</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel" id="label12">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">CRT</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkButton" id="button_projector">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <child>
+                                      <object class="GtkVBox" id="vbox9">
+                                        <property name="visible">True</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="spacing">6</property>
+                                        <child>
+                                          <object class="GtkImage" id="image3">
+                                            <property name="visible">True</property>
+                                            <property name="pixel_size">150</property>
+                                            <property name="icon_name">projector</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel" id="label13">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">Projector</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHScale" id="hscale_red">
+                              <object class="GtkLabel" id="label8">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="restrict_to_fill_level">False</property>
-                                <property name="fill_level">0.5</property>
-                                <property name="draw_value">False</property>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
+                          </object>
+                        </child>
+                        <child type="tab">
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="label">crt-lcd-projector</property>
+                          </object>
+                          <packing>
+                            <property name="tab_fill">False</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkVBox" id="vbox_target_type">
+                            <property name="visible">True</property>
+                            <property name="border_width">9</property>
+                            <property name="orientation">vertical</property>
+                            <property name="spacing">6</property>
                             <child>
-                              <object class="GtkHScale" id="hscale_green">
+                              <object class="GtkImage" id="image_target">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="restrict_to_fill_level">False</property>
-                                <property name="fill_level">0.5</property>
-                                <property name="draw_value">False</property>
+                                <property name="stock">gtk-missing-image</property>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHScale" id="hscale_blue">
+                              <object class="GtkComboBox" id="combobox_target">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="restrict_to_fill_level">False</property>
-                                <property name="fill_level">0.5</property>
-                                <property name="draw_value">False</property>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">3</property>
-                                <property name="bottom_attach">4</property>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox6">
+                              <object class="GtkLabel" id="label14">
                                 <property name="visible">True</property>
-                                <child>
-                                  <object class="GtkLabel" id="label4">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Brightness:</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
                               </object>
                               <packing>
-                                <property name="x_options">GTK_FILL</property>
+                                <property name="position">2</property>
                               </packing>
                             </child>
+                          </object>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child type="tab">
+                          <object class="GtkLabel" id="label9">
+                            <property name="visible">True</property>
+                            <property name="label">target-type</property>
+                          </object>
+                          <packing>
+                            <property name="position">1</property>
+                            <property name="tab_fill">False</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkVBox" id="vbox_manual">
+                            <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
                             <child>
-                              <object class="GtkHBox" id="hbox7">
+                              <object class="GtkAspectFrame" id="aspectframe_gamma">
                                 <property name="visible">True</property>
+                                <property name="label_xalign">0</property>
+                                <property name="shadow_type">none</property>
                                 <child>
-                                  <object class="GtkLabel" id="label5">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Red:</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
+                                  <placeholder/>
                                 </child>
                               </object>
                               <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">GTK_FILL</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox8">
+                              <object class="GtkAspectFrame" id="aspectframe_trc">
                                 <property name="visible">True</property>
+                                <property name="label_xalign">0</property>
+                                <property name="shadow_type">none</property>
                                 <child>
-                                  <object class="GtkLabel" id="label6">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Green:</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
+                                  <placeholder/>
                                 </child>
                               </object>
                               <packing>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="x_options">GTK_FILL</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox9">
+                              <object class="GtkAlignment" id="alignment9">
                                 <property name="visible">True</property>
+                                <property name="left_padding">18</property>
+                                <property name="right_padding">18</property>
                                 <child>
-                                  <object class="GtkLabel" id="label7">
+                                  <object class="GtkTable" id="table_adjust">
                                     <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Blue:</property>
+                                    <property name="n_rows">4</property>
+                                    <property name="n_columns">2</property>
+                                    <property name="column_spacing">6</property>
+                                    <property name="row_spacing">6</property>
+                                    <child>
+                                      <object class="GtkHScale" id="hscale_brightness">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="restrict_to_fill_level">False</property>
+                                        <property name="fill_level">0.5</property>
+                                        <property name="draw_value">False</property>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHScale" id="hscale_red">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="restrict_to_fill_level">False</property>
+                                        <property name="fill_level">0.5</property>
+                                        <property name="draw_value">False</property>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHScale" id="hscale_green">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="restrict_to_fill_level">False</property>
+                                        <property name="fill_level">0.5</property>
+                                        <property name="draw_value">False</property>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">2</property>
+                                        <property name="bottom_attach">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHScale" id="hscale_blue">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="restrict_to_fill_level">False</property>
+                                        <property name="fill_level">0.5</property>
+                                        <property name="draw_value">False</property>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">3</property>
+                                        <property name="bottom_attach">4</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHBox" id="hbox6">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <object class="GtkLabel" id="label4">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">Brightness:</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="x_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHBox" id="hbox7">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <object class="GtkLabel" id="label5">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">Red:</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
+                                        <property name="x_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHBox" id="hbox8">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <object class="GtkLabel" id="label6">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">Green:</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="top_attach">2</property>
+                                        <property name="bottom_attach">3</property>
+                                        <property name="x_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkHBox" id="hbox9">
+                                        <property name="visible">True</property>
+                                        <child>
+                                          <object class="GtkLabel" id="label7">
+                                            <property name="visible">True</property>
+                                            <property name="label" translatable="yes">Blue:</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                      <packing>
+                                        <property name="top_attach">3</property>
+                                        <property name="bottom_attach">4</property>
+                                        <property name="x_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
                                   </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
                                 </child>
                               </object>
                               <packing>
-                                <property name="top_attach">3</property>
-                                <property name="bottom_attach">4</property>
-                                <property name="x_options">GTK_FILL</property>
+                                <property name="expand">False</property>
+                                <property name="padding">18</property>
+                                <property name="position">2</property>
                               </packing>
                             </child>
                           </object>
+                          <packing>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child type="tab">
+                          <object class="GtkLabel" id="label2">
+                            <property name="visible">True</property>
+                            <property name="label">manual</property>
+                          </object>
+                          <packing>
+                            <property name="position">2</property>
+                            <property name="tab_fill">False</property>
+                          </packing>
                         </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="padding">18</property>
-                        <property name="position">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkExpander" id="expander_details">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
                         <child>
-                          <object class="GtkAlignment" id="alignment10">
+                          <object class="GtkVBox" id="vbox_generic">
                             <property name="visible">True</property>
-                            <property name="left_padding">26</property>
+                            <property name="orientation">vertical</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <object class="GtkImage" id="image_generic">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-missing-image</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
                             <child>
-                              <object class="GtkHBox" id="hbox12">
+                              <object class="GtkExpander" id="expander_details">
                                 <property name="visible">True</property>
+                                <property name="can_focus">True</property>
                                 <child>
-                                  <object class="GtkLabel" id="label_details">
+                                  <object class="GtkAlignment" id="alignment10">
                                     <property name="visible">True</property>
-                                    <property name="label">Here be dragons...</property>
+                                    <property name="left_padding">26</property>
+                                    <child>
+                                      <object class="GtkVBox" id="vbox_details">
+                                        <property name="visible">True</property>
+                                        <property name="orientation">vertical</property>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                                <child type="label">
+                                  <object class="GtkLabel" id="label10">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">Details</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                    </attributes>
                                   </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
                                 </child>
                               </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label15">
+                                <property name="visible">True</property>
+                              </object>
+                              <packing>
+                                <property name="position">2</property>
+                              </packing>
                             </child>
                           </object>
+                          <packing>
+                            <property name="position">3</property>
+                          </packing>
                         </child>
-                        <child type="label">
-                          <object class="GtkLabel" id="label10">
+                        <child type="tab">
+                          <object class="GtkLabel" id="label3">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">Details</property>
-                            <attributes>
-                              <attribute name="weight" value="bold"/>
-                            </attributes>
+                            <property name="label">progress-generic</property>
                           </object>
+                          <packing>
+                            <property name="position">3</property>
+                            <property name="tab_fill">False</property>
+                          </packing>
                         </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
-                        <property name="position">5</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                   </object>
@@ -377,8 +617,8 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="button_prev">
-                <property name="label">gtk-media-previous</property>
+              <object class="GtkButton" id="button_ok">
+                <property name="label">gtk-ok</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -390,34 +630,6 @@
                 <property name="position">2</property>
               </packing>
             </child>
-            <child>
-              <object class="GtkButton" id="button_next">
-                <property name="label">gtk-media-next</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button_apply">
-                <property name="label">gtk-apply</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">4</property>
-              </packing>
-            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -430,9 +642,7 @@
     <action-widgets>
       <action-widget response="0">button_help</action-widget>
       <action-widget response="0">button_cancel</action-widget>
-      <action-widget response="0">button_prev</action-widget>
-      <action-widget response="0">button_next</action-widget>
-      <action-widget response="0">button_apply</action-widget>
+      <action-widget response="0">button_ok</action-widget>
     </action-widgets>
   </object>
 </interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 7aa9cf0..102004f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -219,6 +219,8 @@ gcm_prefs_SOURCES =					\
 	gcm-calibrate-argyll.h				\
 	gcm-calibrate-manual.c				\
 	gcm-calibrate-manual.h				\
+	gcm-calibrate-dialog.c				\
+	gcm-calibrate-dialog.h				\
 	gcm-brightness.c				\
 	gcm-brightness.h				\
 	gcm-prefs.c
diff --git a/src/gcm-calibrate-argyll.c b/src/gcm-calibrate-argyll.c
index b3c2b68..9ebfb75 100644
--- a/src/gcm-calibrate-argyll.c
+++ b/src/gcm-calibrate-argyll.c
@@ -42,6 +42,7 @@
 #include "gcm-colorimeter.h"
 #include "gcm-utils.h"
 #include "gcm-screen.h"
+#include "gcm-calibrate-dialog.h"
 
 #include "egg-debug.h"
 
@@ -64,13 +65,6 @@ typedef enum {
 	GCM_CALIBRATE_ARGYLL_STATE_LAST
 } GcmCalibrateArgyllState;
 
-typedef struct {
-	gchar		*title;
-	gchar		*message;
-	gchar		*filename;
-	gboolean	 show_okay;
-} GcmCalibrateArgyllDialog;
-
 /**
  * GcmCalibrateArgyllPrivate:
  *
@@ -83,13 +77,12 @@ struct _GcmCalibrateArgyllPrivate
 	GcmCalibrateArgyllPrecision	 precision;
 	GMainLoop			*loop;
 	GtkWidget			*terminal;
-	GtkBuilder			*builder;
+	GcmCalibrateDialog		*calibrate_dialog;
 	pid_t				 child_pid;
 	GtkResponseType			 response;
 	GcmScreen			*screen;
 	glong				 vte_previous_row;
 	glong				 vte_previous_col;
-	GPtrArray			*cached_dialogs;
 	gboolean			 already_on_window;
 	GcmCalibrateArgyllState		 state;
 };
@@ -264,115 +257,6 @@ gcm_calibrate_argyll_get_display_type (GcmCalibrateArgyll *calibrate_argyll)
 }
 
 /**
- * gcm_calibrate_argyll_dialog_free:
- **/
-static void
-gcm_calibrate_argyll_dialog_free (GcmCalibrateArgyllDialog *dialog)
-{
-	g_free (dialog->title);
-	g_free (dialog->message);
-	g_free (dialog->filename);
-	g_free (dialog);
-}
-
-/**
- * gcm_calibrate_argyll_set_dialog:
- **/
-static void
-gcm_calibrate_argyll_set_dialog (GcmCalibrateArgyll *calibrate_argyll,
-				 const gchar *title,
-				 const gchar *message,
-				 const gchar *image_filename,
-				 gboolean show_okay)
-{
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
-	GtkWidget *widget;
-	gchar *text;
-	gchar *filename = NULL;
-	GdkPixbuf *pixbuf;
-	GError *error = NULL;
-	GcmCalibrateArgyllDialog *dialog;
-
-	/* save in case we need to reuse */
-	dialog = g_new0 (GcmCalibrateArgyllDialog, 1);
-	dialog->title = g_strdup (title);
-	dialog->message = g_strdup (message);
-	dialog->filename = g_strdup (image_filename);
-	dialog->show_okay = show_okay;
-	g_ptr_array_add (priv->cached_dialogs, dialog);
-
-	/* set the text */
-	text = g_strdup_printf ("<big><b>%s</b></big>", title);
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_title"));
-	gtk_label_set_markup (GTK_LABEL(widget), text);
-	g_free (text);
-
-	/* set the image */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "image_figure"));
-	if (image_filename != NULL) {
-		filename = g_build_filename (GCM_DATA, "icons", image_filename, NULL);
-		pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 200, 400, &error);
-		if (pixbuf == NULL) {
-			egg_warning ("failed to load image: %s", error->message);
-			g_error_free (error);
-			gtk_widget_hide (widget);
-		} else {
-			gtk_image_set_from_pixbuf (GTK_IMAGE (widget), pixbuf);
-			gtk_widget_show (widget);
-		}
-		g_free (filename);
-	} else {
-		gtk_widget_hide (widget);
-	}
-
-	/* set the text */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_message"));
-	gtk_label_set_markup (GTK_LABEL(widget), message);
-
-	/* show the okay button */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_ok"));
-	gtk_widget_set_visible (widget, show_okay);
-}
-
-/**
- * gcm_calibrate_argyll_pop_dialog:
- **/
-static void
-gcm_calibrate_argyll_pop_dialog (GcmCalibrateArgyll *calibrate_argyll)
-{
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
-	GtkWidget *widget;
-	gchar *text;
-	guint len;
-	GcmCalibrateArgyllDialog *dialog;
-
-	/* save in case we need to reuse */
-	len = priv->cached_dialogs->len;
-	if (len < 2) {
-		egg_warning ("cannot pop dialog as nothing to recover");
-		return;
-	}
-	dialog = g_ptr_array_index (priv->cached_dialogs, len-2);
-
-	/* set the text */
-	text = g_strdup_printf ("<big><b>%s</b></big>", dialog->title);
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_title"));
-	gtk_label_set_markup (GTK_LABEL(widget), text);
-	g_free (text);
-
-	/* set the text */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_message"));
-	gtk_label_set_markup (GTK_LABEL(widget), dialog->message);
-
-	/* show the okay button */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_ok"));
-	gtk_widget_set_visible (widget, dialog->show_okay);
-
-	/* remove from the stack */
-	g_ptr_array_remove_index (priv->cached_dialogs, len-1);
-}
-
-/**
  * gcm_calibrate_argyll_debug_argv:
  **/
 static void
@@ -432,10 +316,8 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	gchar type;
 	gchar *command = NULL;
 	gchar **argv = NULL;
-	GtkWidget *widget;
 	GnomeRROutput *output;
 	GPtrArray *array = NULL;
-	gint x, y;
 	gchar *basename = NULL;
 	gchar *output_name = NULL;
 	const gchar *title;
@@ -471,12 +353,6 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	/* get l-cd or c-rt */
 	type = gcm_calibrate_argyll_get_display_type (calibrate_argyll);
 
-	/* move the dialog out of the way, so the grey square doesn't cover it */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
-	gtk_window_get_position (GTK_WINDOW(widget), &x, &y);
-	egg_debug ("currently at %i,%i, moving left", x, y);
-	gtk_window_move (GTK_WINDOW(widget), 10, y);
-
 	/* TRANSLATORS: title, default paramters needed to calibrate_argyll */
 	title = _("Getting default parameters");
 
@@ -484,7 +360,9 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	message = _("This pre-calibrates the screen by sending colored and gray patches to your screen and measuring them with the hardware device.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -562,7 +440,9 @@ gcm_calibrate_argyll_display_generate_patches (GcmCalibrateArgyll *calibrate_arg
 	message = _("Generating the patches that will be measured with the hardware device.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -640,7 +520,9 @@ gcm_calibrate_argyll_display_draw_and_measure (GcmCalibrateArgyll *calibrate_arg
 	message = _("Drawing the generated patches to the screen, which will then be measured by the hardware device.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -739,7 +621,9 @@ gcm_calibrate_argyll_display_generate_profile (GcmCalibrateArgyll *calibrate_arg
 	message = _("Generating the ICC color profile that can be used with this screen.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -815,6 +699,7 @@ gcm_calibrate_argyll_reference_kind_to_filename (GcmCalibrateReferenceKind kind)
 		return "LaserSoftDCPro.cht";
 	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201)
 		return "QPcard_201.cht";
+	g_assert_not_reached ();
 	return NULL;
 }
 
@@ -843,6 +728,7 @@ gcm_calibrate_argyll_device_copy (GcmCalibrateArgyll *calibrate_argyll, GError *
 	const gchar *message;
 	const gchar *filename_tmp;
 	GcmCalibrateReferenceKind reference_kind;
+	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
 	/* get shared data */
 	g_object_get (calibrate_argyll,
@@ -858,7 +744,9 @@ gcm_calibrate_argyll_device_copy (GcmCalibrateArgyll *calibrate_argyll, GError *
 	message = _("Copying source image, chart data and CIE reference values.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 
 	/* build filenames */
 	filename = g_strdup_printf ("%s.tif", basename);
@@ -933,7 +821,9 @@ gcm_calibrate_argyll_device_measure (GcmCalibrateArgyll *calibrate_argyll, GErro
 	message = _("Detecting the reference patches and measuring them.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 	/* get correct name of the command */
 	command = gcm_calibrate_argyll_get_tool_filename ("scanin", error);
@@ -1043,7 +933,9 @@ gcm_calibrate_argyll_device_generate_profile (GcmCalibrateArgyll *calibrate_argy
 	message = _("Generating the ICC color profile that can be used with this device.");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 	/* argument array */
 	array = g_ptr_array_new_with_free_func (g_free);
@@ -1175,19 +1067,12 @@ out:
 static gboolean
 gcm_calibrate_argyll_display (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
 {
-	GtkWidget *widget;
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 	gboolean ret;
 	const gchar *title;
 	const gchar *message;
 
-	/* show main UI */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
-	gtk_widget_show_all (widget);
-	if (window != NULL)
-		gdk_window_set_transient_for (gtk_widget_get_window (widget), gtk_widget_get_window (GTK_WIDGET(window)));
-
 	/* TRANSLATORS: title, hardware refers to a calibration device */
 	title = _("Set up display");
 
@@ -1195,7 +1080,9 @@ gcm_calibrate_argyll_display (GcmCalibrate *calibrate, GtkWindow *window, GError
 	message = _("Setting up display device for use...");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 
 	/* step 1 */
 	ret = gcm_calibrate_argyll_display_neutralise (calibrate_argyll, error);
@@ -1231,19 +1118,12 @@ out:
 static gboolean
 gcm_calibrate_argyll_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
 {
-	GtkWidget *widget;
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL(calibrate);
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 	gboolean ret;
 	const gchar *title;
 	const gchar *message;
 
-	/* show main UI */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
-	gtk_widget_show_all (widget);
-	if (window != NULL)
-		gdk_window_set_transient_for (gtk_widget_get_window (widget), gtk_widget_get_window (GTK_WIDGET(window)));
-
 	/* TRANSLATORS: title, hardware refers to a calibration device */
 	title = _("Set up device");
 
@@ -1251,7 +1131,9 @@ gcm_calibrate_argyll_device (GcmCalibrate *calibrate, GtkWindow *window, GError
 	message = _("Setting up device for use...");
 
 	/* push new messages into the UI */
-	gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, FALSE);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 
 	/* step 1 */
 	ret = gcm_calibrate_argyll_device_copy (calibrate_argyll, error);
@@ -1352,7 +1234,10 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 		egg_debug ("blocking waiting for user input: %s", title);
 
 		/* push new messages into the UI */
-		gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, filename, TRUE);
+		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
+		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, filename);
+		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 
 		/* set state */
 		priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN,
@@ -1384,7 +1269,10 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 		}
 
 		/* push new messages into the UI */
-		gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, filename, TRUE);
+		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
+		gcm_calibrate_dialog_set_image_filename (priv->calibrate_dialog, filename);
+		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 
 		/* set state */
 		priv->state = GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN;
@@ -1423,7 +1311,9 @@ gcm_calibrate_argyll_process_output_cmd (GcmCalibrateArgyll *calibrate_argyll, c
 		}
 
 		/* push new messages into the UI */
-		gcm_calibrate_argyll_set_dialog (calibrate_argyll, title, message, NULL, TRUE);
+		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, title, message);
+		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
+		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, TRUE);
 		egg_debug ("VTE: error: %s", found+8);
 
 		/* set state */
@@ -1489,78 +1379,70 @@ gcm_calibrate_argyll_cursor_moved_cb (VteTerminal *terminal, GcmCalibrateArgyll
 }
 
 /**
- * gcm_calibrate_argyll_get_property:
- **/
-static void
-gcm_calibrate_argyll_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	switch (prop_id) {
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-/**
- * gcm_calibrate_argyll_cancel_cb:
+ * gcm_calibrate_argyll_response_cb:
  **/
 static void
-gcm_calibrate_argyll_cancel_cb (GtkWidget *widget, GcmCalibrateArgyll *calibrate_argyll)
+gcm_calibrate_argyll_response_cb (GtkWidget *widget, GtkResponseType response, GcmCalibrateArgyll *calibrate_argyll)
 {
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
-	priv->response = GTK_RESPONSE_CANCEL;
+	/* save our state */
+	priv->response = response;
 
-	/* send input if waiting */
-	if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
-		vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), "Q", 1);
-		priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
-	}
+	/* ok */
+	if (response == GTK_RESPONSE_OK) {
 
-	/* clear loop if waiting */
-	if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
-		g_main_loop_quit (priv->loop);
-		priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		/* send input if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
+			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), " ", 1);
+			gcm_calibrate_dialog_pop (priv->calibrate_dialog);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
+
+		/* clear loop if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
+			g_main_loop_quit (priv->loop);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
+
+		goto out;
 	}
 
-	/* stop loop */
-	if (g_main_loop_is_running (priv->loop))
-		g_main_loop_quit (priv->loop);
-}
+	/* cancel */
+	if (response == GTK_RESPONSE_CANCEL) {
 
-/**
- * gcm_calibrate_argyll_ok_cb:
- **/
-static void
-gcm_calibrate_argyll_ok_cb (GtkWidget *widget, GcmCalibrateArgyll *calibrate_argyll)
-{
-	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
+		/* send input if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
+			vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), "Q", 1);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
 
-	/* send input if waiting */
-	if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_STDIN) {
-		vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), " ", 1);
-		gcm_calibrate_argyll_pop_dialog (calibrate_argyll);
-		priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
-	}
+		/* clear loop if waiting */
+		if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
+			g_main_loop_quit (priv->loop);
+			priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		}
 
-	/* clear loop if waiting */
-	if (priv->state == GCM_CALIBRATE_ARGYLL_STATE_WAITING_FOR_LOOP) {
-		g_main_loop_quit (priv->loop);
-		priv->state = GCM_CALIBRATE_ARGYLL_STATE_RUNNING;
+		/* stop loop */
+		if (g_main_loop_is_running (priv->loop))
+			g_main_loop_quit (priv->loop);
+		goto out;
 	}
-
-	priv->response = GTK_RESPONSE_OK;
-	gtk_widget_hide (widget);
+out:
+	return;
 }
 
 /**
- * gcm_calibrate_argyll_delete_event_cb:
+ * gcm_calibrate_argyll_get_property:
  **/
-static gboolean
-gcm_calibrate_argyll_delete_event_cb (GtkWidget *widget, GdkEvent *event, GcmCalibrateArgyll *calibrate_argyll)
+static void
+gcm_calibrate_argyll_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
-	gcm_calibrate_argyll_cancel_cb (widget, calibrate_argyll);
-	return FALSE;
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
 }
 
 /**
@@ -1601,10 +1483,6 @@ gcm_calibrate_argyll_class_init (GcmCalibrateArgyllClass *klass)
 static void
 gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 {
-	gint retval;
-	GError *error = NULL;
-	GtkWidget *widget;
-	GtkWidget *main_window;
 	gchar *precision;
 
 	calibrate_argyll->priv = GCM_CALIBRATE_ARGYLL_GET_PRIVATE (calibrate_argyll);
@@ -1612,18 +1490,11 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 	calibrate_argyll->priv->loop = g_main_loop_new (NULL, FALSE);
 	calibrate_argyll->priv->vte_previous_row = 0;
 	calibrate_argyll->priv->vte_previous_col = 0;
-	calibrate_argyll->priv->cached_dialogs = g_ptr_array_new_with_free_func ((GDestroyNotify)gcm_calibrate_argyll_dialog_free);
 	calibrate_argyll->priv->already_on_window = FALSE;
 	calibrate_argyll->priv->state = GCM_CALIBRATE_ARGYLL_STATE_IDLE;
-
-	/* get UI */
-	calibrate_argyll->priv->builder = gtk_builder_new ();
-	retval = gtk_builder_add_from_file (calibrate_argyll->priv->builder, GCM_DATA "/gcm-spawn.ui", &error);
-	if (retval == 0) {
-		egg_warning ("failed to load ui: %s", error->message);
-		g_error_free (error);
-		return;
-	}
+	calibrate_argyll->priv->calibrate_dialog = gcm_calibrate_dialog_new ();
+	g_signal_connect (calibrate_argyll->priv->calibrate_dialog, "response",
+			  G_CALLBACK (gcm_calibrate_argyll_response_cb), calibrate_argyll);
 
 	/* use GConf to get defaults */
 	calibrate_argyll->priv->gconf_client = gconf_client_get_default ();
@@ -1631,19 +1502,6 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 	/* get screen */
 	calibrate_argyll->priv->screen = gcm_screen_new ();
 
-	/* set icon */
-	main_window = GTK_WIDGET (gtk_builder_get_object (calibrate_argyll->priv->builder, "dialog_calibrate"));
-	gtk_window_set_icon_name (GTK_WINDOW (main_window), GCM_STOCK_ICON);
-	g_signal_connect (main_window, "delete_event",
-			  G_CALLBACK (gcm_calibrate_argyll_delete_event_cb), calibrate_argyll);
-
-	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_argyll->priv->builder, "button_cancel"));
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (gcm_calibrate_argyll_cancel_cb), calibrate_argyll);
-	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_argyll->priv->builder, "button_ok"));
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (gcm_calibrate_argyll_ok_cb), calibrate_argyll);
-
 	/* add vte widget */
 	calibrate_argyll->priv->terminal = vte_terminal_new ();
 	vte_terminal_set_size (VTE_TERMINAL(calibrate_argyll->priv->terminal), 80, 10);
@@ -1651,9 +1509,8 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 			  G_CALLBACK (gcm_calibrate_argyll_exit_cb), calibrate_argyll);
 	g_signal_connect (calibrate_argyll->priv->terminal, "cursor-moved",
 			  G_CALLBACK (gcm_calibrate_argyll_cursor_moved_cb), calibrate_argyll);
-
-	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_argyll->priv->builder, "vbox_details"));
-	gtk_box_pack_end (GTK_BOX(widget), calibrate_argyll->priv->terminal, TRUE, TRUE, 6);
+	gcm_calibrate_dialog_pack_details (calibrate_argyll->priv->calibrate_dialog,
+					   calibrate_argyll->priv->terminal);
 
 	/* get default precision */
 	precision = gconf_client_get_string (calibrate_argyll->priv->gconf_client, GCM_SETTINGS_CALIBRATION_LENGTH, NULL);
@@ -1667,7 +1524,6 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 static void
 gcm_calibrate_argyll_finalize (GObject *object)
 {
-	GtkWidget *widget;
 	GcmCalibrateArgyll *calibrate_argyll = GCM_CALIBRATE_ARGYLL (object);
 	GcmCalibrateArgyllPrivate *priv = calibrate_argyll->priv;
 
@@ -1680,15 +1536,13 @@ gcm_calibrate_argyll_finalize (GObject *object)
 		g_main_loop_run (priv->loop);
 	}
 
-	/* hide window */
-	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
-	gtk_widget_hide (widget);
+	/* hide */
+	gcm_calibrate_dialog_hide (priv->calibrate_dialog);
 
 	g_main_loop_unref (priv->loop);
-	g_object_unref (priv->builder);
 	g_object_unref (priv->screen);
 	g_object_unref (priv->gconf_client);
-	g_ptr_array_unref (priv->cached_dialogs);
+	g_object_unref (priv->calibrate_dialog);
 
 	G_OBJECT_CLASS (gcm_calibrate_argyll_parent_class)->finalize (object);
 }
diff --git a/src/gcm-calibrate-dialog.c b/src/gcm-calibrate-dialog.c
new file mode 100644
index 0000000..3b1898c
--- /dev/null
+++ b/src/gcm-calibrate-dialog.c
@@ -0,0 +1,752 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 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.
+ */
+
+/**
+ * SECTION:gcm-calibrate-dialog
+ * @short_description: Calibration object
+ *
+ * This object allows calibration functionality using CMS.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gcm-enum.h"
+#include "gcm-calibrate.h"
+#include "gcm-calibrate-dialog.h"
+#include "gcm-utils.h"
+
+#include "egg-debug.h"
+
+static void     gcm_calibrate_dialog_finalize	(GObject     *object);
+
+#define GCM_CALIBRATE_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_CALIBRATE_DIALOG, GcmCalibrateDialogPrivate))
+
+/**
+ * GcmCalibrateDialogPrivate:
+ *
+ * Private #GcmCalibrateDialog data
+ **/
+struct _GcmCalibrateDialogPrivate
+{
+	GPtrArray			*cached_dialogs;
+	GtkBuilder			*builder;
+	GcmCalibrateDeviceKind		 device_kind;
+	GcmCalibrateReferenceKind	 reference_kind;
+	GtkResponseType			 response;
+	GMainLoop			*loop;
+};
+
+enum {
+	SIGNAL_RESPONSE,
+	SIGNAL_LAST
+};
+
+enum {
+	PROP_0,
+	PROP_DEVICE_KIND,
+	PROP_REFERENCE_KIND,
+	PROP_LAST
+};
+
+typedef struct {
+	gchar		*title;
+	gchar		*message;
+	gchar		*image_filename;
+	gboolean	 show_okay;
+	gboolean	 show_expander;
+} GcmCalibrateDialogItem;
+
+static gpointer gcm_calibrate_dialog_object = NULL;
+static guint signals[SIGNAL_LAST] = { 0 };
+
+G_DEFINE_TYPE (GcmCalibrateDialog, gcm_calibrate_dialog, G_TYPE_OBJECT)
+
+/**
+ * gcm_calibrate_dialog_emit_response:
+ **/
+static void
+gcm_calibrate_dialog_emit_response (GcmCalibrateDialog *calibrate_dialog, GtkResponseType response)
+{
+	calibrate_dialog->priv->response = response;
+	g_signal_emit (calibrate_dialog, signals[SIGNAL_RESPONSE], 0, response);
+
+	/* don't block anymore */
+	if (g_main_loop_is_running (calibrate_dialog->priv->loop))
+		g_main_loop_quit (calibrate_dialog->priv->loop);
+}
+
+/**
+ * gcm_calibrate_dialog_button_clicked_lcd_cb:
+ **/
+static void
+gcm_calibrate_dialog_button_clicked_lcd_cb (GtkWidget *widget, GcmCalibrateDialog *calibrate_dialog)
+{
+	calibrate_dialog->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_LCD;
+	gcm_calibrate_dialog_emit_response (calibrate_dialog, GTK_RESPONSE_OK);
+}
+
+/**
+ * gcm_calibrate_dialog_button_clicked_crt_cb:
+ **/
+static void
+gcm_calibrate_dialog_button_clicked_crt_cb (GtkWidget *widget, GcmCalibrateDialog *calibrate_dialog)
+{
+	calibrate_dialog->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_CRT;
+	gcm_calibrate_dialog_emit_response (calibrate_dialog, GTK_RESPONSE_OK);
+}
+
+/**
+ * gcm_calibrate_dialog_button_clicked_projector_cb:
+ **/
+static void
+gcm_calibrate_dialog_button_clicked_projector_cb (GtkWidget *widget, GcmCalibrateDialog *calibrate_dialog)
+{
+	calibrate_dialog->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_PROJECTOR;
+	gcm_calibrate_dialog_emit_response (calibrate_dialog, GTK_RESPONSE_OK);
+}
+
+/**
+ * gcm_calibrate_dialog_button_clicked_ok_cb:
+ **/
+static void
+gcm_calibrate_dialog_button_clicked_ok_cb (GtkWidget *widget, GcmCalibrateDialog *calibrate_dialog)
+{
+	gcm_calibrate_dialog_emit_response (calibrate_dialog, GTK_RESPONSE_OK);
+}
+
+/**
+ * gcm_calibrate_dialog_button_clicked_cancel_cb:
+ **/
+static void
+gcm_calibrate_dialog_button_clicked_cancel_cb (GtkWidget *widget, GcmCalibrateDialog *calibrate_dialog)
+{
+	gcm_calibrate_dialog_emit_response (calibrate_dialog, GTK_RESPONSE_CANCEL);
+}
+
+/**
+ * gcm_calibrate_dialog_set_image_filename_private:
+ **/
+static void
+gcm_calibrate_dialog_set_image_filename_private (GcmCalibrateDialog *calibrate_dialog, const gchar *image_filename)
+{
+	GtkWidget *widget;
+	gchar *filename = NULL;
+	GdkPixbuf *pixbuf;
+	GError *error = NULL;
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+
+	/* set the image */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "image_generic"));
+	if (image_filename != NULL) {
+		filename = g_build_filename (GCM_DATA, "icons", image_filename, NULL);
+		pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 200, 400, &error);
+		if (pixbuf == NULL) {
+			egg_warning ("failed to load image: %s", error->message);
+			g_error_free (error);
+			gtk_widget_hide (widget);
+		} else {
+			gtk_image_set_from_pixbuf (GTK_IMAGE (widget), pixbuf);
+			gtk_widget_show (widget);
+		}
+		g_free (filename);
+	} else {
+		gtk_widget_hide (widget);
+	}
+}
+
+/**
+ * gcm_calibrate_dialog_set_image_filename:
+ **/
+void
+gcm_calibrate_dialog_set_image_filename (GcmCalibrateDialog *calibrate_dialog, const gchar *image_filename)
+{
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+	GcmCalibrateDialogItem *dialog;
+
+	/* get the last entry */
+	dialog = g_ptr_array_index (priv->cached_dialogs, priv->cached_dialogs->len - 1);
+	g_free (dialog->image_filename);
+	dialog->image_filename = g_strdup (image_filename);
+
+	/* actually load the image */
+	gcm_calibrate_dialog_set_image_filename_private (calibrate_dialog, image_filename);
+}
+
+/**
+ * gcm_calibrate_dialog_dialog_free:
+ **/
+static void
+gcm_calibrate_dialog_dialog_free (GcmCalibrateDialogItem *dialog)
+{
+	g_free (dialog->title);
+	g_free (dialog->message);
+	g_free (dialog->image_filename);
+	g_free (dialog);
+}
+
+/**
+ * gcm_calibrate_dialog_set_window:
+ **/
+void
+gcm_calibrate_dialog_set_window	(GcmCalibrateDialog *calibrate_dialog, GtkWindow *window)
+{
+	GtkWidget *widget;
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
+
+	/* run dialog */
+	if (window != NULL)
+		gtk_window_set_transient_for (GTK_WINDOW (widget), window);
+}
+
+/**
+ * gcm_calibrate_dialog_get_window:
+ **/
+GtkWindow *
+gcm_calibrate_dialog_get_window (GcmCalibrateDialog *calibrate_dialog)
+{
+	GtkWindow *window;
+	window = GTK_WINDOW (gtk_builder_get_object (calibrate_dialog->priv->builder, "dialog_calibrate"));
+	return window;
+}
+
+/**
+ * gcm_calibrate_dialog_run:
+ **/
+GtkResponseType
+gcm_calibrate_dialog_run (GcmCalibrateDialog *calibrate_dialog)
+{
+	if (g_main_loop_is_running (calibrate_dialog->priv->loop))
+		egg_error ("you can't call this recursively");
+
+	g_main_loop_run (calibrate_dialog->priv->loop);
+	return calibrate_dialog->priv->response;
+}
+
+/**
+ * gcm_calibrate_dialog_show:
+ **/
+void
+gcm_calibrate_dialog_show (GcmCalibrateDialog		*calibrate_dialog,
+			   GcmCalibrateDialogTab	 tab,
+			   const gchar			*title,
+			   const gchar			*message)
+{
+	GtkWidget *widget;
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+	gint x, y;
+	GcmCalibrateDialogItem *dialog;
+
+	/* save in case we need to reuse */
+	dialog = g_new0 (GcmCalibrateDialogItem, 1);
+	dialog->title = g_strdup (title);
+	dialog->message = g_strdup (message);
+	g_ptr_array_add (priv->cached_dialogs, dialog);
+
+	/* hide elements that should not be seen */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "vbox_display_type"));
+	gtk_widget_set_visible (widget, (tab == GCM_CALIBRATE_DIALOG_TAB_DISPLAY_TYPE));
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "vbox_target_type"));
+	gtk_widget_set_visible (widget, (tab == GCM_CALIBRATE_DIALOG_TAB_TARGET_TYPE));
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "vbox_manual"));
+	gtk_widget_set_visible (widget, (tab == GCM_CALIBRATE_DIALOG_TAB_MANUAL));
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "vbox_generic"));
+	gtk_widget_set_visible (widget, (tab == GCM_CALIBRATE_DIALOG_TAB_GENERIC));
+
+	/* reset */
+	gcm_calibrate_dialog_set_image_filename (calibrate_dialog, NULL);
+	gcm_calibrate_dialog_set_show_expander (calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_button_ok (calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_image_filename_private (calibrate_dialog, NULL);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_title"));
+	gtk_label_set_label (GTK_LABEL (widget), title);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_message"));
+	gtk_label_set_label (GTK_LABEL (widget), message);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "notebook1"));
+	gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), tab);
+
+	/* move the dialog out of the way, so the grey square doesn't cover it */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
+	gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
+	egg_debug ("currently at %i,%i, moving left", x, y);
+	gtk_window_move (GTK_WINDOW (widget), 10, y);
+
+	gtk_widget_show (widget);
+}
+
+/**
+ * gcm_calibrate_dialog_hide:
+ **/
+void
+gcm_calibrate_dialog_hide (GcmCalibrateDialog *calibrate_dialog)
+{
+	GtkWidget *widget;
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "dialog_calibrate"));
+	gtk_widget_hide (widget);
+}
+
+/**
+ * gcm_calibrate_dialog_pop:
+ **/
+void
+gcm_calibrate_dialog_pop (GcmCalibrateDialog *calibrate_dialog)
+{
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+	GtkWidget *widget;
+	gchar *text;
+	guint len;
+	GcmCalibrateDialogItem *dialog;
+
+	/* save in case we need to reuse */
+	len = priv->cached_dialogs->len;
+	if (len < 2) {
+		egg_warning ("cannot pop dialog as nothing to recover");
+		return;
+	}
+	dialog = g_ptr_array_index (priv->cached_dialogs, len-2);
+
+	/* set the text */
+	text = g_strdup_printf ("<big><b>%s</b></big>", dialog->title);
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_title"));
+	gtk_label_set_markup (GTK_LABEL(widget), text);
+	g_free (text);
+
+	/* set the text */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_message"));
+	gtk_label_set_markup (GTK_LABEL(widget), dialog->message);
+
+	/* show the okay button */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_ok"));
+	gtk_widget_set_visible (widget, dialog->show_okay);
+
+	/* show the expander */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "expander_details"));
+	gtk_widget_set_visible (widget, dialog->show_expander);
+
+	/* show the correct image */
+	gcm_calibrate_dialog_set_image_filename_private (calibrate_dialog, dialog->image_filename);
+
+	/* remove from the stack */
+	g_ptr_array_remove_index (priv->cached_dialogs, len-1);
+}
+
+/**
+ * gcm_calibrate_dialog_pack_details:
+ **/
+void
+gcm_calibrate_dialog_pack_details (GcmCalibrateDialog *calibrate_dialog, GtkWidget *widget)
+{
+	GtkWidget *vbox;
+	vbox = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "vbox_details"));
+	gtk_box_pack_end (GTK_BOX(vbox), widget, TRUE, TRUE, 6);
+	gtk_widget_show (widget);
+}
+
+/**
+ * gcm_calibrate_dialog_set_show_button_ok:
+ **/
+void
+gcm_calibrate_dialog_set_show_button_ok (GcmCalibrateDialog *calibrate_dialog, gboolean visible)
+{
+	GtkWidget *widget;
+	GcmCalibrateDialogItem *dialog;
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_ok"));
+	gtk_widget_set_visible (widget, visible);
+
+	/* get the last entry */
+	dialog = g_ptr_array_index (priv->cached_dialogs, priv->cached_dialogs->len - 1);
+	dialog->show_okay = visible;
+}
+
+/**
+ * gcm_calibrate_dialog_set_show_expander:
+ **/
+void
+gcm_calibrate_dialog_set_show_expander (GcmCalibrateDialog *calibrate_dialog, gboolean visible)
+{
+	GcmCalibrateDialogItem *dialog;
+	GtkWidget *widget;
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "expander_details"));
+	gtk_widget_set_visible (widget, visible);
+
+	/* get the last entry */
+	dialog = g_ptr_array_index (priv->cached_dialogs, priv->cached_dialogs->len - 1);
+	dialog->show_expander = visible;
+}
+
+/**
+ * gcm_calibrate_dialog_delete_event_cb:
+ **/
+//static gboolean
+//gcm_calibrate_dialog_delete_event_cb (GtkWidget *widget, GdkEvent *event, GcmCalibrateArgyll *calibrate_argyll)
+//{
+//	gcm_calibrate_dialog_cancel_cb (widget, calibrate_argyll);
+//	return FALSE;
+//}
+
+/**
+ * gcm_calibrate_dialog_reference_kind_to_thumbnail_image_filename:
+ **/
+static const gchar *
+gcm_calibrate_dialog_reference_kind_to_thumbnail_image_filename (GcmCalibrateReferenceKind kind)
+{
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DIGITAL_TARGET_3)
+		return "CMP-DigitalTarget3.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DT_003)
+		return NULL;
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER)
+		return "ColorChecker24.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_DC)
+		return "ColorCheckerDC.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_SG)
+		return "ColorCheckerSG.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_HUTCHCOLOR)
+		return NULL;
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_I1_RGB_SCAN_1_4)
+		return "i1_RGB_Scan_14.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_IT8)
+		return "IT872.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_LASER_SOFT_DC_PRO)
+		return "LaserSoftDCPro.png";
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201)
+		return "QPcard_201.png";
+	return NULL;
+}
+
+/**
+ * gcm_calibrate_dialog_reference_kind_to_localised_string:
+ **/
+static const gchar *
+gcm_calibrate_dialog_reference_kind_to_localised_string (GcmCalibrateReferenceKind kind)
+{
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DIGITAL_TARGET_3) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("CMP Digital Target 3");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DT_003) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("CMP DT 003");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Color Checker");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_DC) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Color Checker DC");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_SG) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Color Checker SG");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_HUTCHCOLOR) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Hutchcolor");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_I1_RGB_SCAN_1_4) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("i1 RGB Scan 1.4");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_IT8) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("IT8.7/2");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_LASER_SOFT_DC_PRO) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("Laser Soft DC Pro");
+	}
+	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201) {
+		/* TRANSLATORS: this is probably a brand name */
+		return _("QPcard 201");
+	}
+	return NULL;
+}
+
+/**
+ * gcm_calibrate_dialog_reference_kind_combobox_cb:
+ **/
+static void
+gcm_calibrate_dialog_reference_kind_combobox_cb (GtkComboBox *combo_box, GcmCalibrateDialog *calibrate_dialog)
+{
+	const gchar *filename;
+	gchar *path;
+	GtkWidget *widget;
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+
+	/* not sorted so we can just use the index */
+	priv->reference_kind = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
+	filename = gcm_calibrate_dialog_reference_kind_to_thumbnail_image_filename (priv->reference_kind);
+
+	/* fallback */
+	if (filename == NULL)
+		filename = "unknown.png";
+
+	path = g_build_filename (GCM_DATA, "targets", filename, NULL);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "image_target"));
+	gtk_image_set_from_file (GTK_IMAGE (widget), path);
+	g_free (path);
+}
+
+/**
+ * gcm_calibrate_dialog_setup_combo_simple_text:
+ **/
+static void
+gcm_calibrate_dialog_setup_combo_simple_text (GtkWidget *combo_box)
+{
+	GtkCellRenderer *cell;
+	GtkListStore *store;
+
+	store = gtk_list_store_new (1, G_TYPE_STRING);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store));
+	g_object_unref (store);
+
+	cell = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell,
+					"text", 0,
+					NULL);
+}
+
+/**
+ * gcm_calibrate_dialog_get_property:
+ **/
+static void
+gcm_calibrate_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	GcmCalibrateDialog *calibrate_dialog = GCM_CALIBRATE_DIALOG (object);
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+
+	switch (prop_id) {
+	case PROP_REFERENCE_KIND:
+		g_value_set_uint (value, priv->reference_kind);
+		break;
+	case PROP_DEVICE_KIND:
+		g_value_set_uint (value, priv->device_kind);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
+ * gcm_calibrate_dialog_set_property:
+ **/
+static void
+gcm_calibrate_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
+ * gcm_calibrate_dialog_class_init:
+ **/
+static void
+gcm_calibrate_dialog_class_init (GcmCalibrateDialogClass *klass)
+{
+	GParamSpec *pspec;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gcm_calibrate_dialog_finalize;
+	object_class->get_property = gcm_calibrate_dialog_get_property;
+	object_class->set_property = gcm_calibrate_dialog_set_property;
+
+	/**
+	 * GcmCalibrateDialog:reference-kind:
+	 */
+	pspec = g_param_spec_uint ("reference-kind", NULL, NULL,
+				   0, G_MAXUINT, 0,
+				   G_PARAM_READABLE);
+	g_object_class_install_property (object_class, PROP_REFERENCE_KIND, pspec);
+
+	/**
+	 * GcmCalibrateDialog:device-kind:
+	 */
+	pspec = g_param_spec_uint ("device-kind", NULL, NULL,
+				   0, G_MAXUINT, 0,
+				   G_PARAM_READABLE);
+	g_object_class_install_property (object_class, PROP_DEVICE_KIND, pspec);
+
+	/**
+	 * GcmCalibrateDialog::response:
+	 **/
+	signals[SIGNAL_RESPONSE] =
+		g_signal_new ("response",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GcmCalibrateDialogClass, response),
+			      NULL, NULL, g_cclosure_marshal_VOID__INT,
+			      G_TYPE_NONE, 1, G_TYPE_INT);
+
+	g_type_class_add_private (klass, sizeof (GcmCalibrateDialogPrivate));
+}
+
+/**
+ * gcm_calibrate_dialog_init:
+ **/
+static void
+gcm_calibrate_dialog_init (GcmCalibrateDialog *calibrate_dialog)
+{
+	gint retval;
+	GError *error = NULL;
+	GtkWidget *widget;
+	guint i;
+
+	calibrate_dialog->priv = GCM_CALIBRATE_DIALOG_GET_PRIVATE (calibrate_dialog);
+
+	calibrate_dialog->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_UNKNOWN;
+	calibrate_dialog->priv->reference_kind = GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN;
+	calibrate_dialog->priv->loop = g_main_loop_new (NULL, FALSE);
+	calibrate_dialog->priv->cached_dialogs = g_ptr_array_new_with_free_func ((GDestroyNotify)gcm_calibrate_dialog_dialog_free);
+
+	/* get UI */
+	calibrate_dialog->priv->builder = gtk_builder_new ();
+	retval = gtk_builder_add_from_file (calibrate_dialog->priv->builder, GCM_DATA "/gcm-calibrate.ui", &error);
+	if (retval == 0) {
+		egg_error ("failed to load ui: %s", error->message);
+		g_error_free (error);
+	}
+
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "button_lcd"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_calibrate_dialog_button_clicked_lcd_cb), calibrate_dialog);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "button_crt"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_calibrate_dialog_button_clicked_crt_cb), calibrate_dialog);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "button_projector"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_calibrate_dialog_button_clicked_projector_cb), calibrate_dialog);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "button_cancel"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_calibrate_dialog_button_clicked_cancel_cb), calibrate_dialog);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "button_ok"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_calibrate_dialog_button_clicked_ok_cb), calibrate_dialog);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "image_target"));
+	gtk_widget_set_size_request (widget, 200, 140);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "combobox_target"));
+	gcm_calibrate_dialog_setup_combo_simple_text (widget);
+	g_signal_connect (widget, "changed", G_CALLBACK (gcm_calibrate_dialog_reference_kind_combobox_cb), calibrate_dialog);
+
+//	g_signal_connect (main_window, "delete_event",
+//			  G_CALLBACK (gcm_calibrate_dialog_delete_event_cb), calibrate_argyll);
+
+	/* add the list of charts */
+	for (i = 0; i < GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN; i++) {
+		gtk_combo_box_append_text (GTK_COMBO_BOX (widget),
+					   gcm_calibrate_dialog_reference_kind_to_localised_string (i));
+	}
+
+	/* use IT8 by default */
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), GCM_CALIBRATE_REFERENCE_KIND_IT8);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate_dialog->priv->builder, "notebook1"));
+	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
+}
+
+/**
+ * gcm_calibrate_dialog_finalize:
+ **/
+static void
+gcm_calibrate_dialog_finalize (GObject *object)
+{
+	GcmCalibrateDialog *calibrate_dialog = GCM_CALIBRATE_DIALOG (object);
+	GcmCalibrateDialogPrivate *priv = calibrate_dialog->priv;
+
+	g_object_unref (priv->builder);
+	g_ptr_array_unref (priv->cached_dialogs);
+	g_main_loop_unref (priv->loop);
+
+	G_OBJECT_CLASS (gcm_calibrate_dialog_parent_class)->finalize (object);
+}
+
+/**
+ * gcm_calibrate_dialog_new:
+ *
+ * Return value: a new GcmCalibrateDialog object.
+ **/
+GcmCalibrateDialog *
+gcm_calibrate_dialog_new (void)
+{
+	if (gcm_calibrate_dialog_object != NULL) {
+		g_object_ref (gcm_calibrate_dialog_object);
+	} else {
+		gcm_calibrate_dialog_object = g_object_new (GCM_TYPE_CALIBRATE_DIALOG, NULL);
+		g_object_add_weak_pointer (gcm_calibrate_dialog_object, &gcm_calibrate_dialog_object);
+	}
+	return GCM_CALIBRATE_DIALOG (gcm_calibrate_dialog_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+gcm_calibrate_dialog_test (EggTest *test)
+{
+	GcmCalibrateDialog *calibrate_dialog;
+	gboolean ret;
+	GError *error = NULL;
+	gchar *filename;
+
+	if (!egg_test_start (test, "GcmCalibrateDialog"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get a calibrate_dialog object");
+	calibrate_dialog = gcm_calibrate_dialog_new ();
+	egg_test_assert (test, calibrate_dialog != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "calibrate_dialog display manually");
+	filename = egg_test_get_data_file ("test.tif");
+	ret = gcm_calibrate_dialog_set_from_exif (GCM_CALIBRATE_DIALOG(calibrate_dialog), filename, &error);
+	if (!ret)
+		egg_test_failed (test, "error: %s", error->message);
+	else if (g_strcmp0 (gcm_calibrate_dialog_get_model_fallback (calibrate_dialog), "NIKON D60") != 0)
+		egg_test_failed (test, "got model: %s", gcm_calibrate_dialog_get_model_fallback (calibrate_dialog));
+	else if (g_strcmp0 (gcm_calibrate_dialog_get_manufacturer_fallback (calibrate_dialog), "NIKON CORPORATION") != 0)
+		egg_test_failed (test, "got manufacturer: %s", gcm_calibrate_dialog_get_manufacturer_fallback (calibrate_dialog));
+	else
+		egg_test_success (test, NULL);
+
+	g_object_unref (calibrate_dialog);
+	g_free (filename);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/src/gcm-calibrate-dialog.h b/src/gcm-calibrate-dialog.h
new file mode 100644
index 0000000..63b53db
--- /dev/null
+++ b/src/gcm-calibrate-dialog.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GCM_CALIBRATE_DIALOG_H
+#define __GCM_CALIBRATE_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gcm-device.h"
+
+G_BEGIN_DECLS
+
+#define GCM_TYPE_CALIBRATE_DIALOG		(gcm_calibrate_dialog_get_type ())
+#define GCM_CALIBRATE_DIALOG(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), GCM_TYPE_CALIBRATE_DIALOG, GcmCalibrateDialog))
+#define GCM_CALIBRATE_DIALOG_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), GCM_TYPE_CALIBRATE_DIALOG, GcmCalibrateDialogClass))
+#define GCM_IS_CALIBRATE_DIALOG(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GCM_TYPE_CALIBRATE_DIALOG))
+#define GCM_IS_CALIBRATE_DIALOG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GCM_TYPE_CALIBRATE_DIALOG))
+#define GCM_CALIBRATE_DIALOG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GCM_TYPE_CALIBRATE_DIALOG, GcmCalibrateDialogClass))
+
+typedef struct _GcmCalibrateDialogPrivate	GcmCalibrateDialogPrivate;
+typedef struct _GcmCalibrateDialog		GcmCalibrateDialog;
+typedef struct _GcmCalibrateDialogClass		GcmCalibrateDialogClass;
+
+struct _GcmCalibrateDialog
+{
+	 GObject				 parent;
+	 GcmCalibrateDialogPrivate		*priv;
+};
+
+struct _GcmCalibrateDialogClass
+{
+	GObjectClass	parent_class;
+	void		(* response)				(GcmCalibrateDialog	*calibrate_dialog,
+								 GtkResponseType		 response);
+};
+
+typedef enum {
+	GCM_CALIBRATE_DIALOG_TAB_DISPLAY_TYPE,
+	GCM_CALIBRATE_DIALOG_TAB_TARGET_TYPE,
+	GCM_CALIBRATE_DIALOG_TAB_MANUAL,
+	GCM_CALIBRATE_DIALOG_TAB_GENERIC,
+	GCM_CALIBRATE_DIALOG_TAB_LAST
+} GcmCalibrateDialogTab;
+
+GType			 gcm_calibrate_dialog_get_type		(void);
+GcmCalibrateDialog	*gcm_calibrate_dialog_new		(void);
+
+void			 gcm_calibrate_dialog_set_window	(GcmCalibrateDialog	*calibrate_dialog,
+								 GtkWindow		*window);
+void			 gcm_calibrate_dialog_show		(GcmCalibrateDialog	*calibrate_dialog,
+								 GcmCalibrateDialogTab	 tab,
+								 const gchar		*title,
+								 const gchar		*message);
+void			 gcm_calibrate_dialog_set_show_expander	(GcmCalibrateDialog	*calibrate_dialog,
+								 gboolean		 visible);
+void			 gcm_calibrate_dialog_set_show_button_ok (GcmCalibrateDialog	*calibrate_dialog,
+								 gboolean		 visible);
+void			 gcm_calibrate_dialog_set_image_filename (GcmCalibrateDialog	*calibrate_dialog,
+								 const gchar		*image_filename);
+void			 gcm_calibrate_dialog_pop		(GcmCalibrateDialog	*calibrate_dialog);
+void			 gcm_calibrate_dialog_hide		(GcmCalibrateDialog	*calibrate_dialog);
+GtkResponseType		 gcm_calibrate_dialog_run		(GcmCalibrateDialog	*calibrate_dialog);
+GtkWindow		*gcm_calibrate_dialog_get_window	(GcmCalibrateDialog	*calibrate_dialog);
+void			 gcm_calibrate_dialog_pack_details	(GcmCalibrateDialog	*calibrate_dialog,
+								 GtkWidget		*widget);
+
+G_END_DECLS
+
+#endif /* __GCM_CALIBRATE_DIALOG_H */
+
diff --git a/src/gcm-calibrate.c b/src/gcm-calibrate.c
index 4a7bacf..a8a3fd6 100644
--- a/src/gcm-calibrate.c
+++ b/src/gcm-calibrate.c
@@ -37,6 +37,7 @@
 #include "gcm-utils.h"
 #include "gcm-brightness.h"
 #include "gcm-colorimeter.h"
+#include "gcm-calibrate-dialog.h"
 
 #include "egg-debug.h"
 
@@ -55,6 +56,7 @@ struct _GcmCalibratePrivate
 	GcmCalibrateReferenceKind	 reference_kind;
 	GcmCalibrateDeviceKind		 device_kind;
 	GcmColorimeterKind		 colorimeter_kind;
+	GcmCalibrateDialog		*calibrate_dialog;
 	gchar				*output_name;
 	gchar				*filename_source;
 	gchar				*filename_reference;
@@ -65,7 +67,6 @@ struct _GcmCalibratePrivate
 	gchar				*description;
 	gchar				*serial;
 	gchar				*device;
-	GtkDialog			*dialog_tmp;
 };
 
 enum {
@@ -300,134 +301,38 @@ out:
 }
 
 /**
- * gcm_calibrate_create_large_button:
- **/
-static GtkWidget *
-gcm_calibrate_create_large_button (const gchar *filename, const gchar *title)
-{
-	GtkWidget *vbox;
-	GtkWidget *image;
-	GtkWidget *label;
-	GError *error = NULL;
-	GtkIconTheme *icon_theme;
-	GdkPixbuf *pixbuf;
-
-	/* pack label into a vbox */
-	vbox = gtk_vbox_new (FALSE, 3);
-	label = gtk_label_new (title);
-	gtk_box_pack_end (GTK_BOX(vbox), label, TRUE, TRUE, 3);
-	gtk_widget_show (label);
-
-	/* image widget */
-	icon_theme = gtk_icon_theme_get_default ();
-	pixbuf = gtk_icon_theme_load_icon (icon_theme, filename, 150, 0, &error);
-	if (pixbuf == NULL) {
-		egg_warning ("failed to load: %s", error->message);
-		goto out;
-	}
-	image = gtk_image_new_from_pixbuf (pixbuf);
-	gtk_box_pack_end (GTK_BOX(vbox), image, TRUE, TRUE, 3);
-	gtk_widget_show (image);
-out:
-	gtk_widget_show (vbox);
-	return vbox;
-}
-
-/**
- * gcm_calibrate_button_clicked_lcd_cb:
- **/
-static void
-gcm_calibrate_button_clicked_lcd_cb (GtkWidget *widget, GcmCalibrate *calibrate)
-{
-	calibrate->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_LCD;
-	gtk_dialog_response (calibrate->priv->dialog_tmp, GTK_RESPONSE_OK);
-}
-
-/**
- * gcm_calibrate_button_clicked_crt_cb:
- **/
-static void
-gcm_calibrate_button_clicked_crt_cb (GtkWidget *widget, GcmCalibrate *calibrate)
-{
-	calibrate->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_CRT;
-	gtk_dialog_response (calibrate->priv->dialog_tmp, GTK_RESPONSE_OK);
-}
-
-/**
- * gcm_calibrate_button_clicked_projector_cb:
- **/
-static void
-gcm_calibrate_button_clicked_projector_cb (GtkWidget *widget, GcmCalibrate *calibrate)
-{
-	calibrate->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_PROJECTOR;
-	gtk_dialog_response (calibrate->priv->dialog_tmp, GTK_RESPONSE_OK);
-}
-
-/**
  * gcm_calibrate_get_display_type:
  **/
 static gboolean
 gcm_calibrate_get_display_type (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
 {
 	gboolean ret = TRUE;
-	GtkWidget *vbox;
-	GtkWidget *hbox;
-	GtkWidget *dialog;
-	GtkWidget *image;
-	GtkWidget *widget;
+	const gchar *title;
+	const gchar *message;
 	GtkResponseType response;
+	GcmCalibratePrivate *priv = calibrate->priv;
 
-	dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
-					 /* TRANSLATORS: title, usually we can tell based on the EDID data or output name */
-					 _("Could not detect screen type"));
-	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-						  /* TRANSLATORS: dialog message */
-						  _("Please indicate if the screen you are trying to profile is a LCD, CRT or a projector."));
-	gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
+	/* TRANSLATORS: title, usually we can tell based on the EDID data or output name */
+	title = _("Could not detect screen type");
 
-	/* pack it */
-	vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-	hbox = gtk_hbox_new (FALSE, 3);
-
-	/* TRANSLATORS: device type */
-	image = gcm_calibrate_create_large_button ("lcd", _("LCD"));
-	widget = gtk_button_new ();
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (gcm_calibrate_button_clicked_lcd_cb), calibrate);
-	gtk_container_add (GTK_CONTAINER (widget), image);
-	gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 3);
-	gtk_widget_show (widget);
-
-	/* TRANSLATORS: device type */
-	image = gcm_calibrate_create_large_button ("crt", _("CRT"));
-	widget = gtk_button_new ();
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (gcm_calibrate_button_clicked_crt_cb), calibrate);
-	gtk_container_add (GTK_CONTAINER (widget), image);
-	gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 3);
-	gtk_widget_show (widget);
-
-	/* TRANSLATORS: device type */
-	image = gcm_calibrate_create_large_button ("projector", _("Projector"));
-	widget = gtk_button_new ();
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (gcm_calibrate_button_clicked_projector_cb), calibrate);
-	gtk_container_add (GTK_CONTAINER (widget), image);
-	gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 3);
-	gtk_widget_show (widget);
-
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, 3);
-
-	/* save this so we can call async */
-	calibrate->priv->dialog_tmp = GTK_DIALOG (dialog);
-	response = gtk_dialog_run (GTK_DIALOG (dialog));
-	gtk_widget_destroy (dialog);
+	/* TRANSLATORS: dialog message */
+	message = _("Please indicate if the screen you are trying to profile is a LCD, CRT or a projector.");
+
+	/* show the ui */
+	gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_DISPLAY_TYPE, title, message);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
+	response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
 	if (response != GTK_RESPONSE_OK) {
+		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
 		g_set_error_literal (error, 1, 0, "user did not choose crt or lcd");
 		ret = FALSE;
 		goto out;
 	}
+
+	/* copy */
+	g_object_get (priv->calibrate_dialog, "device-kind", &priv->device_kind, NULL);
 out:
 	return ret;
 }
@@ -442,7 +347,6 @@ gcm_calibrate_display (GcmCalibrate *calibrate, GtkWindow *window, GError **erro
 	gboolean ret = TRUE;
 	const gchar *hardware_device;
 	gboolean ret_tmp;
-	GtkWidget *dialog;
 	GString *string = NULL;
 	GcmBrightness *brightness = NULL;
 	guint percentage = G_MAXUINT;
@@ -478,7 +382,6 @@ gcm_calibrate_display (GcmCalibrate *calibrate, GtkWindow *window, GError **erro
 		      "device", hardware_device,
 		      NULL);
 
-
 	/* this wasn't previously set */
 	if (priv->device_kind == GCM_CALIBRATE_DEVICE_KIND_UNKNOWN) {
 		ret = gcm_calibrate_get_display_type (calibrate, window, error);
@@ -515,15 +418,14 @@ gcm_calibrate_display (GcmCalibrate *calibrate, GtkWindow *window, GError **erro
 		/* TRANSLATORS: dialog message, suffix */
 		g_string_append_printf (string, "\n%s\n", _("For best results, the display should have been powered for at least 15 minutes before starting the calibration."));
 
-
-		dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
-						 /* TRANSLATORS: window title */
-						 _("Display setup"));
-		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", string->str);
-		gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
-		response = gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
+		/* TRANSLATORS: window title */
+		gcm_calibrate_dialog_set_window (priv->calibrate_dialog, window);
+		gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_GENERIC, _("Display setup"), string->str);
+		gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
+		gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
+		response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
 		if (response != GTK_RESPONSE_OK) {
+			gcm_calibrate_dialog_hide (priv->calibrate_dialog);
 			g_set_error_literal (error, 1, 0, "user did not follow calibration steps");
 			ret = FALSE;
 			goto out;
@@ -714,177 +616,6 @@ out:
 }
 
 /**
- * gcm_calibrate_reference_kind_to_localised_string:
- **/
-static const gchar *
-gcm_calibrate_reference_kind_to_localised_string (GcmCalibrateReferenceKind kind)
-{
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DIGITAL_TARGET_3) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("CMP Digital Target 3");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DT_003) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("CMP DT 003");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("Color Checker");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_DC) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("Color Checker DC");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_SG) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("Color Checker SG");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_HUTCHCOLOR) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("Hutchcolor");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_I1_RGB_SCAN_1_4) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("i1 RGB Scan 1.4");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_IT8) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("IT8.7/2");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_LASER_SOFT_DC_PRO) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("Laser Soft DC Pro");
-	}
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201) {
-		/* TRANSLATORS: this is probably a brand name */
-		return _("QPcard 201");
-	}
-	return NULL;
-}
-
-/**
- * gcm_calibrate_reference_kind_to_thumbnail_image_filename:
- **/
-static const gchar *
-gcm_calibrate_reference_kind_to_thumbnail_image_filename (GcmCalibrateReferenceKind kind)
-{
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DIGITAL_TARGET_3)
-		return "CMP-DigitalTarget3.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_CMP_DT_003)
-		return NULL;
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER)
-		return "ColorChecker24.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_DC)
-		return "ColorCheckerDC.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_COLOR_CHECKER_SG)
-		return "ColorCheckerSG.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_HUTCHCOLOR)
-		return NULL;
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_I1_RGB_SCAN_1_4)
-		return "i1_RGB_Scan_14.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_IT8)
-		return "IT872.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_LASER_SOFT_DC_PRO)
-		return "LaserSoftDCPro.png";
-	if (kind == GCM_CALIBRATE_REFERENCE_KIND_QPCARD_201)
-		return "QPcard_201.png";
-	return NULL;
-}
-
-/**
- * gcm_calibrate_reference_kind_combobox_cb:
- **/
-static void
-gcm_calibrate_reference_kind_combobox_cb (GtkComboBox *combo_box, GtkImage *image)
-{
-	GcmCalibrateReferenceKind reference_kind;
-	const gchar *filename;
-	gchar *path;
-
-	/* not sorted so we can just use the index */
-	reference_kind = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
-	filename = gcm_calibrate_reference_kind_to_thumbnail_image_filename (reference_kind);
-
-	/* fallback */
-	if (filename == NULL)
-		filename = "unknown.png";
-
-	path = g_build_filename (GCM_DATA, "targets", filename, NULL);
-	gtk_image_set_from_file (GTK_IMAGE (image), path);
-	g_free (path);
-}
-
-/**
- * gcm_calibrate_get_reference_kind:
- **/
-static GcmCalibrateReferenceKind
-gcm_calibrate_get_reference_kind (GtkWindow *window)
-{
-	GtkResponseType response;
-	GtkWidget *dialog;
-	GtkWidget *vbox;
-	GtkWidget *combo_box;
-	GtkWidget *image;
-	const gchar *title;
-	const gchar *message;
-	guint i;
-	GcmCalibrateReferenceKind reference_kind = GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN;
-
-	/* TRANSLATORS: this is the window title for when the user selects the chart type.
-	                A chart is a type of reference image the user has purchased. */
-	title = _("Please select chart type");
-
-	/* TRANSLATORS: this is the message body for the chart selection */
-	message = _("Please select the chart type which corresponds to your reference file.");
-
-	dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL, "%s", title);
-	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", message);
-	gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
-	/* TRANSLATORS: button, confirm the chart type */
-	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Use this type"), GTK_RESPONSE_YES);
-
-	/* use image to display a picture of the target */
-	image = gtk_image_new ();
-	gtk_widget_set_size_request (image, 200, 140);
-
-	/* create the combobox */
-	combo_box = gtk_combo_box_new_text ();
-	g_signal_connect (combo_box, "changed", G_CALLBACK (gcm_calibrate_reference_kind_combobox_cb), image);
-
-	/* add the list of charts */
-	for (i = 0; i < GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN; i++) {
-		gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
-					   gcm_calibrate_reference_kind_to_localised_string (i));
-	}
-
-	/* use IT8 by default */
-	gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), GCM_CALIBRATE_REFERENCE_KIND_IT8);
-
-	/* pack it */
-	vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-
-	gtk_box_pack_start (GTK_BOX(vbox), image, TRUE, TRUE, 6);
-	gtk_box_pack_start (GTK_BOX(vbox), combo_box, TRUE, TRUE, 6);
-	gtk_widget_show (combo_box);
-	gtk_widget_show (image);
-
-	/* run the dialog */
-	response = gtk_dialog_run (GTK_DIALOG (dialog));
-
-	/* not sorted so we can just use the index */
-	reference_kind = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
-
-	/* nuke the UI */
-	gtk_widget_destroy (dialog);
-	if (response != GTK_RESPONSE_YES) {
-		reference_kind = GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN;
-		goto out;
-	}
-out:
-	return reference_kind;
-}
-
-/**
  * gcm_calibrate_device:
  **/
 gboolean
@@ -940,12 +671,13 @@ gcm_calibrate_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error
 #endif
 	}
 
-	/* TRANSLATORS: title, we're setting up the device ready for calibration */
-	title = _("Setting up device");
+	/* TRANSLATORS: this is the window title for when the user selects the chart type.
+	                A chart is a type of reference image the user has purchased. */
+	title = _("Please select chart type");
 	g_string_set_size (string, 0);
 
 	/* TRANSLATORS: dialog message, preface */
-	g_string_append_printf (string, "%s\n", _("Before calibrating the device, you have to manually acquire a reference image and save it as a TIFF image file."));
+	g_string_append_printf (string, "%s\n", _("Before calibrating the device, you have to manually capture an image of a calibrated target and save it as a TIFF image file."));
 
 	/* TRANSLATORS: dialog message, preface */
 	g_string_append_printf (string, "%s\n", _("Ensure that the contrast and brightness is not changed and color correction profiles are not applied."));
@@ -954,35 +686,29 @@ gcm_calibrate_device (GcmCalibrate *calibrate, GtkWindow *window, GError **error
 	g_string_append_printf (string, "%s\n", _("The device sensor should have been cleaned prior to scanning and the output file resolution should be at least 200dpi."));
 
 	/* TRANSLATORS: dialog message, suffix */
-	g_string_append_printf (string, "\n%s\n", _("For best results, the reference image should also be less than two years old."));
+	g_string_append_printf (string, "\n%s\n", _("For best results, the reference target should also be less than two years old."));
 
-	/* TRANSLATORS: dialog question */
-	g_string_append_printf (string, "\n%s", _("Do you have a TIFF file of the reference image?"));
+	/* TRANSLATORS: this is the message body for the chart selection */
+	g_string_append_printf (string, "\n%s\n", _("Please select the chart type which corresponds to your reference file."));
 
-	/* ask the user to confirm */
-	dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL, "%s", title);
-	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", string->str);
-	gtk_window_set_icon_name (GTK_WINDOW (dialog), GCM_STOCK_ICON);
-	/* TRANSLATORS: button, confirm the user has a file */
-	gtk_dialog_add_button (GTK_DIALOG (dialog), _("I have a reference file"), GTK_RESPONSE_YES);
-	response = gtk_dialog_run (GTK_DIALOG (dialog));
-	gtk_widget_destroy (dialog);
-	if (response != GTK_RESPONSE_YES) {
-		g_set_error_literal (error, 1, 0, "user has not got a file");
+	/* push new messages into the UI */
+	gcm_calibrate_dialog_show (priv->calibrate_dialog, GCM_CALIBRATE_DIALOG_TAB_TARGET_TYPE, title, string->str);
+	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, TRUE);
+	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
+	response = gcm_calibrate_dialog_run (priv->calibrate_dialog);
+	if (response != GTK_RESPONSE_OK) {
+		gcm_calibrate_dialog_hide (priv->calibrate_dialog);
+		g_set_error_literal (error, 1, 0, "user did not choose chart type");
 		ret = FALSE;
 		goto out;
 	}
 
-	/* set the reference kind */
-	priv->reference_kind = gcm_calibrate_get_reference_kind (window);
-	if (priv->reference_kind == GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN) {
-		g_set_error_literal (error, 1, 0, "could not get reference kind");
-		ret = FALSE;
-		goto out;
-	}
+	/* copy */
+	g_object_get (priv->calibrate_dialog, "reference-kind", &priv->reference_kind, NULL);
 
 	/* get scanned image */
 	directory = g_get_home_dir ();
+	window = gcm_calibrate_dialog_get_window (priv->calibrate_dialog);
 	reference_image = gcm_calibrate_device_get_reference_image (directory, window);
 	if (reference_image == NULL) {
 		g_set_error_literal (error, 1, 0, "could not get reference image");
@@ -1310,6 +1036,7 @@ gcm_calibrate_init (GcmCalibrate *calibrate)
 	calibrate->priv->device_kind = GCM_CALIBRATE_DEVICE_KIND_UNKNOWN;
 	calibrate->priv->reference_kind = GCM_CALIBRATE_REFERENCE_KIND_UNKNOWN;
 	calibrate->priv->colorimeter = gcm_colorimeter_new ();
+	calibrate->priv->calibrate_dialog = gcm_calibrate_dialog_new ();
 
 	/* coldplug, and watch for changes */
 	calibrate->priv->colorimeter_kind = gcm_colorimeter_get_kind (calibrate->priv->colorimeter);
@@ -1336,6 +1063,7 @@ gcm_calibrate_finalize (GObject *object)
 	g_free (priv->device);
 	g_free (priv->serial);
 	g_object_unref (priv->colorimeter);
+	g_object_unref (priv->calibrate_dialog);
 
 	G_OBJECT_CLASS (gcm_calibrate_parent_class)->finalize (object);
 }



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