[gnome-color-manager] Add UI elements to assign multiple profiles for each device



commit 53223d8c789c897d8aaee198deeaad78329770b1
Author: Richard Hughes <richard hughsie com>
Date:   Wed May 26 16:51:28 2010 +0100

    Add UI elements to assign multiple profiles for each device

 data/gcm-prefs.ui |  202 ++++++++++++++----
 src/gcm-prefs.c   |  640 +++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 638 insertions(+), 204 deletions(-)
---
diff --git a/data/gcm-prefs.ui b/data/gcm-prefs.ui
index d613fd3..c3dc27a 100644
--- a/data/gcm-prefs.ui
+++ b/data/gcm-prefs.ui
@@ -2,6 +2,7 @@
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
+  <object class="GtkListStore" id="liststore1"/>
   <object class="GtkDialog" id="dialog_prefs">
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Color Management</property>
@@ -62,7 +63,7 @@
                                 <property name="spacing">6</property>
                                 <child>
                                   <object class="GtkButton" id="button_device_add">
-                                    <property name="label" translatable="yes" comments="This is a button to add a virtual device">_Add device&#x2026;</property>
+                                    <property name="label" translatable="yes" comments="This is a button to add a virtual device">Add d_evice&#x2026;</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
@@ -77,7 +78,7 @@
                                 </child>
                                 <child>
                                   <object class="GtkButton" id="button_delete">
-                                    <property name="label" translatable="yes" comments="This is a button to delete the saved or virtual device">Remove device</property>
+                                    <property name="label" translatable="yes" comments="This is a button to delete the saved or virtual device">Remove de_vice</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
@@ -124,7 +125,7 @@
                                 <child>
                                   <object class="GtkLabel" id="label_profile">
                                     <property name="visible">True</property>
-                                    <property name="label" translatable="yes" comments="Section heading for device profile settings">Color Profile</property>
+                                    <property name="label" translatable="yes" comments="Section heading for device profile settings">Color Profiles</property>
                                     <attributes>
                                       <attribute name="weight" value="bold"/>
                                     </attributes>
@@ -145,21 +146,22 @@
                                 <property name="visible">True</property>
                                 <property name="left_padding">12</property>
                                 <child>
-                                  <object class="GtkHBox" id="hbox29">
+                                  <object class="GtkHBox" id="hbox_assign">
                                     <property name="visible">True</property>
-                                    <property name="spacing">9</property>
+                                    <property name="spacing">6</property>
                                     <child>
-                                      <object class="GtkVBox" id="vbox5">
+                                      <object class="GtkScrolledWindow" id="scrolledwindow_assign">
                                         <property name="visible">True</property>
-                                        <property name="orientation">vertical</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="hscrollbar_policy">automatic</property>
+                                        <property name="vscrollbar_policy">automatic</property>
+                                        <property name="shadow_type">in</property>
                                         <child>
-                                          <object class="GtkComboBox" id="combobox_profile">
+                                          <object class="GtkTreeView" id="treeview_assign">
                                             <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="headers_visible">False</property>
                                           </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">0</property>
-                                          </packing>
                                         </child>
                                       </object>
                                       <packing>
@@ -167,12 +169,60 @@
                                       </packing>
                                     </child>
                                     <child>
-                                      <object class="GtkButton" id="button_calibrate">
-                                        <property name="label" translatable="yes" comments="This is a button to calibrate the device by creating an ICC profile file using a hardware device or a reference image">Create _Profile</property>
+                                      <object class="GtkHBox" id="hbox55">
                                         <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <property name="use_underline">True</property>
+                                        <property name="orientation">vertical</property>
+                                        <property name="spacing">6</property>
+                                        <child>
+                                          <object class="GtkButton" id="button_assign_add">
+                                            <property name="label">gtk-add</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="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkButton" id="button_assign_remove">
+                                            <property name="label">gtk-remove</property>
+                                            <property name="visible">True</property>
+                                            <property name="sensitive">False</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                            <property name="use_stock">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkButton" id="button_calibrate">
+                                            <property name="label" translatable="yes" comments="This is a button to calibrate the device by creating an ICC profile file using a hardware device or a reference image">Create _Profile</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                            <property name="use_underline">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkButton" id="button_assign_make_default">
+                                            <property name="label" translatable="yes" comments="Makes the profile the default for the device">_Make Default</property>
+                                            <property name="visible">True</property>
+                                            <property name="sensitive">False</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                            <property name="use_underline">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="position">3</property>
+                                          </packing>
+                                        </child>
                                       </object>
                                       <packing>
                                         <property name="expand">False</property>
@@ -475,7 +525,6 @@
                                 <child>
                                   <object class="GtkVBox" id="vbox10">
                                     <property name="visible">True</property>
