[gnome-control-center] Add a color panel based on the functionality available in gnome-color-manager
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] Add a color panel based on the functionality available in gnome-color-manager
- Date: Fri, 20 May 2011 14:59:54 +0000 (UTC)
commit 2e7e54c3c2d89cb8376bccb34cfeb95e19c3582f
Author: Richard Hughes <richard hughsie com>
Date: Thu May 19 17:36:48 2011 +0100
Add a color panel based on the functionality available in gnome-color-manager
All the major functionality is present, but the virtual device stuff needs
further work with the designers before being included.
configure.ac | 3 +
panels/Makefile.am | 1 +
panels/color/Makefile.am | 34 +
panels/color/cc-color-panel.c | 1939 ++++++++++++++++++++++++++
panels/color/cc-color-panel.h | 74 +
panels/color/color-module.c | 42 +
panels/color/color.ui | 365 +++++
panels/color/gnome-color-panel.desktop.in.in | 17 +
po/POTFILES.in | 3 +
po/POTFILES.skip | 1 +
10 files changed, 2479 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index da06a40..f2729be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,7 @@ PKG_CHECK_MODULES(MOUSE_PANEL, $COMMON_MODULES xi >= 1.2
gnome-settings-daemon >= $GSD_REQUIRED_VERSION x11)
PKG_CHECK_MODULES(NETWORK_PANEL, $COMMON_MODULES)
PKG_CHECK_MODULES(POWER_PANEL, $COMMON_MODULES upower-glib >= 0.9.1)
+PKG_CHECK_MODULES(COLOR_PANEL, $COMMON_MODULES colord >= 0.1.8)
PKG_CHECK_MODULES(PRINTERS_PANEL, $COMMON_MODULES dbus-glib-1
polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
PKG_CHECK_MODULES(REGION_PANEL, $COMMON_MODULES libgnomekbd >= 2.91.91
@@ -354,6 +355,8 @@ panels/info/Makefile
panels/info/gnome-info-panel.desktop.in
panels/power/Makefile
panels/power/gnome-power-panel.desktop.in
+panels/color/Makefile
+panels/color/gnome-color-panel.desktop.in
panels/printers/Makefile
panels/printers/gnome-printers-panel.desktop.in
panels/network/Makefile
diff --git a/panels/Makefile.am b/panels/Makefile.am
index 06f9fdc..b4e335a 100644
--- a/panels/Makefile.am
+++ b/panels/Makefile.am
@@ -3,6 +3,7 @@ SUBDIRS= \
background \
screen \
power \
+ color \
display \
media \
mouse \
diff --git a/panels/color/Makefile.am b/panels/color/Makefile.am
new file mode 100644
index 0000000..e94eb91
--- /dev/null
+++ b/panels/color/Makefile.am
@@ -0,0 +1,34 @@
+cappletname = color
+
+INCLUDES = \
+ $(PANEL_CFLAGS) \
+ $(COLOR_PANEL_CFLAGS) \
+ -DGNOMECC_UI_DIR="\"$(uidir)\"" \
+ -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \
+ -DBINDIR="\"$(bindir)\"" \
+ -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \
+ $(NULL)
+
+ccpanelsdir = $(PANELS_DIR)
+ccpanels_LTLIBRARIES = libcolor.la
+
+libcolor_la_SOURCES = \
+ color-module.c \
+ cc-color-panel.c \
+ cc-color-panel.h
+
+libcolor_la_LIBADD = $(PANEL_LIBS) $(COLOR_PANEL_LIBS)
+libcolor_la_LDFLAGS = $(PANEL_LDFLAGS)
+
+uidir = $(pkgdatadir)/ui
+dist_ui_DATA = color.ui
+
+ INTLTOOL_DESKTOP_RULE@
+
+desktopdir = $(datadir)/applications
+desktop_in_files = gnome-color-panel.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+CLEANFILES = $(desktop_in_files) $(desktop_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/color/cc-color-panel.c b/panels/color/cc-color-panel.c
new file mode 100644
index 0000000..6ab5a4f
--- /dev/null
+++ b/panels/color/cc-color-panel.c
@@ -0,0 +1,1939 @@
+/* -*- 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <colord.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "cc-color-panel.h"
+
+#define WID(b, w) (GtkWidget *) gtk_builder_get_object (b, w)
+
+G_DEFINE_DYNAMIC_TYPE (CcColorPanel, cc_color_panel, CC_TYPE_PANEL)
+
+#define COLOR_PANEL_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_COLOR_PANEL, CcColorPanelPrivate))
+
+struct _CcColorPanelPrivate
+{
+ CdClient *client;
+ CdDevice *current_device;
+ CdSensor *sensor;
+ GCancellable *cancellable;
+ GDBusProxy *proxy;
+ GSettings *settings;
+ GtkBuilder *builder;
+ GtkTreeStore *list_store_devices;
+ GtkWidget *main_window;
+};
+
+enum {
+ GCM_PREFS_COLUMN_DEVICE_ID,
+ GCM_PREFS_COLUMN_SORT,
+ GCM_PREFS_COLUMN_ICON,
+ GCM_PREFS_COLUMN_TITLE,
+ GCM_PREFS_COLUMN_DEVICE,
+ GCM_PREFS_COLUMN_PROFILE,
+ GCM_PREFS_COLUMN_STATUS,
+ GCM_PREFS_COLUMN_STATUS_IMAGE,
+ GCM_PREFS_COLUMN_TOOLTIP,
+ GCM_PREFS_COLUMN_RADIO_ACTIVE,
+ GCM_PREFS_COLUMN_RADIO_VISIBLE,
+ GCM_PREFS_COLUMN_NUM_COLUMNS
+};
+
+enum {
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ GCM_PREFS_COMBO_COLUMN_PROFILE,
+ GCM_PREFS_COMBO_COLUMN_TYPE,
+ GCM_PREFS_COMBO_COLUMN_NUM_COLUMNS
+};
+
+typedef enum {
+ GCM_PREFS_ENTRY_TYPE_PROFILE,
+ GCM_PREFS_ENTRY_TYPE_IMPORT
+} GcmPrefsEntryType;
+
+#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"
+
+static void
+gcm_prefs_combobox_add_profile (GtkWidget *widget,
+ CdProfile *profile,
+ GcmPrefsEntryType entry_type,
+ GtkTreeIter *iter)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter_tmp;
+ const gchar *description;
+
+ /* iter is optional */
+ if (iter == NULL)
+ iter = &iter_tmp;
+
+ /* use description */
+ if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT)
+ {
+ /* TRANSLATORS: this is where the user can click and import a profile */
+ description = _("Other profileâ?¦");
+ }
+ else
+ {
+ description = cd_profile_get_title (profile);
+ }
+
+ /* also add profile */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_list_store_append (GTK_LIST_STORE(model), iter);
+ gtk_list_store_set (GTK_LIST_STORE(model), iter,
+ GCM_PREFS_COMBO_COLUMN_TEXT, description,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
+ GCM_PREFS_COMBO_COLUMN_TYPE, entry_type,
+ -1);
+}
+
+static void
+gcm_prefs_default_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ gboolean ret;
+ GError *error = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* TODO: check if the profile is already systemwide */
+ profile = cd_device_get_default_profile (priv->current_device);
+ if (profile == NULL)
+ goto out;
+
+ /* install somewhere out of $HOME */
+ ret = cd_profile_install_system_wide_sync (profile,
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to set profile system-wide: %s",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static GFile *
+gcm_prefs_file_chooser_get_icc_profile (CcColorPanel *prefs)
+{
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GFile *file = NULL;
+ GtkFileFilter *filter;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* create new dialog */
+ window = GTK_WINDOW(gtk_builder_get_object (priv->builder,
+ "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,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Import"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(dialog), g_get_home_dir ());
+ gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER(dialog), FALSE);
+ gtk_file_chooser_set_local_only (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 (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER(dialog));
+
+ /* we're done */
+ gtk_widget_destroy (dialog);
+
+ /* or NULL for missing */
+ return file;
+}
+
+static void
+gcm_prefs_calibrate_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ gboolean ret;
+ GError *error = NULL;
+ guint xid;
+ GPtrArray *argv;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get xid */
+ xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (priv->main_window)));
+
+ /* run with modal set */
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_build_filename (BINDIR, "gcm-calibrate", NULL));
+ g_ptr_array_add (argv, g_strdup ("--device"));
+ g_ptr_array_add (argv, g_strdup (cd_device_get_id (priv->current_device)));
+ g_ptr_array_add (argv, g_strdup ("--parent-window"));
+ g_ptr_array_add (argv, g_strdup_printf ("%i", xid));
+ ret = g_spawn_async (NULL, (gchar**) argv->pdata, NULL, 0,
+ NULL, NULL, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("failed to run calibrate: %s", error->message);
+ g_error_free (error);
+ }
+ g_ptr_array_unref (argv);
+}
+
+static void
+gcm_prefs_device_add_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* show ui */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "dialog_virtual"));
+ gtk_widget_show (widget);
+ gtk_window_set_transient_for (GTK_WINDOW (widget),
+ GTK_WINDOW (priv->main_window));
+
+ /* clear entries */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "combobox_virtual_type"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX(widget), 0);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "entry_virtual_model"));
+ gtk_entry_set_text (GTK_ENTRY (widget), "");
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "entry_virtual_manufacturer"));
+ gtk_entry_set_text (GTK_ENTRY (widget), "");
+}
+
+static gboolean
+gcm_prefs_is_profile_suitable_for_device (CdProfile *profile,
+ CdDevice *device)
+{
+ CdProfileKind profile_kind_tmp;
+ CdProfileKind profile_kind;
+ CdColorspace profile_colorspace;
+ CdColorspace device_colorspace = 0;
+ gboolean ret = FALSE;
+ CdDeviceKind device_kind;
+
+ /* 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;
+
+ /* 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;
+
+ /* 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;
+ gchar *text_a;
+ gchar *text_b;
+ gint retval;
+
+ /* 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)
+ retval = -1;
+ else if (type_a > type_b)
+ retval = 1;
+ else
+ retval = g_strcmp0 (text_a, text_b);
+
+ g_free (text_a);
+ g_free (text_b);
+ return retval;
+}
+
+static void
+gcm_prefs_add_profiles_suitable_for_devices (CcColorPanel *prefs,
+ GtkWidget *widget,
+ CdProfile *profile)
+{
+ CdProfile *profile_tmp;
+ gboolean ret;
+ GError *error = NULL;
+ GPtrArray *profile_array = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ guint i;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* clear existing entries */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_list_store_clear (GTK_LIST_STORE (model));
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ gcm_prefs_combo_sort_func_cb,
+ model, NULL);
+
+ /* get profiles */
+ profile_array = cd_client_get_profiles_sync (priv->client,
+ priv->cancellable,
+ &error);
+ if (profile_array == NULL)
+ {
+ g_warning ("failed to get profiles: %s",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* add profiles of the right kind */
+ for (i = 0; i < profile_array->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profile_array, i);
+
+ /* don't add the current profile */
+ if (profile != NULL && cd_profile_equal (profile, profile_tmp))
+ continue;
+
+ /* only add correct types */
+ ret = gcm_prefs_is_profile_suitable_for_device (profile_tmp,
+ priv->current_device);
+ if (!ret)
+ continue;
+
+ /* add */
+ gcm_prefs_combobox_add_profile (widget,
+ profile_tmp,
+ 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);
+out:
+ if (profile_array != NULL)
+ g_ptr_array_unref (profile_array);
+}
+
+static void
+gcm_prefs_profile_add_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ CdProfile *profile = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* add profiles of the right kind */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "combobox_profile"));
+ profile = cd_device_get_default_profile (priv->current_device);
+ gcm_prefs_add_profiles_suitable_for_devices (prefs, widget, profile);
+
+ /* show the dialog */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "dialog_assign"));
+ gtk_widget_show (widget);
+ gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (priv->main_window));
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static void
+gcm_prefs_profile_remove_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ gboolean ret = FALSE;
+ CdProfile *profile = NULL;
+ GError *error = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get the selected row */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "treeview_devices"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ g_assert_not_reached ();
+
+ /* if the profile is default, then we'll have to make the first profile default */
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* just remove it, the list store will get ::changed */
+ ret = cd_device_remove_profile_sync (priv->current_device,
+ profile,
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to remove profile: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (profile != NULL)
+ g_object_unref (profile);
+ return;
+}
+
+static void
+gcm_prefs_profile_make_default_internal (CcColorPanel *prefs,
+ GtkTreeModel *model,
+ GtkTreeIter *iter_selected)
+{
+ CdProfile *profile;
+ GError *error = NULL;
+ gboolean ret = FALSE;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get currentlt selected item */
+ gtk_tree_model_get (model, iter_selected,
+ GCM_PREFS_COLUMN_PROFILE, &profile,
+ -1);
+ if (profile == NULL)
+ goto out;
+
+ /* just set it default */
+ ret = cd_device_make_profile_default_sync (priv->current_device,
+ profile,
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to set default profile: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static void
+gcm_prefs_profile_view_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ CdProfile *profile = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ gchar *options = NULL;
+ GPtrArray *argv = NULL;
+ guint xid;
+ gboolean ret;
+ GError *error = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get the selected row */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "treeview_devices"));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ g_assert_not_reached ();
+
+ /* get currentlt selected item */
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* get xid */
+ xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (priv->main_window)));
+
+ /* open up gcm-viewer as a info pane */
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_build_filename (BINDIR, "gcm-viewer", NULL));
+ 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));
+ ret = g_spawn_async (NULL, (gchar**) argv->pdata, NULL, 0,
+ NULL, NULL, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("failed to run calibrate: %s", error->message);
+ g_error_free (error);
+ }
+
+ if (argv != NULL)
+ g_ptr_array_unref (argv);
+ g_free (options);
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static void
+gcm_prefs_button_assign_cancel_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ CcColorPanelPrivate *priv = prefs->priv;
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "dialog_assign"));
+ gtk_widget_hide (widget);
+}
+
+static void
+gcm_prefs_button_assign_ok_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ CdProfile *profile = NULL;
+ gboolean ret = FALSE;
+ GError *error = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* hide window */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "dialog_assign"));
+ gtk_widget_hide (widget);
+
+ /* get entry */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "combobox_profile"));
+ ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+ if (!ret)
+ goto out;
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* just add it, the list store will get ::changed */
+ ret = cd_device_add_profile_sync (priv->current_device,
+ CD_DEVICE_RELATION_HARD,
+ profile,
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to add: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* make it default */
+ ret = cd_device_make_profile_default_sync (priv->current_device,
+ profile,
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to set default: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static gboolean
+gcm_prefs_profile_delete_event_cb (GtkWidget *widget,
+ GdkEvent *event,
+ CcColorPanel *prefs)
+{
+ gcm_prefs_button_assign_cancel_cb (widget, prefs);
+ return TRUE;
+}
+
+static void
+gcm_prefs_delete_cb (GtkWidget *widget, CcColorPanel *prefs)
+{
+ gboolean ret = FALSE;
+ GError *error = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* try to delete device */
+ ret = cd_client_delete_device_sync (priv->client,
+ cd_device_get_id (priv->current_device),
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to delete device: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+gcm_prefs_treeview_renderer_toggled (GtkCellRendererToggle *cell,
+ const gchar *path, CcColorPanel *prefs)
+{
+ gboolean ret;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ model = GTK_TREE_MODEL (priv->list_store_devices);
+ ret = gtk_tree_model_get_iter_from_string (model, &iter, path);
+ if (!ret)
+ return;
+ gcm_prefs_profile_make_default_internal (prefs, model, &iter);
+}
+
+static void
+gcm_prefs_add_devices_columns (CcColorPanel *prefs,
+ GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ gtk_tree_view_set_headers_visible (treeview, TRUE);
+
+ /* --- column for device image and device title --- */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, TRUE);
+ /* TRANSLATORS: column for device list */
+ gtk_tree_view_column_set_title (column, _("Device"));
+
+ /* image */
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_MENU, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "icon-name", GCM_PREFS_COLUMN_ICON);
+
+ /* option */
+ renderer = gtk_cell_renderer_toggle_new ();
+ g_signal_connect (renderer, "toggled",
+ G_CALLBACK (gcm_prefs_treeview_renderer_toggled), prefs);
+ g_object_set (renderer, "radio", TRUE, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "active", GCM_PREFS_COLUMN_RADIO_ACTIVE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "visible", GCM_PREFS_COLUMN_RADIO_VISIBLE);
+
+ /* text */
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", GCM_PREFS_COLUMN_TITLE);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->list_store_devices),
+ GCM_PREFS_COLUMN_SORT,
+ GTK_SORT_DESCENDING);
+ gtk_tree_view_append_column (treeview, GTK_TREE_VIEW_COLUMN(column));
+
+ /* --- column for device status --- */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, TRUE);
+ /* TRANSLATORS: column for device list */
+ gtk_tree_view_column_set_title (column, _("Calibration"));
+
+ /* image */
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_MENU, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "icon-name", GCM_PREFS_COLUMN_STATUS_IMAGE);
+
+ /* text */
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", GCM_PREFS_COLUMN_STATUS);
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_append_column (treeview, GTK_TREE_VIEW_COLUMN(column));
+
+ /* tooltip */
+ gtk_tree_view_set_tooltip_column (treeview,
+ GCM_PREFS_COLUMN_TOOLTIP);
+}
+
+static void
+gcm_prefs_set_calibrate_button_sensitivity (CcColorPanel *prefs)
+{
+ gboolean ret = FALSE;
+ GtkWidget *widget;
+ const gchar *tooltip;
+ CdDeviceKind kind;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* TRANSLATORS: this is when the button is sensitive */
+ tooltip = _("Create a color profile for the selected device");
+
+ /* no device selected */
+ if (priv->current_device == NULL)
+ goto out;
+
+ /* are we a display */
+ kind = cd_device_get_kind (priv->current_device);
+ if (kind == CD_DEVICE_KIND_DISPLAY)
+ {
+
+ /* find whether we have hardware installed */
+ if (priv->sensor == NULL) {
+ /* 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 (priv->sensor == NULL)
+ {
+ /* 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 */
+ ret = cd_sensor_has_cap (priv->sensor, 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 */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_calibrate"));
+ gtk_widget_set_tooltip_text (widget, tooltip);
+ gtk_widget_set_sensitive (widget, ret);
+}
+
+static void
+gcm_prefs_device_clicked (CcColorPanel *prefs, CdDevice *device)
+{
+ GtkWidget *widget;
+ CdDeviceMode device_mode;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ if (device == NULL)
+ g_assert_not_reached ();
+
+ /* get current device */
+ if (priv->current_device != NULL)
+ g_object_unref (priv->current_device);
+ priv->current_device = g_object_ref (device);
+
+ /* we have a new device */
+ g_debug ("selected device is: %s",
+ cd_device_get_id (device));
+
+ /* make sure selectable */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "combobox_profile"));
+ gtk_widget_set_sensitive (widget, TRUE);
+
+ /* can we delete this device? */
+ device_mode = cd_device_get_mode (priv->current_device);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_remove"));
+ gtk_widget_set_visible (widget, device_mode == CD_DEVICE_MODE_VIRTUAL);
+
+ /* can this device calibrate */
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+}
+
+static void
+gcm_prefs_profile_clicked (CcColorPanel *prefs, CdProfile *profile, CdDevice *device)
+{
+ GtkWidget *widget;
+ CdDeviceRelation relation;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get profile */
+ g_debug ("selected profile = %s",
+ cd_profile_get_filename (profile));
+
+
+ /* find the profile relationship */
+ relation = cd_device_get_profile_relation (device,
+ profile,
+ NULL, NULL);
+
+ /* we can only remove hard relationships */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_remove"));
+ if (relation == CD_DEVICE_RELATION_HARD)
+ {
+ gtk_widget_set_tooltip_text (widget, "");
+ gtk_widget_set_sensitive (widget, TRUE);
+ }
+ else
+ {
+ /* TRANSLATORS: this is when an auto-added profile cannot be removed */
+ gtk_widget_set_tooltip_text (widget, _("Cannot remove automatically added profile"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+ /* allow getting profile info */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_view"));
+ gtk_widget_set_sensitive (widget, TRUE);
+}
+
+static void
+gcm_prefs_devices_treeview_clicked_cb (GtkTreeSelection *selection,
+ CcColorPanel *prefs)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ CdDevice *device = NULL;
+ CdProfile *profile = NULL;
+ GtkWidget *widget;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get selection */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ g_assert_not_reached ();
+
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COLUMN_DEVICE, &device,
+ GCM_PREFS_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* device actions */
+ if (device != NULL)
+ gcm_prefs_device_clicked (prefs, device);
+ if (profile != NULL)
+ gcm_prefs_profile_clicked (prefs, profile, device);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_default"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_add"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_calibrate"));
+ gtk_widget_set_visible (widget, profile == NULL);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_view"));
+ gtk_widget_set_visible (widget, profile != NULL);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_remove"));
+ gtk_widget_set_visible (widget, profile != NULL);
+
+ if (device != NULL)
+ g_object_unref (device);
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static void
+gcm_prefs_treeview_row_activated_cb (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ CcColorPanel *prefs)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean ret;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get the iter */
+ model = GTK_TREE_MODEL (priv->list_store_devices);
+ ret = gtk_tree_model_get_iter (model, &iter, path);
+ if (!ret)
+ return;
+
+ /* make this profile the default */
+ gcm_prefs_profile_make_default_internal (prefs, model, &iter);
+}
+
+static const gchar *
+gcm_prefs_device_kind_to_sort (CdDeviceKind kind)
+{
+ if (kind == CD_DEVICE_KIND_DISPLAY)
+ return "4";
+ if (kind == CD_DEVICE_KIND_SCANNER)
+ return "3";
+ if (kind == CD_DEVICE_KIND_CAMERA)
+ return "2";
+ if (kind == CD_DEVICE_KIND_PRINTER)
+ return "1";
+ return "0";
+}
+
+static gchar *
+gcm_device_get_title (CdDevice *device)
+{
+ const gchar *model;
+ const gchar *vendor;
+ GString *string;
+
+ /* try to get a nice string suitable for display */
+ vendor = cd_device_get_vendor (device);
+ model = cd_device_get_model (device);
+ string = g_string_new ("");
+
+ if (vendor != NULL && model != NULL)
+ {
+ g_string_append_printf (string, "%s - %s",
+ vendor, model);
+ goto out;
+ }
+
+ /* just model */
+ if (model != NULL)
+ {
+ g_string_append (string, model);
+ goto out;
+ }
+
+ /* just vendor */
+ if (vendor != NULL)
+ {
+ g_string_append (string, vendor);
+ goto out;
+ }
+
+ /* fallback to id */
+ g_string_append (string, cd_device_get_id (device));
+out:
+ return g_string_free (string, FALSE);
+}
+
+static void
+gcm_prefs_set_combo_simple_text (GtkWidget *combo_box)
+{
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
+
+ store = gtk_list_store_new (GCM_PREFS_COMBO_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING,
+ CD_TYPE_PROFILE,
+ G_TYPE_UINT);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box),
+ GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR,
+ "width-chars", 60,
+ NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
+ "text", GCM_PREFS_COMBO_COLUMN_TEXT,
+ NULL);
+}
+
+static void
+gcm_prefs_profile_combo_changed_cb (GtkWidget *widget,
+ CcColorPanel *prefs)
+{
+ GFile *file = NULL;
+ gboolean ret;
+ CdProfile *profile = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GcmPrefsEntryType entry_type;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* no devices */
+ if (priv->current_device == NULL)
+ return;
+
+ /* no selection */
+ ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+ if (!ret)
+ return;
+
+ /* get entry */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_TYPE, &entry_type,
+ -1);
+
+ /* import */
+ if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT)
+ {
+ file = gcm_prefs_file_chooser_get_icc_profile (prefs);
+ if (file == NULL)
+ {
+ g_warning ("failed to get ICC file");
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ 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,
+ -1);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
+ }
+out:
+ if (file != NULL)
+ g_object_unref (file);
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+
+
+static void
+gcm_prefs_sensor_coldplug (CcColorPanel *prefs)
+{
+ GPtrArray *sensors;
+ GError *error = NULL;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* unref old */
+ if (priv->sensor != NULL)
+ {
+ g_object_unref (priv->sensor);
+ priv->sensor = NULL;
+ }
+
+ /* no present */
+ sensors = cd_client_get_sensors_sync (priv->client, NULL, &error);
+ if (sensors == NULL)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ if (sensors->len == 0)
+ goto out;
+
+ /* save a copy of the sensor */
+ priv->sensor = g_object_ref (g_ptr_array_index (sensors, 0));
+out:
+ if (sensors != NULL)
+ g_ptr_array_unref (sensors);
+}
+
+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 const gchar *
+gcm_prefs_device_kind_to_icon_name (CdDeviceKind kind)
+{
+ if (kind == CD_DEVICE_KIND_DISPLAY)
+ return "video-display";
+ if (kind == CD_DEVICE_KIND_SCANNER)
+ return "scanner";
+ if (kind == CD_DEVICE_KIND_PRINTER)
+ return "printer";
+ if (kind == CD_DEVICE_KIND_CAMERA)
+ return "camera-photo";
+ if (kind == CD_DEVICE_KIND_CAMERA)
+ return "camera-photo";
+ if (kind == CD_DEVICE_KIND_WEBCAM)
+ return "camera-web";
+ return "image-missing";
+}
+
+static gboolean
+gcm_prefs_profile_is_based_from_edid (CdProfile *profile)
+{
+ if (cd_profile_get_kind (profile) != CD_PROFILE_KIND_DISPLAY_DEVICE)
+ return FALSE;
+ if (cd_profile_get_metadata_item (profile, "EDID_md5") == NULL)
+ return FALSE;
+ return TRUE;
+}
+
+static GString *
+gcm_prefs_get_profile_age_as_string (CdProfile *profile)
+{
+ gint64 age;
+ GString *string;
+
+ if (profile == NULL)
+ {
+ /* TRANSLATORS: this is when there is no profile for the device */
+ string = g_string_new (_("No profile"));
+ goto out;
+ }
+
+ /* days */
+ age = cd_profile_get_age (profile);
+ if (age == 0)
+ {
+ string = g_string_new (NULL);
+ goto out;
+ }
+ age /= 60 * 60 * 24;
+ string = g_string_new ("");
+
+ /* approximate years */
+ if (age > 365)
+ {
+ age /= 365;
+ g_string_append_printf (string, ngettext (
+ "%i year",
+ "%i years",
+ age), (guint) age);
+ goto out;
+ }
+
+ /* approximate months */
+ if (age > 30)
+ {
+ age /= 30;
+ g_string_append_printf (string, ngettext (
+ "%i month",
+ "%i months",
+ age), (guint) age);
+ goto out;
+ }
+
+ /* approximate weeks */
+ if (age > 7)
+ {
+ age /= 7;
+ g_string_append_printf (string, ngettext (
+ "%i week",
+ "%i weeks",
+ age), (guint) age);
+ goto out;
+ }
+
+ /* fallback */
+ g_string_append_printf (string, _("Less than 1 week"));
+out:
+ return string;
+}
+
+static gchar *
+gcm_prefs_get_profile_created_for_sort (CdProfile *profile)
+{
+ gint64 created;
+ gchar *string = NULL;
+ GDateTime *dt = NULL;
+
+ /* get profile age */
+ created = cd_profile_get_created (profile);
+ if (created == 0)
+ goto out;
+ dt = g_date_time_new_from_unix_utc (created);
+ /* note: this is not shown in the UI, just used for sorting */
+ string = g_date_time_format (dt, "%Y%m%d");
+out:
+ if (dt != NULL)
+ g_date_time_unref (dt);
+ return string;
+}
+
+static gchar *
+gcm_prefs_get_profile_title (CdProfile *profile)
+{
+ CdColorspace colorspace;
+ const gchar *title;
+ gchar *string;
+
+ g_return_val_if_fail (profile != NULL, NULL);
+
+ /* add profile description */
+ title = cd_profile_get_title (profile);
+ if (title != NULL)
+ {
+ string = g_strdup (title);
+ goto out;
+ }
+
+ /* some meta profiles do not have ICC profiles */
+ colorspace = cd_profile_get_colorspace (profile);
+ if (colorspace == CD_COLORSPACE_RGB)
+ {
+ string = g_strdup (C_("Colorspace fallback", "Default RGB"));
+ goto out;
+ }
+ if (colorspace == CD_COLORSPACE_CMYK)
+ {
+ string = g_strdup (C_("Colorspace fallback", "Default CMYK"));
+ goto out;
+ }
+ if (colorspace == CD_COLORSPACE_GRAY)
+ {
+ string = g_strdup (C_("Colorspace fallback", "Default Gray"));
+ goto out;
+ }
+
+ /* fall back to ID, ick */
+ string = g_strdup (cd_profile_get_id (profile));
+out:
+ return string;
+}
+
+static void
+gcm_prefs_device_remove_profiles_phase1 (CcColorPanel *prefs, GtkTreeIter *parent)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gboolean ret;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get first element */
+ model = GTK_TREE_MODEL (priv->list_store_devices);
+ ret = gtk_tree_model_iter_children (model, &iter, parent);
+ if (!ret)
+ return;
+
+ /* mark to be removed */
+ do {
+ gtk_tree_store_set (priv->list_store_devices, &iter,
+ GCM_PREFS_COLUMN_DEVICE_ID, NULL,
+ -1);
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+gcm_prefs_device_remove_profiles_phase2 (CcColorPanel *prefs, GtkTreeIter *parent)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gchar *id_tmp;
+ gboolean ret;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get first element */
+ model = GTK_TREE_MODEL (priv->list_store_devices);
+ ret = gtk_tree_model_iter_children (model, &iter, parent);
+ if (!ret)
+ return;
+
+ /* remove the other elements */
+ do
+ {
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COLUMN_DEVICE_ID, &id_tmp,
+ -1);
+ if (id_tmp == NULL)
+ ret = gtk_tree_store_remove (priv->list_store_devices, &iter);
+ else
+ ret = gtk_tree_model_iter_next (model, &iter);
+ g_free (id_tmp);
+ } while (ret);
+}
+
+static GtkTreeIter *
+get_iter_for_profile (GtkTreeModel *model, CdProfile *profile, GtkTreeIter *parent)
+{
+ const gchar *id;
+ GtkTreeIter iter_tmp;
+ gboolean ret;
+ GtkTreeIter *iter = NULL;
+ CdProfile *profile_tmp;
+
+ /* get first element */
+ ret = gtk_tree_model_iter_children (model, &iter_tmp, parent);
+ if (!ret)
+ goto out;
+
+ /* remove the other elements */
+ id = cd_profile_get_id (profile);
+ do
+ {
+ gtk_tree_model_get (model, &iter_tmp,
+ GCM_PREFS_COLUMN_PROFILE, &profile_tmp,
+ -1);
+ if (g_strcmp0 (id, cd_profile_get_id (profile_tmp)) == 0)
+ iter = &iter_tmp;
+ g_object_unref (profile_tmp);
+ } while (iter == NULL && gtk_tree_model_iter_next (model, &iter_tmp));
+out:
+ return iter;
+}
+
+static void
+gcm_prefs_device_set_model_by_iter (CcColorPanel *prefs, CdDevice *device, GtkTreeIter *iter)
+{
+ GString *status;
+ const gchar *status_image = NULL;
+ const gchar *tooltip = NULL;
+ CdProfile *profile = NULL;
+ gint age;
+ GPtrArray *profiles;
+ CdProfile *profile_tmp;
+ guint i;
+ gchar *title_tmp;
+ GString *date_tmp;
+ gchar *sort_tmp;
+ GtkTreeIter iter_tmp;
+ GtkTreeIter *iter_tmp_p;
+ guint threshold = 0;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* set status */
+ profile = cd_device_get_default_profile (device);
+ if (profile == NULL)
+ {
+ status = g_string_new (_("Uncalibrated"));
+ g_string_prepend (status, "<span foreground='gray'><i>");
+ g_string_append (status, "</i></span>");
+ tooltip = _("This device is not color managed.");
+ goto skip;
+ }
+
+ /* autogenerated printer defaults */
+ if (cd_device_get_kind (device) == CD_DEVICE_KIND_PRINTER &&
+ cd_profile_get_filename (profile) == NULL)
+ {
+ status = g_string_new (_("Uncalibrated"));
+ g_string_prepend (status, "<span foreground='gray'><i>");
+ g_string_append (status, "</i></span>");
+ tooltip = _("This device is using manufacturing calibrated data.");
+ goto skip;
+ }
+
+ /* autogenerated profiles are crap */
+ if (cd_profile_get_kind (profile) == CD_PROFILE_KIND_DISPLAY_DEVICE &&
+ !cd_profile_get_has_vcgt (profile))
+ {
+ status = g_string_new (_("Uncalibrated"));
+ g_string_prepend (status, "<span foreground='gray'><i>");
+ g_string_append (status, "</i></span>");
+ tooltip = _("This device does not have a profile suitable for whole-screen color correction.");
+ goto skip;
+ }
+
+ /* yay! */
+ status = gcm_prefs_get_profile_age_as_string (profile);
+
+ /* greater than the calibration threshold for the device type */
+ age = cd_profile_get_age (profile);
+ age /= 60 * 60 * 24;
+ if (cd_device_get_kind (device) == CD_DEVICE_KIND_DISPLAY)
+ {
+ g_settings_get (priv->settings,
+ GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD,
+ "u",
+ &threshold);
+ }
+ else if (cd_device_get_kind (device) == CD_DEVICE_KIND_DISPLAY)
+ {
+ g_settings_get (priv->settings,
+ GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD,
+ "u",
+ &threshold);
+ }
+ if (threshold > 0 && age > threshold)
+ {
+ status_image = "dialog-warning-symbolic";
+ tooltip = _("This device has an old profile that may no longer be accurate.");
+ }
+skip:
+ /* save to store */
+ gtk_tree_store_set (priv->list_store_devices, iter,
+ GCM_PREFS_COLUMN_STATUS, status->str,
+ GCM_PREFS_COLUMN_STATUS_IMAGE, status_image,
+ GCM_PREFS_COLUMN_TOOLTIP, tooltip,
+ -1);
+
+ /* remove old profiles */
+ gcm_prefs_device_remove_profiles_phase1 (prefs, iter);
+
+ /* add profiles */
+ profiles = cd_device_get_profiles (device);
+ if (profiles == NULL)
+ goto out;
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ title_tmp = gcm_prefs_get_profile_title (profile_tmp);
+
+ /* don't show details for EDID profiles */
+ if (gcm_prefs_profile_is_based_from_edid (profile_tmp))
+ {
+ date_tmp = g_string_new ("Not specified");
+ g_string_prepend (date_tmp, "<span foreground='gray'><i>");
+ g_string_append (date_tmp, "</i></span>");
+ }
+ else
+ {
+ date_tmp = gcm_prefs_get_profile_age_as_string (profile_tmp);
+ }
+ sort_tmp = gcm_prefs_get_profile_created_for_sort (profile_tmp);
+
+ /* get an existing profile, or create a new one */
+ iter_tmp_p = get_iter_for_profile (GTK_TREE_MODEL (priv->list_store_devices),
+ profile_tmp, iter);
+ if (iter_tmp_p == NULL)
+ {
+ gtk_tree_store_append (priv->list_store_devices, &iter_tmp, iter);
+ iter_tmp_p = &iter_tmp;
+ }
+
+ gtk_tree_store_set (priv->list_store_devices, iter_tmp_p,
+ GCM_PREFS_COLUMN_DEVICE, device,
+ GCM_PREFS_COLUMN_PROFILE, profile_tmp,
+ GCM_PREFS_COLUMN_DEVICE_ID, cd_device_get_id (device),
+ GCM_PREFS_COLUMN_SORT, sort_tmp,
+ GCM_PREFS_COLUMN_STATUS, date_tmp->str,
+ GCM_PREFS_COLUMN_TITLE, title_tmp,
+ GCM_PREFS_COLUMN_RADIO_VISIBLE, TRUE,
+ GCM_PREFS_COLUMN_RADIO_ACTIVE, i==0,
+ -1);
+ g_free (title_tmp);
+ g_free (sort_tmp);
+ g_string_free (date_tmp, TRUE);
+ }
+
+ /* remove old profiles that no longer exist */
+ gcm_prefs_device_remove_profiles_phase2 (prefs, iter);
+out:
+ g_string_free (status, TRUE);
+ if (profiles != NULL)
+ g_ptr_array_unref (profiles);
+ if (profile != NULL)
+ g_object_unref (profile);
+}
+
+static void
+gcm_prefs_device_changed_cb (CdDevice *device, CcColorPanel *prefs)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ const gchar *id;
+ gchar *id_tmp;
+ gboolean ret;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get first element */
+ model = GTK_TREE_MODEL (priv->list_store_devices);
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ if (!ret)
+ return;
+
+ /* get the other elements */
+ id = cd_device_get_id (device);
+ do
+ {
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COLUMN_DEVICE_ID, &id_tmp,
+ -1);
+ if (g_strcmp0 (id_tmp, id) == 0)
+ gcm_prefs_device_set_model_by_iter (prefs, device, &iter);
+ g_free (id_tmp);
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+gcm_prefs_add_device (CcColorPanel *prefs, CdDevice *device)
+{
+ CdDeviceKind kind;
+ const gchar *icon_name;
+ const gchar *id;
+ gchar *sort = NULL;
+ gchar *title = NULL;
+ GtkTreeIter parent;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* get icon */
+ kind = cd_device_get_kind (device);
+ icon_name = gcm_prefs_device_kind_to_icon_name (kind);
+
+ /* italic for non-connected devices */
+ title = gcm_device_get_title (device);
+
+ /* create sort order */
+ sort = g_strdup_printf ("%s%s",
+ gcm_prefs_device_kind_to_sort (kind),
+ title);
+
+ /* watch for changes to update the status icons */
+ g_signal_connect (device, "changed",
+ G_CALLBACK (gcm_prefs_device_changed_cb), prefs);
+
+ /* add to list */
+ id = cd_device_get_id (device);
+ g_debug ("add %s to device list", id);
+ gtk_tree_store_append (priv->list_store_devices, &parent, NULL);
+ gtk_tree_store_set (priv->list_store_devices, &parent,
+ GCM_PREFS_COLUMN_DEVICE, device,
+ GCM_PREFS_COLUMN_DEVICE_ID, id,
+ GCM_PREFS_COLUMN_SORT, sort,
+ GCM_PREFS_COLUMN_TITLE, title,
+ GCM_PREFS_COLUMN_ICON, icon_name,
+ -1);
+ gcm_prefs_device_set_model_by_iter (prefs, device, &parent);
+ g_free (sort);
+ g_free (title);
+}
+
+static void
+gcm_prefs_remove_device (CcColorPanel *prefs, CdDevice *cd_device)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ const gchar *id;
+ gchar *id_tmp;
+ gboolean ret;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* remove */
+ id = cd_device_get_id (cd_device);
+
+ /* get first element */
+ model = GTK_TREE_MODEL (priv->list_store_devices);
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ if (!ret)
+ return;
+
+ /* get the other elements */
+ do
+ {
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COLUMN_DEVICE_ID, &id_tmp,
+ -1);
+ if (g_strcmp0 (id_tmp, id) == 0)
+ {
+ gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
+ g_free (id_tmp);
+ break;
+ }
+ g_free (id_tmp);
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+gcm_prefs_device_added_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ /* remove the saved device if it's already there */
+ gcm_prefs_remove_device (prefs, device);
+
+ /* add the device */
+ gcm_prefs_add_device (prefs, device);
+}
+
+static void
+gcm_prefs_changed_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ g_debug ("changed: %s (doing nothing)", cd_device_get_id (device));
+}
+
+static void
+gcm_prefs_device_removed_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+ GtkWidget *widget;
+ gboolean ret;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* remove from the UI */
+ gcm_prefs_remove_device (prefs, device);
+
+ /* select the first device */
+ ret = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->list_store_devices), &iter);
+ if (!ret)
+ return;
+
+ /* click it */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "treeview_devices"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (priv->list_store_devices));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ gtk_tree_selection_select_iter (selection, &iter);
+}
+
+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;
+ GError *error = NULL;
+ GPtrArray *devices;
+ GtkTreePath *path;
+ GtkWidget *widget;
+ guint i;
+ CcColorPanelPrivate *priv = prefs->priv;
+
+ /* 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);
+ g_error_free (error);
+ goto out;
+ }
+ for (i = 0; i < devices->len; i++)
+ {
+ device = g_ptr_array_index (devices, i);
+ gcm_prefs_add_device (prefs, device);
+ }
+
+ /* set the cursor on the first device */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "treeview_devices"));
+ path = gtk_tree_path_new_from_string ("0");
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE);
+ gtk_tree_path_free (path);
+out:
+ if (devices != NULL)
+ g_ptr_array_unref (devices);
+}
+
+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)
+{
+ CcColorPanelPrivate *priv = CC_COLOR_PANEL (object)->priv;
+
+ if (priv->settings)
+ {
+ g_object_unref (priv->settings);
+ priv->settings = NULL;
+ }
+ if (priv->cancellable != NULL)
+ {
+ g_cancellable_cancel (priv->cancellable);
+ g_object_unref (priv->cancellable);
+ priv->cancellable = NULL;
+ }
+ if (priv->builder != NULL)
+ {
+ g_object_unref (priv->builder);
+ priv->builder = NULL;
+ }
+ if (priv->client != NULL)
+ {
+ g_object_unref (priv->client);
+ priv->client = NULL;
+ }
+ if (priv->current_device != NULL)
+ {
+ g_object_unref (priv->current_device);
+ priv->current_device = NULL;
+ }
+ if (priv->sensor != NULL)
+ {
+ g_object_unref (priv->sensor);
+ priv->sensor = NULL;
+ }
+
+ 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);
+
+ g_type_class_add_private (klass, sizeof (CcColorPanelPrivate));
+
+ 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;
+}
+
+static void
+cc_color_panel_class_finalize (CcColorPanelClass *klass)
+{
+}
+
+static void
+cc_color_panel_init (CcColorPanel *prefs)
+{
+ CcColorPanelPrivate *priv;
+ gboolean ret;
+ gchar *text = NULL;
+ GError *error = NULL;
+ GtkStyleContext *context;
+ GtkTreeSelection *selection;
+ GtkWidget *widget;
+
+ priv = prefs->priv = COLOR_PANEL_PRIVATE (prefs);
+
+ priv->builder = gtk_builder_new ();
+ gtk_builder_add_from_file (priv->builder,
+ GNOMECC_UI_DIR "/color.ui",
+ &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Could not load interface file: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ priv->cancellable = g_cancellable_new ();
+
+ /* setup defaults */
+ priv->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
+
+ /* create list stores */
+ priv->list_store_devices = gtk_tree_store_new (GCM_PREFS_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ CD_TYPE_DEVICE,
+ CD_TYPE_PROFILE,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+
+ /* assign buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_add"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_profile_add_cb), prefs);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_remove"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_profile_remove_cb), prefs);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_profile_view"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_profile_view_cb), prefs);
+
+ /* create device tree view */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "treeview_devices"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (priv->list_store_devices));
+ gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (widget), TRUE);
+ gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (widget), 0);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (gcm_prefs_devices_treeview_clicked_cb),
+ prefs);
+ g_signal_connect (GTK_TREE_VIEW (widget), "row-activated",
+ G_CALLBACK (gcm_prefs_treeview_row_activated_cb),
+ prefs);
+
+ /* add columns to the tree view */
+ gcm_prefs_add_devices_columns (prefs, GTK_TREE_VIEW (widget));
+
+ /* force to be at least 3 rows high */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "scrolledwindow_devices"));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_default"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_default_cb), prefs);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_remove"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_delete_cb), prefs);
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_add"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_device_add_cb), prefs);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbutton_device_calibrate"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_calibrate_cb), prefs);
+
+ /* make devices toolbar sexy */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "scrolledwindow_devices"));
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "toolbar_devices"));
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+ gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+
+ /* set up assign dialog */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "dialog_assign"));
+ g_signal_connect (widget, "delete-event",
+ G_CALLBACK (gcm_prefs_profile_delete_event_cb), prefs);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "button_assign_cancel"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_button_assign_cancel_cb), prefs);
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "button_assign_ok"));
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (gcm_prefs_button_assign_ok_cb), prefs);
+
+ /* setup icc profiles list */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
+ "combobox_profile"));
+ gcm_prefs_set_combo_simple_text (widget);
+ gtk_widget_set_sensitive (widget, FALSE);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (gcm_prefs_profile_combo_changed_cb), prefs);
+
+ /* use a device client array */
+ priv->client = cd_client_new ();
+ g_signal_connect (priv->client, "device-added",
+ G_CALLBACK (gcm_prefs_device_added_cb), prefs);
+ g_signal_connect (priv->client, "device-removed",
+ G_CALLBACK (gcm_prefs_device_removed_cb), prefs);
+ g_signal_connect (priv->client, "changed",
+ G_CALLBACK (gcm_prefs_changed_cb), prefs);
+
+ /* connect to colord */
+ ret = cd_client_connect_sync (priv->client,
+ priv->cancellable,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to connect to colord: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* get devices async */
+ cd_client_get_devices (priv->client,
+ priv->cancellable,
+ gcm_prefs_get_devices_cb,
+ prefs);
+
+ /* use the color sensor */
+ g_signal_connect (priv->client, "sensor-added",
+ G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
+ prefs);
+ g_signal_connect (priv->client, "sensor-removed",
+ G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
+ prefs);
+
+out:
+ g_free (text);
+
+ /* set calibrate button sensitivity */
+ gcm_prefs_sensor_coldplug (prefs);
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+
+ widget = WID (priv->builder, "dialog-vbox1");
+ gtk_widget_reparent (widget, (GtkWidget *) prefs);
+ priv->main_window = gtk_widget_get_toplevel (widget);
+}
+
+void
+cc_color_panel_register (GIOModule *module)
+{
+ cc_color_panel_register_type (G_TYPE_MODULE (module));
+ g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT,
+ CC_TYPE_COLOR_PANEL,
+ "color", 0);
+}
+
diff --git a/panels/color/cc-color-panel.h b/panels/color/cc-color-panel.h
new file mode 100644
index 0000000..2b7070e
--- /dev/null
+++ b/panels/color/cc-color-panel.h
@@ -0,0 +1,74 @@
+/* -*- 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef _CC_COLOR_PANEL_H
+#define _CC_COLOR_PANEL_H
+
+#include <libgnome-control-center/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_PANEL cc_color_panel_get_type()
+
+#define CC_COLOR_PANEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ CC_TYPE_COLOR_PANEL, CcColorPanel))
+
+#define CC_COLOR_PANEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ CC_TYPE_COLOR_PANEL, CcColorPanelClass))
+
+#define CC_IS_COLOR_PANEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ CC_TYPE_COLOR_PANEL))
+
+#define CC_IS_COLOR_PANEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ CC_TYPE_COLOR_PANEL))
+
+#define CC_COLOR_PANEL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ CC_TYPE_COLOR_PANEL, CcColorPanelClass))
+
+typedef struct _CcColorPanel CcColorPanel;
+typedef struct _CcColorPanelClass CcColorPanelClass;
+typedef struct _CcColorPanelPrivate CcColorPanelPrivate;
+
+struct _CcColorPanel
+{
+ CcPanel parent;
+
+ CcColorPanelPrivate *priv;
+};
+
+struct _CcColorPanelClass
+{
+ CcPanelClass parent_class;
+};
+
+GType cc_color_panel_get_type (void) G_GNUC_CONST;
+
+void cc_color_panel_register (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* _CC_COLOR_PANEL_H */
diff --git a/panels/color/color-module.c b/panels/color/color-module.c
new file mode 100644
index 0000000..31106d8
--- /dev/null
+++ b/panels/color/color-module.c
@@ -0,0 +1,42 @@
+/* -*- 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#include <config.h>
+
+#include "cc-color-panel.h"
+
+#include <glib/gi18n-lib.h>
+
+void
+g_io_module_load (GIOModule *module)
+{
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ /* register the panel */
+ cc_color_panel_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/panels/color/color.ui b/panels/color/color.ui
new file mode 100644
index 0000000..e802b51
--- /dev/null
+++ b/panels/color/color.ui
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkDialog" id="dialog_assign">
+ <property name="can_focus">False</property>
+ <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>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</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_action_appearance">False</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_action_appearance">False</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="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkHBox" id="hbox29">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" comments="Profiles that can be added to the device">Available Profiles</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox_profile">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox57">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-dialog-info</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" comments="Some profiles are not compatible with some devices">Only profiles that are compatible with the device will be listed above.</property>
+ <property name="wrap">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="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</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="GtkWindow" id="dialog_prefs">
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="title" translatable="yes">Color</property>
+ <property name="window_position">center</property>
+ <property name="icon_name">preferences-system</property>
+ <child>
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">15</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Each device needs an up to date color profile to be color managed.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_devices">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_devices">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="toolbar_devices">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_arrow">False</property>
+ <property name="icon_size">1</property>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_device_add">
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Add a virtual device</property>
+ <property name="tooltip_text">Add a virtual device</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">Add device</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_device_remove">
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Remove a device</property>
+ <property name="tooltip_text">Remove a device</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">Delete device</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="toolbutton2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_device_default">
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Set this device for all users on this computer</property>
+ <property name="tooltip_text">Set this device for all users on this computer</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">Set for all users</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_profile_add">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">Add profile</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_device_calibrate">
+ <property name="can_focus">False</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Calibrate the device</property>
+ <property name="tooltip_text" translatable="yes">Calibrate the device</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">Calibrateâ?¦</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_profile_remove">
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">Remove profile</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_profile_view">
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="is_important">True</property>
+ <property name="label" translatable="yes">View details</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_buttons"/>
+ <object class="GtkSizeGroup" id="sizegroup_combos"/>
+ <object class="GtkSizeGroup" id="sizegroup_defaults"/>
+ <object class="GtkSizeGroup" id="sizegroup_devices"/>
+</interface>
diff --git a/panels/color/gnome-color-panel.desktop.in.in b/panels/color/gnome-color-panel.desktop.in.in
new file mode 100644
index 0000000..7a8e8ec
--- /dev/null
+++ b/panels/color/gnome-color-panel.desktop.in.in
@@ -0,0 +1,17 @@
+[Desktop Entry]
+_Name=Color
+_Comment=Color management settings
+Exec=gnome-control-center color
+Icon=gnome-color-manager
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;HardwareSettings
+OnlyShowIn=GNOME;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=color
+X-GNOME-Bugzilla-Version= VERSION@
+X-GNOME-Settings-Panel=color
+# Translators: those are keywords for the color control-center panel
+_X-GNOME-Keywords=Color;ICC;Profile;Calibrate;Printer;Display;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9d4c33e..da6fe10 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -53,6 +53,9 @@ panels/network/panel-common.c
panels/power/gnome-power-panel.desktop.in.in
panels/power/cc-power-panel.c
[type: gettext/glade]panels/power/power.ui
+panels/color/gnome-color-panel.desktop.in.in
+panels/color/cc-color-panel.c
+[type: gettext/glade]panels/color/color.ui
panels/screen/gnome-screen-panel.desktop.in.in
[type: gettext/glade]panels/screen/screen.ui
panels/sound/applet-main.c
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 5923745..345d8ef 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -9,6 +9,7 @@ panels/info/gnome-info-panel.desktop.in
panels/keyboard/gnome-keyboard-panel.desktop.in
panels/media/gnome-media-panel.desktop.in
panels/power/gnome-power-panel.desktop.in
+panels/color/gnome-color-panel.desktop.in
panels/printers/gnome-printers-panel.desktop.in
panels/region/gnome-region-panel.desktop.in
panels/screen/gnome-screen-panel.desktop.in
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]