When the asynchronous operation is finished in the Color panel, the user may potentially have already changed to another panel, making the CcColorPanel reference invalid. In the callback, the first thing that is done is casting (and type-checking) the CcColorPanel pointer, causing a segmentation fault. Fix that by only casting anything after checking the result of the asynchronous call. https://bugzilla.gnome.org/show_bug.cgi?id=786096
2568 lines
83 KiB
C
2568 lines
83 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <glib/gi18n.h>
|
|
#include <colord.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdkx.h>
|
|
#include <libsoup/soup.h>
|
|
|
|
#include "shell/list-box-helper.h"
|
|
#include "cc-color-calibrate.h"
|
|
#include "cc-color-cell-renderer-text.h"
|
|
#include "cc-color-panel.h"
|
|
#include "cc-color-resources.h"
|
|
#include "cc-color-common.h"
|
|
#include "cc-color-device.h"
|
|
#include "cc-color-profile.h"
|
|
|
|
#define WID(b, w) (GtkWidget *) gtk_builder_get_object (b, w)
|
|
|
|
CC_PANEL_REGISTER (CcColorPanel, cc_color_panel)
|
|
|
|
#define COLOR_PANEL_PRIVATE(o) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_COLOR_PANEL, CcColorPanelPrivate))
|
|
|
|
struct _CcColorPanelPrivate
|
|
{
|
|
CdClient *client;
|
|
CdDevice *current_device;
|
|
GPtrArray *devices;
|
|
GPtrArray *sensors;
|
|
GCancellable *cancellable;
|
|
GDBusProxy *proxy;
|
|
GSettings *settings;
|
|
GSettings *settings_colord;
|
|
GtkBuilder *builder;
|
|
GtkWidget *assistant_calib;
|
|
GtkWidget *dialog_assign;
|
|
GtkWidget *main_window;
|
|
CcColorCalibrate *calibrate;
|
|
GtkListBox *list_box;
|
|
gchar *list_box_filter;
|
|
guint list_box_selected_id;
|
|
guint list_box_activated_id;
|
|
GtkSizeGroup *list_box_size;
|
|
gboolean is_live_cd;
|
|
gboolean model_is_changing;
|
|
};
|
|
|
|
enum {
|
|
GCM_PREFS_COMBO_COLUMN_TEXT,
|
|
GCM_PREFS_COMBO_COLUMN_PROFILE,
|
|
GCM_PREFS_COMBO_COLUMN_TYPE,
|
|
GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME,
|
|
GCM_PREFS_COMBO_COLUMN_NUM_COLUMNS
|
|
};
|
|
|
|
/* for the GtkListStores */
|
|
enum {
|
|
COLUMN_CALIB_KIND_DESCRIPTION,
|
|
COLUMN_CALIB_KIND_CAP_VALUE,
|
|
COLUMN_CALIB_KIND_VISIBLE,
|
|
COLUMN_CALIB_KIND_LAST
|
|
};
|
|
enum {
|
|
COLUMN_CALIB_QUALITY_DESCRIPTION,
|
|
COLUMN_CALIB_QUALITY_APPROX_TIME,
|
|
COLUMN_CALIB_QUALITY_VALUE,
|
|
COLUMN_CALIB_QUALITY_LAST
|
|
};
|
|
enum {
|
|
COLUMN_CALIB_SENSOR_OBJECT,
|
|
COLUMN_CALIB_SENSOR_DESCRIPTION,
|
|
COLUMN_CALIB_SENSOR_LAST
|
|
};
|
|
enum {
|
|
COLUMN_CALIB_TEMP_DESCRIPTION,
|
|
COLUMN_CALIB_TEMP_VALUE_K,
|
|
COLUMN_CALIB_TEMP_LAST
|
|
};
|
|
|
|
#define COLORD_SETTINGS_SCHEMA "org.freedesktop.ColorHelper"
|
|
#define GCM_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.color"
|
|
#define GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD "recalibrate-printer-threshold"
|
|
#define GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD "recalibrate-display-threshold"
|
|
|
|
/* max number of devices and profiles to cause auto-expand at startup */
|
|
#define GCM_PREFS_MAX_DEVICES_PROFILES_EXPANDED 5
|
|
|
|
static void gcm_prefs_refresh_toolbar_buttons (CcColorPanel *panel);
|
|
|
|
static void
|
|
gcm_prefs_combobox_add_profile (CcColorPanel *prefs,
|
|
CdProfile *profile,
|
|
GtkTreeIter *iter)
|
|
{
|
|
const gchar *id;
|
|
GtkTreeIter iter_tmp;
|
|
GString *string;
|
|
GtkListStore *list_store;
|
|
gchar *escaped = NULL;
|
|
guint kind = 0;
|
|
const gchar *warning = NULL;
|
|
#if CD_CHECK_VERSION(0,1,25)
|
|
gchar **warnings;
|
|
#endif
|
|
|
|
/* iter is optional */
|
|
if (iter == NULL)
|
|
iter = &iter_tmp;
|
|
|
|
/* use description */
|
|
string = g_string_new (cd_profile_get_title (profile));
|
|
|
|
/* any source prefix? */
|
|
id = cd_profile_get_metadata_item (profile,
|
|
CD_PROFILE_METADATA_DATA_SOURCE);
|
|
if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_EDID) == 0)
|
|
{
|
|
/* TRANSLATORS: this is a profile prefix to signify the
|
|
* profile has been auto-generated for this hardware */
|
|
g_string_prepend (string, _("Default: "));
|
|
kind = 1;
|
|
}
|
|
#if CD_CHECK_VERSION(0,1,14)
|
|
if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
|
|
{
|
|
/* TRANSLATORS: this is a profile prefix to signify the
|
|
* profile his a standard space like AdobeRGB */
|
|
g_string_prepend (string, _("Colorspace: "));
|
|
kind = 2;
|
|
}
|
|
if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_TEST) == 0)
|
|
{
|
|
/* TRANSLATORS: this is a profile prefix to signify the
|
|
* profile is a test profile */
|
|
g_string_prepend (string, _("Test profile: "));
|
|
kind = 3;
|
|
}
|
|
#endif
|
|
|
|
/* is the profile faulty */
|
|
#if CD_CHECK_VERSION(0,1,25)
|
|
warnings = cd_profile_get_warnings (profile);
|
|
if (warnings != NULL && warnings[0] != NULL)
|
|
warning = "dialog-warning-symbolic";
|
|
#endif
|
|
|
|
escaped = g_markup_escape_text (string->str, -1);
|
|
list_store = GTK_LIST_STORE(gtk_builder_get_object (prefs->priv->builder,
|
|
"liststore_assign"));
|
|
gtk_list_store_append (list_store, iter);
|
|
gtk_list_store_set (list_store, iter,
|
|
GCM_PREFS_COMBO_COLUMN_TEXT, escaped,
|
|
GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
|
|
GCM_PREFS_COMBO_COLUMN_TYPE, kind,
|
|
GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME, warning,
|
|
-1);
|
|
|
|
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 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 (priv->dialog_assign);
|
|
/* TRANSLATORS: an ICC profile is a file containing colorspace data */
|
|
dialog = gtk_file_chooser_dialog_new (_("Select ICC Profile File"), window,
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
_("_Import"), GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
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_calib_cancel_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
gtk_widget_hide (prefs->priv->assistant_calib);
|
|
}
|
|
|
|
static gboolean
|
|
gcm_prefs_calib_delayed_complete_cb (gpointer user_data)
|
|
{
|
|
CcColorPanel *panel = CC_COLOR_PANEL (user_data);
|
|
GtkAssistant *assistant;
|
|
GtkWidget *widget;
|
|
|
|
assistant = GTK_ASSISTANT (panel->priv->assistant_calib);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
|
|
"box_calib_brightness"));
|
|
gtk_assistant_set_page_complete (assistant, widget, TRUE);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_prepare_cb (GtkAssistant *assistant,
|
|
GtkWidget *page,
|
|
CcColorPanel *panel)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
/* give the user the indication they should actually manually set the
|
|
* desired brightness rather than clicking blindly by delaying the
|
|
* "Next" button deliberately for a second or so */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
|
|
"box_calib_brightness"));
|
|
if (widget == page)
|
|
{
|
|
g_timeout_add_seconds (1, gcm_prefs_calib_delayed_complete_cb, panel);
|
|
return;
|
|
}
|
|
|
|
/* disable the brightness page as we don't want to show a 'Finished'
|
|
* button if the user goes back at any point */
|
|
gtk_assistant_set_page_complete (assistant, widget, FALSE);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_apply_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
GtkWindow *window = NULL;
|
|
|
|
/* setup the calibration object with items that can fail */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"button_calib_upload"));
|
|
gtk_widget_show (widget);
|
|
ret = cc_color_calibrate_setup (prefs->priv->calibrate,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to setup calibrate: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
/* actually start the calibration */
|
|
window = GTK_WINDOW (prefs->priv->assistant_calib);
|
|
ret = cc_color_calibrate_start (prefs->priv->calibrate,
|
|
window,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to start calibrate: %s", error->message);
|
|
gtk_widget_hide (GTK_WIDGET (window));
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
/* if we are a LiveCD then don't close the window as there is another
|
|
* summary pane with the export button */
|
|
if (!prefs->priv->is_live_cd)
|
|
gtk_widget_hide (GTK_WIDGET (window));
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static gboolean
|
|
gcm_prefs_calib_delete_event_cb (GtkWidget *widget,
|
|
GdkEvent *event,
|
|
CcColorPanel *prefs)
|
|
{
|
|
/* do not destroy the window */
|
|
gcm_prefs_calib_cancel_cb (widget, prefs);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_temp_treeview_clicked_cb (GtkTreeSelection *selection,
|
|
CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
gboolean ret;
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
GtkWidget *widget;
|
|
guint target_whitepoint;
|
|
GtkAssistant *assistant;
|
|
|
|
/* check to see if anything is selected */
|
|
ret = gtk_tree_selection_get_selected (selection, &model, &iter);
|
|
assistant = GTK_ASSISTANT (prefs->priv->assistant_calib);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_temp"));
|
|
gtk_assistant_set_page_complete (assistant, widget, ret);
|
|
if (!ret)
|
|
return;
|
|
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_CALIB_TEMP_VALUE_K, &target_whitepoint,
|
|
-1);
|
|
cc_color_calibrate_set_temperature (priv->calibrate, target_whitepoint);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_kind_treeview_clicked_cb (GtkTreeSelection *selection,
|
|
CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdSensorCap device_kind;
|
|
gboolean ret;
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
GtkWidget *widget;
|
|
GtkAssistant *assistant;
|
|
|
|
/* check to see if anything is selected */
|
|
ret = gtk_tree_selection_get_selected (selection, &model, &iter);
|
|
assistant = GTK_ASSISTANT (prefs->priv->assistant_calib);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_kind"));
|
|
gtk_assistant_set_page_complete (assistant, widget, ret);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* save the values if we have a selection */
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_CALIB_KIND_CAP_VALUE, &device_kind,
|
|
-1);
|
|
cc_color_calibrate_set_kind (priv->calibrate, device_kind);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_quality_treeview_clicked_cb (GtkTreeSelection *selection,
|
|
CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdProfileQuality quality;
|
|
gboolean ret;
|
|
GtkAssistant *assistant;
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
GtkWidget *widget;
|
|
|
|
/* check to see if anything is selected */
|
|
ret = gtk_tree_selection_get_selected (selection, &model, &iter);
|
|
assistant = GTK_ASSISTANT (prefs->priv->assistant_calib);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_quality"));
|
|
gtk_assistant_set_page_complete (assistant, widget, ret);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* save the values if we have a selection */
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_CALIB_QUALITY_VALUE, &quality,
|
|
-1);
|
|
cc_color_calibrate_set_quality (priv->calibrate, quality);
|
|
}
|
|
|
|
static gboolean
|
|
gcm_prefs_calib_set_sensor_cap_supported_cb (GtkTreeModel *model,
|
|
GtkTreePath *path,
|
|
GtkTreeIter *iter,
|
|
gpointer data)
|
|
{
|
|
CdSensorCap cap;
|
|
CdSensor *sensor = CD_SENSOR (data);
|
|
gboolean supported;
|
|
|
|
gtk_tree_model_get (model, iter,
|
|
COLUMN_CALIB_KIND_CAP_VALUE, &cap,
|
|
-1);
|
|
supported = cd_sensor_has_cap (sensor, cap);
|
|
g_debug ("%s(%s) is %s",
|
|
cd_sensor_get_model (sensor),
|
|
cd_sensor_cap_to_string (cap),
|
|
supported ? "supported" : "not-supported");
|
|
gtk_list_store_set (GTK_LIST_STORE (model), iter,
|
|
COLUMN_CALIB_KIND_VISIBLE, supported,
|
|
-1);
|
|
return FALSE;
|
|
}
|
|
|
|
static guint8
|
|
_cd_bitfield_popcount (guint64 bitfield)
|
|
{
|
|
guint8 i;
|
|
guint8 tmp = 0;
|
|
for (i = 0; i < 64; i++)
|
|
tmp += cd_bitfield_contain (bitfield, i);
|
|
return tmp;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_set_sensor (CcColorPanel *prefs,
|
|
CdSensor *sensor)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
GtkTreeModel *model;
|
|
GtkWidget *page;
|
|
guint64 caps;
|
|
guint8 i;
|
|
|
|
/* use this sensor for calibration */
|
|
cc_color_calibrate_set_sensor (priv->calibrate, sensor);
|
|
|
|
/* hide display types the sensor does not support */
|
|
model = GTK_TREE_MODEL (gtk_builder_get_object (priv->builder,
|
|
"liststore_calib_kind"));
|
|
gtk_tree_model_foreach (model,
|
|
gcm_prefs_calib_set_sensor_cap_supported_cb,
|
|
sensor);
|
|
|
|
/* if the sensor only supports one kind then do not show the panel at all */
|
|
page = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_kind"));
|
|
caps = cd_sensor_get_caps (sensor);
|
|
if (_cd_bitfield_popcount (caps) == 1)
|
|
{
|
|
gtk_widget_set_visible (page, FALSE);
|
|
for (i = 0; i < CD_SENSOR_CAP_LAST; i++)
|
|
{
|
|
if (cd_bitfield_contain (caps, i))
|
|
cc_color_calibrate_set_kind (priv->calibrate, i);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cc_color_calibrate_set_kind (priv->calibrate, CD_SENSOR_CAP_UNKNOWN);
|
|
gtk_widget_set_visible (page, TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_sensor_treeview_clicked_cb (GtkTreeSelection *selection,
|
|
CcColorPanel *prefs)
|
|
{
|
|
gboolean ret;
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
GtkWidget *widget;
|
|
CdSensor *sensor;
|
|
GtkAssistant *assistant;
|
|
|
|
/* check to see if anything is selected */
|
|
ret = gtk_tree_selection_get_selected (selection, &model, &iter);
|
|
assistant = GTK_ASSISTANT (prefs->priv->assistant_calib);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_sensor"));
|
|
gtk_assistant_set_page_complete (assistant, widget, ret);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* save the values if we have a selection */
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_CALIB_SENSOR_OBJECT, &sensor,
|
|
-1);
|
|
gcm_prefs_calib_set_sensor (prefs, sensor);
|
|
g_object_unref (sensor);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calibrate_display (CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdSensor *sensor_tmp;
|
|
const gchar *tmp;
|
|
GtkListStore *liststore;
|
|
GtkTreeIter iter;
|
|
GtkWidget *page;
|
|
GtkWidget *widget;
|
|
guint i;
|
|
|
|
/* set target device */
|
|
cc_color_calibrate_set_device (priv->calibrate, priv->current_device);
|
|
|
|
/* add sensors to list */
|
|
liststore = GTK_LIST_STORE (gtk_builder_get_object (priv->builder,
|
|
"liststore_calib_sensor"));
|
|
gtk_list_store_clear (liststore);
|
|
page = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_sensor"));
|
|
if (priv->sensors->len > 1)
|
|
{
|
|
for (i = 0; i < priv->sensors->len; i++)
|
|
{
|
|
sensor_tmp = g_ptr_array_index (priv->sensors, i);
|
|
gtk_list_store_append (liststore, &iter);
|
|
gtk_list_store_set (liststore, &iter,
|
|
COLUMN_CALIB_SENSOR_OBJECT, sensor_tmp,
|
|
COLUMN_CALIB_SENSOR_DESCRIPTION, cd_sensor_get_model (sensor_tmp),
|
|
-1);
|
|
}
|
|
gtk_widget_set_visible (page, TRUE);
|
|
}
|
|
else
|
|
{
|
|
sensor_tmp = g_ptr_array_index (priv->sensors, 0);
|
|
gcm_prefs_calib_set_sensor (prefs, sensor_tmp);
|
|
gtk_widget_set_visible (page, FALSE);
|
|
}
|
|
|
|
/* set default profile title */
|
|
tmp = cd_device_get_model (priv->current_device);
|
|
if (tmp == NULL)
|
|
tmp = cd_device_get_vendor (priv->current_device);
|
|
if (tmp == NULL)
|
|
tmp = _("Screen");
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"entry_calib_title"));
|
|
gtk_entry_set_text (GTK_ENTRY (widget), tmp);
|
|
cc_color_calibrate_set_title (priv->calibrate, tmp);
|
|
|
|
/* set the display whitepoint to D65 by default */
|
|
//FIXME?
|
|
|
|
/* show ui */
|
|
widget = GTK_WIDGET (priv->assistant_calib);
|
|
gtk_window_set_transient_for (GTK_WINDOW (widget),
|
|
GTK_WINDOW (priv->main_window));
|
|
gtk_widget_show (widget);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_title_entry_changed_cb (GtkWidget *widget,
|
|
GParamSpec *param_spec,
|
|
CcColorPanel *prefs)
|
|
{
|
|
GtkAssistant *assistant;
|
|
GtkWidget *page;
|
|
const gchar *value;
|
|
|
|
assistant = GTK_ASSISTANT (prefs->priv->assistant_calib);
|
|
page = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"box_calib_title"));
|
|
value = gtk_entry_get_text (GTK_ENTRY (widget));
|
|
cc_color_calibrate_set_title (prefs->priv->calibrate, value);
|
|
gtk_assistant_set_page_complete (assistant, page, value[0] != '\0');
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calibrate_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
guint xid;
|
|
GPtrArray *argv;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
/* use the new-style calibration helper */
|
|
if (cd_device_get_kind (priv->current_device) == CD_DEVICE_KIND_DISPLAY)
|
|
{
|
|
gcm_prefs_calibrate_display (prefs);
|
|
return;
|
|
}
|
|
|
|
/* 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 gboolean
|
|
gcm_prefs_is_profile_suitable_for_device (CdProfile *profile,
|
|
CdDevice *device)
|
|
{
|
|
const gchar *data_source;
|
|
CdProfileKind profile_kind_tmp;
|
|
CdProfileKind profile_kind;
|
|
CdColorspace profile_colorspace;
|
|
CdColorspace device_colorspace = 0;
|
|
gboolean ret = FALSE;
|
|
CdDeviceKind device_kind;
|
|
CdStandardSpace standard_space;
|
|
|
|
/* not the right colorspace */
|
|
device_colorspace = cd_device_get_colorspace (device);
|
|
profile_colorspace = cd_profile_get_colorspace (profile);
|
|
if (device_colorspace != profile_colorspace)
|
|
goto out;
|
|
|
|
/* if this is a display matching with one of the standard spaces that displays
|
|
* could emulate, also mark it as suitable */
|
|
if (cd_device_get_kind (device) == CD_DEVICE_KIND_DISPLAY &&
|
|
cd_profile_get_kind (profile) == CD_PROFILE_KIND_DISPLAY_DEVICE)
|
|
{
|
|
data_source = cd_profile_get_metadata_item (profile,
|
|
CD_PROFILE_METADATA_STANDARD_SPACE);
|
|
standard_space = cd_standard_space_from_string (data_source);
|
|
if (standard_space == CD_STANDARD_SPACE_SRGB ||
|
|
standard_space == CD_STANDARD_SPACE_ADOBE_RGB)
|
|
{
|
|
ret = TRUE;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* not the correct kind */
|
|
device_kind = cd_device_get_kind (device);
|
|
profile_kind_tmp = cd_profile_get_kind (profile);
|
|
profile_kind = cd_device_kind_to_profile_kind (device_kind);
|
|
if (profile_kind_tmp != profile_kind)
|
|
goto out;
|
|
|
|
/* ignore the colorspace profiles */
|
|
data_source = cd_profile_get_metadata_item (profile,
|
|
CD_PROFILE_METADATA_DATA_SOURCE);
|
|
if (g_strcmp0 (data_source, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
|
|
goto out;
|
|
|
|
/* success */
|
|
ret = TRUE;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static gint
|
|
gcm_prefs_combo_sort_func_cb (GtkTreeModel *model,
|
|
GtkTreeIter *a,
|
|
GtkTreeIter *b,
|
|
gpointer user_data)
|
|
{
|
|
gint type_a, type_b;
|
|
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_profile_exists_in_array (GPtrArray *array, CdProfile *profile)
|
|
{
|
|
CdProfile *profile_tmp;
|
|
guint i;
|
|
|
|
for (i = 0; i < array->len; i++)
|
|
{
|
|
profile_tmp = g_ptr_array_index (array, i);
|
|
if (cd_profile_equal (profile, profile_tmp))
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_add_profiles_suitable_for_devices (CcColorPanel *prefs,
|
|
GPtrArray *profiles)
|
|
{
|
|
CdProfile *profile_tmp;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
GPtrArray *profile_array = NULL;
|
|
GtkTreeIter iter;
|
|
GtkListStore *list_store;
|
|
GtkWidget *widget;
|
|
guint i;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
list_store = GTK_LIST_STORE(gtk_builder_get_object (prefs->priv->builder,
|
|
"liststore_assign"));
|
|
gtk_list_store_clear (list_store);
|
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store),
|
|
GCM_PREFS_COMBO_COLUMN_TEXT,
|
|
GTK_SORT_ASCENDING);
|
|
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list_store),
|
|
GCM_PREFS_COMBO_COLUMN_TEXT,
|
|
gcm_prefs_combo_sort_func_cb,
|
|
list_store, NULL);
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"label_assign_warning"));
|
|
gtk_widget_hide (widget);
|
|
|
|
/* 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 any of the already added profiles */
|
|
if (profiles != NULL)
|
|
{
|
|
if (gcm_prefs_profile_exists_in_array (profiles, profile_tmp))
|
|
continue;
|
|
}
|
|
|
|
/* only add correct types */
|
|
ret = gcm_prefs_is_profile_suitable_for_device (profile_tmp,
|
|
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 (prefs,
|
|
profile_tmp,
|
|
&iter);
|
|
}
|
|
out:
|
|
if (profile_array != NULL)
|
|
g_ptr_array_unref (profile_array);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_upload_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdProfile *profile;
|
|
const gchar *uri;
|
|
gboolean ret;
|
|
gchar *upload_uri = NULL;
|
|
gchar *msg_result = NULL;
|
|
gchar *data = NULL;
|
|
GError *error = NULL;
|
|
gsize length;
|
|
guint status_code;
|
|
SoupBuffer *buffer = NULL;
|
|
SoupMessage *msg = NULL;
|
|
SoupMultipart *multipart = NULL;
|
|
SoupSession *session = NULL;
|
|
|
|
profile = cc_color_calibrate_get_profile (prefs->priv->calibrate);
|
|
ret = cd_profile_connect_sync (profile, NULL, &error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("Failed to get imported profile: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
/* read file */
|
|
ret = g_file_get_contents (cd_profile_get_filename (profile),
|
|
&data,
|
|
&length,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("Failed to read file: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
/* setup the session */
|
|
session = soup_session_sync_new_with_options (SOUP_SESSION_USER_AGENT, "gnome-control-center",
|
|
SOUP_SESSION_TIMEOUT, 5000,
|
|
NULL);
|
|
if (session == NULL)
|
|
{
|
|
g_warning ("Failed to setup networking");
|
|
goto out;
|
|
}
|
|
soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT);
|
|
|
|
/* create multipart form and upload file */
|
|
multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
|
|
buffer = soup_buffer_new (SOUP_MEMORY_STATIC, data, length);
|
|
soup_multipart_append_form_file (multipart,
|
|
"upload",
|
|
cd_profile_get_filename (profile),
|
|
NULL,
|
|
buffer);
|
|
upload_uri = g_settings_get_string (priv->settings_colord, "profile-upload-uri");
|
|
msg = soup_form_request_new_from_multipart (upload_uri, multipart);
|
|
status_code = soup_session_send_message (session, msg);
|
|
if (status_code != 201)
|
|
{
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"label_calib_upload_location"));
|
|
/* TRANSLATORS: this is when the upload of the profile failed */
|
|
msg_result = g_strdup_printf (_("Failed to upload file: %s"), msg->reason_phrase),
|
|
gtk_label_set_label (GTK_LABEL (widget), msg_result);
|
|
gtk_widget_show (widget);
|
|
goto out;
|
|
}
|
|
|
|
/* show instructions to the user */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"label_calib_upload_location"));
|
|
uri = soup_message_headers_get_one (msg->response_headers, "Location");
|
|
msg_result = g_strdup_printf ("%s %s\n\n• %s\n• %s\n• %s",
|
|
/* TRANSLATORS: these are instructions on how to recover
|
|
* the ICC profile on the native operating system and are
|
|
* only shown when the user uses a LiveCD to calibrate */
|
|
_("The profile has been uploaded to:"),
|
|
uri,
|
|
_("Write down this URL."),
|
|
_("Restart this computer and boot your normal operating system."),
|
|
_("Type the URL into your browser to download and install the profile.")),
|
|
gtk_label_set_label (GTK_LABEL (widget), msg_result);
|
|
gtk_widget_show (widget);
|
|
|
|
/* hide the upload button as duplicate uploads will fail */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"button_calib_upload"));
|
|
gtk_widget_hide (widget);
|
|
out:
|
|
if (session != NULL)
|
|
g_object_unref (session);
|
|
if (buffer != NULL)
|
|
soup_buffer_free (buffer);
|
|
if (msg != NULL)
|
|
g_object_unref (msg);
|
|
if (multipart != NULL)
|
|
soup_multipart_free (multipart);
|
|
g_free (data);
|
|
g_free (upload_uri);
|
|
g_free (msg_result);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_export_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
CdProfile *profile;
|
|
gboolean ret;
|
|
gchar *default_name = NULL;
|
|
GError *error = NULL;
|
|
GFile *destination = NULL;
|
|
GFile *source = NULL;
|
|
GtkWidget *dialog;
|
|
|
|
/* TRANSLATORS: this is the dialog to save the ICC profile */
|
|
dialog = gtk_file_chooser_dialog_new (_("Save Profile"),
|
|
GTK_WINDOW (prefs->priv->main_window),
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
_("_Save"), GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
|
|
|
|
profile = cc_color_calibrate_get_profile (prefs->priv->calibrate);
|
|
ret = cd_profile_connect_sync (profile, NULL, &error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("Failed to get imported profile: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
default_name = g_strdup_printf ("%s.icc", cd_profile_get_title (profile));
|
|
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_name);
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
|
{
|
|
source = g_file_new_for_path (cd_profile_get_filename (profile));
|
|
destination = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
|
ret = g_file_copy (source,
|
|
destination,
|
|
G_FILE_COPY_OVERWRITE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("Failed to copy profile: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
}
|
|
out:
|
|
gtk_widget_destroy (dialog);
|
|
g_free (default_name);
|
|
if (source != NULL)
|
|
g_object_unref (source);
|
|
if (destination != NULL)
|
|
g_object_unref (destination);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_calib_export_link_cb (GtkLabel *widget,
|
|
const gchar *url,
|
|
CcColorPanel *prefs)
|
|
{
|
|
gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (prefs->priv->main_window)),
|
|
"help:gnome-help/color-howtoimport",
|
|
GDK_CURRENT_TIME, NULL);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profile_add_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
GPtrArray *profiles;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
/* add profiles of the right kind */
|
|
profiles = cd_device_get_profiles (priv->current_device);
|
|
gcm_prefs_add_profiles_suitable_for_devices (prefs, profiles);
|
|
|
|
/* make insensitve until we have a selection */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"button_assign_ok"));
|
|
gtk_widget_set_sensitive (widget, FALSE);
|
|
|
|
/* show the dialog */
|
|
widget = GTK_WIDGET (priv->dialog_assign);
|
|
gtk_widget_show (widget);
|
|
gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (priv->main_window));
|
|
if (profiles != NULL)
|
|
g_ptr_array_unref (profiles);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profile_remove_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdProfile *profile;
|
|
gboolean ret = FALSE;
|
|
GError *error = NULL;
|
|
GtkListBoxRow *row;
|
|
|
|
/* get the selected profile */
|
|
row = gtk_list_box_get_selected_row (priv->list_box);
|
|
if (row == NULL)
|
|
return;
|
|
profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
|
|
if (profile == NULL)
|
|
{
|
|
g_warning ("failed to get the active profile");
|
|
return;
|
|
}
|
|
|
|
/* just remove it, the list store will get ::changed */
|
|
ret = cd_device_remove_profile_sync (priv->current_device,
|
|
profile,
|
|
priv->cancellable,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to remove profile: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_make_profile_default_cb (GObject *object,
|
|
GAsyncResult *res,
|
|
CcColorPanel *prefs)
|
|
{
|
|
CdDevice *device = CD_DEVICE (object);
|
|
gboolean ret = FALSE;
|
|
GError *error = NULL;
|
|
|
|
ret = cd_device_make_profile_default_finish (device,
|
|
res,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to set default profile on %s: %s",
|
|
cd_device_get_id (device),
|
|
error->message);
|
|
g_error_free (error);
|
|
}
|
|
else
|
|
{
|
|
gcm_prefs_refresh_toolbar_buttons (prefs);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_device_profile_enable_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdProfile *profile;
|
|
GtkListBoxRow *row;
|
|
|
|
/* get the selected profile */
|
|
row = gtk_list_box_get_selected_row (priv->list_box);
|
|
if (row == NULL)
|
|
return;
|
|
profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
|
|
if (profile == NULL)
|
|
{
|
|
g_warning ("failed to get the active profile");
|
|
return;
|
|
}
|
|
|
|
/* just set it default */
|
|
g_debug ("setting %s default on %s",
|
|
cd_profile_get_id (profile),
|
|
cd_device_get_id (priv->current_device));
|
|
cd_device_make_profile_default (priv->current_device,
|
|
profile,
|
|
priv->cancellable,
|
|
(GAsyncReadyCallback) gcm_prefs_make_profile_default_cb,
|
|
prefs);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profile_view (CcColorPanel *prefs, CdProfile *profile)
|
|
{
|
|
GPtrArray *argv = NULL;
|
|
guint xid;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
/* 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);
|
|
}
|
|
|
|
g_ptr_array_unref (argv);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profile_assign_link_activate_cb (GtkLabel *label,
|
|
const gchar *uri,
|
|
CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdProfile *profile;
|
|
GtkListBoxRow *row;
|
|
|
|
/* get the selected profile */
|
|
row = gtk_list_box_get_selected_row (priv->list_box);
|
|
if (row == NULL)
|
|
return;
|
|
profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
|
|
if (profile == NULL)
|
|
{
|
|
g_warning ("failed to get the active profile");
|
|
return;
|
|
}
|
|
|
|
/* show it in the viewer */
|
|
gcm_prefs_profile_view (prefs, profile);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profile_view_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
CdProfile *profile;
|
|
GtkListBoxRow *row;
|
|
|
|
/* get the selected profile */
|
|
row = gtk_list_box_get_selected_row (prefs->priv->list_box);
|
|
if (row == NULL)
|
|
return;
|
|
profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
|
|
if (profile == NULL)
|
|
{
|
|
g_warning ("failed to get the active profile");
|
|
return;
|
|
}
|
|
|
|
/* open up gcm-viewer as a info pane */
|
|
gcm_prefs_profile_view (prefs, profile);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_button_assign_cancel_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
gtk_widget_hide (priv->dialog_assign);
|
|
}
|
|
|
|
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;
|
|
GtkTreeSelection *selection;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
/* hide window */
|
|
widget = GTK_WIDGET (priv->dialog_assign);
|
|
gtk_widget_hide (widget);
|
|
|
|
/* get the selected profile */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"treeview_assign"));
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
|
|
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
goto out;
|
|
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;
|
|
}
|
|
|
|
/* if the device is disabled, enable the device so that we can
|
|
* add color profiles to it */
|
|
if (!cd_device_get_enabled (priv->current_device))
|
|
{
|
|
ret = cd_device_set_enabled_sync (priv->current_device,
|
|
TRUE,
|
|
priv->cancellable,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to enabled device: %s", error->message);
|
|
g_error_free (error);
|
|
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 */
|
|
cd_device_make_profile_default (priv->current_device,
|
|
profile,
|
|
priv->cancellable,
|
|
(GAsyncReadyCallback) gcm_prefs_make_profile_default_cb,
|
|
prefs);
|
|
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_add_profiles_columns (CcColorPanel *prefs,
|
|
GtkTreeView *treeview)
|
|
{
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeViewColumn *column;
|
|
|
|
/* text */
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
column = gtk_tree_view_column_new ();
|
|
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
|
gtk_tree_view_column_add_attribute (column, renderer,
|
|
"markup", GCM_PREFS_COMBO_COLUMN_TEXT);
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
gtk_tree_view_append_column (treeview, column);
|
|
|
|
/* image */
|
|
column = gtk_tree_view_column_new ();
|
|
renderer = gtk_cell_renderer_pixbuf_new ();
|
|
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_COMBO_COLUMN_WARNING_FILENAME);
|
|
gtk_tree_view_append_column (treeview, column);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_set_calibrate_button_sensitivity (CcColorPanel *prefs)
|
|
{
|
|
gboolean ret = FALSE;
|
|
GtkWidget *widget;
|
|
const gchar *tooltip;
|
|
CdDeviceKind kind;
|
|
CdSensor *sensor_tmp;
|
|
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->sensors == NULL || priv->sensors->len == 0)
|
|
{
|
|
/* TRANSLATORS: this is when the button is insensitive */
|
|
tooltip = _("The measuring instrument is not detected. Please check it is turned on and correctly connected.");
|
|
goto out;
|
|
}
|
|
|
|
/* success */
|
|
ret = TRUE;
|
|
|
|
}
|
|
else if (kind == CD_DEVICE_KIND_SCANNER ||
|
|
kind == CD_DEVICE_KIND_CAMERA ||
|
|
kind == CD_DEVICE_KIND_WEBCAM)
|
|
{
|
|
|
|
/* TODO: find out if we can scan using gnome-scan */
|
|
ret = TRUE;
|
|
|
|
}
|
|
else if (kind == CD_DEVICE_KIND_PRINTER)
|
|
{
|
|
|
|
/* find whether we have hardware installed */
|
|
if (priv->sensors == NULL || priv->sensors->len == 0)
|
|
{
|
|
/* TRANSLATORS: this is when the button is insensitive */
|
|
tooltip = _("The measuring instrument is not detected. Please check it is turned on and correctly connected.");
|
|
goto out;
|
|
}
|
|
|
|
/* find whether we have hardware installed */
|
|
sensor_tmp = g_ptr_array_index (priv->sensors, 0);
|
|
ret = cd_sensor_has_cap (sensor_tmp, CD_SENSOR_CAP_PRINTER);
|
|
if (!ret)
|
|
{
|
|
/* TRANSLATORS: this is when the button is insensitive */
|
|
tooltip = _("The measuring instrument does not support printer profiling.");
|
|
goto out;
|
|
}
|
|
|
|
/* success */
|
|
ret = TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* TRANSLATORS: this is when the button is insensitive */
|
|
tooltip = _("The device type is not currently supported.");
|
|
}
|
|
out:
|
|
/* control the tooltip and sensitivity of the button */
|
|
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)
|
|
{
|
|
/* we have a new device */
|
|
g_debug ("selected device is: %s",
|
|
cd_device_get_id (device));
|
|
|
|
/* can this device calibrate */
|
|
gcm_prefs_set_calibrate_button_sensitivity (prefs);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profile_clicked (CcColorPanel *prefs, CdProfile *profile, CdDevice *device)
|
|
{
|
|
GtkWidget *widget;
|
|
gchar *s;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
/* get profile */
|
|
g_debug ("selected profile = %s",
|
|
cd_profile_get_filename (profile));
|
|
|
|
/* allow getting profile info */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_profile_view"));
|
|
if (cd_profile_get_filename (profile) != NULL &&
|
|
(s = g_find_program_in_path ("gcm-viewer")) != NULL)
|
|
{
|
|
gtk_widget_set_sensitive (widget, TRUE);
|
|
g_free (s);
|
|
}
|
|
else
|
|
gtk_widget_set_sensitive (widget, FALSE);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profiles_treeview_clicked_cb (GtkTreeSelection *selection,
|
|
CcColorPanel *prefs)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
CdProfile *profile = NULL;
|
|
#if CD_CHECK_VERSION(0,1,25)
|
|
gchar **warnings;
|
|
#endif
|
|
|
|
/* get selection */
|
|
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
return;
|
|
gtk_tree_model_get (model, &iter,
|
|
GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
|
|
-1);
|
|
|
|
|
|
/* as soon as anything is selected, make the Add button sensitive */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"button_assign_ok"));
|
|
gtk_widget_set_sensitive (widget, TRUE);
|
|
|
|
/* is the profile faulty */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (prefs->priv->builder,
|
|
"label_assign_warning"));
|
|
#if CD_CHECK_VERSION(0,1,25)
|
|
warnings = cd_profile_get_warnings (profile);
|
|
gtk_widget_set_visible (widget, warnings != NULL && warnings[0] != NULL);
|
|
#else
|
|
gtk_widget_set_visible (widget, FALSE);
|
|
#endif
|
|
g_object_unref (profile);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_profiles_row_activated_cb (GtkTreeView *tree_view,
|
|
GtkTreePath *path,
|
|
GtkTreeViewColumn *column,
|
|
CcColorPanel *prefs)
|
|
{
|
|
GtkTreeIter iter;
|
|
gboolean ret;
|
|
|
|
ret = gtk_tree_model_get_iter (gtk_tree_view_get_model (tree_view), &iter, path);
|
|
if (!ret)
|
|
return;
|
|
gcm_prefs_button_assign_ok_cb (NULL, prefs);
|
|
}
|
|
|
|
|
|
static void
|
|
gcm_prefs_button_assign_import_cb (GtkWidget *widget,
|
|
CcColorPanel *prefs)
|
|
{
|
|
GFile *file = NULL;
|
|
GError *error = NULL;
|
|
CdProfile *profile = NULL;
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
|
|
file = gcm_prefs_file_chooser_get_icc_profile (prefs);
|
|
if (file == NULL)
|
|
{
|
|
g_warning ("failed to get ICC file");
|
|
widget = GTK_WIDGET (priv->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 list view */
|
|
gcm_prefs_profile_add_cb (NULL, prefs);
|
|
out:
|
|
if (file != NULL)
|
|
g_object_unref (file);
|
|
if (profile != NULL)
|
|
g_object_unref (profile);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_sensor_coldplug (CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdSensor *sensor_tmp;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
GPtrArray *sensors;
|
|
guint i;
|
|
|
|
/* unref old */
|
|
g_clear_pointer (&priv->sensors, g_ptr_array_unref);
|
|
|
|
/* 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 list */
|
|
priv->sensors = g_ptr_array_ref (sensors);
|
|
|
|
/* connect to each sensor */
|
|
for (i = 0; i < sensors->len; i++)
|
|
{
|
|
sensor_tmp = g_ptr_array_index (sensors, i);
|
|
ret = cd_sensor_connect_sync (sensor_tmp, NULL, &error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("%s", error->message);
|
|
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 void
|
|
gcm_prefs_add_device_profile (CcColorPanel *prefs,
|
|
CdDevice *device,
|
|
CdProfile *profile,
|
|
gboolean is_default)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
GtkWidget *widget;
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* ignore profiles from other user accounts */
|
|
if (!cd_profile_has_access (profile))
|
|
{
|
|
/* only print the filename if it exists */
|
|
if (cd_profile_get_filename (profile) != NULL)
|
|
{
|
|
g_warning ("%s is not usable by this user",
|
|
cd_profile_get_filename (profile));
|
|
}
|
|
else
|
|
{
|
|
g_warning ("%s is not usable by this user",
|
|
cd_profile_get_id (profile));
|
|
}
|
|
goto out;
|
|
}
|
|
|
|
/* add to listbox */
|
|
widget = cc_color_profile_new (device, profile, is_default);
|
|
gtk_widget_show (widget);
|
|
gtk_container_add (GTK_CONTAINER (priv->list_box), widget);
|
|
gtk_size_group_add_widget (priv->list_box_size, widget);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_add_device_profiles (CcColorPanel *prefs, CdDevice *device)
|
|
{
|
|
CdProfile *profile_tmp;
|
|
GPtrArray *profiles = NULL;
|
|
guint i;
|
|
|
|
/* 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);
|
|
gcm_prefs_add_device_profile (prefs, device, profile_tmp, i == 0);
|
|
}
|
|
out:
|
|
if (profiles != NULL)
|
|
g_ptr_array_unref (profiles);
|
|
}
|
|
|
|
/* find the profile in the array -- for flicker-free changes */
|
|
static gboolean
|
|
gcm_prefs_find_profile_by_object_path (GPtrArray *profiles,
|
|
const gchar *object_path)
|
|
{
|
|
CdProfile *profile_tmp;
|
|
guint i;
|
|
|
|
for (i = 0; i < profiles->len; i++)
|
|
{
|
|
profile_tmp = g_ptr_array_index (profiles, i);
|
|
if (g_strcmp0 (cd_profile_get_object_path (profile_tmp), object_path) == 0)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/* find the profile in the list view -- for flicker-free changes */
|
|
static gboolean
|
|
gcm_prefs_find_widget_by_object_path (GList *list,
|
|
const gchar *object_path_device,
|
|
const gchar *object_path_profile)
|
|
{
|
|
GList *l;
|
|
CdDevice *device_tmp;
|
|
CdProfile *profile_tmp;
|
|
|
|
for (l = list; l != NULL; l = l->next)
|
|
{
|
|
if (!CC_IS_COLOR_PROFILE (l->data))
|
|
continue;
|
|
|
|
/* correct device ? */
|
|
device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (l->data));
|
|
if (g_strcmp0 (object_path_device,
|
|
cd_device_get_object_path (device_tmp)) != 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* this profile */
|
|
profile_tmp = cc_color_profile_get_profile (CC_COLOR_PROFILE (l->data));
|
|
if (g_strcmp0 (object_path_profile,
|
|
cd_profile_get_object_path (profile_tmp)) == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_device_changed_cb (CdDevice *device, CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdDevice *device_tmp;
|
|
CdProfile *profile_tmp;
|
|
gboolean ret;
|
|
GList *l;
|
|
GList *list;
|
|
GPtrArray *profiles;
|
|
guint i;
|
|
|
|
/* remove anything in the list view that's not in Device.Profiles */
|
|
profiles = cd_device_get_profiles (device);
|
|
list = gtk_container_get_children (GTK_CONTAINER (priv->list_box));
|
|
for (l = list; l != NULL; l = l->next)
|
|
{
|
|
if (!CC_IS_COLOR_PROFILE (l->data))
|
|
continue;
|
|
|
|
/* correct device ? */
|
|
device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (l->data));
|
|
if (g_strcmp0 (cd_device_get_id (device),
|
|
cd_device_get_id (device_tmp)) != 0)
|
|
continue;
|
|
|
|
/* if profile is not in Device.Profiles then remove */
|
|
profile_tmp = cc_color_profile_get_profile (CC_COLOR_PROFILE (l->data));
|
|
ret = gcm_prefs_find_profile_by_object_path (profiles,
|
|
cd_profile_get_object_path (profile_tmp));
|
|
if (!ret) {
|
|
gtk_widget_destroy (GTK_WIDGET (l->data));
|
|
/* Don't look at the destroyed widget below */
|
|
l->data = NULL;
|
|
}
|
|
}
|
|
|
|
/* add anything in Device.Profiles that's not in the list view */
|
|
for (i = 0; i < profiles->len; i++)
|
|
{
|
|
profile_tmp = g_ptr_array_index (profiles, i);
|
|
ret = gcm_prefs_find_widget_by_object_path (list,
|
|
cd_device_get_object_path (device),
|
|
cd_profile_get_object_path (profile_tmp));
|
|
if (!ret)
|
|
gcm_prefs_add_device_profile (prefs, device, profile_tmp, i == 0);
|
|
}
|
|
g_list_free (list);
|
|
|
|
/* resort */
|
|
gtk_list_box_invalidate_sort (priv->list_box);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_device_expanded_changed_cb (CcColorDevice *widget,
|
|
gboolean is_expanded,
|
|
CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
GList *l;
|
|
GList *list;
|
|
|
|
/* ignore internal changes */
|
|
if (prefs->priv->model_is_changing)
|
|
return;
|
|
|
|
g_free (prefs->priv->list_box_filter);
|
|
if (is_expanded)
|
|
{
|
|
priv->list_box_filter = g_strdup (cd_device_get_id (cc_color_device_get_device (widget)));
|
|
|
|
/* unexpand other device widgets */
|
|
list = gtk_container_get_children (GTK_CONTAINER (priv->list_box));
|
|
prefs->priv->model_is_changing = TRUE;
|
|
for (l = list; l != NULL; l = l->next)
|
|
{
|
|
if (!CC_IS_COLOR_DEVICE (l->data))
|
|
continue;
|
|
if (l->data != widget)
|
|
cc_color_device_set_expanded (CC_COLOR_DEVICE (l->data), FALSE);
|
|
}
|
|
prefs->priv->model_is_changing = FALSE;
|
|
g_list_free (list);
|
|
}
|
|
else
|
|
{
|
|
priv->list_box_filter = NULL;
|
|
}
|
|
gtk_list_box_invalidate_filter (priv->list_box);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_add_device (CcColorPanel *prefs, CdDevice *device)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
GtkWidget *widget;
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* add device */
|
|
widget = cc_color_device_new (device);
|
|
g_signal_connect (widget, "expanded-changed",
|
|
G_CALLBACK (gcm_prefs_device_expanded_changed_cb), prefs);
|
|
gtk_widget_show (widget);
|
|
gtk_container_add (GTK_CONTAINER (priv->list_box), widget);
|
|
gtk_size_group_add_widget (priv->list_box_size, widget);
|
|
|
|
/* add profiles */
|
|
gcm_prefs_add_device_profiles (prefs, device);
|
|
|
|
/* watch for changes */
|
|
g_ptr_array_add (priv->devices, g_object_ref (device));
|
|
g_signal_connect (device, "changed",
|
|
G_CALLBACK (gcm_prefs_device_changed_cb), prefs);
|
|
gtk_list_box_invalidate_sort (priv->list_box);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_remove_device (CcColorPanel *prefs, CdDevice *device)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
CdDevice *device_tmp;
|
|
GList *l;
|
|
GList *list;
|
|
|
|
list = gtk_container_get_children (GTK_CONTAINER (priv->list_box));
|
|
for (l = list; l != NULL; l = l->next)
|
|
{
|
|
if (CC_IS_COLOR_DEVICE (l->data))
|
|
device_tmp = cc_color_device_get_device (CC_COLOR_DEVICE (l->data));
|
|
else
|
|
device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (l->data));
|
|
if (g_strcmp0 (cd_device_get_object_path (device),
|
|
cd_device_get_object_path (device_tmp)) == 0)
|
|
{
|
|
gtk_widget_destroy (GTK_WIDGET (l->data));
|
|
}
|
|
}
|
|
g_list_free (list);
|
|
g_signal_handlers_disconnect_by_func (device,
|
|
G_CALLBACK (gcm_prefs_device_changed_cb),
|
|
prefs);
|
|
g_ptr_array_remove (priv->devices, device);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_update_device_list_extra_entry (CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv = prefs->priv;
|
|
GList *device_widgets;
|
|
GtkWidget *widget;
|
|
guint number_of_devices;
|
|
|
|
/* any devices to show? */
|
|
device_widgets = gtk_container_get_children (GTK_CONTAINER (priv->list_box));
|
|
number_of_devices = g_list_length (device_widgets);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"label_no_devices"));
|
|
gtk_widget_set_visible (widget, number_of_devices == 0);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"vbox3"));
|
|
gtk_widget_set_visible (widget, number_of_devices > 0);
|
|
|
|
/* if we have only one device expand it by default */
|
|
if (number_of_devices == 1)
|
|
cc_color_device_set_expanded (CC_COLOR_DEVICE (device_widgets->data), TRUE);
|
|
g_list_free (device_widgets);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_device_added_cb (CdClient *client,
|
|
CdDevice *device,
|
|
CcColorPanel *prefs)
|
|
{
|
|
/* add the device */
|
|
gcm_prefs_add_device (prefs, device);
|
|
|
|
/* ensure we're not showing the 'No devices detected' entry */
|
|
gcm_prefs_update_device_list_extra_entry (prefs);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_device_removed_cb (CdClient *client,
|
|
CdDevice *device,
|
|
CcColorPanel *prefs)
|
|
{
|
|
/* remove from the UI */
|
|
gcm_prefs_remove_device (prefs, device);
|
|
|
|
/* ensure we showing the 'No devices detected' entry if required */
|
|
gcm_prefs_update_device_list_extra_entry (prefs);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_get_devices_cb (GObject *object,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
CcColorPanel *prefs = (CcColorPanel *) user_data;
|
|
CdClient *client = CD_CLIENT (object);
|
|
CdDevice *device;
|
|
GError *error = NULL;
|
|
GPtrArray *devices;
|
|
guint i;
|
|
|
|
/* get devices and add them */
|
|
devices = cd_client_get_devices_finish (client, res, &error);
|
|
if (devices == NULL)
|
|
{
|
|
g_warning ("failed to add connected devices: %s",
|
|
error->message);
|
|
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);
|
|
out:
|
|
if (devices != NULL)
|
|
g_ptr_array_unref (devices);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_list_box_row_selected_cb (GtkListBox *list_box,
|
|
GtkListBoxRow *row,
|
|
CcColorPanel *panel)
|
|
{
|
|
gcm_prefs_refresh_toolbar_buttons (panel);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_refresh_toolbar_buttons (CcColorPanel *panel)
|
|
{
|
|
CdProfile *profile = NULL;
|
|
GtkWidget *widget;
|
|
CcColorPanelPrivate *priv = panel->priv;
|
|
GtkListBoxRow *row;
|
|
gboolean is_device;
|
|
|
|
/* get the selected profile */
|
|
row = gtk_list_box_get_selected_row (priv->list_box);
|
|
|
|
is_device = CC_IS_COLOR_DEVICE (row);
|
|
|
|
/* nothing selected */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbar_devices"));
|
|
gtk_widget_set_visible (widget, row != NULL);
|
|
if (row == NULL)
|
|
return;
|
|
|
|
/* save current device */
|
|
if (priv->current_device != NULL)
|
|
g_object_unref (priv->current_device);
|
|
g_object_get (row, "device", &priv->current_device, NULL);
|
|
|
|
/* device actions */
|
|
g_debug ("%s selected", is_device ? "device" : "profile");
|
|
if (CC_IS_COLOR_DEVICE (row))
|
|
{
|
|
gcm_prefs_device_clicked (panel, priv->current_device);
|
|
cc_color_device_set_expanded (CC_COLOR_DEVICE (row), TRUE);
|
|
}
|
|
else if (CC_IS_COLOR_PROFILE (row))
|
|
{
|
|
profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
|
|
gcm_prefs_profile_clicked (panel, profile, priv->current_device);
|
|
}
|
|
else
|
|
g_assert_not_reached ();
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_device_default"));
|
|
gtk_widget_set_visible (widget, !is_device && cc_color_profile_get_is_default (CC_COLOR_PROFILE (row)));
|
|
if (profile)
|
|
gtk_widget_set_sensitive (widget, !cd_profile_get_is_system_wide (profile));
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_device_enable"));
|
|
gtk_widget_set_visible (widget, !is_device && !cc_color_profile_get_is_default (CC_COLOR_PROFILE (row)));
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_device_calibrate"));
|
|
gtk_widget_set_visible (widget, is_device);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_profile_add"));
|
|
gtk_widget_set_visible (widget, is_device);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_profile_view"));
|
|
gtk_widget_set_visible (widget, !is_device);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"toolbutton_profile_remove"));
|
|
gtk_widget_set_visible (widget, !is_device);
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_list_box_row_activated_cb (GtkListBox *list_box,
|
|
GtkListBoxRow *row,
|
|
CcColorPanel *prefs)
|
|
{
|
|
if (CC_IS_COLOR_PROFILE (row))
|
|
{
|
|
gcm_prefs_device_profile_enable_cb (NULL, prefs);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_connect_cb (GObject *object,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
CcColorPanelPrivate *priv;
|
|
CcColorPanel *prefs;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
|
|
ret = cd_client_connect_finish (CD_CLIENT (object),
|
|
res,
|
|
&error);
|
|
if (!ret)
|
|
{
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
g_warning ("failed to connect to colord: %s", error->message);
|
|
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
|
|
/* Only cast the parameters after making sure it didn't fail. At this point,
|
|
* the user can potentially already have changed to another panel, effectively
|
|
* making user_data invalid. */
|
|
prefs = CC_COLOR_PANEL (user_data);
|
|
priv = prefs->priv;
|
|
|
|
/* 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 gboolean
|
|
gcm_prefs_is_livecd (void)
|
|
{
|
|
#ifdef __linux__
|
|
gboolean ret = TRUE;
|
|
gchar *data = NULL;
|
|
GError *error = NULL;
|
|
|
|
/* allow testing */
|
|
if (g_getenv ("CC_COLOR_PANEL_IS_LIVECD") != NULL)
|
|
goto out;
|
|
|
|
/* get the kernel commandline */
|
|
ret = g_file_get_contents ("/proc/cmdline", &data, NULL, &error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to get kernel command line: %s",
|
|
error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
ret = (g_strstr_len (data, -1, "liveimg") != NULL ||
|
|
g_strstr_len (data, -1, "casper") != NULL);
|
|
out:
|
|
g_free (data);
|
|
return ret;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
gcm_prefs_window_realize_cb (GtkWidget *widget, CcColorPanel *prefs)
|
|
{
|
|
prefs->priv->main_window = gtk_widget_get_toplevel (widget);
|
|
}
|
|
|
|
static const char *
|
|
cc_color_panel_get_help_uri (CcPanel *panel)
|
|
{
|
|
return "help:gnome-help/color";
|
|
}
|
|
|
|
static void
|
|
cc_color_panel_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id)
|
|
{
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cc_color_panel_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id)
|
|
{
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cc_color_panel_dispose (GObject *object)
|
|
{
|
|
CcColorPanelPrivate *priv = CC_COLOR_PANEL (object)->priv;
|
|
CdDevice *device;
|
|
guint i;
|
|
|
|
/* stop the EggListView from firing when it gets disposed */
|
|
if (priv->list_box_selected_id != 0)
|
|
{
|
|
g_signal_handler_disconnect (priv->list_box,
|
|
priv->list_box_selected_id);
|
|
priv->list_box_selected_id = 0;
|
|
|
|
/* row-activated event should be connected at this point */
|
|
g_signal_handler_disconnect (priv->list_box,
|
|
priv->list_box_activated_id);
|
|
priv->list_box_activated_id = 0;
|
|
}
|
|
|
|
/* stop the devices from emitting after the ListBox has been disposed */
|
|
if (priv->devices != NULL)
|
|
{
|
|
for (i = 0; i < priv->devices->len; i++)
|
|
{
|
|
device = g_ptr_array_index (priv->devices, i);
|
|
g_signal_handlers_disconnect_by_func (device,
|
|
G_CALLBACK (gcm_prefs_device_changed_cb),
|
|
CC_COLOR_PANEL (object));
|
|
}
|
|
g_ptr_array_unref (priv->devices);
|
|
priv->devices = NULL;
|
|
}
|
|
|
|
if (priv->cancellable != NULL)
|
|
g_cancellable_cancel (priv->cancellable);
|
|
g_clear_object (&priv->settings);
|
|
g_clear_object (&priv->settings_colord);
|
|
g_clear_object (&priv->cancellable);
|
|
g_clear_object (&priv->builder);
|
|
g_clear_object (&priv->client);
|
|
g_clear_object (&priv->current_device);
|
|
g_clear_object (&priv->calibrate);
|
|
g_clear_object (&priv->list_box_size);
|
|
g_clear_pointer (&priv->sensors, g_ptr_array_unref);
|
|
g_clear_pointer (&priv->list_box_filter, g_free);
|
|
g_clear_pointer (&priv->dialog_assign, gtk_widget_destroy);
|
|
|
|
G_OBJECT_CLASS (cc_color_panel_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
cc_color_panel_finalize (GObject *object)
|
|
{
|
|
G_OBJECT_CLASS (cc_color_panel_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
cc_color_panel_class_init (CcColorPanelClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
|
|
|
|
g_type_class_add_private (klass, sizeof (CcColorPanelPrivate));
|
|
|
|
panel_class->get_help_uri = cc_color_panel_get_help_uri;
|
|
|
|
object_class->get_property = cc_color_panel_get_property;
|
|
object_class->set_property = cc_color_panel_set_property;
|
|
object_class->dispose = cc_color_panel_dispose;
|
|
object_class->finalize = cc_color_panel_finalize;
|
|
}
|
|
|
|
static gint
|
|
cc_color_panel_sort_func (GtkListBoxRow *a,
|
|
GtkListBoxRow *b,
|
|
gpointer user_data)
|
|
{
|
|
const gchar *sort_a = NULL;
|
|
const gchar *sort_b = NULL;
|
|
if (CC_IS_COLOR_DEVICE (a))
|
|
sort_a = cc_color_device_get_sortable (CC_COLOR_DEVICE (a));
|
|
else if (CC_IS_COLOR_PROFILE (a))
|
|
sort_a = cc_color_profile_get_sortable (CC_COLOR_PROFILE (a));
|
|
else
|
|
g_assert_not_reached ();
|
|
if (CC_IS_COLOR_DEVICE (b))
|
|
sort_b = cc_color_device_get_sortable (CC_COLOR_DEVICE (b));
|
|
else if (CC_IS_COLOR_PROFILE (b))
|
|
sort_b = cc_color_profile_get_sortable (CC_COLOR_PROFILE (b));
|
|
else
|
|
g_assert_not_reached ();
|
|
return g_strcmp0 (sort_b, sort_a);
|
|
}
|
|
|
|
static gboolean
|
|
cc_color_panel_filter_func (GtkListBoxRow *row, void *user_data)
|
|
{
|
|
CcColorPanel *prefs = CC_COLOR_PANEL (user_data);
|
|
CdDevice *device;
|
|
gboolean ret;
|
|
|
|
/* always show all devices */
|
|
if (CC_IS_COLOR_DEVICE (row))
|
|
return TRUE;
|
|
|
|
g_object_get (row, "device", &device, NULL);
|
|
ret = g_strcmp0 (cd_device_get_id (device), prefs->priv->list_box_filter) == 0;
|
|
g_object_unref (device);
|
|
return ret;
|
|
}
|
|
|
|
static gboolean
|
|
cc_color_panel_treeview_quality_default_cb (GtkTreeModel *model,
|
|
GtkTreePath *path,
|
|
GtkTreeIter *iter,
|
|
gpointer data)
|
|
{
|
|
CdProfileQuality quality;
|
|
GtkTreeSelection *selection = GTK_TREE_SELECTION (data);
|
|
|
|
gtk_tree_model_get (model, iter,
|
|
COLUMN_CALIB_QUALITY_VALUE, &quality,
|
|
-1);
|
|
if (quality == CD_PROFILE_QUALITY_MEDIUM)
|
|
gtk_tree_selection_select_iter (selection, iter);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
cc_color_panel_init (CcColorPanel *prefs)
|
|
{
|
|
CcColorPanelPrivate *priv;
|
|
GError *error = NULL;
|
|
GtkCellRenderer *renderer;
|
|
GtkStyleContext *context;
|
|
GtkTreeModel *model;
|
|
GtkTreeModel *model_filter;
|
|
GtkTreeSelection *selection;
|
|
GtkTreeViewColumn *column;
|
|
GtkWidget *widget;
|
|
|
|
priv = prefs->priv = COLOR_PANEL_PRIVATE (prefs);
|
|
g_resources_register (cc_color_get_resource ());
|
|
|
|
priv->builder = gtk_builder_new ();
|
|
gtk_builder_add_from_resource (priv->builder,
|
|
"/org/gnome/control-center/color/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 ();
|
|
priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
|
|
|
/* can do native display calibration using colord-session */
|
|
priv->calibrate = cc_color_calibrate_new ();
|
|
cc_color_calibrate_set_quality (priv->calibrate, CD_PROFILE_QUALITY_MEDIUM);
|
|
|
|
/* setup defaults */
|
|
priv->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
|
|
priv->settings_colord = g_settings_new (COLORD_SETTINGS_SCHEMA);
|
|
|
|
/* 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);
|
|
|
|
/* href */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"label_assign_warning"));
|
|
g_signal_connect (widget, "activate-link",
|
|
G_CALLBACK (gcm_prefs_profile_assign_link_activate_cb), prefs);
|
|
|
|
/* add columns to profile tree view */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"treeview_assign"));
|
|
gcm_prefs_add_profiles_columns (prefs, GTK_TREE_VIEW (widget));
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
|
|
g_signal_connect (selection, "changed",
|
|
G_CALLBACK (gcm_prefs_profiles_treeview_clicked_cb),
|
|
prefs);
|
|
g_signal_connect (GTK_TREE_VIEW (widget), "row-activated",
|
|
G_CALLBACK (gcm_prefs_profiles_row_activated_cb),
|
|
prefs);
|
|
|
|
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_enable"));
|
|
g_signal_connect (widget, "clicked",
|
|
G_CALLBACK (gcm_prefs_device_profile_enable_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);
|
|
|
|
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);
|
|
priv->dialog_assign = widget;
|
|
|
|
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,
|
|
"button_assign_import"));
|
|
g_signal_connect (widget, "clicked",
|
|
G_CALLBACK (gcm_prefs_button_assign_import_cb), prefs);
|
|
|
|
/* setup the calibration helper */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"assistant_calib"));
|
|
g_signal_connect (widget, "delete-event",
|
|
G_CALLBACK (gcm_prefs_calib_delete_event_cb),
|
|
prefs);
|
|
g_signal_connect (widget, "apply",
|
|
G_CALLBACK (gcm_prefs_calib_apply_cb),
|
|
prefs);
|
|
g_signal_connect (widget, "cancel",
|
|
G_CALLBACK (gcm_prefs_calib_cancel_cb),
|
|
prefs);
|
|
g_signal_connect (widget, "close",
|
|
G_CALLBACK (gcm_prefs_calib_cancel_cb),
|
|
prefs);
|
|
g_signal_connect (widget, "prepare",
|
|
G_CALLBACK (gcm_prefs_calib_prepare_cb),
|
|
prefs);
|
|
priv->assistant_calib = widget;
|
|
|
|
/* setup the calibration helper ::TreeView */
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"treeview_calib_quality"));
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
|
|
gtk_tree_model_foreach (model,
|
|
cc_color_panel_treeview_quality_default_cb,
|
|
selection);
|
|
g_signal_connect (selection, "changed",
|
|
G_CALLBACK (gcm_prefs_calib_quality_treeview_clicked_cb),
|
|
prefs);
|
|
column = gtk_tree_view_column_new ();
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
g_object_set (renderer,
|
|
"xpad", 9,
|
|
"ypad", 9,
|
|
NULL);
|
|
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
|
gtk_tree_view_column_add_attribute (column, renderer,
|
|
"markup", COLUMN_CALIB_QUALITY_DESCRIPTION);
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
|
|
GTK_TREE_VIEW_COLUMN (column));
|
|
column = gtk_tree_view_column_new ();
|
|
renderer = cc_color_cell_renderer_text_new ();
|
|
g_object_set (renderer,
|
|
"xpad", 9,
|
|
"ypad", 9,
|
|
"is-dim-label", TRUE,
|
|
NULL);
|
|
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
|
gtk_tree_view_column_add_attribute (column, renderer,
|
|
"markup", COLUMN_CALIB_QUALITY_APPROX_TIME);
|
|
gtk_tree_view_column_set_expand (column, FALSE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
|
|
GTK_TREE_VIEW_COLUMN (column));
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"treeview_calib_sensor"));
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
|
|
g_signal_connect (selection, "changed",
|
|
G_CALLBACK (gcm_prefs_calib_sensor_treeview_clicked_cb),
|
|
prefs);
|
|
column = gtk_tree_view_column_new ();
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
g_object_set (renderer,
|
|
"xpad", 9,
|
|
"ypad", 9,
|
|
NULL);
|
|
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
|
gtk_tree_view_column_add_attribute (column, renderer,
|
|
"markup", COLUMN_CALIB_SENSOR_DESCRIPTION);
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
|
|
GTK_TREE_VIEW_COLUMN (column));
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"treeview_calib_kind"));
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
|
|
g_signal_connect (selection, "changed",
|
|
G_CALLBACK (gcm_prefs_calib_kind_treeview_clicked_cb),
|
|
prefs);
|
|
column = gtk_tree_view_column_new ();
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
g_object_set (renderer,
|
|
"xpad", 9,
|
|
"ypad", 9,
|
|
NULL);
|
|
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
|
gtk_tree_view_column_add_attribute (column, renderer,
|
|
"markup", COLUMN_CALIB_KIND_DESCRIPTION);
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
|
|
model_filter = gtk_tree_model_filter_new (model, NULL);
|
|
gtk_tree_view_set_model (GTK_TREE_VIEW (widget), model_filter);
|
|
gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (model_filter),
|
|
COLUMN_CALIB_KIND_VISIBLE);
|
|
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
|
|
GTK_TREE_VIEW_COLUMN (column));
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"treeview_calib_temp"));
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
|
|
g_signal_connect (selection, "changed",
|
|
G_CALLBACK (gcm_prefs_calib_temp_treeview_clicked_cb),
|
|
prefs);
|
|
column = gtk_tree_view_column_new ();
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
g_object_set (renderer,
|
|
"xpad", 9,
|
|
"ypad", 9,
|
|
NULL);
|
|
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
|
gtk_tree_view_column_add_attribute (column, renderer,
|
|
"markup", COLUMN_CALIB_TEMP_DESCRIPTION);
|
|
gtk_tree_view_column_set_expand (column, TRUE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget),
|
|
GTK_TREE_VIEW_COLUMN (column));
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"entry_calib_title"));
|
|
g_signal_connect (widget, "notify::text",
|
|
G_CALLBACK (gcm_prefs_title_entry_changed_cb), prefs);
|
|
|
|
/* use a device client array */
|
|
priv->client = cd_client_new ();
|
|
g_signal_connect_object (priv->client, "device-added",
|
|
G_CALLBACK (gcm_prefs_device_added_cb), prefs, 0);
|
|
g_signal_connect_object (priv->client, "device-removed",
|
|
G_CALLBACK (gcm_prefs_device_removed_cb), prefs, 0);
|
|
|
|
/* use a listbox for the main UI */
|
|
priv->list_box = GTK_LIST_BOX (gtk_list_box_new ());
|
|
gtk_list_box_set_filter_func (priv->list_box,
|
|
cc_color_panel_filter_func,
|
|
prefs,
|
|
NULL);
|
|
gtk_list_box_set_sort_func (priv->list_box,
|
|
cc_color_panel_sort_func,
|
|
prefs,
|
|
NULL);
|
|
gtk_list_box_set_header_func (priv->list_box,
|
|
cc_list_box_update_header_func,
|
|
prefs, NULL);
|
|
gtk_list_box_set_selection_mode (priv->list_box,
|
|
GTK_SELECTION_SINGLE);
|
|
gtk_list_box_set_activate_on_single_click (priv->list_box, FALSE);
|
|
priv->list_box_selected_id =
|
|
g_signal_connect (priv->list_box, "row-selected",
|
|
G_CALLBACK (gcm_prefs_list_box_row_selected_cb),
|
|
prefs);
|
|
priv->list_box_activated_id =
|
|
g_signal_connect (priv->list_box, "row-activated",
|
|
G_CALLBACK (gcm_prefs_list_box_row_activated_cb),
|
|
prefs);
|
|
priv->list_box_size = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "frame_devices"));
|
|
gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (priv->list_box));
|
|
gtk_widget_show (GTK_WIDGET (priv->list_box));
|
|
|
|
/* connect to colord */
|
|
cd_client_connect (priv->client,
|
|
priv->cancellable,
|
|
gcm_prefs_connect_cb,
|
|
prefs);
|
|
|
|
/* use the color sensor */
|
|
g_signal_connect_object (priv->client, "sensor-added",
|
|
G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
|
|
prefs, 0);
|
|
g_signal_connect_object (priv->client, "sensor-removed",
|
|
G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
|
|
prefs, 0);
|
|
|
|
/* set calibrate button sensitivity */
|
|
gcm_prefs_set_calibrate_button_sensitivity (prefs);
|
|
|
|
/* show the confirmation export page if we are running from a LiveCD */
|
|
priv->is_live_cd = gcm_prefs_is_livecd ();
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"box_calib_summary"));
|
|
gtk_widget_set_visible (widget, priv->is_live_cd);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"button_calib_export"));
|
|
g_signal_connect (widget, "clicked",
|
|
G_CALLBACK (gcm_prefs_calib_export_cb), prefs);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"button_calib_upload"));
|
|
g_signal_connect (widget, "clicked",
|
|
G_CALLBACK (gcm_prefs_calib_upload_cb), prefs);
|
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
|
|
"label_calib_summary_message"));
|
|
g_signal_connect (widget, "activate-link",
|
|
G_CALLBACK (gcm_prefs_calib_export_link_cb), prefs);
|
|
|
|
|
|
widget = WID (priv->builder, "dialog-vbox1");
|
|
gtk_container_add (GTK_CONTAINER (prefs), widget);
|
|
g_signal_connect (widget, "realize",
|
|
G_CALLBACK (gcm_prefs_window_realize_cb),
|
|
prefs);
|
|
}
|