-                                    <property name="orientation">vertical</property>
                                     <property name="spacing">3</property>
                                     <child>
                                       <object class="GtkTable" id="table1">
@@ -591,7 +640,7 @@
                                         <property name="visible">True</property>
                                         <child>
                                           <object class="GtkButton" id="button_reset">
-                                            <property name="label" translatable="yes" comments="This resets the device to it's defaults, and removes any user tweaked settings.">_Reset to defaults</property>
+                                            <property name="label" translatable="yes" comments="This resets the device to it's defaults, and removes any user tweaked settings.">Rese_t</property>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">True</property>
@@ -691,7 +740,7 @@
                             </child>
                             <child>
                               <object class="GtkButton" id="button_profile_delete">
-                                <property name="label" translatable="yes">Remove</property>
+                                <property name="label" translatable="yes">_Remove</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">True</property>
@@ -1416,7 +1465,7 @@
                             </child>
                             <child>
                               <object class="GtkCheckButton" id="checkbutton_profile">
-                                <property name="label" translatable="yes">_Set profile for color managed applications</property>
+                                <property name="label" translatable="yes">Set profile for _color managed applications</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
@@ -1718,7 +1767,7 @@
             </child>
             <child>
               <object class="GtkButton" id="button_default">
-                <property name="label" translatable="yes">_Make Default</property>
+                <property name="label" translatable="yes" comments="This is when the settings are set for all users, unless they have per-user settings themselves">_Set System Default</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -2045,47 +2094,120 @@
       <action-widget response="0">button_virtual_add</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkDialog" id="dialog_assign">
+    <property name="border_width">5</property>
+    <property name="title"> </property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="icon_name">gnome-color-manager</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="skip_pager_hint">True</property>
+    <property name="transient_for">dialog_prefs</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox3">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkComboBox" id="combobox_profile">
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button_assign_cancel">
+                <property name="label">gtk-cancel</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">0</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_assign_ok">
+                <property name="label">gtk-add</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">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">button_assign_cancel</action-widget>
+      <action-widget response="0">button_assign_ok</action-widget>
+    </action-widgets>
+  </object>
   <object class="GtkSizeGroup" id="sizegroup_lists">
     <widgets>
-      <widget name="scrolledwindow2"/>
       <widget name="scrolledwindow1"/>
+      <widget name="scrolledwindow2"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="sizegroup_defaults">
     <widgets>
-      <widget name="hbox17"/>
-      <widget name="hbox15"/>
-      <widget name="hbox46"/>
       <widget name="hbox43"/>
+      <widget name="hbox46"/>
+      <widget name="hbox15"/>
+      <widget name="hbox17"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="sizegroup_devices">
     <widgets>
-      <widget name="hbox53"/>
-      <widget name="hbox23"/>
-      <widget name="hbox22"/>
       <widget name="hbox21"/>
+      <widget name="hbox22"/>
+      <widget name="hbox23"/>
+      <widget name="hbox53"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="sizegroup_profiles">
     <widgets>
-      <widget name="hbox33"/>
-      <widget name="hbox31"/>
-      <widget name="hbox12"/>
-      <widget name="hbox48"/>
-      <widget name="hbox34"/>
-      <widget name="hbox10"/>
-      <widget name="hbox36"/>
-      <widget name="hbox39"/>
       <widget name="hbox6"/>
+      <widget name="hbox39"/>
+      <widget name="hbox36"/>
+      <widget name="hbox10"/>
+      <widget name="hbox34"/>
+      <widget name="hbox48"/>
+      <widget name="hbox12"/>
+      <widget name="hbox31"/>
+      <widget name="hbox33"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="sizegroup_combos">
     <widgets>
-      <widget name="combobox_space_rgb"/>
-      <widget name="combobox_space_cmyk"/>
-      <widget name="combobox_rendering_display"/>
       <widget name="combobox_rendering_softproof"/>
+      <widget name="combobox_rendering_display"/>
+      <widget name="combobox_space_cmyk"/>
+      <widget name="combobox_space_rgb"/>
     </widgets>
   </object>
 </interface>
diff --git a/src/gcm-prefs.c b/src/gcm-prefs.c
index 83b972c..e5fd7db 100644
--- a/src/gcm-prefs.c
+++ b/src/gcm-prefs.c
@@ -50,6 +50,7 @@
 static GtkBuilder *builder = NULL;
 static GtkListStore *list_store_devices = NULL;
 static GtkListStore *list_store_profiles = NULL;
+static GtkListStore *list_store_assign = NULL;
 static GcmDevice *current_device = NULL;
 static GcmProfileStore *profile_store = NULL;
 static GcmClient *gcm_client = NULL;
