summaryrefslogtreecommitdiffstats
path: root/panels/color/cc-color-panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'panels/color/cc-color-panel.c')
-rw-r--r--panels/color/cc-color-panel.c2208
1 files changed, 2208 insertions, 0 deletions
diff --git a/panels/color/cc-color-panel.c b/panels/color/cc-color-panel.c
new file mode 100644
index 0000000..42820c7
--- /dev/null
+++ b/panels/color/cc-color-panel.c
@@ -0,0 +1,2208 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2011 Richard Hughes <richard@hughsie.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <colord.h>
+#include <gtk/gtk.h>
+#include <gdk/x11/gdkx.h>
+
+#include "cc-color-calibrate.h"
+#include "cc-color-cell-renderer-text.h"
+#include "cc-color-panel.h"
+#include "cc-color-resources.h"
+#include "cc-color-common.h"
+#include "cc-color-device.h"
+#include "cc-color-profile.h"
+
+struct _CcColorPanel
+{
+ CcPanel parent_instance;
+
+ CdClient *client;
+ CdDevice *current_device;
+ GPtrArray *devices;
+ GPtrArray *sensors;
+ GDBusProxy *proxy;
+ GSettings *settings;
+ GSettings *settings_colord;
+ GtkWidget *assistant_calib;
+ GtkWidget *box_calib_brightness;
+ GtkWidget *box_calib_kind;
+ GtkWidget *box_calib_quality;
+ GtkWidget *box_calib_sensor;
+ GtkWidget *box_calib_summary;
+ GtkWidget *box_calib_temp;
+ GtkWidget *box_calib_title;
+ GtkWidget *box_devices;
+ GtkWidget *button_assign_import;
+ GtkWidget *button_assign_ok;
+ GtkWidget *button_calib_export;
+ GtkWidget *dialog_assign;
+ GtkWidget *entry_calib_title;
+ GtkWidget *label_assign_warning;
+ GtkWidget *label_calib_summary_message;
+ GtkWidget *label_no_devices;
+ GtkTreeModel *liststore_assign;
+ GtkTreeModel *liststore_calib_kind;
+ GtkTreeModel *liststore_calib_sensor;
+ GtkWidget *toolbar_devices;
+ GtkWidget *toolbutton_device_calibrate;
+ GtkWidget *toolbutton_device_default;
+ GtkWidget *toolbutton_device_enable;
+ GtkWidget *toolbutton_profile_add;
+ GtkWidget *toolbutton_profile_remove;
+ GtkWidget *toolbutton_profile_view;
+ GtkWidget *treeview_assign;
+ GtkWidget *treeview_calib_kind;
+ GtkWidget *treeview_calib_quality;
+ GtkWidget *treeview_calib_sensor;
+ GtkWidget *treeview_calib_temp;
+ CcColorCalibrate *calibrate;
+ GtkListBox *list_box;
+ gchar *list_box_filter;
+ GtkSizeGroup *list_box_size;
+ gboolean is_live_cd;
+ gboolean model_is_changing;
+};
+
+CC_PANEL_REGISTER (CcColorPanel, cc_color_panel)
+
+enum {
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ GCM_PREFS_COMBO_COLUMN_PROFILE,
+ GCM_PREFS_COMBO_COLUMN_TYPE,
+ GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME,
+ GCM_PREFS_COMBO_COLUMN_NUM_COLUMNS
+};
+
+/* for the GtkListStores */
+enum {
+ COLUMN_CALIB_KIND_DESCRIPTION,
+ COLUMN_CALIB_KIND_CAP_VALUE,
+ COLUMN_CALIB_KIND_VISIBLE,
+ COLUMN_CALIB_KIND_LAST
+};
+enum {
+ COLUMN_CALIB_QUALITY_DESCRIPTION,
+ COLUMN_CALIB_QUALITY_APPROX_TIME,
+ COLUMN_CALIB_QUALITY_VALUE,
+ COLUMN_CALIB_QUALITY_LAST
+};
+enum {
+ COLUMN_CALIB_SENSOR_OBJECT,
+ COLUMN_CALIB_SENSOR_DESCRIPTION,
+ COLUMN_CALIB_SENSOR_LAST
+};
+enum {
+ COLUMN_CALIB_TEMP_DESCRIPTION,
+ COLUMN_CALIB_TEMP_VALUE_K,
+ COLUMN_CALIB_TEMP_LAST
+};
+
+#define COLORD_SETTINGS_SCHEMA "org.freedesktop.ColorHelper"
+#define GCM_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.color"
+#define GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD "recalibrate-printer-threshold"
+#define GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD "recalibrate-display-threshold"
+
+/* max number of devices and profiles to cause auto-expand at startup */
+#define GCM_PREFS_MAX_DEVICES_PROFILES_EXPANDED 5
+
+static void gcm_prefs_refresh_toolbar_buttons (CcColorPanel *panel);
+
+static void
+gcm_prefs_combobox_add_profile (CcColorPanel *prefs,
+ CdProfile *profile,
+ GtkTreeIter *iter)
+{
+ const gchar *id;
+ GtkTreeIter iter_tmp;
+ g_autoptr(GString) string = NULL;
+ gchar *escaped = NULL;
+ guint kind = 0;
+ const gchar *warning = NULL;
+#if CD_CHECK_VERSION(0,1,25)
+ gchar **warnings;
+#endif
+
+ /* iter is optional */
+ if (iter == NULL)
+ iter = &iter_tmp;
+
+ /* use description */
+ string = g_string_new (cd_profile_get_title (profile));
+
+ /* any source prefix? */
+ id = cd_profile_get_metadata_item (profile,
+ CD_PROFILE_METADATA_DATA_SOURCE);
+ if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_EDID) == 0)
+ {
+ /* TRANSLATORS: this is a profile prefix to signify the
+ * profile has been auto-generated for this hardware */
+ g_string_prepend (string, _("Default: "));
+ kind = 1;
+ }
+#if CD_CHECK_VERSION(0,1,14)
+ if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
+ {
+ /* TRANSLATORS: this is a profile prefix to signify the
+ * profile his a standard space like AdobeRGB */
+ g_string_prepend (string, _("Colorspace: "));
+ kind = 2;
+ }
+ if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_TEST) == 0)
+ {
+ /* TRANSLATORS: this is a profile prefix to signify the
+ * profile is a test profile */
+ g_string_prepend (string, _("Test profile: "));
+ kind = 3;
+ }
+#endif
+
+ /* is the profile faulty */
+#if CD_CHECK_VERSION(0,1,25)
+ warnings = cd_profile_get_warnings (profile);
+ if (warnings != NULL && warnings[0] != NULL)
+ warning = "dialog-warning-symbolic";
+#endif
+
+ escaped = g_markup_escape_text (string->str, -1);
+ gtk_list_store_append (GTK_LIST_STORE (prefs->liststore_assign), iter);
+ gtk_list_store_set (GTK_LIST_STORE (prefs->liststore_assign), iter,
+ GCM_PREFS_COMBO_COLUMN_TEXT, escaped,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
+ GCM_PREFS_COMBO_COLUMN_TYPE, kind,
+ GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME, warning,
+ -1);
+}
+
+static void
+gcm_prefs_default_cb (CcColorPanel *prefs)
+{
+ g_autoptr(CdProfile) profile = NULL;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ /* TODO: check if the profile is already systemwide */
+ profile = cd_device_get_default_profile (prefs->current_device);
+ if (profile == NULL)
+ return;
+
+ /* install somewhere out of $HOME */
+ ret = cd_profile_install_system_wide_sync (profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ g_warning ("failed to set profile system-wide: %s",
+ error->message);
+}
+
+typedef struct
+{
+ GtkResponseType response;
+ GMainLoop *mainloop;
+} DialogRunData;
+
+static void
+dialog_response_cb (GtkDialog *dialog,
+ GtkResponseType response,
+ DialogRunData *run_data)
+{
+ run_data->response = response;
+ g_main_loop_quit (run_data->mainloop);
+}
+
+static gboolean
+dialog_close_cb (GtkDialog *dialog,
+ GtkResponseType response,
+ DialogRunData *run_data)
+{
+ g_main_loop_quit (run_data->mainloop);
+ return GDK_EVENT_PROPAGATE;
+}
+
+static GtkResponseType
+run_dialog (GtkDialog *dialog)
+{
+ g_autoptr(GMainLoop) mainloop = NULL;
+ DialogRunData run_data;
+ guint response_id;
+ guint close_id;
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ run_data = (DialogRunData) {
+ .response = GTK_RESPONSE_DELETE_EVENT,
+ .mainloop = mainloop,
+ };
+
+ response_id = g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), &run_data);
+ close_id = g_signal_connect (dialog, "close-request", G_CALLBACK (dialog_close_cb), &run_data);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ g_main_loop_run (mainloop);
+
+ g_signal_handler_disconnect (dialog, response_id);
+ g_signal_handler_disconnect (dialog, close_id);
+
+ return run_data.response;
+}
+
+static GFile *
+gcm_prefs_file_chooser_get_icc_profile (CcColorPanel *prefs)
+{
+ g_autoptr(GFile) current_folder = NULL;
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GFile *file = NULL;
+ GtkFileFilter *filter;
+
+ /* create new dialog */
+ window = GTK_WINDOW (prefs->dialog_assign);
+ /* TRANSLATORS: an ICC profile is a file containing colorspace data */
+ dialog = gtk_file_chooser_dialog_new (_("Select ICC Profile File"), window,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Import"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ current_folder = g_file_new_for_path (g_get_home_dir ());
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(dialog), current_folder, NULL);
+ gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER(dialog), FALSE);
+
+ /* setup the filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_mime_type (filter, "application/vnd.iccprofile");
+
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("Supported ICC profiles"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* setup the all files filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* did user choose file */
+ if (run_dialog (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER(dialog));
+
+ /* we're done */
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ /* or NULL for missing */
+ return file;
+}
+
+static void
+gcm_prefs_calib_cancel_cb (CcColorPanel *prefs)
+{
+ gtk_widget_hide (prefs->assistant_calib);
+}
+
+static gboolean
+gcm_prefs_calib_delayed_complete_cb (gpointer user_data)
+{
+ CcColorPanel *panel = CC_COLOR_PANEL (user_data);
+ GtkAssistant *assistant;
+
+ assistant = GTK_ASSISTANT (panel->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, panel->box_calib_brightness, TRUE);
+ return FALSE;
+}
+
+static void
+gcm_prefs_calib_prepare_cb (CcColorPanel *panel,
+ GtkWidget *page)
+{
+ /* give the user the indication they should actually manually set the
+ * desired brightness rather than clicking blindly by delaying the
+ * "Next" button deliberately for a second or so */
+ if (page == panel->box_calib_brightness)
+ {
+ g_timeout_add_seconds (1, gcm_prefs_calib_delayed_complete_cb, panel);
+ return;
+ }
+
+ /* disable the brightness page as we don't want to show a 'Finished'
+ * button if the user goes back at any point */
+ gtk_assistant_set_page_complete (GTK_ASSISTANT (panel->assistant_calib), panel->box_calib_brightness, FALSE);
+}
+
+static void
+gcm_prefs_calib_apply_cb (CcColorPanel *prefs)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GtkWindow *window = NULL;
+
+ /* setup the calibration object with items that can fail */
+ ret = cc_color_calibrate_setup (prefs->calibrate,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to setup calibrate: %s", error->message);
+ return;
+ }
+
+ /* actually start the calibration */
+ window = GTK_WINDOW (prefs->assistant_calib);
+ ret = cc_color_calibrate_start (prefs->calibrate,
+ window,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to start calibrate: %s", error->message);
+ gtk_widget_hide (GTK_WIDGET (window));
+ return;
+ }
+
+ /* if we are a LiveCD then don't close the window as there is another
+ * summary pane with the export button */
+ if (!prefs->is_live_cd)
+ gtk_widget_hide (GTK_WIDGET (window));
+}
+
+static void
+gcm_prefs_calib_temp_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ gboolean ret;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ guint target_whitepoint;
+ GtkAssistant *assistant;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_temp, ret);
+ if (!ret)
+ return;
+
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_TEMP_VALUE_K, &target_whitepoint,
+ -1);
+ cc_color_calibrate_set_temperature (prefs->calibrate, target_whitepoint);
+}
+
+static void
+gcm_prefs_calib_kind_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ CdSensorCap device_kind;
+ gboolean ret;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkAssistant *assistant;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_kind, ret);
+ if (!ret)
+ return;
+
+ /* save the values if we have a selection */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_KIND_CAP_VALUE, &device_kind,
+ -1);
+ cc_color_calibrate_set_kind (prefs->calibrate, device_kind);
+}
+
+static void
+gcm_prefs_calib_quality_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ CdProfileQuality quality;
+ gboolean ret;
+ GtkAssistant *assistant;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_quality, ret);
+ if (!ret)
+ return;
+
+ /* save the values if we have a selection */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_QUALITY_VALUE, &quality,
+ -1);
+ cc_color_calibrate_set_quality (prefs->calibrate, quality);
+}
+
+static gboolean
+gcm_prefs_calib_set_sensor_cap_supported_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ CdSensorCap cap;
+ CdSensor *sensor = CD_SENSOR (data);
+ gboolean supported;
+
+ gtk_tree_model_get (model, iter,
+ COLUMN_CALIB_KIND_CAP_VALUE, &cap,
+ -1);
+ supported = cd_sensor_has_cap (sensor, cap);
+ g_debug ("%s(%s) is %s",
+ cd_sensor_get_model (sensor),
+ cd_sensor_cap_to_string (cap),
+ supported ? "supported" : "not-supported");
+ gtk_list_store_set (GTK_LIST_STORE (model), iter,
+ COLUMN_CALIB_KIND_VISIBLE, supported,
+ -1);
+ return FALSE;
+}
+
+static guint8
+_cd_bitfield_popcount (guint64 bitfield)
+{
+ guint8 i;
+ guint8 tmp = 0;
+ for (i = 0; i < 64; i++)
+ tmp += cd_bitfield_contain (bitfield, i);
+ return tmp;
+}
+
+static void
+gcm_prefs_calib_set_sensor (CcColorPanel *prefs,
+ CdSensor *sensor)
+{
+ guint64 caps;
+ guint8 i;
+
+ /* use this sensor for calibration */
+ cc_color_calibrate_set_sensor (prefs->calibrate, sensor);
+
+ /* hide display types the sensor does not support */
+ gtk_tree_model_foreach (prefs->liststore_calib_kind,
+ gcm_prefs_calib_set_sensor_cap_supported_cb,
+ sensor);
+
+ /* if the sensor only supports one kind then do not show the panel at all */
+ caps = cd_sensor_get_caps (sensor);
+ if (_cd_bitfield_popcount (caps) == 1)
+ {
+ gtk_widget_set_visible (prefs->box_calib_kind, FALSE);
+ for (i = 0; i < CD_SENSOR_CAP_LAST; i++)
+ {
+ if (cd_bitfield_contain (caps, i))
+ cc_color_calibrate_set_kind (prefs->calibrate, i);
+ }
+ }
+ else
+ {
+ cc_color_calibrate_set_kind (prefs->calibrate, CD_SENSOR_CAP_UNKNOWN);
+ gtk_widget_set_visible (prefs->box_calib_kind, TRUE);
+ }
+}
+
+static void
+gcm_prefs_calib_sensor_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ gboolean ret;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ g_autoptr(CdSensor) sensor = NULL;
+ GtkAssistant *assistant;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_sensor, ret);
+ if (!ret)
+ return;
+
+ /* save the values if we have a selection */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_SENSOR_OBJECT, &sensor,
+ -1);
+ gcm_prefs_calib_set_sensor (prefs, sensor);
+}
+
+static void
+gcm_prefs_calibrate_display (CcColorPanel *prefs)
+{
+ CdSensor *sensor_tmp;
+ const gchar *tmp;
+ GtkTreeIter iter;
+ guint i;
+
+ /* set target device */
+ cc_color_calibrate_set_device (prefs->calibrate, prefs->current_device);
+
+ /* add sensors to list */
+ gtk_list_store_clear (GTK_LIST_STORE (prefs->liststore_calib_sensor));
+ if (prefs->sensors->len > 1)
+ {
+ for (i = 0; i < prefs->sensors->len; i++)
+ {
+ sensor_tmp = g_ptr_array_index (prefs->sensors, i);
+ gtk_list_store_append (GTK_LIST_STORE (prefs->liststore_calib_sensor), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (prefs->liststore_calib_sensor), &iter,
+ COLUMN_CALIB_SENSOR_OBJECT, sensor_tmp,
+ COLUMN_CALIB_SENSOR_DESCRIPTION, cd_sensor_get_model (sensor_tmp),
+ -1);
+ }
+ gtk_widget_set_visible (prefs->box_calib_sensor, TRUE);
+ }
+ else
+ {
+ sensor_tmp = g_ptr_array_index (prefs->sensors, 0);
+ gcm_prefs_calib_set_sensor (prefs, sensor_tmp);
+ gtk_widget_set_visible (prefs->box_calib_sensor, FALSE);
+ }
+
+ /* set default profile title */
+ tmp = cd_device_get_model (prefs->current_device);
+ if (tmp == NULL)
+ tmp = cd_device_get_vendor (prefs->current_device);
+ if (tmp == NULL)
+ tmp = _("Screen");
+ gtk_editable_set_text (GTK_EDITABLE (prefs->entry_calib_title), tmp);
+ cc_color_calibrate_set_title (prefs->calibrate, tmp);
+
+ /* set the display whitepoint to D65 by default */
+ //FIXME?
+
+ /* show ui */
+ gtk_window_set_transient_for (GTK_WINDOW (prefs->assistant_calib),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))));
+ gtk_widget_show (prefs->assistant_calib);
+}
+
+static void
+gcm_prefs_title_entry_changed_cb (CcColorPanel *prefs)
+{
+ GtkAssistant *assistant;
+ const gchar *value;
+
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ value = gtk_editable_get_text (GTK_EDITABLE (prefs->entry_calib_title));
+ cc_color_calibrate_set_title (prefs->calibrate, value);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_title, value[0] != '\0');
+}
+
+static void
+gcm_prefs_calibrate_cb (CcColorPanel *prefs)
+{
+ GtkNative *native;
+ GdkSurface *surface;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ guint xid = 0;
+ g_autoptr(GPtrArray) argv = NULL;
+
+ /* use the new-style calibration helper */
+ if (cd_device_get_kind (prefs->current_device) == CD_DEVICE_KIND_DISPLAY)
+ {
+ gcm_prefs_calibrate_display (prefs);
+ return;
+ }
+
+ /* get xid */
+ native = gtk_widget_get_native (GTK_WIDGET (prefs));
+ surface = gtk_native_get_surface (native);
+
+ if (GDK_IS_X11_SURFACE (surface))
+ xid = gdk_x11_surface_get_xid (GDK_X11_SURFACE (surface));
+
+ /* run with modal set */
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_strdup ("gcm-calibrate"));
+ g_ptr_array_add (argv, g_strdup ("--device"));
+ g_ptr_array_add (argv, g_strdup (cd_device_get_id (prefs->current_device)));
+ g_ptr_array_add (argv, g_strdup ("--parent-window"));
+ g_ptr_array_add (argv, g_strdup_printf ("%i", xid));
+ g_ptr_array_add (argv, NULL);
+ ret = g_spawn_async (NULL, (gchar**) argv->pdata, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (!ret)
+ g_warning ("failed to run calibrate: %s", error->message);
+}
+
+static gboolean
+gcm_prefs_is_profile_suitable_for_device (CdProfile *profile,
+ CdDevice *device)
+{
+ const gchar *data_source;
+ CdProfileKind profile_kind_tmp;
+ CdProfileKind profile_kind;
+ CdColorspace profile_colorspace;
+ CdColorspace device_colorspace = 0;
+ gboolean ret = FALSE;
+ CdDeviceKind device_kind;
+ CdStandardSpace standard_space;
+
+ /* not the right colorspace */
+ device_colorspace = cd_device_get_colorspace (device);
+ profile_colorspace = cd_profile_get_colorspace (profile);
+ if (device_colorspace != profile_colorspace)
+ goto out;
+
+ /* if this is a display matching with one of the standard spaces that displays
+ * could emulate, also mark it as suitable */
+ if (cd_device_get_kind (device) == CD_DEVICE_KIND_DISPLAY &&
+ cd_profile_get_kind (profile) == CD_PROFILE_KIND_DISPLAY_DEVICE)
+ {
+ data_source = cd_profile_get_metadata_item (profile,
+ CD_PROFILE_METADATA_STANDARD_SPACE);
+ standard_space = cd_standard_space_from_string (data_source);
+ if (standard_space == CD_STANDARD_SPACE_SRGB ||
+ standard_space == CD_STANDARD_SPACE_ADOBE_RGB)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ }
+
+ /* not the correct kind */
+ device_kind = cd_device_get_kind (device);
+ profile_kind_tmp = cd_profile_get_kind (profile);
+ profile_kind = cd_device_kind_to_profile_kind (device_kind);
+ if (profile_kind_tmp != profile_kind)
+ goto out;
+
+ /* ignore the colorspace profiles */
+ data_source = cd_profile_get_metadata_item (profile,
+ CD_PROFILE_METADATA_DATA_SOURCE);
+ if (g_strcmp0 (data_source, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
+ goto out;
+
+ /* success */
+ ret = TRUE;
+out:
+ return ret;
+}
+
+static gint
+gcm_prefs_combo_sort_func_cb (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ gint type_a, type_b;
+ g_autofree gchar *text_a = NULL;
+ g_autofree gchar *text_b = NULL;
+
+ /* get data from model */
+ gtk_tree_model_get (model, a,
+ GCM_PREFS_COMBO_COLUMN_TYPE, &type_a,
+ GCM_PREFS_COMBO_COLUMN_TEXT, &text_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ GCM_PREFS_COMBO_COLUMN_TYPE, &type_b,
+ GCM_PREFS_COMBO_COLUMN_TEXT, &text_b,
+ -1);
+
+ /* prefer normal type profiles over the 'Other Profile...' entry */
+ if (type_a < type_b)
+ return -1;
+ else if (type_a > type_b)
+ return 1;
+ else
+ return g_strcmp0 (text_a, text_b);
+}
+
+static gboolean
+gcm_prefs_profile_exists_in_array (GPtrArray *array, CdProfile *profile)
+{
+ CdProfile *profile_tmp;
+ guint i;
+
+ for (i = 0; i < array->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (array, i);
+ if (cd_profile_equal (profile, profile_tmp))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+gcm_prefs_add_profiles_suitable_for_devices (CcColorPanel *prefs,
+ GPtrArray *profiles)
+{
+ CdProfile *profile_tmp;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) profile_array = NULL;
+ GtkTreeIter iter;
+ guint i;
+
+ gtk_list_store_clear (GTK_LIST_STORE (prefs->liststore_assign));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (prefs->liststore_assign),
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (prefs->liststore_assign),
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ gcm_prefs_combo_sort_func_cb,
+ prefs->liststore_assign, NULL);
+
+ gtk_widget_hide (prefs->label_assign_warning);
+
+ /* get profiles */
+ profile_array = cd_client_get_profiles_sync (prefs->client,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (profile_array == NULL)
+ {
+ g_warning ("failed to get profiles: %s",
+ error->message);
+ return;
+ }
+
+ /* add profiles of the right kind */
+ for (i = 0; i < profile_array->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profile_array, i);
+
+ /* get properties */
+ ret = cd_profile_connect_sync (profile_tmp,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to get profile: %s", error->message);
+ return;
+ }
+
+ /* don't add any of the already added profiles */
+ if (profiles != NULL)
+ {
+ if (gcm_prefs_profile_exists_in_array (profiles, profile_tmp))
+ continue;
+ }
+
+ /* only add correct types */
+ ret = gcm_prefs_is_profile_suitable_for_device (profile_tmp,
+ prefs->current_device);
+ if (!ret)
+ continue;
+
+#if CD_CHECK_VERSION(0,1,13)
+ /* ignore profiles from other user accounts */
+ if (!cd_profile_has_access (profile_tmp))
+ continue;
+#endif
+
+ /* add */
+ gcm_prefs_combobox_add_profile (prefs,
+ profile_tmp,
+ &iter);
+ }
+}
+
+static void
+gcm_prefs_calib_export_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ gboolean ret;
+ g_autofree gchar *default_name = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) destination = NULL;
+ g_autoptr(GFile) source = NULL;
+ GtkWidget *dialog;
+
+ profile = cc_color_calibrate_get_profile (prefs->calibrate);
+ ret = cd_profile_connect_sync (profile, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("Failed to get imported profile: %s", error->message);
+ return;
+ }
+
+ /* TRANSLATORS: this is the dialog to save the ICC profile */
+ dialog = gtk_file_chooser_dialog_new (_("Save Profile"),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ default_name = g_strdup_printf ("%s.icc", cd_profile_get_title (profile));
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_name);
+
+ if (run_dialog (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ source = g_file_new_for_path (cd_profile_get_filename (profile));
+ destination = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ ret = g_file_copy (source,
+ destination,
+ G_FILE_COPY_OVERWRITE,
+ NULL,
+ NULL,
+ NULL,
+ &error);
+ if (!ret)
+ g_warning ("Failed to copy profile: %s", error->message);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+gcm_prefs_calib_export_link_cb (CcColorPanel *prefs,
+ const gchar *url)
+{
+ gtk_show_uri (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))),
+ "help:gnome-help/color-howtoimport",
+ GDK_CURRENT_TIME);
+}
+
+static void
+gcm_prefs_profile_add_cb (CcColorPanel *prefs)
+{
+ g_autoptr(GPtrArray) profiles = NULL;
+
+ /* add profiles of the right kind */
+ profiles = cd_device_get_profiles (prefs->current_device);
+ gcm_prefs_add_profiles_suitable_for_devices (prefs, profiles);
+
+ /* make insensitive until we have a selection */
+ gtk_widget_set_sensitive (prefs->button_assign_ok, FALSE);
+
+ /* show the dialog */
+ gtk_window_set_transient_for (GTK_WINDOW (prefs->dialog_assign),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))));
+
+ gtk_widget_show (prefs->dialog_assign);
+}
+
+static void
+gcm_prefs_profile_remove_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ gboolean ret = FALSE;
+ g_autoptr(GError) error = NULL;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* just remove it, the list store will get ::changed */
+ ret = cd_device_remove_profile_sync (prefs->current_device,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ g_warning ("failed to remove profile: %s", error->message);
+}
+
+static void
+gcm_prefs_make_profile_default_cb (GObject *object,
+ GAsyncResult *res,
+ CcColorPanel *prefs)
+{
+ CdDevice *device = CD_DEVICE (object);
+ gboolean ret = FALSE;
+ g_autoptr(GError) error = NULL;
+
+ ret = cd_device_make_profile_default_finish (device,
+ res,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to set default profile on %s: %s",
+ cd_device_get_id (device),
+ error->message);
+ }
+ else
+ {
+ gcm_prefs_refresh_toolbar_buttons (prefs);
+ }
+}
+
+static void
+gcm_prefs_device_profile_enable_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* just set it default */
+ g_debug ("setting %s default on %s",
+ cd_profile_get_id (profile),
+ cd_device_get_id (prefs->current_device));
+ cd_device_make_profile_default (prefs->current_device,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ (GAsyncReadyCallback) gcm_prefs_make_profile_default_cb,
+ prefs);
+}
+
+static void
+gcm_prefs_profile_view (CcColorPanel *prefs, CdProfile *profile)
+{
+ GtkNative *native;
+ GdkSurface *surface;
+ g_autoptr(GPtrArray) argv = NULL;
+ guint xid = 0;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ /* get xid */
+ native = gtk_widget_get_native (GTK_WIDGET (prefs));
+ surface = gtk_native_get_surface (native);
+
+ if (GDK_IS_X11_SURFACE (surface))
+ xid = gdk_x11_surface_get_xid (GDK_X11_SURFACE (surface));
+
+ /* open up gcm-viewer as a info pane */
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_strdup ("gcm-viewer"));
+ g_ptr_array_add (argv, g_strdup ("--profile"));
+ g_ptr_array_add (argv, g_strdup (cd_profile_get_id (profile)));
+ g_ptr_array_add (argv, g_strdup ("--parent-window"));
+ g_ptr_array_add (argv, g_strdup_printf ("%i", xid));
+ g_ptr_array_add (argv, NULL);
+ ret = g_spawn_async (NULL, (gchar**) argv->pdata, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (!ret)
+ g_warning ("failed to run calibrate: %s", error->message);
+}
+
+static void
+gcm_prefs_profile_assign_link_activate_cb (CcColorPanel *prefs,
+ const gchar *uri)
+{
+ CdProfile *profile;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* show it in the viewer */
+ gcm_prefs_profile_view (prefs, profile);
+}
+
+static void
+gcm_prefs_profile_view_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* open up gcm-viewer as a info pane */
+ gcm_prefs_profile_view (prefs, profile);
+}
+
+static void
+gcm_prefs_button_assign_ok_cb (CcColorPanel *prefs)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ g_autoptr(CdProfile) profile = NULL;
+ gboolean ret = FALSE;
+ g_autoptr(GError) error = NULL;
+ GtkTreeSelection *selection;
+
+ /* hide window */
+ gtk_widget_hide (GTK_WIDGET (prefs->dialog_assign));
+
+ /* get the selected profile */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_assign));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* if the device is disabled, enable the device so that we can
+ * add color profiles to it */
+ if (!cd_device_get_enabled (prefs->current_device))
+ {
+ ret = cd_device_set_enabled_sync (prefs->current_device,
+ TRUE,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to enabled device: %s", error->message);
+ return;
+ }
+ }
+
+ /* just add it, the list store will get ::changed */
+ ret = cd_device_add_profile_sync (prefs->current_device,
+ CD_DEVICE_RELATION_HARD,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to add: %s", error->message);
+ return;
+ }
+
+ /* make it default */
+ cd_device_make_profile_default (prefs->current_device,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ (GAsyncReadyCallback) gcm_prefs_make_profile_default_cb,
+ prefs);
+}
+
+static void
+gcm_prefs_add_profiles_columns (CcColorPanel *prefs,
+ GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* text */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", GCM_PREFS_COMBO_COLUMN_TEXT);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* image */
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "icon-name", GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME);
+ gtk_tree_view_append_column (treeview, column);
+}
+
+static void
+gcm_prefs_set_calibrate_button_sensitivity (CcColorPanel *prefs)
+{
+ gboolean ret = FALSE;
+ const gchar *tooltip;
+ CdDeviceKind kind;
+ CdSensor *sensor_tmp;
+
+ /* TRANSLATORS: this is when the button is sensitive */
+ tooltip = _("Create a color profile for the selected device");
+
+ /* no device selected */
+ if (prefs->current_device == NULL)
+ goto out;
+
+ /* are we a display */
+ kind = cd_device_get_kind (prefs->current_device);
+ if (kind == CD_DEVICE_KIND_DISPLAY)
+ {
+
+ /* find whether we have hardware installed */
+ if (prefs->sensors == NULL || prefs->sensors->len == 0)
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The measuring instrument is not detected. Please check it is turned on and correctly connected.");
+ goto out;
+ }
+
+ /* success */
+ ret = TRUE;
+
+ }
+ else if (kind == CD_DEVICE_KIND_SCANNER ||
+ kind == CD_DEVICE_KIND_CAMERA ||
+ kind == CD_DEVICE_KIND_WEBCAM)
+ {
+
+ /* TODO: find out if we can scan using gnome-scan */
+ ret = TRUE;
+
+ }
+ else if (kind == CD_DEVICE_KIND_PRINTER)
+ {
+
+ /* find whether we have hardware installed */
+ if (prefs->sensors == NULL || prefs->sensors->len == 0)
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The measuring instrument is not detected. Please check it is turned on and correctly connected.");
+ goto out;
+ }
+
+ /* find whether we have hardware installed */
+ sensor_tmp = g_ptr_array_index (prefs->sensors, 0);
+ ret = cd_sensor_has_cap (sensor_tmp, CD_SENSOR_CAP_PRINTER);
+ if (!ret)
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The measuring instrument does not support printer profiling.");
+ goto out;
+ }
+
+ /* success */
+ ret = TRUE;
+
+ }
+ else
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The device type is not currently supported.");
+ }
+out:
+ /* control the tooltip and sensitivity of the button */
+ gtk_widget_set_tooltip_text (prefs->toolbutton_device_calibrate, tooltip);
+ gtk_widget_set_sensitive (prefs->toolbutton_device_calibrate, ret);
+}
+
+static void
+gcm_prefs_device_clicked (CcColorPanel *prefs, CdDevice *device)
+{
+ /* we have a new device */
+ g_debug ("selected device is: %s",
+ cd_device_get_id (device));
+
+ /* can this device calibrate */
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+}
+
+static void
+gcm_prefs_profile_clicked (CcColorPanel *prefs, CdProfile *profile, CdDevice *device)
+{
+ g_autofree gchar *s = NULL;
+
+ /* get profile */
+ g_debug ("selected profile = %s",
+ cd_profile_get_filename (profile));
+
+ /* allow getting profile info */
+ if (cd_profile_get_filename (profile) != NULL &&
+ (s = g_find_program_in_path ("gcm-viewer")) != NULL)
+ gtk_widget_set_sensitive (prefs->toolbutton_profile_view, TRUE);
+ else
+ gtk_widget_set_sensitive (prefs->toolbutton_profile_view, FALSE);
+}
+
+static void
+gcm_prefs_profiles_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ g_autoptr(CdProfile) profile = NULL;
+#if CD_CHECK_VERSION(0,1,25)
+ gchar **warnings;
+#endif
+
+ /* get selection */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* as soon as anything is selected, make the Add button sensitive */
+ gtk_widget_set_sensitive (prefs->button_assign_ok, TRUE);
+
+ /* is the profile faulty */
+#if CD_CHECK_VERSION(0,1,25)
+ warnings = cd_profile_get_warnings (profile);
+ gtk_widget_set_visible (prefs->label_assign_warning, warnings != NULL && warnings[0] != NULL);
+#else
+ gtk_widget_set_visible (prefs->label_assign_warning, FALSE);
+#endif
+}
+
+static void
+gcm_prefs_profiles_row_activated_cb (CcColorPanel *prefs,
+ GtkTreePath *path)
+{
+ GtkTreeIter iter;
+ gboolean ret;
+
+ ret = gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->treeview_assign)), &iter, path);
+ if (!ret)
+ return;
+ gcm_prefs_button_assign_ok_cb (prefs);
+}
+
+
+static void
+gcm_prefs_button_assign_import_cb (CcColorPanel *prefs)
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(CdProfile) profile = NULL;
+
+ file = gcm_prefs_file_chooser_get_icc_profile (prefs);
+ if (file == NULL)
+ {
+ g_warning ("failed to get ICC file");
+ gtk_widget_hide (GTK_WIDGET (prefs->dialog_assign));
+ return;
+ }
+
+#if CD_CHECK_VERSION(0,1,12)
+ profile = cd_client_import_profile_sync (prefs->client,
+ file,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (profile == NULL)
+ {
+ g_warning ("failed to get imported profile: %s", error->message);
+ return;
+ }
+#endif
+
+ /* add to list view */
+ gcm_prefs_profile_add_cb (prefs);
+}
+
+static void
+gcm_prefs_sensor_coldplug (CcColorPanel *prefs)
+{
+ CdSensor *sensor_tmp;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) sensors = NULL;
+ guint i;
+
+ /* unref old */
+ g_clear_pointer (&prefs->sensors, g_ptr_array_unref);
+
+ /* no present */
+ sensors = cd_client_get_sensors_sync (prefs->client, NULL, &error);
+ if (sensors == NULL)
+ {
+ g_warning ("%s", error->message);
+ return;
+ }
+ if (sensors->len == 0)
+ return;
+
+ /* save a copy of the sensor list */
+ prefs->sensors = g_ptr_array_ref (sensors);
+
+ /* connect to each sensor */
+ for (i = 0; i < sensors->len; i++)
+ {
+ sensor_tmp = g_ptr_array_index (sensors, i);
+ ret = cd_sensor_connect_sync (sensor_tmp, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("%s", error->message);
+ return;
+ }
+ }
+}
+
+static void
+gcm_prefs_client_sensor_changed_cb (CdClient *client,
+ CdSensor *sensor,
+ CcColorPanel *prefs)
+{
+ gcm_prefs_sensor_coldplug (prefs);
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+}
+
+static void
+gcm_prefs_add_device_profile (CcColorPanel *prefs,
+ CdDevice *device,
+ CdProfile *profile,
+ gboolean is_default)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GtkWidget *widget;
+
+ /* get properties */
+ ret = cd_profile_connect_sync (profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to get profile: %s", error->message);
+ return;
+ }
+
+ /* ignore profiles from other user accounts */
+ if (!cd_profile_has_access (profile))
+ {
+ /* only print the filename if it exists */
+ if (cd_profile_get_filename (profile) != NULL)
+ {
+ g_warning ("%s is not usable by this user",
+ cd_profile_get_filename (profile));
+ }
+ else
+ {
+ g_warning ("%s is not usable by this user",
+ cd_profile_get_id (profile));
+ }
+ return;
+ }
+
+ /* add to listbox */
+ widget = cc_color_profile_new (device, profile, is_default);
+ gtk_list_box_append (prefs->list_box, widget);
+ gtk_size_group_add_widget (prefs->list_box_size, widget);
+}
+
+static void
+gcm_prefs_add_device_profiles (CcColorPanel *prefs, CdDevice *device)
+{
+ CdProfile *profile_tmp;
+ g_autoptr(GPtrArray) profiles = NULL;
+ guint i;
+
+ /* add profiles */
+ profiles = cd_device_get_profiles (device);
+ if (profiles == NULL)
+ return;
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ gcm_prefs_add_device_profile (prefs, device, profile_tmp, i == 0);
+ }
+}
+
+/* find the profile in the array -- for flicker-free changes */
+static gboolean
+gcm_prefs_find_profile_by_object_path (GPtrArray *profiles,
+ const gchar *object_path)
+{
+ CdProfile *profile_tmp;
+ guint i;
+
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ if (g_strcmp0 (cd_profile_get_object_path (profile_tmp), object_path) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* find the profile in the list view -- for flicker-free changes */
+static gboolean
+gcm_prefs_find_widget_by_object_path (GList *list,
+ const gchar *object_path_device,
+ const gchar *object_path_profile)
+{
+ GList *l;
+ CdDevice *device_tmp;
+ CdProfile *profile_tmp;
+
+ for (l = list; l != NULL; l = l->next)
+ {
+ if (!CC_IS_COLOR_PROFILE (l->data))
+ continue;
+
+ /* correct device ? */
+ device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (l->data));
+ if (g_strcmp0 (object_path_device,
+ cd_device_get_object_path (device_tmp)) != 0)
+ {
+ continue;
+ }
+
+ /* this profile */
+ profile_tmp = cc_color_profile_get_profile (CC_COLOR_PROFILE (l->data));
+ if (g_strcmp0 (object_path_profile,
+ cd_profile_get_object_path (profile_tmp)) == 0)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+gcm_prefs_device_changed_cb (CcColorPanel *prefs, CdDevice *device)
+{
+ GtkWidget *child;
+ CdDevice *device_tmp;
+ CdProfile *profile_tmp;
+ gboolean ret;
+ g_autoptr(GList) list = NULL;
+ GPtrArray *profiles;
+ guint i;
+
+ /* remove anything in the list view that's not in Device.Profiles */
+ profiles = cd_device_get_profiles (device);
+ child = gtk_widget_get_first_child (GTK_WIDGET (prefs->list_box));
+ while (child)
+ {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (!CC_IS_COLOR_PROFILE (child))
+ {
+ list = g_list_prepend (list, child);
+ goto next;
+ }
+
+ /* correct device ? */
+ device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (child));
+ if (g_strcmp0 (cd_device_get_id (device),
+ cd_device_get_id (device_tmp)) != 0)
+ {
+ list = g_list_prepend (list, child);
+ goto next;
+ }
+
+ /* if profile is not in Device.Profiles then remove */
+ profile_tmp = cc_color_profile_get_profile (CC_COLOR_PROFILE (child));
+ ret = gcm_prefs_find_profile_by_object_path (profiles,
+ cd_profile_get_object_path (profile_tmp));
+ if (!ret)
+ gtk_list_box_remove (prefs->list_box, child);
+ else
+ list = g_list_prepend (list, child);
+
+next:
+ child = next;
+ }
+
+ /* add anything in Device.Profiles that's not in the list view */
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ ret = gcm_prefs_find_widget_by_object_path (list,
+ cd_device_get_object_path (device),
+ cd_profile_get_object_path (profile_tmp));
+ if (!ret)
+ gcm_prefs_add_device_profile (prefs, device, profile_tmp, i == 0);
+ }
+
+ /* resort */
+ gtk_list_box_invalidate_sort (prefs->list_box);
+}
+
+static void
+gcm_prefs_device_expanded_changed_cb (CcColorPanel *prefs,
+ gboolean is_expanded,
+ CcColorDevice *widget)
+{
+ /* ignore internal changes */
+ if (prefs->model_is_changing)
+ return;
+
+ g_free (prefs->list_box_filter);
+ if (is_expanded)
+ {
+ GtkWidget *child;
+
+ prefs->list_box_filter = g_strdup (cd_device_get_id (cc_color_device_get_device (widget)));
+
+ /* unexpand other device widgets */
+ prefs->model_is_changing = TRUE;
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (prefs->list_box));
+ child != NULL;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!CC_IS_COLOR_DEVICE (child))
+ continue;
+ if (CC_COLOR_DEVICE (child) != widget)
+ cc_color_device_set_expanded (CC_COLOR_DEVICE (child), FALSE);
+ }
+ prefs->model_is_changing = FALSE;
+ }
+ else
+ {
+ prefs->list_box_filter = NULL;
+ }
+ gtk_list_box_invalidate_filter (prefs->list_box);
+}
+
+static void
+gcm_prefs_add_device (CcColorPanel *prefs, CdDevice *device)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GtkWidget *widget;
+
+ /* get device properties */
+ ret = cd_device_connect_sync (device, cc_panel_get_cancellable (CC_PANEL (prefs)), &error);
+ if (!ret)
+ {
+ g_warning ("failed to connect to the device: %s", error->message);
+ return;
+ }
+
+ /* add device */
+ widget = cc_color_device_new (device);
+ g_signal_connect_object (widget, "expanded-changed",
+ G_CALLBACK (gcm_prefs_device_expanded_changed_cb), prefs, G_CONNECT_SWAPPED);
+ gtk_list_box_append (prefs->list_box, widget);
+ gtk_size_group_add_widget (prefs->list_box_size, widget);
+
+ /* add profiles */
+ gcm_prefs_add_device_profiles (prefs, device);
+
+ /* watch for changes */
+ g_ptr_array_add (prefs->devices, g_object_ref (device));
+ g_signal_connect_object (device, "changed",
+ G_CALLBACK (gcm_prefs_device_changed_cb), prefs, G_CONNECT_SWAPPED);
+ gtk_list_box_invalidate_sort (prefs->list_box);
+}
+
+static void
+gcm_prefs_remove_device (CcColorPanel *prefs, CdDevice *device)
+{
+ GtkWidget *child;
+ CdDevice *device_tmp;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (prefs->list_box));
+ while (child)
+ {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (CC_IS_COLOR_DEVICE (child))
+ device_tmp = cc_color_device_get_device (CC_COLOR_DEVICE (child));
+ else
+ device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (child));
+ if (g_strcmp0 (cd_device_get_object_path (device),
+ cd_device_get_object_path (device_tmp)) == 0)
+ {
+ gtk_list_box_remove (prefs->list_box, child);
+ }
+
+ child = next;
+ }
+ g_signal_handlers_disconnect_by_func (device,
+ G_CALLBACK (gcm_prefs_device_changed_cb),
+ prefs);
+ g_ptr_array_remove (prefs->devices, device);
+}
+
+static void
+gcm_prefs_update_device_list_extra_entry (CcColorPanel *prefs)
+{
+ GtkListBoxRow *first_row;
+
+ /* any devices to show? */
+ first_row = gtk_list_box_get_row_at_index (prefs->list_box, 0);
+ gtk_widget_set_visible (prefs->label_no_devices, first_row == NULL);
+ gtk_widget_set_visible (prefs->box_devices, first_row != NULL);
+
+ /* if we have only one device expand it by default */
+ if (first_row != NULL &&
+ gtk_list_box_get_row_at_index (prefs->list_box, 1) == NULL)
+ cc_color_device_set_expanded (CC_COLOR_DEVICE (first_row), TRUE);
+}
+
+static void
+gcm_prefs_device_added_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ /* add the device */
+ gcm_prefs_add_device (prefs, device);
+
+ /* ensure we're not showing the 'No devices detected' entry */
+ gcm_prefs_update_device_list_extra_entry (prefs);
+}
+
+static void
+gcm_prefs_device_removed_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ /* remove from the UI */
+ gcm_prefs_remove_device (prefs, device);
+
+ /* ensure we showing the 'No devices detected' entry if required */
+ gcm_prefs_update_device_list_extra_entry (prefs);
+}
+
+static void
+gcm_prefs_get_devices_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcColorPanel *prefs = (CcColorPanel *) user_data;
+ CdClient *client = CD_CLIENT (object);
+ CdDevice *device;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ guint i;
+
+ /* get devices and add them */
+ devices = cd_client_get_devices_finish (client, res, &error);
+ if (devices == NULL)
+ {
+ g_warning ("failed to add connected devices: %s",
+ error->message);
+ return;
+ }
+ for (i = 0; i < devices->len; i++)
+ {
+ device = g_ptr_array_index (devices, i);
+ gcm_prefs_add_device (prefs, device);
+ }
+
+ /* ensure we show the 'No devices detected' entry if empty */
+ gcm_prefs_update_device_list_extra_entry (prefs);
+}
+
+static void
+gcm_prefs_list_box_row_selected_cb (CcColorPanel *panel,
+ GtkListBoxRow *row)
+{
+ if (gtk_widget_in_destruction (panel->toolbar_devices))
+ return;
+
+ gcm_prefs_refresh_toolbar_buttons (panel);
+}
+
+static void
+gcm_prefs_refresh_toolbar_buttons (CcColorPanel *panel)
+{
+ CdProfile *profile = NULL;
+ GtkListBoxRow *row;
+ gboolean is_device;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (panel->list_box);
+
+ is_device = CC_IS_COLOR_DEVICE (row);
+
+ /* nothing selected */
+ gtk_widget_set_visible (panel->toolbar_devices, row != NULL);
+ if (row == NULL)
+ return;
+
+ /* save current device */
+ g_clear_object (&panel->current_device);
+ g_object_get (row, "device", &panel->current_device, NULL);
+
+ /* device actions */
+ g_debug ("%s selected", is_device ? "device" : "profile");
+ if (CC_IS_COLOR_DEVICE (row))
+ {
+ gcm_prefs_device_clicked (panel, panel->current_device);
+ cc_color_device_set_expanded (CC_COLOR_DEVICE (row), TRUE);
+ }
+ else if (CC_IS_COLOR_PROFILE (row))
+ {
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ gcm_prefs_profile_clicked (panel, profile, panel->current_device);
+ }
+ else
+ g_assert_not_reached ();
+
+ gtk_widget_set_visible (panel->toolbutton_device_default, !is_device && cc_color_profile_get_is_default (CC_COLOR_PROFILE (row)));
+ if (profile)
+ gtk_widget_set_sensitive (panel->toolbutton_device_default, !cd_profile_get_is_system_wide (profile));
+ gtk_widget_set_visible (panel->toolbutton_device_enable, !is_device && !cc_color_profile_get_is_default (CC_COLOR_PROFILE (row)));
+ gtk_widget_set_visible (panel->toolbutton_device_calibrate, is_device);
+ gtk_widget_set_visible (panel->toolbutton_profile_add, is_device);
+ gtk_widget_set_visible (panel->toolbutton_profile_view, !is_device);
+ gtk_widget_set_visible (panel->toolbutton_profile_remove, !is_device);
+}
+
+static void
+gcm_prefs_list_box_row_activated_cb (CcColorPanel *prefs,
+ GtkListBoxRow *row)
+{
+ if (CC_IS_COLOR_PROFILE (row))
+ {
+ gcm_prefs_device_profile_enable_cb (prefs);
+ }
+}
+
+static void
+gcm_prefs_connect_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcColorPanel *prefs;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ ret = cd_client_connect_finish (CD_CLIENT (object),
+ res,
+ &error);
+ if (!ret)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("failed to connect to colord: %s", error->message);
+ return;
+ }
+
+ /* Only cast the parameters after making sure it didn't fail. At this point,
+ * the user can potentially already have changed to another panel, effectively
+ * making user_data invalid. */
+ prefs = CC_COLOR_PANEL (user_data);
+
+ /* set calibrate button sensitivity */
+ gcm_prefs_sensor_coldplug (prefs);
+
+ /* get devices */
+ cd_client_get_devices (prefs->client,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ gcm_prefs_get_devices_cb,
+ prefs);
+}
+
+static gboolean
+gcm_prefs_is_livecd (void)
+{
+#ifdef __linux__
+ gboolean ret = TRUE;
+ g_autofree gchar *data = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* allow testing */
+ if (g_getenv ("CC_COLOR_PANEL_IS_LIVECD") != NULL)
+ return TRUE;
+
+ /* get the kernel commandline */
+ ret = g_file_get_contents ("/proc/cmdline", &data, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("failed to get kernel command line: %s",
+ error->message);
+ return TRUE;
+ }
+ return (g_strstr_len (data, -1, "liveimg") != NULL ||
+ g_strstr_len (data, -1, "casper") != NULL);
+#else
+ return FALSE;
+#endif
+}
+
+static const char *
+cc_color_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/color";
+}
+
+static void
+cc_color_panel_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_color_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_color_panel_dispose (GObject *object)
+{
+ CcColorPanel *prefs = CC_COLOR_PANEL (object);
+
+ g_clear_object (&prefs->settings);
+ g_clear_object (&prefs->settings_colord);
+ g_clear_object (&prefs->client);
+ g_clear_object (&prefs->current_device);
+ g_clear_pointer (&prefs->devices, g_ptr_array_unref);
+ g_clear_object (&prefs->calibrate);
+ g_clear_object (&prefs->list_box_size);
+ g_clear_pointer (&prefs->sensors, g_ptr_array_unref);
+ g_clear_pointer (&prefs->list_box_filter, g_free);
+ g_clear_pointer ((GtkWindow **)&prefs->dialog_assign, gtk_window_destroy);
+
+ G_OBJECT_CLASS (cc_color_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_color_panel_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (cc_color_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_color_panel_class_init (CcColorPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_color_panel_get_help_uri;
+
+ object_class->get_property = cc_color_panel_get_property;
+ object_class->set_property = cc_color_panel_set_property;
+ object_class->dispose = cc_color_panel_dispose;
+ object_class->finalize = cc_color_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/color/cc-color-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, assistant_calib);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_brightness);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_kind);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_quality);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_sensor);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_summary);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_temp);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_title);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_devices);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, button_assign_import);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, button_assign_ok);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, button_calib_export);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, dialog_assign);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, entry_calib_title);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, label_assign_warning);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, label_calib_summary_message);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, label_no_devices);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, liststore_assign);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, liststore_calib_kind);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, liststore_calib_sensor);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbar_devices);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_device_calibrate);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_device_default);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_device_enable);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_profile_add);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_profile_remove);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_profile_view);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_assign);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_kind);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_quality);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_sensor);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_temp);
+}
+
+static gint
+cc_color_panel_sort_func (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ const gchar *sort_a = NULL;
+ const gchar *sort_b = NULL;
+ if (CC_IS_COLOR_DEVICE (a))
+ sort_a = cc_color_device_get_sortable (CC_COLOR_DEVICE (a));
+ else if (CC_IS_COLOR_PROFILE (a))
+ sort_a = cc_color_profile_get_sortable (CC_COLOR_PROFILE (a));
+ else
+ g_assert_not_reached ();
+ if (CC_IS_COLOR_DEVICE (b))
+ sort_b = cc_color_device_get_sortable (CC_COLOR_DEVICE (b));
+ else if (CC_IS_COLOR_PROFILE (b))
+ sort_b = cc_color_profile_get_sortable (CC_COLOR_PROFILE (b));
+ else
+ g_assert_not_reached ();
+ return g_strcmp0 (sort_b, sort_a);
+}
+
+static gboolean
+cc_color_panel_filter_func (GtkListBoxRow *row, void *user_data)
+{
+ CcColorPanel *prefs = CC_COLOR_PANEL (user_data);
+ g_autoptr(CdDevice) device = NULL;
+
+ /* always show all devices */
+ if (CC_IS_COLOR_DEVICE (row))
+ return TRUE;
+
+ g_object_get (row, "device", &device, NULL);
+ return g_strcmp0 (cd_device_get_id (device), prefs->list_box_filter) == 0;
+}
+
+static gboolean
+cc_color_panel_treeview_quality_default_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ CdProfileQuality quality;
+ GtkTreeSelection *selection = GTK_TREE_SELECTION (data);
+
+ gtk_tree_model_get (model, iter,
+ COLUMN_CALIB_QUALITY_VALUE, &quality,
+ -1);
+ if (quality == CD_PROFILE_QUALITY_MEDIUM)
+ gtk_tree_selection_select_iter (selection, iter);
+ return FALSE;
+}
+
+static void
+cc_color_panel_init (CcColorPanel *prefs)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeModel *model;
+ GtkTreeModel *model_filter;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+
+ g_resources_register (cc_color_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (prefs));
+
+ prefs->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+ /* can do native display calibration using colord-session */
+ prefs->calibrate = cc_color_calibrate_new ();
+ cc_color_calibrate_set_quality (prefs->calibrate, CD_PROFILE_QUALITY_MEDIUM);
+
+ /* setup defaults */
+ prefs->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
+ prefs->settings_colord = g_settings_new (COLORD_SETTINGS_SCHEMA);
+
+ /* assign buttons */
+ g_signal_connect_object (prefs->toolbutton_profile_add, "clicked",
+ G_CALLBACK (gcm_prefs_profile_add_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_profile_remove, "clicked",
+ G_CALLBACK (gcm_prefs_profile_remove_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_profile_view, "clicked",
+ G_CALLBACK (gcm_prefs_profile_view_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* href */
+ g_signal_connect_object (prefs->label_assign_warning, "activate-link",
+ G_CALLBACK (gcm_prefs_profile_assign_link_activate_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* add columns to profile tree view */
+ gcm_prefs_add_profiles_columns (prefs, GTK_TREE_VIEW (prefs->treeview_assign));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_assign));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_profiles_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->treeview_assign, "row-activated",
+ G_CALLBACK (gcm_prefs_profiles_row_activated_cb),
+ prefs, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (prefs->toolbutton_device_default, "clicked",
+ G_CALLBACK (gcm_prefs_default_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_device_enable, "clicked",
+ G_CALLBACK (gcm_prefs_device_profile_enable_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_device_calibrate, "clicked",
+ G_CALLBACK (gcm_prefs_calibrate_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* set up assign dialog */
+ g_signal_connect_object (prefs->button_assign_ok, "clicked",
+ G_CALLBACK (gcm_prefs_button_assign_ok_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* setup icc profiles list */
+ g_signal_connect_object (prefs->button_assign_import, "clicked",
+ G_CALLBACK (gcm_prefs_button_assign_import_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* setup the calibration helper */
+ g_signal_connect_object (prefs->assistant_calib, "apply",
+ G_CALLBACK (gcm_prefs_calib_apply_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->assistant_calib, "cancel",
+ G_CALLBACK (gcm_prefs_calib_cancel_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->assistant_calib, "close",
+ G_CALLBACK (gcm_prefs_calib_cancel_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->assistant_calib, "prepare",
+ G_CALLBACK (gcm_prefs_calib_prepare_cb),
+ prefs, G_CONNECT_SWAPPED);
+
+ /* setup the calibration helper ::TreeView */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_quality));
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->treeview_calib_quality));
+ gtk_tree_model_foreach (model,
+ cc_color_panel_treeview_quality_default_cb,
+ selection);
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_quality_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_QUALITY_DESCRIPTION);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_quality),
+ GTK_TREE_VIEW_COLUMN (column));
+ column = gtk_tree_view_column_new ();
+ renderer = cc_color_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ "is-dim-label", TRUE,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_QUALITY_APPROX_TIME);
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_quality),
+ GTK_TREE_VIEW_COLUMN (column));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_sensor));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_sensor_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_SENSOR_DESCRIPTION);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_sensor),
+ GTK_TREE_VIEW_COLUMN (column));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_kind));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_kind_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_KIND_DESCRIPTION);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->treeview_calib_kind));
+ model_filter = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (prefs->treeview_calib_kind), model_filter);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (model_filter),
+ COLUMN_CALIB_KIND_VISIBLE);
+
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_kind),
+ GTK_TREE_VIEW_COLUMN (column));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_temp));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_temp_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_TEMP_DESCRIPTION);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_temp),
+ GTK_TREE_VIEW_COLUMN (column));
+ g_signal_connect_object (prefs->entry_calib_title, "notify::text",
+ G_CALLBACK (gcm_prefs_title_entry_changed_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* use a device client array */
+ prefs->client = cd_client_new ();
+ g_signal_connect_object (prefs->client, "device-added",
+ G_CALLBACK (gcm_prefs_device_added_cb), prefs, 0);
+ g_signal_connect_object (prefs->client, "device-removed",
+ G_CALLBACK (gcm_prefs_device_removed_cb), prefs, 0);
+
+ /* use a listbox for the main UI */
+ gtk_list_box_set_filter_func (prefs->list_box,
+ cc_color_panel_filter_func,
+ prefs,
+ NULL);
+ gtk_list_box_set_sort_func (prefs->list_box,
+ cc_color_panel_sort_func,
+ prefs,
+ NULL);
+ g_signal_connect_object (prefs->list_box, "row-selected",
+ G_CALLBACK (gcm_prefs_list_box_row_selected_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->list_box, "row-activated",
+ G_CALLBACK (gcm_prefs_list_box_row_activated_cb),
+ prefs, G_CONNECT_SWAPPED);
+ prefs->list_box_size = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
+ /* connect to colord */
+ cd_client_connect (prefs->client,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ gcm_prefs_connect_cb,
+ prefs);
+
+ /* use the color sensor */
+ g_signal_connect_object (prefs->client, "sensor-added",
+ G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
+ prefs, 0);
+ g_signal_connect_object (prefs->client, "sensor-removed",
+ G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
+ prefs, 0);
+
+ /* set calibrate button sensitivity */
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+
+ /* show the confirmation export page if we are running from a LiveCD */
+ prefs->is_live_cd = gcm_prefs_is_livecd ();
+ gtk_widget_set_visible (prefs->box_calib_summary, prefs->is_live_cd);
+ g_signal_connect_object (prefs->button_calib_export, "clicked",
+ G_CALLBACK (gcm_prefs_calib_export_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->label_calib_summary_message, "activate-link",
+ G_CALLBACK (gcm_prefs_calib_export_link_cb), prefs, G_CONNECT_SWAPPED);
+}