g_settings_bind() fixes

- track sensitivity changes
 - move vuntz-mapping code to new file
 - option to only get initial value from settings
This commit is contained in:
Ryan Lortie 2010-04-16 22:49:35 -04:00
parent ed0544b305
commit eedfbdf80f
5 changed files with 485 additions and 372 deletions

View File

@ -97,6 +97,8 @@ settings_sources = \
gsettingsbackend.c \
gsettingsschema.h \
gsettingsschema.c \
gsettings-mapping.h \
gsettings-mapping.c \
gsettings.c
local_sources = \

367
gio/gsettings-mapping.c Normal file
View File

@ -0,0 +1,367 @@
/*
* Copyright © 2010 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the licence, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Vincent Untz <vuntz@gnome.org>
*/
#include "config.h"
#include "gsettings-mapping.h"
static GVariant *
g_settings_set_mapping_numeric (const GValue *value,
const GVariantType *expected_type)
{
GVariant *variant = NULL;
glong l;
if (G_VALUE_HOLDS_INT (value))
l = g_value_get_int (value);
else if (G_VALUE_HOLDS_INT64 (value))
l = g_value_get_int64 (value);
else if (G_VALUE_HOLDS_DOUBLE (value))
l = g_value_get_double (value);
else
return NULL;
if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
{
if (G_MININT16 <= l && l <= G_MAXINT16)
variant = g_variant_new_int16 ((gint16) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
{
if (0 <= l && l <= G_MAXUINT16)
variant = g_variant_new_uint16 ((guint16) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
{
if (G_MININT32 <= l && l <= G_MAXINT32)
variant = g_variant_new_int32 ((gint) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
{
if (0 <= l && l <= G_MAXUINT32)
variant = g_variant_new_uint32 ((guint) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
{
if (G_MININT64 <= l && l <= G_MAXINT64)
variant = g_variant_new_int64 ((gint64) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
{
if (0 <= l && l <= G_MAXUINT64)
variant = g_variant_new_uint64 ((guint64) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
{
if (0 <= l && l <= G_MAXUINT32)
variant = g_variant_new_handle ((guint) l);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
variant = g_variant_new_double ((double) l);
return variant;
}
static GVariant *
g_settings_set_mapping_unsigned_numeric (const GValue *value,
const GVariantType *expected_type)
{
GVariant *variant = NULL;
gulong u;
if (G_VALUE_HOLDS_UINT (value))
u = g_value_get_uint (value);
else if (G_VALUE_HOLDS_UINT64 (value))
u = g_value_get_uint64 (value);
else
return NULL;
if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
{
if (u <= G_MAXINT16)
variant = g_variant_new_int16 ((gint16) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
{
if (u <= G_MAXUINT16)
variant = g_variant_new_uint16 ((guint16) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
{
if (u <= G_MAXINT32)
variant = g_variant_new_int32 ((gint) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
{
if (u <= G_MAXUINT32)
variant = g_variant_new_uint32 ((guint) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
{
if (u <= G_MAXINT64)
variant = g_variant_new_int64 ((gint64) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
{
if (u <= G_MAXUINT64)
variant = g_variant_new_uint64 ((guint64) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
{
if (u <= G_MAXUINT32)
variant = g_variant_new_handle ((guint) u);
}
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
variant = g_variant_new_double ((double) u);
return variant;
}
static gboolean
g_settings_get_mapping_numeric (GValue *value,
GVariant *variant)
{
const GVariantType *type;
glong l;
type = g_variant_get_type (variant);
if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
l = g_variant_get_int16 (variant);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
l = g_variant_get_int32 (variant);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
l = g_variant_get_int64 (variant);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
l = g_variant_get_double (variant);
else
return FALSE;
if (G_VALUE_HOLDS_INT (value))
{
g_value_set_int (value, l);
return (G_MININT32 <= l && l <= G_MAXINT32);
}
else if (G_VALUE_HOLDS_UINT (value))
{
g_value_set_uint (value, l);
return (0 <= l && l <= G_MAXUINT32);
}
else if (G_VALUE_HOLDS_INT64 (value))
{
g_value_set_int64 (value, l);
return (G_MININT64 <= l && l <= G_MAXINT64);
}
else if (G_VALUE_HOLDS_UINT64 (value))
{
g_value_set_uint64 (value, l);
return (0 <= l && l <= G_MAXUINT64);
}
else if (G_VALUE_HOLDS_DOUBLE (value))
{
g_value_set_double (value, l);
return TRUE;
}
return FALSE;
}
static gboolean
g_settings_get_mapping_unsigned_numeric (GValue *value,
GVariant *variant)
{
const GVariantType *type;
gulong u;
type = g_variant_get_type (variant);
if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
u = g_variant_get_uint16 (variant);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
u = g_variant_get_uint32 (variant);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
u = g_variant_get_uint64 (variant);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
u = g_variant_get_handle (variant);
else
return FALSE;
if (G_VALUE_HOLDS_INT (value))
{
g_value_set_int (value, u);
return (u <= G_MAXINT32);
}
else if (G_VALUE_HOLDS_UINT (value))
{
g_value_set_uint (value, u);
return (u <= G_MAXUINT32);
}
else if (G_VALUE_HOLDS_INT64 (value))
{
g_value_set_int64 (value, u);
return (u <= G_MAXINT64);
}
else if (G_VALUE_HOLDS_UINT64 (value))
{
g_value_set_uint64 (value, u);
return (u <= G_MAXUINT64);
}
else if (G_VALUE_HOLDS_DOUBLE (value))
{
g_value_set_double (value, u);
return TRUE;
}
return FALSE;
}
GVariant *
g_settings_set_mapping (const GValue *value,
const GVariantType *expected_type,
gpointer user_data)
{
gchar *type_string;
if (G_VALUE_HOLDS_BOOLEAN (value))
{
if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN))
return g_variant_new_boolean (g_value_get_boolean (value));
}
else if (G_VALUE_HOLDS_CHAR (value) ||
G_VALUE_HOLDS_UCHAR (value))
{
if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE))
{
if (G_VALUE_HOLDS_CHAR (value))
return g_variant_new_byte (g_value_get_char (value));
else
return g_variant_new_byte (g_value_get_uchar (value));
}
}
else if (G_VALUE_HOLDS_INT (value) ||
G_VALUE_HOLDS_INT64 (value) ||
G_VALUE_HOLDS_DOUBLE (value))
return g_settings_set_mapping_numeric (value, expected_type);
else if (G_VALUE_HOLDS_UINT (value) ||
G_VALUE_HOLDS_UINT64 (value))
return g_settings_set_mapping_unsigned_numeric (value, expected_type);
else if (G_VALUE_HOLDS_STRING (value))
{
if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
return g_variant_new_string (g_value_get_string (value));
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
return g_variant_new_object_path (g_value_get_string (value));
else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE))
return g_variant_new_signature (g_value_get_string (value));
}
type_string = g_variant_type_dup_string (expected_type);
g_critical ("No GSettings bind handler for type \"%s\".", type_string);
g_free (type_string);
return NULL;
}
gboolean
g_settings_get_mapping (GValue *value,
GVariant *variant,
gpointer user_data)
{
if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
{
if (!G_VALUE_HOLDS_BOOLEAN (value))
return FALSE;
g_value_set_boolean (value, g_variant_get_boolean (variant));
return TRUE;
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
{
if (G_VALUE_HOLDS_UCHAR (value))
g_value_set_uchar (value, g_variant_get_byte (variant));
else if (G_VALUE_HOLDS_CHAR (value))
g_value_set_char (value, (gchar) g_variant_get_byte (variant));
else
return FALSE;
return TRUE;
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
return g_settings_get_mapping_numeric (value, variant);
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
return g_settings_get_mapping_unsigned_numeric (value, variant);
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
{
g_value_set_string (value, g_variant_get_string (variant, NULL));
return TRUE;
}
g_critical ("No GSettings bind handler for type \"%s\".",
g_variant_get_type_string (variant));
return FALSE;
}
gboolean
g_settings_mapping_is_compatible (GType gvalue_type,
const GVariantType *variant_type)
{
gboolean ok = FALSE;
if (gvalue_type == G_TYPE_BOOLEAN)
ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN);
else if (gvalue_type == G_TYPE_CHAR ||
gvalue_type == G_TYPE_UCHAR)
ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE);
else if (gvalue_type == G_TYPE_INT ||
gvalue_type == G_TYPE_UINT ||
gvalue_type == G_TYPE_INT64 ||
gvalue_type == G_TYPE_UINT64 ||
gvalue_type == G_TYPE_DOUBLE)
ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_HANDLE) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
else if (gvalue_type == G_TYPE_STRING)
ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
return ok;
}

39
gio/gsettings-mapping.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright © 2010 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the licence, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Vincent Untz <vuntz@gnome.org>
*/
#ifndef __G_SETTINGS_MAPPING_H__
#define __G_SETTINGS_MAPPING_H__
#include <glib-object.h>
G_GNUC_INTERNAL
GVariant * g_settings_set_mapping (const GValue *value,
const GVariantType *expected_type,
gpointer user_data);
G_GNUC_INTERNAL
gboolean g_settings_get_mapping (GValue *value,
GVariant *variant,
gpointer user_data);
G_GNUC_INTERNAL
gboolean g_settings_mapping_is_compatible (GType gvalue_type,
const GVariantType *variant_type);
#endif /* __G_SETTINGS_MAPPING_H__ */

View File

@ -1,11 +1,22 @@
/*
* Copyright © 2009 Codethink Limited
* Copyright © 2009, 2010 Codethink Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the licence, or (at your option) any later version.
*
* See the included COPYING file for more information.
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#include "config.h"
@ -17,6 +28,7 @@
#include "gdelayedsettingsbackend.h"
#include "gsettingsbackendinternal.h"
#include "gsettings-mapping.h"
#include "gio-marshal.h"
#include "gsettingsschema.h"
@ -1086,6 +1098,7 @@ typedef struct
gpointer user_data;
GDestroyNotify destroy;
guint writable_handler_id;
guint property_handler_id;
const GParamSpec *property;
guint key_handler_id;
@ -1103,8 +1116,11 @@ g_settings_binding_free (gpointer data)
g_assert (!binding->running);
if (g_signal_handler_is_connected (binding->settings,
binding->key_handler_id))
if (binding->writable_handler_id)
g_signal_handler_disconnect (binding->settings,
binding->writable_handler_id);
if (binding->key_handler_id)
g_signal_handler_disconnect (binding->settings,
binding->key_handler_id);
@ -1163,6 +1179,21 @@ g_settings_binding_key_changed (GSettings *settings,
binding->running = FALSE;
}
static void
g_settings_binding_writable_changed (GSettings *settings,
const gchar *key,
gpointer user_data)
{
GSettingsBinding *binding = user_data;
gboolean writable;
g_assert (settings == binding->settings);
g_assert (key == binding->key);
writable = g_settings_is_writable (settings, key);
g_object_set (binding->object, "sensitive", writable, NULL);
}
static void
g_settings_binding_property_changed (GObject *object,
const GParamSpec *pspec,
@ -1195,316 +1226,6 @@ g_settings_binding_property_changed (GObject *object,
binding->running = FALSE;
}
static GVariant *
g_settings_set_mapping_numeric (const GValue *value,
const GVariantType *expected_type)
{
GVariant *variant = NULL;
glong l;
if (G_VALUE_HOLDS_INT (value))
l = g_value_get_int (value);
else if (G_VALUE_HOLDS_INT64 (value))
l = g_value_get_int64 (value);
else if (G_VALUE_HOLDS_DOUBLE (value))
l = g_value_get_double (value);
else
return NULL;
if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_INT16))
{
if (G_MININT16 <= l && l <= G_MAXINT16)
variant = g_variant_new_int16 ((gint16) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_UINT16))
{
if (0 <= l && l <= G_MAXUINT16)
variant = g_variant_new_uint16 ((guint16) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_INT32))
{
if (G_MININT32 <= l && l <= G_MAXINT32)
variant = g_variant_new_int32 ((gint) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_UINT32))
{
if (0 <= l && l <= G_MAXUINT32)
variant = g_variant_new_uint32 ((guint) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_INT64))
{
if (G_MININT64 <= l && l <= G_MAXINT64)
variant = g_variant_new_int64 ((gint64) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_UINT64))
{
if (0 <= l && l <= G_MAXUINT64)
variant = g_variant_new_uint64 ((guint64) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_HANDLE))
{
if (0 <= l && l <= G_MAXUINT32)
variant = g_variant_new_handle ((guint) l);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_DOUBLE))
variant = g_variant_new_double ((double) l);
return variant;
}
static GVariant *
g_settings_set_mapping_unsigned_numeric (const GValue *value,
const GVariantType *expected_type)
{
GVariant *variant = NULL;
gulong u;
if (G_VALUE_HOLDS_UINT (value))
u = g_value_get_uint (value);
else if (G_VALUE_HOLDS_UINT64 (value))
u = g_value_get_uint64 (value);
else
return NULL;
if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_INT16))
{
if (u <= G_MAXINT16)
variant = g_variant_new_int16 ((gint16) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_UINT16))
{
if (u <= G_MAXUINT16)
variant = g_variant_new_uint16 ((guint16) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_INT32))
{
if (u <= G_MAXINT32)
variant = g_variant_new_int32 ((gint) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_UINT32))
{
if (u <= G_MAXUINT32)
variant = g_variant_new_uint32 ((guint) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_INT64))
{
if (u <= G_MAXINT64)
variant = g_variant_new_int64 ((gint64) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_UINT64))
{
if (u <= G_MAXUINT64)
variant = g_variant_new_uint64 ((guint64) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_HANDLE))
{
if (u <= G_MAXUINT32)
variant = g_variant_new_handle ((guint) u);
}
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_DOUBLE))
variant = g_variant_new_double ((double) u);
return variant;
}
static gboolean
g_settings_get_mapping_numeric (GValue *value,
GVariant *variant)
{
const GVariantType *type;
glong l;
type = g_variant_get_type (variant);
if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_INT16))
l = g_variant_get_int16 (variant);
else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_INT32))
l = g_variant_get_int32 (variant);
else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_INT64))
l = g_variant_get_int64 (variant);
else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DOUBLE))
l = g_variant_get_double (variant);
else
return FALSE;
if (G_VALUE_HOLDS_INT (value))
{
g_value_set_int (value, l);
return (G_MININT32 <= l && l <= G_MAXINT32);
}
else if (G_VALUE_HOLDS_UINT (value))
{
g_value_set_uint (value, l);
return (0 <= l && l <= G_MAXUINT32);
}
else if (G_VALUE_HOLDS_INT64 (value))
{
g_value_set_int64 (value, l);
return (G_MININT64 <= l && l <= G_MAXINT64);
}
else if (G_VALUE_HOLDS_UINT64 (value))
{
g_value_set_uint64 (value, l);
return (0 <= l && l <= G_MAXUINT64);
}
else if (G_VALUE_HOLDS_DOUBLE (value))
{
g_value_set_double (value, l);
return TRUE;
}
return FALSE;
}
static gboolean
g_settings_get_mapping_unsigned_numeric (GValue *value,
GVariant *variant)
{
const GVariantType *type;
gulong u;
type = g_variant_get_type (variant);
if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_UINT16))
u = g_variant_get_uint16 (variant);
else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_UINT32))
u = g_variant_get_uint32 (variant);
else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_UINT64))
u = g_variant_get_uint64 (variant);
else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_HANDLE))
u = g_variant_get_handle (variant);
else
return FALSE;
if (G_VALUE_HOLDS_INT (value))
{
g_value_set_int (value, u);
return (u <= G_MAXINT32);
}
else if (G_VALUE_HOLDS_UINT (value))
{
g_value_set_uint (value, u);
return (u <= G_MAXUINT32);
}
else if (G_VALUE_HOLDS_INT64 (value))
{
g_value_set_int64 (value, u);
return (u <= G_MAXINT64);
}
else if (G_VALUE_HOLDS_UINT64 (value))
{
g_value_set_uint64 (value, u);
return (u <= G_MAXUINT64);
}
else if (G_VALUE_HOLDS_DOUBLE (value))
{
g_value_set_double (value, u);
return TRUE;
}
return FALSE;
}
static GVariant *
g_settings_set_mapping (const GValue *value,
const GVariantType *expected_type,
gpointer user_data)
{
gchar *type_string;
if (G_VALUE_HOLDS_BOOLEAN (value))
{
if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_BOOLEAN))
return g_variant_new_boolean (g_value_get_boolean (value));
}
else if (G_VALUE_HOLDS_CHAR (value) ||
G_VALUE_HOLDS_UCHAR (value))
{
if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_BYTE))
{
if (G_VALUE_HOLDS_CHAR (value))
return g_variant_new_byte (g_value_get_char (value));
else
return g_variant_new_byte (g_value_get_uchar (value));
}
}
else if (G_VALUE_HOLDS_INT (value) ||
G_VALUE_HOLDS_INT64 (value) ||
G_VALUE_HOLDS_DOUBLE (value))
return g_settings_set_mapping_numeric (value, expected_type);
else if (G_VALUE_HOLDS_UINT (value) ||
G_VALUE_HOLDS_UINT64 (value))
return g_settings_set_mapping_unsigned_numeric (value, expected_type);
else if (G_VALUE_HOLDS_STRING (value))
{
if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_STRING))
return g_variant_new_string (g_value_get_string (value));
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
return g_variant_new_object_path (g_value_get_string (value));
else if (g_variant_type_is_subtype_of (expected_type, G_VARIANT_TYPE_SIGNATURE))
return g_variant_new_signature (g_value_get_string (value));
}
type_string = g_variant_type_dup_string (expected_type);
g_critical ("No GSettings bind handler for type \"%s\".", type_string);
g_free (type_string);
return NULL;
}
static gboolean
g_settings_get_mapping (GValue *value,
GVariant *variant,
gpointer user_data)
{
if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
{
if (!G_VALUE_HOLDS_BOOLEAN (value))
return FALSE;
g_value_set_boolean (value, g_variant_get_boolean (variant));
return TRUE;
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
{
if (G_VALUE_HOLDS_UCHAR (value))
g_value_set_uchar (value, g_variant_get_byte (variant));
else if (G_VALUE_HOLDS_CHAR (value))
g_value_set_char (value, (gchar) g_variant_get_byte (variant));
else
return FALSE;
return TRUE;
}
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
return g_settings_get_mapping_numeric (value, variant);
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
return g_settings_get_mapping_unsigned_numeric (value, variant);
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
{
g_value_set_string (value, g_variant_get_string (variant, NULL));
return TRUE;
}
g_critical ("No GSettings bind handler for type \"%s\".", g_variant_get_type_string (variant));
return FALSE;
}
/**
* g_settings_bind:
* @settings: a #GSettings object
@ -1581,18 +1302,17 @@ g_settings_bind_with_mapping (GSettings *settings,
{
GSettingsBinding *binding;
GObjectClass *objectclass;
gboolean bind_sensitive;
gchar *detailed_signal;
GQuark binding_quark;
gboolean insensitive;
objectclass = G_OBJECT_GET_CLASS (object);
binding = g_slice_new (GSettingsBinding);
binding = g_slice_new0 (GSettingsBinding);
binding->settings = g_object_ref (settings);
binding->object = object;
binding->key = g_intern_string (key);
binding->property = g_object_class_find_property (objectclass, property);
binding->running = FALSE;
binding->user_data = user_data;
binding->destroy = destroy;
binding->get_mapping = get_mapping ? get_mapping : g_settings_get_mapping;
@ -1624,63 +1344,32 @@ g_settings_bind_with_mapping (GSettings *settings,
return;
}
if ((get_mapping == NULL && (flags & G_SETTINGS_BIND_GET)) ||
(set_mapping == NULL && (flags & G_SETTINGS_BIND_SET)))
if (((get_mapping == NULL && (flags & G_SETTINGS_BIND_GET)) ||
(set_mapping == NULL && (flags & G_SETTINGS_BIND_SET))) &&
!g_settings_mapping_is_compatible (binding->property->value_type,
binding->type))
{
gboolean ok = FALSE;
if (binding->property->value_type == G_TYPE_BOOLEAN)
ok = g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_BOOLEAN);
else if (binding->property->value_type == G_TYPE_CHAR ||
binding->property->value_type == G_TYPE_UCHAR)
ok = g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_BYTE);
else if (binding->property->value_type == G_TYPE_INT ||
binding->property->value_type == G_TYPE_UINT ||
binding->property->value_type == G_TYPE_INT64 ||
binding->property->value_type == G_TYPE_UINT64 ||
binding->property->value_type == G_TYPE_DOUBLE)
ok = (g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_INT16) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_UINT16) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_INT32) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_UINT32) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_INT64) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_UINT64) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_HANDLE) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_DOUBLE));
else if (binding->property->value_type == G_TYPE_STRING)
ok = (g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_STRING) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_OBJECT_PATH) ||
g_variant_type_is_subtype_of (binding->type, G_VARIANT_TYPE_SIGNATURE));
if (!ok)
{
g_critical ("g_settings_bind: property '%s' on class '%s' has type"
"'%s' which is not compatible with type '%s' of key '%s'"
"on schema '%s'", property, G_OBJECT_TYPE_NAME (object),
g_type_name (binding->property->value_type),
g_variant_type_dup_string (binding->type), key,
settings->priv->schema_name);
return;
}
g_critical ("g_settings_bind: property '%s' on class '%s' has type"
"'%s' which is not compatible with type '%s' of key '%s'"
"on schema '%s'", property, G_OBJECT_TYPE_NAME (object),
g_type_name (binding->property->value_type),
g_variant_type_dup_string (binding->type), key,
settings->priv->schema_name);
return;
}
if (~flags & G_SETTINGS_BIND_NO_SENSITIVITY)
if ((flags & G_SETTINGS_BIND_SET) &&
(~flags & G_SETTINGS_BIND_NO_SENSITIVITY))
{
GParamSpec *sensitive;
sensitive = g_object_class_find_property (objectclass, "sensitive");
if (sensitive && sensitive->value_type == G_TYPE_BOOLEAN)
{
insensitive = !g_settings_is_writable (settings, key);
g_object_set (object, "sensitive", !insensitive, NULL);
}
else
insensitive = FALSE;
bind_sensitive = sensitive && sensitive->value_type == G_TYPE_BOOLEAN;
}
else
insensitive = FALSE;
bind_sensitive = FALSE;
if (!insensitive && (flags & G_SETTINGS_BIND_SET))
if (flags & G_SETTINGS_BIND_SET)
{
detailed_signal = g_strdup_printf ("notify::%s", property);
binding->property_handler_id =
@ -1697,14 +1386,29 @@ g_settings_bind_with_mapping (GSettings *settings,
if (flags & G_SETTINGS_BIND_GET)
{
detailed_signal = g_strdup_printf ("changed::%s", key);
binding->key_handler_id =
if (~flags & G_SETTINGS_BIND_GET_NO_CHANGES)
{
detailed_signal = g_strdup_printf ("changed::%s", key);
binding->key_handler_id =
g_signal_connect (settings, detailed_signal,
G_CALLBACK (g_settings_binding_key_changed),
binding);
g_free (detailed_signal);
}
g_settings_binding_key_changed (settings, binding->key, binding);
}
if (bind_sensitive)
{
detailed_signal = g_strdup_printf ("writable-changed::%s", key);
binding->writable_handler_id =
g_signal_connect (settings, detailed_signal,
G_CALLBACK (g_settings_binding_key_changed),
G_CALLBACK (g_settings_binding_writable_changed),
binding);
g_free (detailed_signal);
g_settings_binding_key_changed (settings, binding->key, binding);
g_settings_binding_writable_changed (settings, binding->key, binding);
}
binding_quark = g_settings_binding_quark (property);

View File

@ -177,7 +177,8 @@ typedef enum
G_SETTINGS_BIND_DEFAULT,
G_SETTINGS_BIND_GET = (1<<0),
G_SETTINGS_BIND_SET = (1<<1),
G_SETTINGS_BIND_NO_SENSITIVITY = (1<<2)
G_SETTINGS_BIND_NO_SENSITIVITY = (1<<2),
G_SETTINGS_BIND_GET_NO_CHANGES = (1<<3)
} GSettingsBindFlags;
void g_settings_bind (GSettings *settings,