@@ -79,6 +80,13 @@ enum {
 };
 
 enum {
+	GCM_ASSIGN_COLUMN_SORT,
+	GCM_ASSIGN_COLUMN_PROFILE,
+	GCM_ASSIGN_COLUMN_IS_DEFAULT,
+	GCM_ASSIGN_COLUMN_LAST
+};
+
+enum {
 	GCM_PREFS_COMBO_COLUMN_TEXT,
 	GCM_PREFS_COMBO_COLUMN_PROFILE,
 	GCM_PREFS_COMBO_COLUMN_TYPE,
@@ -88,14 +96,14 @@ enum {
 
 typedef enum {
 	GCM_PREFS_ENTRY_TYPE_PROFILE,
-	GCM_PREFS_ENTRY_TYPE_NONE,
 	GCM_PREFS_ENTRY_TYPE_IMPORT,
 	GCM_PREFS_ENTRY_TYPE_LAST
 } GcmPrefsEntryType;
 
 static void gcm_prefs_devices_treeview_clicked_cb (GtkTreeSelection *selection, gpointer userdata);
 
-#define GCM_PREFS_TREEVIEW_WIDTH	350 /* px */
+#define GCM_PREFS_TREEVIEW_MAIN_WIDTH		350 /* px */
+#define GCM_PREFS_TREEVIEW_PROFILES_WIDTH	450 /* px */
 
 /**
  * gcm_prefs_error_dialog:
@@ -178,11 +186,7 @@ gcm_prefs_combobox_add_profile (GtkWidget *widget, GcmProfile *profile, GcmPrefs
 		iter = &iter_tmp;
 
 	/* use description */
-	if (entry_type == GCM_PREFS_ENTRY_TYPE_NONE) {
-		/* TRANSLATORS: this is where no profile is selected */
-		description = _("None");
-		sortable = g_strdup ("1");
-	} else if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT) {
+	if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT) {
 		/* TRANSLATORS: this is where the user can click and import a profile */
 		description = _("Other profileâ?¦");
 		sortable = g_strdup ("9");
@@ -1007,6 +1011,256 @@ gcm_prefs_device_add_cb (GtkWidget *widget, gpointer data)
 }
 
 /**
+ * gcm_prefs_is_profile_suitable_for_device:
+ **/
+static gboolean
+gcm_prefs_is_profile_suitable_for_device (GcmProfile *profile, GcmDevice *device)
+{
+	GcmProfileKind profile_kind_tmp;
+	GcmProfileKind profile_kind;
+	GcmColorspace profile_colorspace;
+	GcmColorspace device_colorspace;
+	gboolean ret = FALSE;
+	GcmDeviceKind device_kind;
+
+	/* not the right colorspace */
+	device_colorspace = gcm_device_get_colorspace (device);
+	profile_colorspace = gcm_profile_get_colorspace (profile);
+	if (device_colorspace != profile_colorspace)
+		goto out;
+
+	/* not the correct kind */
+	device_kind = gcm_device_get_kind (device);
+	profile_kind_tmp = gcm_profile_get_kind (profile);
+	profile_kind = gcm_utils_device_kind_to_profile_kind (device_kind);
+	if (profile_kind_tmp != profile_kind)
+		goto out;
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_prefs_add_profiles_suitable_for_devices:
+ **/
+static void
+gcm_prefs_add_profiles_suitable_for_devices (GtkWidget *widget, const gchar *profile_filename)
+{
+	GtkTreeModel *model;
+	guint i;
+	gboolean ret;
+	GcmProfile *profile;
+	GPtrArray *profile_array;
+	GtkTreeIter iter;
+
+	/* clear existing entries */
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+	gtk_list_store_clear (GTK_LIST_STORE (model));
+
+	/* get new list */
+	profile_array = gcm_profile_store_get_array (profile_store);
+
+	/* add profiles of the right kind */
+	for (i=0; i<profile_array->len; i++) {
+		profile = g_ptr_array_index (profile_array, i);
+
+		/* don't add the current profile */
+		if (g_strcmp0 (gcm_profile_get_filename (profile), profile_filename) == 0)
+			continue;
+
+		/* only add correct types */
+		ret = gcm_prefs_is_profile_suitable_for_device (profile, current_device);
+		if (!ret)
+			continue;
+
+		/* add */
+		gcm_prefs_combobox_add_profile (widget, profile, GCM_PREFS_ENTRY_TYPE_PROFILE, &iter);
+	}
+
+	/* add a import entry */
+	gcm_prefs_combobox_add_profile (widget, NULL, GCM_PREFS_ENTRY_TYPE_IMPORT, NULL);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+	g_ptr_array_unref (profile_array);
+}
+
+/**
+ * gcm_prefs_assign_save_profiles_for_device:
+ **/
+static void
+gcm_prefs_assign_save_profiles_for_device (GcmDevice *device)
+{
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	gboolean is_default;
+	GcmProfile *profile;
+	GPtrArray *array;
+	gboolean ret;
+	GError *error = NULL;
+
+	/* create empty array */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* get first element */
+	model = GTK_TREE_MODEL (list_store_assign);
+	ret = gtk_tree_model_get_iter_first (model, &iter);
+	if (!ret)
+		goto set_profiles;
+
+	/* add default device first */
+	do {
+		gtk_tree_model_get (model, &iter,
+				    GCM_ASSIGN_COLUMN_PROFILE, &profile,
+				    GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+				    -1);
+		if (is_default)
+			g_ptr_array_add (array, g_object_ref (profile));
+		g_object_unref (profile);
+	} while (gtk_tree_model_iter_next (model, &iter));
+
+	/* add non-default devices next */
+	gtk_tree_model_get_iter_first (model, &iter);
+	do {
+		gtk_tree_model_get (model, &iter,
+				    GCM_ASSIGN_COLUMN_PROFILE, &profile,
+				    GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+				    -1);
+		if (!is_default)
+			g_ptr_array_add (array, g_object_ref (profile));
+		g_object_unref (profile);
+	} while (gtk_tree_model_iter_next (model, &iter));
+
+set_profiles:
+	/* save new array */
+	gcm_device_set_profiles (device, array);
+
+	/* save */
+	ret = gcm_device_save (current_device, &error);
+	if (!ret) {
+		egg_warning ("failed to save config: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* set the profile */
+	ret = gcm_device_apply (current_device, &error);
+	if (!ret) {
+		egg_warning ("failed to apply profile: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+out:
+	g_ptr_array_unref (array);
+}
+
+/**
+ * gcm_prefs_assign_add_cb:
+ **/
+static void
+gcm_prefs_assign_add_cb (GtkWidget *widget, gpointer data)
+{
+	const gchar *profile_filename;
+
+	/* add profiles of the right kind */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_profile"));
+	profile_filename = gcm_device_get_default_profile_filename (current_device);
+	gcm_prefs_add_profiles_suitable_for_devices (widget, profile_filename);
+
+	/* show the dialog */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_assign"));
+	gtk_widget_show (widget);
+}
+
+/**
+ * gcm_prefs_assign_remove_cb:
+ **/
+static void
+gcm_prefs_assign_remove_cb (GtkWidget *widget, gpointer data)
+{
+	GtkTreeIter iter;
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	gboolean is_default;
+	gboolean ret;
+
+	/* get the selected row */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "treeview_assign"));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		egg_debug ("no row selected");
+		goto out;
+	}
+
+	/* if the profile is default, then we'll have to make the first profile default */
+	gtk_tree_model_get (model, &iter,
+			    GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+			    -1);
+
+	/* remove this entry */
+	gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
+
+	/* /something/ has to be the default profile */
+	if (is_default) {
+		ret = gtk_tree_model_get_iter_first (model, &iter);
+		if (ret) {
+			gtk_list_store_set (list_store_assign, &iter,
+					    GCM_ASSIGN_COLUMN_IS_DEFAULT, TRUE,
+					    -1);
+		}
+	}
+
+	/* save device */
+	gcm_prefs_assign_save_profiles_for_device (current_device);
+out:
+	return;
+}
+
+/**
+ * gcm_prefs_assign_make_default_cb:
+ **/
+static void
+gcm_prefs_assign_make_default_cb (GtkWidget *widget, gpointer data)
+{
+	GtkTreeIter iter;
+	GtkTreeIter iter_selected;
+	GtkTreeModel *model;
+	GtkTreeSelection *selection;
+
+	/* get the selected row */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "treeview_assign"));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter_selected)) {
+		egg_debug ("no row selected");
+		goto out;
+	}
+
+	/* make none of the devices default */
+	gtk_tree_model_get_iter_first (model, &iter);
+	do {
+		gtk_list_store_set (list_store_assign, &iter,
+				    GCM_ASSIGN_COLUMN_SORT, "1",
+				    GCM_ASSIGN_COLUMN_IS_DEFAULT, FALSE,
+				    -1);
+	} while (gtk_tree_model_iter_next (model, &iter));
+
+	/* make the selected device default */
+	gtk_list_store_set (list_store_assign, &iter_selected,
+			    GCM_ASSIGN_COLUMN_IS_DEFAULT, TRUE,
+			    GCM_ASSIGN_COLUMN_SORT, "0",
+			    -1);
+
+	/* set button insensitive */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_make_default"));
+	gtk_widget_set_sensitive (widget, FALSE);
+
+	/* save device */
+	gcm_prefs_assign_save_profiles_for_device (current_device);
+out:
+	return;
+}
+
+/**
  * gcm_prefs_button_virtual_add_cb:
  **/
 static void
