This matches the new mockups as specified by Allan in https://raw.github.com/gnome-design-team/gnome-mockups/master/system-settings/color/panel.png The CcColorDevice and CcColorProfile widgets are lines in the EggListBox and are smart by watching for changes in each colord device. To use this new functionality you need colord from git master, and for the 'Laptop' devices to be recognised as internal, you also need to be _running_ gnome-settings-daemon from git, although this is not strictly required.
321 lines
10 KiB
C
321 lines
10 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
|
*
|
|
* Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* Licensed under the GNU General Public License Version 2
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib/gi18n.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "cc-color-common.h"
|
|
#include "cc-color-device.h"
|
|
|
|
struct _CcColorDevicePrivate
|
|
{
|
|
CdDevice *device;
|
|
gboolean expanded;
|
|
gchar *sortable;
|
|
GtkWidget *widget_description;
|
|
GtkWidget *widget_button;
|
|
GtkWidget *widget_switch;
|
|
GtkWidget *widget_arrow;
|
|
GtkWidget *widget_nocalib;
|
|
guint device_changed_id;
|
|
};
|
|
|
|
G_DEFINE_TYPE (CcColorDevice, cc_color_device, GTK_TYPE_BOX)
|
|
|
|
enum
|
|
{
|
|
SIGNAL_EXPANDED_CHANGED,
|
|
SIGNAL_LAST
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_DEVICE,
|
|
PROP_LAST
|
|
};
|
|
|
|
static guint signals [SIGNAL_LAST] = { 0 };
|
|
|
|
static void
|
|
cc_color_device_refresh (CcColorDevice *color_device)
|
|
{
|
|
CcColorDevicePrivate *priv = color_device->priv;
|
|
gchar *title = NULL;
|
|
GPtrArray *profiles = NULL;
|
|
|
|
/* add switch and expander if there are profiles, otherwise use a label */
|
|
profiles = cd_device_get_profiles (priv->device);
|
|
if (profiles == NULL)
|
|
goto out;
|
|
|
|
title = cc_color_device_get_title (priv->device);
|
|
gtk_label_set_label (GTK_LABEL (priv->widget_description), title);
|
|
gtk_widget_set_visible (priv->widget_description, TRUE);
|
|
|
|
gtk_widget_set_visible (priv->widget_switch, profiles->len > 0);
|
|
gtk_widget_set_visible (priv->widget_button, profiles->len > 0);
|
|
gtk_arrow_set (GTK_ARROW (priv->widget_arrow),
|
|
priv->expanded ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT,
|
|
GTK_SHADOW_OUT);
|
|
gtk_widget_set_visible (priv->widget_nocalib, profiles->len == 0);
|
|
gtk_widget_set_sensitive (priv->widget_button, cd_device_get_enabled (priv->device));
|
|
gtk_switch_set_active (GTK_SWITCH (priv->widget_switch),
|
|
cd_device_get_enabled (priv->device));
|
|
out:
|
|
if (profiles != NULL)
|
|
g_ptr_array_unref (profiles);
|
|
g_free (title);
|
|
}
|
|
|
|
CdDevice *
|
|
cc_color_device_get_device (CcColorDevice *color_device)
|
|
{
|
|
g_return_val_if_fail (CC_IS_COLOR_DEVICE (color_device), NULL);
|
|
return color_device->priv->device;
|
|
}
|
|
|
|
const gchar *
|
|
cc_color_device_get_sortable (CcColorDevice *color_device)
|
|
{
|
|
g_return_val_if_fail (CC_IS_COLOR_DEVICE (color_device), NULL);
|
|
return color_device->priv->sortable;
|
|
}
|
|
|
|
static void
|
|
cc_color_device_get_property (GObject *object, guint param_id,
|
|
GValue *value, GParamSpec *pspec)
|
|
{
|
|
CcColorDevice *color_device = CC_COLOR_DEVICE (object);
|
|
switch (param_id)
|
|
{
|
|
case PROP_DEVICE:
|
|
g_value_set_object (value, color_device->priv->device);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cc_color_device_set_property (GObject *object, guint param_id,
|
|
const GValue *value, GParamSpec *pspec)
|
|
{
|
|
CcColorDevice *color_device = CC_COLOR_DEVICE (object);
|
|
|
|
switch (param_id)
|
|
{
|
|
case PROP_DEVICE:
|
|
color_device->priv->device = g_value_dup_object (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cc_color_device_finalize (GObject *object)
|
|
{
|
|
CcColorDevice *color_device = CC_COLOR_DEVICE (object);
|
|
CcColorDevicePrivate *priv = color_device->priv;
|
|
|
|
if (priv->device_changed_id > 0)
|
|
g_signal_handler_disconnect (priv->device, priv->device_changed_id);
|
|
|
|
g_free (priv->sortable);
|
|
g_object_unref (priv->device);
|
|
|
|
G_OBJECT_CLASS (cc_color_device_parent_class)->finalize (object);
|
|
}
|
|
|
|
void
|
|
cc_color_device_set_expanded (CcColorDevice *color_device,
|
|
gboolean expanded)
|
|
{
|
|
CcColorDevicePrivate *priv = color_device->priv;
|
|
priv->expanded = FALSE;
|
|
cc_color_device_refresh (color_device);
|
|
}
|
|
|
|
static void
|
|
cc_color_device_notify_enable_device_cb (GtkSwitch *sw,
|
|
GParamSpec *pspec,
|
|
gpointer user_data)
|
|
{
|
|
CcColorDevice *color_device = CC_COLOR_DEVICE (user_data);
|
|
CcColorDevicePrivate *priv = color_device->priv;
|
|
gboolean enable;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
|
|
enable = gtk_switch_get_active (sw);
|
|
g_debug ("Set %s to %i", cd_device_get_id (priv->device), enable);
|
|
ret = cd_device_set_enabled_sync (priv->device,
|
|
enable, NULL, &error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to %s to the device: %s",
|
|
enable ? "enable" : "disable", error->message);
|
|
g_error_free (error);
|
|
}
|
|
|
|
/* if expanded, close */
|
|
if (priv->expanded)
|
|
{
|
|
cc_color_device_set_expanded (color_device, FALSE);
|
|
g_signal_emit (color_device, signals[SIGNAL_EXPANDED_CHANGED], 0,
|
|
priv->expanded);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cc_color_device_changed_cb (CdDevice *device,
|
|
CcColorDevice *color_device)
|
|
{
|
|
cc_color_device_refresh (color_device);
|
|
}
|
|
|
|
static void
|
|
cc_color_device_constructed (GObject *object)
|
|
{
|
|
CcColorDevice *color_device = CC_COLOR_DEVICE (object);
|
|
CcColorDevicePrivate *priv = color_device->priv;
|
|
gchar *sortable_tmp;
|
|
|
|
/* watch the device for changes */
|
|
priv->device_changed_id =
|
|
g_signal_connect (priv->device, "changed",
|
|
G_CALLBACK (cc_color_device_changed_cb), color_device);
|
|
|
|
/* calculate sortable -- FIXME: we have to hack this as EggListBox
|
|
* does not let us specify a GtkSortType:
|
|
* https://bugzilla.gnome.org/show_bug.cgi?id=691341 */
|
|
sortable_tmp = cc_color_device_get_sortable_base (priv->device);
|
|
priv->sortable = g_strdup_printf ("%sXX", sortable_tmp);
|
|
g_free (sortable_tmp);
|
|
|
|
cc_color_device_refresh (color_device);
|
|
|
|
/* watch to see if the user flicked the switch */
|
|
g_signal_connect (priv->widget_switch, "notify::active",
|
|
G_CALLBACK (cc_color_device_notify_enable_device_cb),
|
|
color_device);
|
|
}
|
|
|
|
static void
|
|
cc_color_device_class_init (CcColorDeviceClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
object_class->get_property = cc_color_device_get_property;
|
|
object_class->set_property = cc_color_device_set_property;
|
|
object_class->constructed = cc_color_device_constructed;
|
|
object_class->finalize = cc_color_device_finalize;
|
|
|
|
g_object_class_install_property (object_class, PROP_DEVICE,
|
|
g_param_spec_object ("device", NULL,
|
|
NULL,
|
|
CD_TYPE_DEVICE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
signals [SIGNAL_EXPANDED_CHANGED] =
|
|
g_signal_new ("expanded-changed",
|
|
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (CcColorDeviceClass, expanded_changed),
|
|
NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
|
|
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
|
|
|
g_type_class_add_private (klass, sizeof (CcColorDevicePrivate));
|
|
}
|
|
|
|
static void
|
|
cc_color_device_clicked_expander_cb (GtkButton *button,
|
|
gpointer user_data)
|
|
{
|
|
CcColorDevice *color_device = CC_COLOR_DEVICE (user_data);
|
|
color_device->priv->expanded = !color_device->priv->expanded;
|
|
cc_color_device_refresh (color_device);
|
|
g_signal_emit (color_device, signals[SIGNAL_EXPANDED_CHANGED], 0,
|
|
color_device->priv->expanded);
|
|
}
|
|
|
|
static void
|
|
cc_color_device_init (CcColorDevice *color_device)
|
|
{
|
|
CcColorDevicePrivate *priv;
|
|
GtkStyleContext *context;
|
|
GtkWidget *box;
|
|
|
|
color_device->priv = G_TYPE_INSTANCE_GET_PRIVATE (color_device,
|
|
CC_TYPE_COLOR_DEVICE,
|
|
CcColorDevicePrivate);
|
|
priv = color_device->priv;
|
|
|
|
/* description */
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 9);
|
|
priv->widget_description = gtk_label_new ("");
|
|
gtk_widget_set_margin_left (priv->widget_description, 12);
|
|
gtk_widget_set_margin_top (priv->widget_description, 6);
|
|
gtk_widget_set_margin_bottom (priv->widget_description, 6);
|
|
gtk_misc_set_alignment (GTK_MISC (priv->widget_description), 0.0f, 0.5f);
|
|
gtk_box_pack_start (GTK_BOX (box), priv->widget_description, TRUE, TRUE, 0);
|
|
|
|
/* switch */
|
|
priv->widget_switch = gtk_switch_new ();
|
|
gtk_box_pack_start (GTK_BOX (box), priv->widget_switch, FALSE, FALSE, 0);
|
|
|
|
/* arrow button */
|
|
priv->widget_arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
|
|
priv->widget_button = gtk_button_new ();
|
|
g_signal_connect (priv->widget_button, "clicked",
|
|
G_CALLBACK (cc_color_device_clicked_expander_cb),
|
|
color_device);
|
|
gtk_button_set_relief (GTK_BUTTON (priv->widget_button), GTK_RELIEF_NONE);
|
|
gtk_container_add (GTK_CONTAINER (priv->widget_button), priv->widget_arrow);
|
|
gtk_widget_set_visible (priv->widget_arrow, TRUE);
|
|
gtk_widget_set_margin_top (priv->widget_button, 3);
|
|
gtk_widget_set_margin_bottom (priv->widget_button, 3);
|
|
gtk_widget_set_margin_right (priv->widget_button, 9);
|
|
gtk_box_pack_start (GTK_BOX (box), priv->widget_button, FALSE, FALSE, 0);
|
|
|
|
/* not calibrated */
|
|
priv->widget_nocalib = gtk_label_new (_("Not calibrated"));
|
|
context = gtk_widget_get_style_context (priv->widget_nocalib);
|
|
gtk_style_context_add_class (context, "dim-label");
|
|
gtk_widget_set_margin_right (priv->widget_nocalib, 18);
|
|
gtk_box_pack_start (GTK_BOX (box), priv->widget_nocalib, FALSE, FALSE, 0);
|
|
|
|
/* refresh */
|
|
gtk_box_pack_start (GTK_BOX (color_device), box, TRUE, TRUE, 0);
|
|
gtk_widget_set_visible (box, TRUE);
|
|
}
|
|
|
|
GtkWidget *
|
|
cc_color_device_new (CdDevice *device)
|
|
{
|
|
return g_object_new (CC_TYPE_COLOR_DEVICE,
|
|
"device", device,
|
|
NULL);
|
|
}
|
|
|