gnome-control-center/panels/color/cc-color-panel.c

2514 lines
79 KiB
C

/* -*- 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_PATH,
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"
/* max number of devices and profiles to cause auto-expand at startup */
#define GCM_PREFS_MAX_DEVICES_PROFILES_EXPANDED 5
static void gcm_prefs_device_add_cb (GtkWidget *widget, CcColorPanel *prefs);
static void
gcm_prefs_combobox_add_profile (GtkWidget *widget,
CdProfile *profile,
GcmPrefsEntryType entry_type,
GtkTreeIter *iter)
{
const gchar *id;
GtkTreeModel *model;
GtkTreeIter iter_tmp;
GString *string;
/* 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 */
string = g_string_new (_("Other profile…"));
}
else
{
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: "));
}
#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: "));
}
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: "));
}
#endif
}
/* 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, string->str,
GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
GCM_PREFS_COMBO_COLUMN_TYPE, entry_type,
-1);
g_string_free (string, TRUE);
}
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 void
gcm_prefs_treeview_popup_menu (CcColorPanel *prefs, GtkWidget *treeview)
{
GtkWidget *menu, *menuitem;
menu = gtk_menu_new ();
/* TRANSLATORS: this is when the profile should be set for all users */
menuitem = gtk_menu_item_new_with_label (_("Set for all users"));
g_signal_connect (menuitem, "activate",
G_CALLBACK (gcm_prefs_default_cb),
prefs);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
/* TRANSLATORS: this is when the profile should be set for all users */
menuitem = gtk_menu_item_new_with_label (_("Create virtual device"));
g_signal_connect (menuitem, "activate",
G_CALLBACK (gcm_prefs_device_add_cb),
prefs);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show_all (menu);
/* Note: gdk_event_get_time() accepts a NULL argument */
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0,
gdk_event_get_time (NULL));
}
static gboolean
gcm_prefs_treeview_popup_menu_cb (GtkWidget *treeview, CcColorPanel *prefs)
{
if (prefs->priv->current_device == NULL)
return FALSE;
gcm_prefs_treeview_popup_menu (prefs, treeview);
return TRUE; /* we handled this */
}
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));
g_ptr_array_add (argv, NULL);
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)
{
#if CD_CHECK_VERSION(0,1,14)
const gchar *data_source;
#endif
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;
#if CD_CHECK_VERSION(0,1,14)
/* 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;
#endif
/* 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 gboolean
gcm_prefs_combo_set_default_cb (gpointer user_data)
{
GtkWidget *widget = GTK_WIDGET (user_data);
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
return FALSE;
}
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_column_id (GTK_TREE_SORTABLE (model),
GCM_PREFS_COMBO_COLUMN_TEXT,
GTK_SORT_ASCENDING);
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);
/* get properties */
ret = cd_profile_connect_sync (profile_tmp,
priv->cancellable,
&error);
if (!ret)
{
g_warning ("failed to get profile: %s", error->message);
g_error_free (error);
goto out;
}
/* 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;
#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 (widget,
profile_tmp,
GCM_PREFS_ENTRY_TYPE_PROFILE,
&iter);
}
/* add a import entry */
#if CD_CHECK_VERSION(0,1,12)
gcm_prefs_combobox_add_profile (widget, NULL, GCM_PREFS_ENTRY_TYPE_IMPORT, NULL);
#endif
g_idle_add (gcm_prefs_combo_set_default_cb, widget);
out:
if (profile_array != NULL)
g_ptr_array_unref (profile_array);
}
static void
gcm_prefs_profile_add_cb (GtkWidget *widget, CcColorPanel *prefs)
{
const gchar *title;
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);
/* set the title */
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"label_assign_title"));
switch (cd_device_get_kind (priv->current_device)) {
case CD_DEVICE_KIND_DISPLAY:
/* TRANSLATORS: this is the dialog title in the 'Add profile' UI */
title = _("Available Profiles for Displays");
break;
case CD_DEVICE_KIND_SCANNER:
/* TRANSLATORS: this is the dialog title in the 'Add profile' UI */
title = _("Available Profiles for Scanners");
break;
case CD_DEVICE_KIND_PRINTER:
/* TRANSLATORS: this is the dialog title in the 'Add profile' UI */
title = _("Available Profiles for Printers");
break;
case CD_DEVICE_KIND_CAMERA:
/* TRANSLATORS: this is the dialog title in the 'Add profile' UI */
title = _("Available Profiles for Cameras");
break;
case CD_DEVICE_KIND_WEBCAM:
/* TRANSLATORS: this is the dialog title in the 'Add profile' UI */
title = _("Available Profiles for Webcams");
break;
default:
/* TRANSLATORS: this is the dialog title in the 'Add profile' UI
* where the device type is not recognised */
title = _("Available Profiles");
break;
}
gtk_label_set_label (GTK_LABEL (widget), title);
/* 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))
goto out;
/* 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)
{
CdDevice *device;
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_DEVICE, &device,
GCM_PREFS_COLUMN_PROFILE, &profile,
-1);
if (profile == NULL || device == NULL)
goto out;
/* just set it default */
ret = cd_device_make_profile_default_sync (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);
if (device != NULL)
g_object_unref (device);
}
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));
g_ptr_array_add (argv, NULL);
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);
if (profile == NULL)
{
g_warning ("failed to get the active profile");
goto out;
}
/* 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,
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;
gchar *s;
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_sync (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"));
if ((s = g_find_program_in_path ("gcm-viewer")))
{
gtk_widget_set_sensitive (widget, TRUE);
g_free (s);
}
else
gtk_widget_set_sensitive (widget, FALSE);
/* hide device specific stuff */
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"toolbutton_device_remove"));
gtk_widget_set_visible (widget, FALSE);
}
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))
return;
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, device != NULL);
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"toolbutton_profile_add"));
gtk_widget_set_visible (widget, device != 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 no buttons then hide toolbar */
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"toolbar_devices"));
gtk_widget_set_visible (widget, profile != NULL || device != 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,
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;
GError *error = 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);
/* if we've got no other existing profiles to choose, then
* just close the assign dialog */
gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
gtk_tree_model_get (model, &iter,
GCM_PREFS_COMBO_COLUMN_TYPE, &entry_type,
-1);
if (entry_type == GCM_PREFS_ENTRY_TYPE_IMPORT)
{
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"dialog_assign"));
gtk_widget_hide (widget);
}
goto out;
}
#if CD_CHECK_VERSION(0,1,12)
profile = cd_client_import_profile_sync (priv->client,
file,
priv->cancellable,
&error);
if (profile == NULL)
{
g_warning ("failed to get imported profile: %s", error->message);
g_error_free (error);
goto out;
}
#endif
/* 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;
gboolean ret;
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));
/* connect to the sensor */
ret = cd_sensor_connect_sync (priv->sensor, NULL, &error);
if (!ret)
{
g_warning ("%s", error->message);
g_error_free (error);
goto out;
}
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 (CcColorPanel *prefs, CdProfile *profile)
{
CdColorspace colorspace;
const gchar *title;
gchar *string;
gboolean ret;
GError *error = NULL;
CcColorPanelPrivate *priv = prefs->priv;
g_return_val_if_fail (profile != NULL, NULL);
/* get properties */
ret = cd_profile_connect_sync (profile,
priv->cancellable,
&error);
if (!ret)
{
g_warning ("failed to get profile: %s", error->message);
g_error_free (error);
goto out;
}
/* add profile description */
title = cd_profile_get_title (profile);
if (title != NULL)
{
string = g_markup_escape_text (title, -1);
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_PATH, 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_PATH, &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 = NULL;
const gchar *status_image = NULL;
const gchar *tooltip = NULL;
CdProfile *profile = NULL;
gint age;
GPtrArray *profiles = NULL;
CdProfile *profile_tmp;
guint i;
gchar *title_tmp;
GString *date_tmp;
gchar *sort_tmp;
GtkTreeIter iter_tmp;
GtkTreeIter *iter_tmp_p;
guint threshold = 0;
gboolean ret;
GError *error = NULL;
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;
}
/* get properties */
ret = cd_profile_connect_sync (profile,
priv->cancellable,
&error);
if (!ret)
{
g_warning ("failed to get profile: %s", error->message);
g_error_free (error);
goto out;
}
#if CD_CHECK_VERSION(0,1,13)
/* ignore profiles from other user accounts */
if (!cd_profile_has_access (profile))
{
g_warning ("%s is not usable by this user",
cd_profile_get_filename (profile));
goto out;
}
#endif
/* 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 (prefs, profile_tmp);
/* don't show details for EDID profiles */
if (gcm_prefs_profile_is_based_from_edid (profile_tmp))
{
/* TRANSLATORS: this is when the calibration profile age is not
* specified as it has been autogenerated from the hardware */
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_PATH, cd_device_get_object_path (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:
if (status != NULL)
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_object_path (device);
do
{
gtk_tree_model_get (model, &iter,
GCM_PREFS_COLUMN_DEVICE_PATH, &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)
{
gboolean ret;
GError *error = NULL;
CdDeviceKind kind;
const gchar *icon_name;
const gchar *id;
gchar *sort = NULL;
gchar *title = NULL;
GtkTreeIter parent;
CcColorPanelPrivate *priv = prefs->priv;
/* get device properties */
ret = cd_device_connect_sync (device, priv->cancellable, &error);
if (!ret)
{
g_warning ("failed to connect to the device: %s", error->message);
g_error_free (error);
goto out;
}
/* 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_object_path (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_PATH, 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);
out:
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_object_path (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_PATH, &id_tmp,
-1);
if (g_strcmp0 (id_tmp, id) == 0)
{
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
g_free (id_tmp);
break;
}
g_free (id_tmp);
} while (gtk_tree_model_iter_next (model, &iter));
}
static void
gcm_prefs_update_device_list_extra_entry (CcColorPanel *prefs)
{
CcColorPanelPrivate *priv = prefs->priv;
gboolean ret;
gchar *id_tmp;
gchar *title = NULL;
GtkTreeIter iter;
/* select the first device */
ret = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->list_store_devices), &iter);
if (!ret)
{
/* add the 'No devices detected' entry */
title = g_strdup_printf ("<i>%s</i>", _("No devices supporting color management detected"));
gtk_tree_store_append (priv->list_store_devices, &iter, NULL);
gtk_tree_store_set (priv->list_store_devices, &iter,
GCM_PREFS_COLUMN_RADIO_VISIBLE, FALSE,
GCM_PREFS_COLUMN_TITLE, title,
-1);
g_free (title);
return;
}
/* remove the 'No devices detected' entry */
do
{
gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store_devices), &iter,
GCM_PREFS_COLUMN_DEVICE_PATH, &id_tmp,
-1);
if (id_tmp == NULL)
{
gtk_tree_store_remove (priv->list_store_devices, &iter);
break;
}
g_free (id_tmp);
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store_devices), &iter));
}
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_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);
/* ensure we showing the 'No devices detected' entry if required */
gcm_prefs_update_device_list_extra_entry (prefs);
/* 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 gboolean
gcm_prefs_tree_model_count_cb (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer user_data)
{
guint *i = (guint *) user_data;
(*i)++;
return FALSE;
}
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;
guint devices_and_profiles = 0;
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);
}
/* ensure we show the 'No devices detected' entry if empty */
gcm_prefs_update_device_list_extra_entry (prefs);
/* 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);
/* if we have only a few devices and profiles expand the treeview
* devices so they can all be seen */
gtk_tree_model_foreach (GTK_TREE_MODEL (priv->list_store_devices),
gcm_prefs_tree_model_count_cb,
&devices_and_profiles);
if (devices_and_profiles <= GCM_PREFS_MAX_DEVICES_PROFILES_EXPANDED)
gtk_tree_view_expand_all (GTK_TREE_VIEW (widget));
out:
if (devices != NULL)
g_ptr_array_unref (devices);
}
static void
gcm_prefs_button_virtual_add_cb (GtkWidget *widget, CcColorPanel *prefs)
{
CdDeviceKind device_kind;
CdDevice *device;
const gchar *model;
const gchar *manufacturer;
gchar *device_id;
GError *error = NULL;
GHashTable *device_props;
CcColorPanelPrivate *priv = prefs->priv;
/* get device details */
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"combobox_virtual_type"));
device_kind = gtk_combo_box_get_active (GTK_COMBO_BOX(widget)) + 2;
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"entry_virtual_model"));
model = gtk_entry_get_text (GTK_ENTRY (widget));
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"entry_virtual_manufacturer"));
manufacturer = gtk_entry_get_text (GTK_ENTRY (widget));
/* create device */
device_id = g_strdup_printf ("%s-%s-%s",
cd_device_kind_to_string (device_kind),
manufacturer,
model);
device_props = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
g_hash_table_insert (device_props,
g_strdup ("Kind"),
g_strdup (cd_device_kind_to_string (device_kind)));
g_hash_table_insert (device_props,
g_strdup ("Mode"),
g_strdup (cd_device_mode_to_string (CD_DEVICE_MODE_VIRTUAL)));
g_hash_table_insert (device_props,
g_strdup ("Colorspace"),
g_strdup (cd_colorspace_to_string (CD_COLORSPACE_RGB)));
g_hash_table_insert (device_props,
g_strdup ("Model"),
g_strdup (model));
g_hash_table_insert (device_props,
g_strdup ("Vendor"),
g_strdup (manufacturer));
device = cd_client_create_device_sync (priv->client,
device_id,
CD_OBJECT_SCOPE_DISK,
device_props,
priv->cancellable,
&error);
if (device == NULL)
{
g_warning ("Failed to add create virtual device: %s",
error->message);
g_error_free (error);
goto out;
}
out:
g_hash_table_unref (device_props);
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"dialog_virtual"));
gtk_widget_hide (widget);
g_free (device_id);
}
static void
gcm_prefs_button_virtual_cancel_cb (GtkWidget *widget, CcColorPanel *prefs)
{
CcColorPanelPrivate *priv = prefs->priv;
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"dialog_virtual"));
gtk_widget_hide (widget);
}
static gboolean
gcm_prefs_virtual_delete_event_cb (GtkWidget *widget,
GdkEvent *event,
CcColorPanel *prefs)
{
gcm_prefs_button_virtual_cancel_cb (widget, prefs);
return TRUE;
}
static const gchar *
cd_device_kind_to_localised_string (CdDeviceKind device_kind)
{
if (device_kind == CD_DEVICE_KIND_DISPLAY)
return C_("Device kind", "Display");
if (device_kind == CD_DEVICE_KIND_SCANNER)
return C_("Device kind", "Scanner");
if (device_kind == CD_DEVICE_KIND_PRINTER)
return C_("Device kind", "Printer");
if (device_kind == CD_DEVICE_KIND_CAMERA)
return C_("Device kind", "Camera");
if (device_kind == CD_DEVICE_KIND_WEBCAM)
return C_("Device kind", "Webcam");
return NULL;
}
static void
gcm_prefs_setup_virtual_combobox (GtkWidget *widget)
{
guint i;
const gchar *text;
for (i=CD_DEVICE_KIND_SCANNER; i<CD_DEVICE_KIND_LAST; i++)
{
text = cd_device_kind_to_localised_string (i);
if (text == NULL)
continue;
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(widget), text);
}
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), CD_DEVICE_KIND_PRINTER - 2);
}
static gboolean
gcm_prefs_virtual_set_from_file (CcColorPanel *prefs, GFile *file)
{
/* TODO: use GCM to get the EXIF data */
return FALSE;
}
static void
gcm_prefs_virtual_drag_data_received_cb (GtkWidget *widget,
GdkDragContext *context,
gint x, gint y,
GtkSelectionData *data,
guint info,
guint _time,
CcColorPanel *prefs)
{
const guchar *filename;
gchar **filenames = NULL;
GFile *file = NULL;
guint i;
gboolean ret;
/* get filenames */
filename = gtk_selection_data_get_data (data);
if (filename == NULL)
{
gtk_drag_finish (context, FALSE, FALSE, _time);
goto out;
}
/* import this */
g_debug ("dropped: %p (%s)", data, filename);
/* split, as multiple drag targets are accepted */
filenames = g_strsplit_set ((const gchar *)filename, "\r\n", -1);
for (i = 0; filenames[i] != NULL; i++)
{
/* blank entry */
if (filenames[i][0] == '\0')
continue;
/* check this is a parsable file */
g_debug ("trying to set %s", filenames[i]);
file = g_file_new_for_uri (filenames[i]);
ret = gcm_prefs_virtual_set_from_file (prefs, file);
if (!ret)
{
g_debug ("%s did not set from file correctly",
filenames[i]);
gtk_drag_finish (context, FALSE, FALSE, _time);
goto out;
}
g_object_unref (file);
file = NULL;
}
gtk_drag_finish (context, TRUE, FALSE, _time);
out:
if (file != NULL)
g_object_unref (file);
g_strfreev (filenames);
}
static void
gcm_prefs_setup_drag_and_drop (GtkWidget *widget)
{
GtkTargetEntry entry;
/* setup a dummy entry */
entry.target = g_strdup ("text/plain");
entry.flags = GTK_TARGET_OTHER_APP;
entry.info = 0;
gtk_drag_dest_set (widget,
GTK_DEST_DEFAULT_ALL,
&entry,
1,
GDK_ACTION_MOVE | GDK_ACTION_COPY);
g_free (entry.target);
}
static void
gcm_prefs_connect_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
gboolean ret;
GError *error = NULL;
CcColorPanel *prefs = CC_COLOR_PANEL (user_data);
CcColorPanelPrivate *priv = prefs->priv;
ret = cd_client_connect_finish (priv->client,
res,
&error);
if (!ret)
{
g_warning ("failed to connect to colord: %s", error->message);
g_error_free (error);
return;
}
/* set calibrate button sensitivity */
gcm_prefs_sensor_coldplug (prefs);
/* get devices */
cd_client_get_devices (priv->client,
priv->cancellable,
gcm_prefs_get_devices_cb,
prefs);
}
static void
gcm_prefs_window_realize_cb (GtkWidget *widget, CcColorPanel *prefs)
{
prefs->priv->main_window = gtk_widget_get_toplevel (widget);
}
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;
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);
g_signal_connect (GTK_TREE_VIEW (widget), "popup-menu",
G_CALLBACK (gcm_prefs_treeview_popup_menu_cb),
prefs);
/* add columns to the tree view */
gcm_prefs_add_devices_columns (prefs, GTK_TREE_VIEW (widget));
/* force to be at least ~6 rows high */
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"scrolledwindow_devices"));
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
200);
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);
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 virtual dialog */
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"dialog_virtual"));
g_signal_connect (widget, "delete-event",
G_CALLBACK (gcm_prefs_virtual_delete_event_cb),
prefs);
g_signal_connect (widget, "drag-data-received",
G_CALLBACK (gcm_prefs_virtual_drag_data_received_cb),
prefs);
gcm_prefs_setup_drag_and_drop (widget);
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"button_virtual_add"));
g_signal_connect (widget, "clicked",
G_CALLBACK (gcm_prefs_button_virtual_add_cb),
prefs);
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"button_virtual_cancel"));
g_signal_connect (widget, "clicked",
G_CALLBACK (gcm_prefs_button_virtual_cancel_cb),
prefs);
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
"combobox_virtual_type"));
gcm_prefs_setup_virtual_combobox (widget);
/* 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 */
cd_client_connect (priv->client,
priv->cancellable,
gcm_prefs_connect_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);
/* set calibrate button sensitivity */
gcm_prefs_set_calibrate_button_sensitivity (prefs);
widget = WID (priv->builder, "dialog-vbox1");
gtk_widget_reparent (widget, (GtkWidget *) prefs);
g_signal_connect (widget, "realize",
G_CALLBACK (gcm_prefs_window_realize_cb),
prefs);
}
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);
}