@@ -1083,6 +1337,68 @@ gcm_prefs_virtual_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer
 }
 
 /**
+ * gcm_prefs_button_assign_cancel_cb:
+ **/
+static void
+gcm_prefs_button_assign_cancel_cb (GtkWidget *widget, gpointer data)
+{
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_assign"));
+	gtk_widget_hide (widget);
+}
+
+/**
+ * gcm_prefs_button_assign_ok_cb:
+ **/
+static void
+gcm_prefs_button_assign_ok_cb (GtkWidget *widget, gpointer data)
+{
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	GcmProfile *profile;
+	gboolean is_default = FALSE;
+	gboolean ret;
+
+	/* hide window */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_assign"));
+	gtk_widget_hide (widget);
+
+	/* get entry */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_profile"));
+	ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+	if (!ret)
+		return;
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+	gtk_tree_model_get (model, &iter,
+			    GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+			    -1);
+
+	/* if list is empty, we want this to be the default item */
+	model = GTK_TREE_MODEL (list_store_assign);
+	is_default = !gtk_tree_model_get_iter_first (model, &iter);
+
+	/* add profile */
+	gtk_list_store_append (list_store_assign, &iter);
+	gtk_list_store_set (list_store_assign, &iter,
+			    GCM_ASSIGN_COLUMN_PROFILE, profile,
+			    GCM_ASSIGN_COLUMN_SORT, "1",
+			    GCM_ASSIGN_COLUMN_IS_DEFAULT, is_default,
+			    -1);
+
+	/* save device */
+	gcm_prefs_assign_save_profiles_for_device (current_device);
+}
+
+/**
+ * gcm_prefs_assign_delete_event_cb:
+ **/
+static gboolean
+gcm_prefs_assign_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+	gcm_prefs_button_assign_cancel_cb (widget, data);
+	return TRUE;
+}
+
+/**
  * gcm_prefs_delete_cb:
  **/
 static void
