gnome-control-center/capplets/common/gconf-property-editor.c
Thomas Hindoe Paaboel Andersen 49cfd993c1 Replace gdk_pixbuf_unref with g_object_unref
svn path=/trunk/; revision=9253
2009-02-09 13:52:54 +00:00

1797 lines
48 KiB
C

/* -*- mode: c; style: linux -*- */
/* gconf-property-editor.c
* Copyright (C) 2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.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, 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.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "gconf-property-editor.h"
#include "gconf-property-editor-marshal.h"
enum {
VALUE_CHANGED,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_KEY,
PROP_CALLBACK,
PROP_CHANGESET,
PROP_CONV_TO_WIDGET_CB,
PROP_CONV_FROM_WIDGET_CB,
PROP_UI_CONTROL,
PROP_DATA,
PROP_DATA_FREE_CB
};
struct _GConfPropertyEditorPrivate
{
gchar *key;
guint handler_id;
GConfChangeSet *changeset;
GObject *ui_control;
GConfPEditorValueConvFn conv_to_widget_cb;
GConfPEditorValueConvFn conv_from_widget_cb;
GConfClientNotifyFunc callback;
gboolean inited;
gpointer data;
GFreeFunc data_free_cb;
};
typedef struct
{
GType enum_type;
GConfPEditorGetValueFn enum_val_true_fn;
gpointer enum_val_true_fn_data;
guint enum_val_false;
gboolean use_nick;
} GConfPropertyEditorEnumData;
static guint peditor_signals[LAST_SIGNAL];
static void gconf_property_editor_set_prop (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gconf_property_editor_get_prop (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gconf_property_editor_finalize (GObject *object);
static GObject *gconf_peditor_new (const gchar *key,
GConfClientNotifyFunc cb,
GConfChangeSet *changeset,
GObject *ui_control,
const gchar *first_prop_name,
va_list var_args,
const gchar *first_custom,
...);
G_DEFINE_TYPE (GConfPropertyEditor, gconf_property_editor, G_TYPE_OBJECT)
#define GCONF_PROPERTY_EDITOR_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), gconf_property_editor_get_type (), GConfPropertyEditorPrivate))
static GConfValue*
gconf_property_editor_conv_default (GConfPropertyEditor *peditor,
const GConfValue *value)
{
return gconf_value_copy (value);
}
static void
gconf_property_editor_init (GConfPropertyEditor *gconf_property_editor)
{
gconf_property_editor->p = GCONF_PROPERTY_EDITOR_GET_PRIVATE (gconf_property_editor);
gconf_property_editor->p->conv_to_widget_cb = gconf_property_editor_conv_default;
gconf_property_editor->p->conv_from_widget_cb = gconf_property_editor_conv_default;
gconf_property_editor->p->inited = FALSE;
}
static void
gconf_property_editor_class_init (GConfPropertyEditorClass *class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (class);
object_class->finalize = gconf_property_editor_finalize;
object_class->set_property = gconf_property_editor_set_prop;
object_class->get_property = gconf_property_editor_get_prop;
g_object_class_install_property
(object_class, PROP_KEY,
g_param_spec_string ("key",
_("Key"),
_("GConf key to which this property editor is attached"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_CALLBACK,
g_param_spec_pointer ("callback",
_("Callback"),
_("Issue this callback when the value associated with key gets changed"),
G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_CHANGESET,
g_param_spec_pointer ("changeset",
_("Change set"),
_("GConf change set containing data to be forwarded to the gconf client on apply"),
G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_CONV_TO_WIDGET_CB,
g_param_spec_pointer ("conv-to-widget-cb",
_("Conversion to widget callback"),
_("Callback to be issued when data are to be converted from GConf to the widget"),
G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_CONV_FROM_WIDGET_CB,
g_param_spec_pointer ("conv-from-widget-cb",
_("Conversion from widget callback"),
_("Callback to be issued when data are to be converted to GConf from the widget"),
G_PARAM_WRITABLE));
g_object_class_install_property
(object_class, PROP_UI_CONTROL,
g_param_spec_object ("ui-control",
_("UI Control"),
_("Object that controls the property (normally a widget)"),
G_TYPE_OBJECT,
G_PARAM_WRITABLE));
peditor_signals[VALUE_CHANGED] =
g_signal_new ("value-changed",
G_TYPE_FROM_CLASS (object_class), 0,
G_STRUCT_OFFSET (GConfPropertyEditorClass, value_changed),
NULL, NULL,
(GSignalCMarshaller) gconf_property_editor_marshal_VOID__STRING_POINTER,
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER);
g_object_class_install_property
(object_class, PROP_DATA,
g_param_spec_pointer ("data",
_("Property editor object data"),
_("Custom data required by the specific property editor"),
G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_DATA_FREE_CB,
g_param_spec_pointer ("data-free-cb",
_("Property editor data freeing callback"),
_("Callback to be issued when property editor object data is to be freed"),
G_PARAM_WRITABLE));
g_type_class_add_private (class, sizeof (GConfPropertyEditorPrivate));
}
static void
gconf_property_editor_set_prop (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GConfPropertyEditor *peditor;
GConfClient *client;
GConfNotifyFunc cb;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (object));
peditor = GCONF_PROPERTY_EDITOR (object);
switch (prop_id) {
case PROP_KEY:
peditor->p->key = g_value_dup_string (value);
break;
case PROP_CALLBACK:
client = gconf_client_get_default ();
cb = g_value_get_pointer (value);
peditor->p->callback = (GConfClientNotifyFunc) cb;
if (peditor->p->handler_id != 0) {
gconf_client_notify_remove (client,
peditor->p->handler_id);
}
peditor->p->handler_id =
gconf_client_notify_add (client, peditor->p->key,
peditor->p->callback,
peditor, NULL, NULL);
g_object_unref (client);
break;
case PROP_CHANGESET:
peditor->p->changeset = g_value_get_pointer (value);
break;
case PROP_CONV_TO_WIDGET_CB:
peditor->p->conv_to_widget_cb = g_value_get_pointer (value);
break;
case PROP_CONV_FROM_WIDGET_CB:
peditor->p->conv_from_widget_cb = g_value_get_pointer (value);
break;
case PROP_UI_CONTROL:
peditor->p->ui_control = g_value_get_object (value);
g_object_weak_ref (peditor->p->ui_control, (GWeakNotify) g_object_unref, object);
break;
case PROP_DATA:
peditor->p->data = g_value_get_pointer (value);
break;
case PROP_DATA_FREE_CB:
peditor->p->data_free_cb = g_value_get_pointer (value);
break;
default:
g_warning ("Bad argument set");
break;
}
}
static void
gconf_property_editor_get_prop (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GConfPropertyEditor *peditor;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (object));
peditor = GCONF_PROPERTY_EDITOR (object);
switch (prop_id) {
case PROP_KEY:
g_value_set_string (value, peditor->p->key);
break;
case PROP_CHANGESET:
g_value_set_pointer (value, peditor->p->changeset);
break;
case PROP_DATA:
g_value_set_pointer (value, peditor->p->data);
break;
default:
g_warning ("Bad argument get");
break;
}
}
static void
gconf_property_editor_finalize (GObject *object)
{
GConfPropertyEditor *gconf_property_editor;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (object));
gconf_property_editor = GCONF_PROPERTY_EDITOR (object);
g_free (gconf_property_editor->p->key);
if (gconf_property_editor->p->data_free_cb)
gconf_property_editor->p->data_free_cb (gconf_property_editor->p->data);
if (gconf_property_editor->p->handler_id != 0) {
GConfClient *client;
client = gconf_client_get_default ();
gconf_client_notify_remove (client,
gconf_property_editor->p->handler_id);
g_object_unref (client);
}
G_OBJECT_CLASS (gconf_property_editor_parent_class)->finalize (object);
}
static GObject *
gconf_peditor_new (const gchar *key,
GConfClientNotifyFunc cb,
GConfChangeSet *changeset,
GObject *ui_control,
const gchar *first_prop_name,
va_list var_args,
const gchar *first_custom,
...)
{
GObject *obj;
GConfClient *client;
GConfEntry *gconf_entry;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (cb != NULL, NULL);
obj = g_object_new (gconf_property_editor_get_type (),
"key", key,
"callback", cb,
"changeset", changeset,
"ui-control", ui_control,
NULL);
g_object_set_valist (obj, first_prop_name, var_args);
if (first_custom)
{
va_list custom_args;
va_start (custom_args, first_custom);
g_object_set_valist (obj, first_custom, custom_args);
va_end (custom_args);
}
client = gconf_client_get_default ();
gconf_entry = gconf_client_get_entry (client, GCONF_PROPERTY_EDITOR (obj)->p->key, NULL, TRUE, NULL);
GCONF_PROPERTY_EDITOR (obj)->p->callback (client, 0, gconf_entry, obj);
GCONF_PROPERTY_EDITOR (obj)->p->inited = TRUE;
gconf_entry_free (gconf_entry);
g_object_unref (client);
return obj;
}
const gchar *
gconf_property_editor_get_key (GConfPropertyEditor *peditor)
{
return peditor->p->key;
}
GObject *
gconf_property_editor_get_ui_control (GConfPropertyEditor *peditor)
{
return peditor->p->ui_control;
}
static void
peditor_set_gconf_value (GConfPropertyEditor *peditor,
const gchar *key,
GConfValue *value)
{
if (peditor->p->changeset != NULL) {
if (value)
gconf_change_set_set (peditor->p->changeset, peditor->p->key, value);
else
gconf_change_set_unset (peditor->p->changeset, peditor->p->key);
} else {
GConfClient *client = gconf_client_get_default();
if (value)
gconf_client_set (client, peditor->p->key, value, NULL);
else
gconf_client_unset (client, peditor->p->key, NULL);
g_object_unref (client);
}
}
static void
peditor_boolean_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (peditor->p->ui_control), gconf_value_get_bool (value_wid));
gconf_value_free (value_wid);
}
}
static void
peditor_boolean_widget_changed (GConfPropertyEditor *peditor,
GtkToggleButton *tb)
{
GConfValue *value, *value_wid;
if (!peditor->p->inited) return;
value_wid = gconf_value_new (GCONF_VALUE_BOOL);
gconf_value_set_bool (value_wid, gtk_toggle_button_get_active (tb));
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
}
GObject *
gconf_peditor_new_boolean (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *checkbox,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (checkbox != NULL, NULL);
g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (checkbox), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_boolean_value_changed,
changeset,
G_OBJECT (checkbox),
first_property_name,
var_args,
NULL);
va_end (var_args);
g_signal_connect_swapped (checkbox, "toggled",
(GCallback) peditor_boolean_widget_changed, peditor);
return peditor;
}
static void
peditor_integer_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
const char *entry_current_text;
int entry_current_integer;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
entry_current_text = gtk_entry_get_text (GTK_ENTRY (peditor->p->ui_control));
entry_current_integer = strtol (entry_current_text, NULL, 10);
if (entry_current_integer != gconf_value_get_int (value)) {
char *buf = g_strdup_printf ("%d", gconf_value_get_int (value_wid));
gtk_entry_set_text (GTK_ENTRY (peditor->p->ui_control), buf);
g_free (buf);
}
gconf_value_free (value_wid);
}
}
static void
peditor_integer_widget_changed (GConfPropertyEditor *peditor,
GtkEntry *entry)
{
GConfValue *value, *value_wid;
if (!peditor->p->inited) return;
value_wid = gconf_value_new (GCONF_VALUE_INT);
gconf_value_set_int (value_wid, strtol (gtk_entry_get_text (entry), NULL, 10));
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
}
static GObject *
gconf_peditor_new_integer_valist (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *entry,
const gchar *first_property_name,
va_list var_args)
{
GObject *peditor;
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_integer_value_changed,
changeset,
G_OBJECT (entry),
first_property_name,
var_args, NULL);
g_signal_connect_swapped (entry, "changed",
(GCallback) peditor_integer_widget_changed, peditor);
return peditor;
}
GObject *
gconf_peditor_new_integer (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *entry,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (entry != NULL, NULL);
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new_integer_valist
(changeset, key, entry,
first_property_name, var_args);
va_end (var_args);
return peditor;
}
static void
peditor_string_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
const char *entry_current_text;
const char *gconf_text;
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
gconf_text = gconf_value_get_string (value_wid);
entry_current_text = gtk_entry_get_text (GTK_ENTRY (peditor->p->ui_control));
if (gconf_text && strcmp (entry_current_text, gconf_text) != 0) {
gtk_entry_set_text (GTK_ENTRY (peditor->p->ui_control), gconf_value_get_string (value_wid));
}
gconf_value_free (value_wid);
}
}
static void
peditor_string_widget_changed (GConfPropertyEditor *peditor,
GtkEntry *entry)
{
GConfValue *value, *value_wid;
if (!peditor->p->inited) return;
value_wid = gconf_value_new (GCONF_VALUE_STRING);
gconf_value_set_string (value_wid, gtk_entry_get_text (entry));
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
}
static GObject *
gconf_peditor_new_string_valist (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *entry,
const gchar *first_property_name,
va_list var_args)
{
GObject *peditor;
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_string_value_changed,
changeset,
G_OBJECT (entry),
first_property_name,
var_args, NULL);
g_signal_connect_swapped (entry, "changed",
(GCallback) peditor_string_widget_changed, peditor);
return peditor;
}
GObject *
gconf_peditor_new_string (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *entry,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (entry != NULL, NULL);
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new_string_valist
(changeset, key, entry,
first_property_name, var_args);
va_end (var_args);
return peditor;
}
static void
peditor_color_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
const gchar *spec;
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
spec = gconf_value_get_string (value_wid);
if (spec) {
GdkColor color;
gdk_color_parse (gconf_value_get_string (value_wid), &color);
gtk_color_button_set_color (
GTK_COLOR_BUTTON (peditor->p->ui_control), &color);
}
gconf_value_free (value_wid);
}
}
static void
peditor_color_widget_changed (GConfPropertyEditor *peditor,
GtkColorButton *cb)
{
gchar *str;
GConfValue *value, *value_wid;
GdkColor color;
if (!peditor->p->inited) return;
value_wid = gconf_value_new (GCONF_VALUE_STRING);
gtk_color_button_get_color (cb, &color);
str = g_strdup_printf ("#%02x%02x%02x", color.red >> 8,
color.green >> 8, color.blue >> 8);
gconf_value_set_string (value_wid, str);
g_free (str);
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
}
GObject *
gconf_peditor_new_color (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *cb,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (cb != NULL, NULL);
g_return_val_if_fail (GTK_IS_COLOR_BUTTON (cb), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_color_value_changed,
changeset,
G_OBJECT (cb),
first_property_name,
var_args, NULL);
va_end (var_args);
g_signal_connect_swapped (cb, "color_set",
(GCallback) peditor_color_widget_changed, peditor);
return peditor;
}
static int
peditor_enum_int_from_string (GType type, const gchar *str, gboolean use_nick)
{
GEnumClass *klass;
GEnumValue *val;
int ret = -1;
klass = g_type_class_ref (type);
if (use_nick)
val = g_enum_get_value_by_nick (klass, str);
else
val = g_enum_get_value_by_name (klass, str);
g_type_class_unref (klass);
if (val)
ret = val->value;
return ret;
}
static gchar*
peditor_enum_string_from_int (GType type, const int index, gboolean use_nick)
{
GEnumClass *klass;
GEnumValue *val;
gchar *ret = NULL;
klass = g_type_class_ref (type);
val = g_enum_get_value (klass, index);
if (val)
{
if (val->value_nick && use_nick)
ret = g_strdup (val->value_nick);
else
ret = g_strdup (val->value_name);
}
g_type_class_unref (klass);
return ret;
}
static GConfValue*
peditor_enum_conv_to_widget (GConfPropertyEditor *peditor,
const GConfValue *value)
{
GConfValue *ret;
GConfPropertyEditorEnumData *data = peditor->p->data;
int index;
if (value->type == GCONF_VALUE_INT)
return gconf_value_copy (value);
ret = gconf_value_new (GCONF_VALUE_INT);
index = peditor_enum_int_from_string (data->enum_type,
gconf_value_get_string (value),
data->use_nick);
gconf_value_set_int (ret, index);
return ret;
}
static GConfValue*
peditor_enum_conv_from_widget (GConfPropertyEditor *peditor,
const GConfValue *value)
{
GConfValue *ret;
GConfPropertyEditorEnumData *data = peditor->p->data;
gchar *str;
if (value->type == GCONF_VALUE_STRING)
return gconf_value_copy (value);
ret = gconf_value_new (GCONF_VALUE_STRING);
str = peditor_enum_string_from_int (data->enum_type,
gconf_value_get_int (value),
data->use_nick);
gconf_value_set_string (ret, str);
g_free (str);
return ret;
}
static void
peditor_combo_box_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
gtk_combo_box_set_active (GTK_COMBO_BOX (peditor->p->ui_control), gconf_value_get_int (value_wid));
gconf_value_free (value_wid);
}
}
static void
peditor_combo_box_widget_changed (GConfPropertyEditor *peditor,
GtkComboBox *combo_box)
{
GConfValue *value, *value_wid;
if (!peditor->p->inited) return;
value_wid = gconf_value_new (GCONF_VALUE_INT);
gconf_value_set_int (value_wid, gtk_combo_box_get_active (combo_box));
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
if (value)
gconf_value_free (value);
}
GObject *
gconf_peditor_new_combo_box (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *combo_box,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (combo_box != NULL, NULL);
g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_combo_box_value_changed,
changeset,
G_OBJECT (combo_box),
first_property_name,
var_args, NULL);
va_end (var_args);
g_signal_connect_swapped (combo_box, "changed",
(GCallback) peditor_combo_box_widget_changed, peditor);
return peditor;
}
GObject *
gconf_peditor_new_combo_box_with_enum (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *combo_box,
GType enum_type,
gboolean use_nick,
const gchar *first_property_name,
...)
{
GObject *peditor;
GConfPropertyEditorEnumData *data;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (combo_box != NULL, NULL);
g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), NULL);
g_return_val_if_fail (enum_type != G_TYPE_NONE, NULL);
data = g_new0 (GConfPropertyEditorEnumData, 1);
data->enum_type = enum_type;
data->use_nick = use_nick;
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_combo_box_value_changed,
changeset,
G_OBJECT (combo_box),
first_property_name,
var_args,
"conv-to-widget-cb",
peditor_enum_conv_to_widget,
"conv-from-widget-cb",
peditor_enum_conv_from_widget,
"data",
data,
"data-free-cb",
g_free,
NULL
);
va_end (var_args);
g_signal_connect_swapped (combo_box, "changed",
(GCallback) peditor_combo_box_widget_changed, peditor);
return peditor;
}
static void
peditor_select_radio_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GSList *group, *link;
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
group = g_slist_copy (gtk_radio_button_get_group (GTK_RADIO_BUTTON (peditor->p->ui_control)));
group = g_slist_reverse (group);
link = g_slist_nth (group, gconf_value_get_int (value_wid));
if (link && link->data)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (link->data), TRUE);
gconf_value_free (value_wid);
g_slist_free (group);
}
}
static void
peditor_select_radio_widget_changed (GConfPropertyEditor *peditor,
GtkToggleButton *tb)
{
GSList *group;
GConfValue *value, *value_wid;
if (!peditor->p->inited) return;
if (!tb->active) return;
value_wid = gconf_value_new (GCONF_VALUE_INT);
group = g_slist_copy (gtk_radio_button_get_group (GTK_RADIO_BUTTON (peditor->p->ui_control)));
group = g_slist_reverse (group);
gconf_value_set_int (value_wid, g_slist_index (group, tb));
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
g_slist_free (group);
}
GObject *
gconf_peditor_new_select_radio (GConfChangeSet *changeset,
const gchar *key,
GSList *radio_group,
const gchar *first_property_name,
...)
{
GObject *peditor;
GtkRadioButton *first_button;
GSList *item;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (radio_group != NULL, NULL);
g_return_val_if_fail (radio_group->data != NULL, NULL);
g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_group->data), NULL);
first_button = GTK_RADIO_BUTTON (radio_group->data);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_select_radio_value_changed,
changeset,
G_OBJECT (first_button),
first_property_name,
var_args, NULL);
va_end (var_args);
for (item = radio_group; item != NULL; item = item->next)
g_signal_connect_swapped (item->data, "toggled",
(GCallback) peditor_select_radio_widget_changed, peditor);
return peditor;
}
static void
peditor_numeric_range_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
switch (value_wid->type) {
case GCONF_VALUE_FLOAT:
gtk_adjustment_set_value (GTK_ADJUSTMENT (peditor->p->ui_control), gconf_value_get_float (value_wid));
break;
case GCONF_VALUE_INT:
gtk_adjustment_set_value (GTK_ADJUSTMENT (peditor->p->ui_control), gconf_value_get_int (value_wid));
break;
default:
g_warning ("Unknown type in range peditor: %d\n", value_wid->type);
}
gconf_value_free (value_wid);
}
}
static void
peditor_numeric_range_widget_changed (GConfPropertyEditor *peditor,
GtkAdjustment *adjustment)
{
GConfValue *value, *value_wid, *default_value;
GConfClient *client;
if (!peditor->p->inited) return;
/* We try to get the default type from the schemas. if not, we default
* to an int.
*/
client = gconf_client_get_default();
default_value = gconf_client_get_default_from_schema (client,
peditor->p->key,
NULL);
g_object_unref (client);
if (default_value) {
value_wid = gconf_value_new (default_value->type);
gconf_value_free (default_value);
} else {
g_warning ("Unable to find a default value for key for %s.\n"
"I'll assume it is an integer, but that may break things.\n"
"Please be sure that the associated schema is installed",
peditor->p->key);
value_wid = gconf_value_new (GCONF_VALUE_INT);
}
g_assert (value_wid);
if (value_wid->type == GCONF_VALUE_INT)
gconf_value_set_int (value_wid, gtk_adjustment_get_value (adjustment));
else if (value_wid->type == GCONF_VALUE_FLOAT)
gconf_value_set_float (value_wid, gtk_adjustment_get_value (adjustment));
else {
g_warning ("unable to set a gconf key for %s of type %d",
peditor->p->key,
value_wid->type);
gconf_value_free (value_wid);
return;
}
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
}
GObject *
gconf_peditor_new_numeric_range (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *range,
const gchar *first_property_name,
...)
{
GObject *peditor;
GObject *adjustment = NULL;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (range != NULL, NULL);
g_return_val_if_fail (GTK_IS_RANGE (range)||GTK_IS_SPIN_BUTTON (range), NULL);
if (GTK_IS_RANGE (range))
adjustment = G_OBJECT (gtk_range_get_adjustment (GTK_RANGE (range)));
else if (GTK_IS_SPIN_BUTTON (range))
adjustment = G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (range)));
else
g_assert_not_reached ();
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_numeric_range_value_changed,
changeset,
adjustment,
first_property_name,
var_args, NULL);
va_end (var_args);
g_signal_connect_swapped (adjustment, "value_changed",
(GCallback) peditor_numeric_range_widget_changed, peditor);
return peditor;
}
static gboolean
guard_get_bool (GConfPropertyEditor *peditor, const GConfValue *value)
{
if (value->type == GCONF_VALUE_BOOL)
return gconf_value_get_bool (value);
else
{
GConfPropertyEditorEnumData *data = peditor->p->data;
int index = peditor_enum_int_from_string (data->enum_type, gconf_value_get_string (value), data->use_nick);
return (index != data->enum_val_false);
}
}
static void
guard_value_changed (GConfPropertyEditor *peditor,
const gchar *key,
const GConfValue *value,
GtkWidget *widget)
{
gtk_widget_set_sensitive (widget, guard_get_bool (peditor, value));
}
void
gconf_peditor_widget_set_guard (GConfPropertyEditor *peditor,
GtkWidget *widget)
{
GConfClient *client;
GConfValue *value;
g_return_if_fail (peditor != NULL);
g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (peditor));
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
client = gconf_client_get_default ();
value = gconf_client_get (client, peditor->p->key, NULL);
g_object_unref (client);
if (value) {
gtk_widget_set_sensitive (widget, guard_get_bool (peditor, value));
gconf_value_free (value);
} else {
g_warning ("NULL GConf value: %s: possibly incomplete setup", peditor->p->key);
}
g_signal_connect (peditor, "value-changed", (GCallback) guard_value_changed, widget);
}
GConfValue *
gconf_value_int_to_float (GConfPropertyEditor *ignored, const GConfValue *value)
{
GConfValue *new_value;
new_value = gconf_value_new (GCONF_VALUE_FLOAT);
gconf_value_set_float (new_value, gconf_value_get_int (value));
return new_value;
}
GConfValue *
gconf_value_float_to_int (GConfPropertyEditor *ignored, const GConfValue *value)
{
GConfValue *new_value;
new_value = gconf_value_new (GCONF_VALUE_INT);
gconf_value_set_int (new_value, gconf_value_get_float (value));
return new_value;
}
static void
peditor_font_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
const gchar *font;
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
font = gconf_value_get_string (value_wid);
gtk_font_button_set_font_name (GTK_FONT_BUTTON (peditor->p->ui_control),
font);
gconf_value_free (value_wid);
}
}
static void
peditor_font_widget_changed (GConfPropertyEditor *peditor,
GtkFontButton *font_button)
{
const gchar *font_name;
GConfValue *value, *value_wid = NULL;
if (!peditor->p->inited)
return;
font_name = gtk_font_button_get_font_name (font_button);
value_wid = gconf_value_new (GCONF_VALUE_STRING);
gconf_value_set_string (value_wid, font_name);
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
}
GObject *
gconf_peditor_new_font (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *font_button,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (GTK_IS_FONT_BUTTON (font_button), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new (key,
(GConfClientNotifyFunc) peditor_font_value_changed,
changeset,
G_OBJECT (font_button),
first_property_name,
var_args,
NULL);
va_end (var_args);
g_signal_connect_swapped (font_button, "font_set",
(GCallback) peditor_font_widget_changed, peditor);
return peditor;
}
static GConfValue*
peditor_enum_toggle_conv_to_widget (GConfPropertyEditor *peditor,
const GConfValue *value)
{
GConfValue *ret;
GConfPropertyEditorEnumData *data = peditor->p->data;
int index;
if (value->type == GCONF_VALUE_BOOL)
return gconf_value_copy (value);
ret = gconf_value_new (GCONF_VALUE_BOOL);
index = peditor_enum_int_from_string (data->enum_type,
gconf_value_get_string (value),
data->use_nick);
gconf_value_set_bool (ret, (index != data->enum_val_false));
return ret;
}
static GConfValue*
peditor_enum_toggle_conv_from_widget (GConfPropertyEditor *peditor,
const GConfValue *value)
{
GConfValue *ret;
GConfPropertyEditorEnumData *data = peditor->p->data;
gchar *str;
int index;
if (value->type == GCONF_VALUE_STRING)
return gconf_value_copy (value);
ret = gconf_value_new (GCONF_VALUE_STRING);
if (gconf_value_get_bool (value))
index = data->enum_val_true_fn (peditor, data->enum_val_true_fn_data);
else
index = data->enum_val_false;
str = peditor_enum_string_from_int (data->enum_type, index, data->use_nick);
gconf_value_set_string (ret, str);
g_free (str);
return ret;
}
GObject *
gconf_peditor_new_enum_toggle (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *checkbox,
GType enum_type,
GConfPEditorGetValueFn val_true_fn,
guint val_false,
gboolean use_nick,
gpointer data,
const gchar *first_property_name,
...)
{
GObject *peditor;
GConfPropertyEditorEnumData *enum_data;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (checkbox != NULL, NULL);
g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (checkbox), NULL);
enum_data = g_new0 (GConfPropertyEditorEnumData, 1);
enum_data->enum_type = enum_type;
enum_data->enum_val_true_fn = val_true_fn;
enum_data->enum_val_true_fn_data = data;
enum_data->enum_val_false = val_false;
enum_data->use_nick = use_nick;
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_boolean_value_changed,
changeset,
G_OBJECT (checkbox),
first_property_name,
var_args,
"conv-to-widget-cb",
peditor_enum_toggle_conv_to_widget,
"conv-from-widget-cb",
peditor_enum_toggle_conv_from_widget,
"data",
enum_data,
"data-free-cb",
g_free,
NULL);
va_end (var_args);
g_signal_connect_swapped (checkbox, "toggled",
(GCallback) peditor_boolean_widget_changed, peditor);
return peditor;
}
static gboolean
peditor_image_set_filename (GConfPropertyEditor *peditor, const gchar *filename)
{
GdkPixbuf *pixbuf = NULL;
GtkImage *image = NULL;
const int scale = 100;
gchar *message = NULL;
GList *l;
/* NULL is not valid, however "" is, but not an error (it's
* the default) */
g_return_val_if_fail (filename != NULL, FALSE);
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
{
message = g_strdup_printf (_("Couldn't find the file '%s'.\n\nPlease make "
"sure it exists and try again, "
"or choose a different background picture."),
filename);
}
else if (!(pixbuf = gdk_pixbuf_new_from_file_at_size (filename, scale, scale, NULL)))
{
message = g_strdup_printf (_("I don't know how to open the file '%s'.\n"
"Perhaps it's "
"a kind of picture that is not yet supported.\n\n"
"Please select a different picture instead."),
filename);
}
if (GTK_IS_IMAGE (GTK_BIN (peditor->p->ui_control)->child))
image = GTK_IMAGE (GTK_BIN (peditor->p->ui_control)->child);
else
{
for (l = gtk_container_get_children (GTK_CONTAINER (GTK_BIN (peditor->p->ui_control)->child)); l != NULL; l = l->next)
{
if (GTK_IS_IMAGE (l->data))
image = GTK_IMAGE (l->data);
else if (GTK_IS_LABEL (l->data) && message == NULL)
{
gchar *base = g_path_get_basename (filename);
gtk_label_set_text (GTK_LABEL (l->data), base);
g_free (base);
}
}
}
if (message)
{
if (peditor->p->inited)
{
GtkWidget *box;
box = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
message);
gtk_dialog_run (GTK_DIALOG (box));
gtk_widget_destroy (box);
} else {
gtk_image_set_from_stock (image, GTK_STOCK_MISSING_IMAGE,
GTK_ICON_SIZE_BUTTON);
}
g_free (message);
return FALSE;
}
gtk_image_set_from_pixbuf (image, pixbuf);
g_object_unref (pixbuf);
return TRUE;
}
static void
peditor_image_chooser_response_cb (GtkWidget *chooser,
gint response,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
gchar *filename;
if (response == GTK_RESPONSE_CANCEL ||
response == GTK_RESPONSE_DELETE_EVENT)
{
gtk_widget_destroy (chooser);
return;
}
if (!peditor->p->inited)
return;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
if (!(filename && peditor_image_set_filename (peditor, filename)))
{
g_free (filename);
return;
}
value_wid = gconf_value_new (GCONF_VALUE_STRING);
gconf_value_set_string (value_wid, filename);
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
gconf_value_free (value_wid);
gconf_value_free (value);
g_free (filename);
gtk_widget_destroy (chooser);
}
static void
peditor_image_chooser_update_preview_cb (GtkFileChooser *chooser,
GtkImage *preview)
{
char *filename;
GdkPixbuf *pixbuf = NULL;
const int scale = 100;
filename = gtk_file_chooser_get_preview_filename (chooser);
if (filename != NULL && g_file_test (filename, G_FILE_TEST_IS_REGULAR))
pixbuf = gdk_pixbuf_new_from_file_at_size (filename, scale, scale, NULL);
gtk_image_set_from_pixbuf (preview, pixbuf);
g_free (filename);
if (pixbuf != NULL)
g_object_unref (pixbuf);
}
static void
peditor_image_clicked_cb (GConfPropertyEditor *peditor, GtkButton *button)
{
GConfValue *value = NULL, *value_wid;
const gchar *filename;
GtkWidget *chooser, *toplevel, *preview, *preview_box;
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
chooser = gtk_file_chooser_dialog_new (_("Please select an image."),
GTK_IS_WINDOW (toplevel) ? GTK_WINDOW (toplevel)
: NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
_("_Select"), GTK_RESPONSE_OK,
NULL);
preview = gtk_image_new ();
preview_box = gtk_hbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (preview_box), preview, FALSE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (preview_box), 6);
gtk_widget_show_all (preview_box);
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (chooser),
preview_box);
gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (chooser),
TRUE);
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
/* need the current filename */
if (peditor->p->changeset)
gconf_change_set_check_value (peditor->p->changeset, peditor->p->key, &value);
if (value)
{
/* the one we got is not a copy */
value = gconf_value_copy (value);
}
else
{
GConfClient *client = gconf_client_get_default ();
value = gconf_client_get (client, peditor->p->key, NULL);
g_object_unref (client);
}
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
filename = gconf_value_get_string (value_wid);
if (filename && strcmp (filename, ""))
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), filename);
g_signal_connect (chooser, "update-preview",
G_CALLBACK (peditor_image_chooser_update_preview_cb),
preview);
g_signal_connect (chooser, "response",
G_CALLBACK (peditor_image_chooser_response_cb),
peditor);
if (gtk_grab_get_current ())
gtk_grab_add (chooser);
gtk_widget_show (chooser);
gconf_value_free (value);
gconf_value_free (value_wid);
}
static void
peditor_image_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value, *value_wid;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
const gchar *filename;
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
filename = gconf_value_get_string (value_wid);
peditor_image_set_filename (peditor, filename);
gconf_value_free (value_wid);
}
}
GObject *
gconf_peditor_new_image (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *button,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (button != NULL, NULL);
g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_image_value_changed,
changeset,
G_OBJECT (button),
first_property_name,
var_args, NULL);
va_end (var_args);
g_signal_connect_swapped (button, "clicked",
(GCallback) peditor_image_clicked_cb, peditor);
return peditor;
}
GObject *
gconf_peditor_new_select_radio_with_enum (GConfChangeSet *changeset,
const gchar *key,
GSList *radio_group,
GType enum_type,
gboolean use_nick,
const gchar *first_property_name,
...)
{
GObject *peditor;
GConfPropertyEditorEnumData *enum_data;
GtkRadioButton *first_button;
GSList *item;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (radio_group != NULL, NULL);
g_return_val_if_fail (radio_group->data != NULL, NULL);
g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_group->data), NULL);
enum_data = g_new0 (GConfPropertyEditorEnumData, 1);
enum_data->enum_type = enum_type;
enum_data->use_nick = use_nick;
first_button = GTK_RADIO_BUTTON (radio_group->data);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_select_radio_value_changed,
changeset,
G_OBJECT (first_button),
first_property_name,
var_args,
"conv-to-widget-cb",
peditor_enum_conv_to_widget,
"conv-from-widget-cb",
peditor_enum_conv_from_widget,
"data",
enum_data,
"data-free-cb",
g_free,
NULL);
va_end (var_args);
for (item = radio_group; item != NULL; item = item->next)
g_signal_connect_swapped (item->data, "toggled",
(GCallback) peditor_select_radio_widget_changed, peditor);
return peditor;
}
static void
peditor_tree_view_value_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
GConfPropertyEditor *peditor)
{
GConfValue *value;
if (peditor->p->changeset != NULL)
gconf_change_set_remove (peditor->p->changeset, peditor->p->key);
if (entry && (value = gconf_entry_get_value (entry))) {
GtkTreeView *treeview;
GtkTreeSelection *selection;
GConfValue *value_wid;
treeview = GTK_TREE_VIEW (peditor->p->ui_control);
selection = gtk_tree_view_get_selection (treeview);
value_wid = peditor->p->conv_to_widget_cb (peditor, value);
if (value_wid != NULL) {
GtkTreePath *path = gtk_tree_path_new_from_string (
gconf_value_get_string (value_wid));
gtk_tree_selection_select_path (selection, path);
gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
gtk_tree_path_free (path);
gconf_value_free (value_wid);
} else {
gtk_tree_selection_unselect_all (selection);
}
}
}
static void
peditor_tree_view_widget_changed (GConfPropertyEditor *peditor,
GtkTreeSelection *selection)
{
GtkTreeModel *model;
GtkTreeIter iter;
GConfValue *value, *value_wid;
if (!peditor->p->inited) return;
/* we don't support GTK_SELECTION_MULTIPLE */
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
gchar *path;
path = gtk_tree_model_get_string_from_iter (model, &iter);
value_wid = gconf_value_new (GCONF_VALUE_STRING);
gconf_value_set_string (value_wid, path);
g_free (path);
} else
value_wid = NULL;
value = peditor->p->conv_from_widget_cb (peditor, value_wid);
peditor_set_gconf_value (peditor, peditor->p->key, value);
g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value);
if (value_wid)
gconf_value_free (value_wid);
if (value)
gconf_value_free (value);
}
GObject *
gconf_peditor_new_tree_view (GConfChangeSet *changeset,
const gchar *key,
GtkWidget *tree_view,
const gchar *first_property_name,
...)
{
GObject *peditor;
va_list var_args;
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (tree_view != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
va_start (var_args, first_property_name);
peditor = gconf_peditor_new
(key,
(GConfClientNotifyFunc) peditor_tree_view_value_changed,
changeset,
G_OBJECT (tree_view),
first_property_name,
var_args, NULL);
va_end (var_args);
g_signal_connect_swapped (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)),
"changed",
(GCallback) peditor_tree_view_widget_changed, peditor);
return peditor;
}