@@ -1167,13 +1483,13 @@ gcm_prefs_add_devices_columns (GtkTreeView *treeview)
 	gtk_tree_view_append_column (treeview, column);
 
 	/* set minimum width */
-	gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_WIDTH, -1);
+	gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_MAIN_WIDTH, -1);
 
 	/* column for text */
 	renderer = gtk_cell_renderer_text_new ();
 	g_object_set (renderer,
 		      "wrap-mode", PANGO_WRAP_WORD,
-		      "wrap-width", GCM_PREFS_TREEVIEW_WIDTH - 62,
+		      "wrap-width", GCM_PREFS_TREEVIEW_MAIN_WIDTH - 62,
 		      NULL);
 	column = gtk_tree_view_column_new_with_attributes ("", renderer,
 							   "markup", GCM_DEVICES_COLUMN_TITLE, NULL);
@@ -1200,13 +1516,13 @@ gcm_prefs_add_profiles_columns (GtkTreeView *treeview)
 	gtk_tree_view_append_column (treeview, column);
 
 	/* set minimum width */
-	gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_WIDTH, -1);
+	gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_MAIN_WIDTH, -1);
 
 	/* column for text */
 	renderer = gcm_cell_renderer_profile_new ();
 	g_object_set (renderer,
 		      "wrap-mode", PANGO_WRAP_WORD,
-		      "wrap-width", GCM_PREFS_TREEVIEW_WIDTH - 62,
+		      "wrap-width", GCM_PREFS_TREEVIEW_MAIN_WIDTH - 62,
 		      NULL);
 	column = gtk_tree_view_column_new_with_attributes ("", renderer,
 							   "profile", GCM_PROFILES_COLUMN_PROFILE, NULL);
@@ -1217,6 +1533,34 @@ gcm_prefs_add_profiles_columns (GtkTreeView *treeview)
 }
 
 /**
+ * gcm_prefs_add_assign_columns:
+ **/
+static void
+gcm_prefs_add_assign_columns (GtkTreeView *treeview)
+{
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+
+	/* set minimum width */
+	gtk_widget_set_size_request (GTK_WIDGET (treeview), GCM_PREFS_TREEVIEW_PROFILES_WIDTH, -1);
+
+	/* column for text */
+	renderer = gcm_cell_renderer_profile_new ();
+	g_object_set (renderer,
+		      "wrap-mode", PANGO_WRAP_WORD,
+		      "wrap-width", GCM_PREFS_TREEVIEW_PROFILES_WIDTH - 62,
+		      NULL);
+	column = gtk_tree_view_column_new_with_attributes ("", renderer,
+							   "profile", GCM_ASSIGN_COLUMN_PROFILE,
+							   "is-default", GCM_ASSIGN_COLUMN_IS_DEFAULT,
+							   NULL);
+	gtk_tree_view_column_set_sort_column_id (column, GCM_ASSIGN_COLUMN_SORT);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store_assign), GCM_ASSIGN_COLUMN_SORT, GTK_SORT_ASCENDING);
+	gtk_tree_view_append_column (treeview, column);
+	gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
  * gcm_prefs_set_calibrate_button_sensitivity:
  **/
 static void
@@ -1303,104 +1647,15 @@ out:
 }
 
 /**
- * gcm_prefs_is_profile_suitable_for_device:
- **/
-static gboolean
-gcm_prefs_is_profile_suitable_for_device (GcmProfile *profile, GcmDevice *device)
-{
-	GcmProfileKind profile_kind_tmp;
-	GcmProfileKind profile_kind;
-	GcmColorspace profile_colorspace;
-	GcmColorspace device_colorspace;
-	gboolean ret = FALSE;
-	GcmDeviceKind device_kind;
-
-	/* not the right colorspace */
-	device_colorspace = gcm_device_get_colorspace (device);
-	profile_colorspace = gcm_profile_get_colorspace (profile);
-	if (device_colorspace != profile_colorspace)
-		goto out;
-
-	/* not the correct kind */
-	device_kind = gcm_device_get_kind (device);
-	profile_kind_tmp = gcm_profile_get_kind (profile);
-	profile_kind = gcm_utils_device_kind_to_profile_kind (device_kind);
-	if (profile_kind_tmp != profile_kind)
-		goto out;
-
-	/* success */
-	ret = TRUE;
-out:
-	return ret;
-}
-
-/**
- * gcm_prefs_add_profiles_suitable_for_devices:
- **/
-static void
-gcm_prefs_add_profiles_suitable_for_devices (GtkWidget *widget, const gchar *profile_filename)
-{
-	GtkTreeModel *model;
-	guint i;
-	const gchar *filename;
-	gboolean ret;
-	gboolean set_active = FALSE;
-	GcmProfile *profile;
-	GPtrArray *profile_array = NULL;
-	GtkTreeIter iter;
-
-	/* clear existing entries */
-	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
-	gtk_list_store_clear (GTK_LIST_STORE (model));
-
-	/* add a 'None' entry */
-	gcm_prefs_combobox_add_profile (widget, NULL, GCM_PREFS_ENTRY_TYPE_NONE, NULL);
-
-	/* get new list */
-	profile_array = gcm_profile_store_get_array (profile_store);
-
-	/* add profiles of the right kind */
-	for (i=0; i<profile_array->len; i++) {
-		profile = g_ptr_array_index (profile_array, i);
-
-		/* only add correct types */
-		ret = gcm_prefs_is_profile_suitable_for_device (profile, current_device);
-		if (ret) {
-			/* add */
-			gcm_prefs_combobox_add_profile (widget, profile, GCM_PREFS_ENTRY_TYPE_PROFILE, &iter);
-
-			/* set active option */
-			filename = gcm_profile_get_filename (profile);
-			if (g_strcmp0 (filename, profile_filename) == 0) {
-				//FIXME: does not work for sorted lists
-				gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
-				set_active = TRUE;
-			}
-		}
-	}
-
-	/* add a import entry */
-	gcm_prefs_combobox_add_profile (widget, NULL, GCM_PREFS_ENTRY_TYPE_IMPORT, NULL);
-
-	/* select 'None' if there was no match */
-	if (!set_active) {
-		if (profile_filename != NULL)
-			egg_warning ("no match for %s", profile_filename);
-		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
-	}
-	if (profile_array != NULL)
-		g_ptr_array_unref (profile_array);
-}
-
-/**
  * gcm_prefs_devices_treeview_clicked_cb:
  **/
 static void
 gcm_prefs_devices_treeview_clicked_cb (GtkTreeSelection *selection, gpointer userdata)
 {
+	guint i;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
-	const gchar *profile_filename = NULL;
+	GtkTreePath *path;
 	GtkWidget *widget;
 	gfloat localgamma;
 	gfloat brightness;
@@ -1413,6 +1668,8 @@ gcm_prefs_devices_treeview_clicked_cb (GtkTreeSelection *selection, gpointer use
 	const gchar *device_model = NULL;
 	const gchar *device_manufacturer = NULL;
 	const gchar *eisa_id = NULL;
+	GPtrArray *profiles;
+	GcmProfile *profile;
 
 	/* This will only work in single or browse selection mode! */
 	if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
@@ -1523,10 +1780,27 @@ gcm_prefs_devices_treeview_clicked_cb (GtkTreeSelection *selection, gpointer use
 	gtk_range_set_value (GTK_RANGE (widget), contrast);
 	setting_up_device = FALSE;
 
-	/* add profiles of the right kind */
-	widget = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_profile"));
-	profile_filename = gcm_device_get_default_profile_filename (current_device);
-	gcm_prefs_add_profiles_suitable_for_devices (widget, profile_filename);
+	/* clear existing list */
+	gtk_list_store_clear (list_store_assign);
+
+	/* add profiles for the device */
+	profiles = gcm_device_get_profiles (current_device);
+	for (i=0; i<profiles->len; i++) {
+		profile = g_ptr_array_index (profiles, i);
+		gtk_list_store_append (list_store_assign, &iter);
+		gtk_list_store_set (list_store_assign, &iter,
+				    GCM_ASSIGN_COLUMN_PROFILE, profile,
+				    GCM_ASSIGN_COLUMN_SORT, "0",
+				    GCM_ASSIGN_COLUMN_IS_DEFAULT, (i == 0),
+				    -1);
+	}
+
+	/* select the default profile to display */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "treeview_assign"));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+	path = gtk_tree_path_new_from_string ("0");
+	gtk_tree_selection_select_path (selection, path);
+	gtk_tree_path_free (path);
 
 	/* make sure selectable */
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_profile"));
@@ -1636,6 +1910,54 @@ gcm_prefs_profile_colorspace_to_string (GcmColorspace colorspace)
 }
 
 /**
+ * gcm_prefs_assign_treeview_clicked_cb:
+ **/
+static void
+gcm_prefs_assign_treeview_clicked_cb (GtkTreeSelection *selection, gpointer userdata)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean is_default;
+	GtkWidget *widget;
+	GcmProfile *profile;
+
+	/* This will only work in single or browse selection mode! */
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+
+		widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_make_default"));
+		gtk_widget_set_sensitive (widget, FALSE);
+		widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_remove"));
+		gtk_widget_set_sensitive (widget, FALSE);
+
+		egg_debug ("no row selected");
+		return;
+	}
+
+	/* get profile */
+	gtk_tree_model_get (model, &iter,
+			    GCM_ASSIGN_COLUMN_PROFILE, &profile,
+			    GCM_ASSIGN_COLUMN_IS_DEFAULT, &is_default,
+			    -1);
+	egg_debug ("selected profile = %s", gcm_profile_get_filename (profile));
+
+	/* is the element the first in the list */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_make_default"));
+	gtk_widget_set_sensitive (widget, !is_default);
+
+	/* we can remove it now */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_remove"));
+	gtk_widget_set_sensitive (widget, TRUE);
+
+	/* show a warning if the profile is crap */
+	if (gcm_device_get_kind (current_device) == GCM_DEVICE_KIND_DISPLAY &&
+	    !gcm_profile_get_has_vcgt (profile)) {
+		gtk_widget_show (info_bar_vcgt);
+	} else {
+		gtk_widget_hide (info_bar_vcgt);
+	}
+}
+
+/**
  * gcm_prefs_profiles_treeview_clicked_cb:
  **/
 static void
@@ -1956,19 +2278,14 @@ gcm_prefs_set_combo_simple_text (GtkWidget *combo_box)
 static void
 gcm_prefs_profile_combo_changed_cb (GtkWidget *widget, gpointer data)
 {
-	const gchar *profile_old;
 	GFile *file = NULL;
 	GFile *dest = NULL;
 	gboolean ret;
 	GError *error = NULL;
 	GcmProfile *profile = NULL;
-	GcmProfile *profile_tmp = NULL;
-	gboolean changed;
-	GcmDeviceKind kind;
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 	GcmPrefsEntryType entry_type;
-	gboolean has_vcgt;
 	gchar *filename = NULL;
 
 	/* no devices */
@@ -1983,7 +2300,6 @@ gcm_prefs_profile_combo_changed_cb (GtkWidget *widget, gpointer data)
 	/* get entry */
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
 	gtk_tree_model_get (model, &iter,
-			    GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
 			    GCM_PREFS_COMBO_COLUMN_TYPE, &entry_type,
 			    -1);
 
@@ -1997,18 +2313,17 @@ gcm_prefs_profile_combo_changed_cb (GtkWidget *widget, gpointer data)
 		}
 
 		/* check the file is suitable */
-		profile_tmp = gcm_profile_default_new ();
+		profile = gcm_profile_default_new ();
 		filename = g_file_get_path (file);
-		ret = gcm_profile_parse (profile_tmp, file, &error);
+		ret = gcm_profile_parse (profile, file, &error);
 		if (!ret) {
-			/* set to 'None' */
+			/* set to first entry */
 			gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
-
 			egg_warning ("failed to parse ICC file: %s", error->message);
 			g_error_free (error);
 			goto out;
 		}
-		ret = gcm_prefs_is_profile_suitable_for_device (profile_tmp, current_device);
+		ret = gcm_prefs_is_profile_suitable_for_device (profile, current_device);
 		if (!ret) {
 			/* set to 'None' */
 			gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
@@ -2034,58 +2349,22 @@ gcm_prefs_profile_combo_changed_cb (GtkWidget *widget, gpointer data)
 		/* now use the new profile as the device default */
 		dest = gcm_utils_get_profile_destination (file);
 		filename = g_file_get_path (dest);
-	}
-
-	/* get the device kind */
-	kind = gcm_device_get_kind (current_device);
-
-	/* get profile filename */
-	if (entry_type == GCM_PREFS_ENTRY_TYPE_PROFILE) {
-
-		/* show a warning if the profile is crap */
-		filename = g_strdup (gcm_profile_get_filename (profile));
-		has_vcgt = gcm_profile_get_has_vcgt (profile);
-		if (kind == GCM_DEVICE_KIND_DISPLAY && !has_vcgt && filename != NULL) {
-			gtk_widget_show (info_bar_vcgt);
-		} else {
-			gtk_widget_hide (info_bar_vcgt);
-		}
-	} else {
-		gtk_widget_hide (info_bar_vcgt);
-	}
-
-	/* see if it's changed */
-	profile_old = gcm_device_get_default_profile_filename (current_device);
-	egg_debug ("old: %s, new:%s", profile_old, filename);
-	changed = ((g_strcmp0 (profile_old, filename) != 0));
-
-	/* set new profile */
-	if (changed) {
-
-		/* save new profile */
-		gcm_device_set_default_profile_filename (current_device, filename);
-		ret = gcm_device_save (current_device, &error);
-		if (!ret) {
-			egg_warning ("failed to save config: %s", error->message);
-			g_error_free (error);
-			goto out;
-		}
 
-		/* set the profile */
-		ret = gcm_device_apply (current_device, &error);
-		if (!ret) {
-			egg_warning ("failed to apply profile: %s", error->message);
-			g_error_free (error);
-			goto out;
-		}
+		/* add to combobox */
+		gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+		gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+				    GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
+				    GCM_PREFS_COMBO_COLUMN_SORTABLE, "0",
+				    -1);
+		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
 	}
 out:
 	if (file != NULL)
 		g_object_unref (file);
 	if (dest != NULL)
 		g_object_unref (dest);
-	if (profile_tmp != NULL)
-		g_object_unref (profile_tmp);
+	if (profile != NULL)
+		g_object_unref (profile);
 }
 
 /**
@@ -2234,7 +2513,6 @@ gcm_prefs_add_device_kind (GcmDevice *device)
 	g_string_free (string, TRUE);
 }
 
-
 /**
  * gcm_prefs_remove_device:
  **/
@@ -2475,7 +2753,6 @@ out:
 		g_object_unref (profile);
 }
 
-
 /**
  * gcm_prefs_renderer_combo_changed_cb:
  **/
@@ -2867,6 +3144,18 @@ main (int argc, char **argv)
 						 G_TYPE_STRING, G_TYPE_STRING);
 	list_store_profiles = gtk_list_store_new (GCM_PROFILES_COLUMN_LAST, G_TYPE_STRING,
 						  G_TYPE_STRING, G_TYPE_STRING, GCM_TYPE_PROFILE);
+	list_store_assign = gtk_list_store_new (GCM_ASSIGN_COLUMN_LAST, G_TYPE_STRING, GCM_TYPE_PROFILE, G_TYPE_BOOLEAN);
+
+	/* assign buttons */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_add"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_prefs_assign_add_cb), NULL);
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_remove"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_prefs_assign_remove_cb), NULL);
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_make_default"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_prefs_assign_make_default_cb), NULL);
 
 	/* create device tree view */
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "treeview_devices"));
@@ -2892,6 +3181,18 @@ main (int argc, char **argv)
 	gcm_prefs_add_profiles_columns (GTK_TREE_VIEW (widget));
 	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
 
+	/* create assign tree view */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "treeview_assign"));
+	gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+				 GTK_TREE_MODEL (list_store_assign));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+	g_signal_connect (selection, "changed",
+			  G_CALLBACK (gcm_prefs_assign_treeview_clicked_cb), NULL);
+
+	/* add columns to the tree view */
+	gcm_prefs_add_assign_columns (GTK_TREE_VIEW (widget));
+	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+
 	main_window = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_prefs"));
 
 	/* Hide window first so that the dialogue resizes itself without redrawing */
@@ -2974,6 +3275,17 @@ main (int argc, char **argv)
 	gcm_prefs_set_combo_simple_text (widget);
 	gcm_prefs_setup_virtual_combobox (widget);
 
+	/* set up assign dialog */
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_assign"));
+	g_signal_connect (widget, "delete-event",
+			  G_CALLBACK (gcm_prefs_assign_delete_event_cb), NULL);
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_cancel"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_prefs_button_assign_cancel_cb), NULL);
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_assign_ok"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_prefs_button_assign_ok_cb), NULL);
+
 	/* disable the add button if nothing in either box */
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "entry_virtual_model"));
 	g_signal_connect (widget, "notify::text",



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