mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-03 22:52:09 +01:00
GSettings: add G_SETTINGS_BIND_INVERT_BOOLEAN flag
When binding a boolean setting to a boolean property, invert the values. This avoids the requirement for writing a pair of mapping functions for this extremely common case. Add a test. https://bugzilla.gnome.org/show_bug.cgi?id=625833
This commit is contained in:
parent
dd2bbc9533
commit
ca3b7b75bf
@ -2285,6 +2285,23 @@ g_settings_binding_property_changed (GObject *object,
|
|||||||
binding->running = FALSE;
|
binding->running = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
g_settings_bind_invert_boolean_get_mapping (GValue *value,
|
||||||
|
GVariant *variant,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_value_set_boolean (value, !g_variant_get_boolean (variant));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
g_settings_bind_invert_boolean_set_mapping (const GValue *value,
|
||||||
|
const GVariantType *expected_type,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
return g_variant_new_boolean (!g_value_get_boolean (value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_settings_bind:
|
* g_settings_bind:
|
||||||
* @settings: a #GSettings object
|
* @settings: a #GSettings object
|
||||||
@ -2323,8 +2340,20 @@ g_settings_bind (GSettings *settings,
|
|||||||
const gchar *property,
|
const gchar *property,
|
||||||
GSettingsBindFlags flags)
|
GSettingsBindFlags flags)
|
||||||
{
|
{
|
||||||
g_settings_bind_with_mapping (settings, key, object, property,
|
GSettingsBindGetMapping get_mapping = NULL;
|
||||||
flags, NULL, NULL, NULL, NULL);
|
GSettingsBindSetMapping set_mapping = NULL;
|
||||||
|
|
||||||
|
if (flags & G_SETTINGS_BIND_INVERT_BOOLEAN)
|
||||||
|
{
|
||||||
|
get_mapping = g_settings_bind_invert_boolean_get_mapping;
|
||||||
|
set_mapping = g_settings_bind_invert_boolean_set_mapping;
|
||||||
|
|
||||||
|
/* can't pass this flag to g_settings_bind_with_mapping() */
|
||||||
|
flags &= ~G_SETTINGS_BIND_INVERT_BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_settings_bind_with_mapping (settings, key, object, property, flags,
|
||||||
|
get_mapping, set_mapping, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2371,6 +2400,7 @@ g_settings_bind_with_mapping (GSettings *settings,
|
|||||||
GQuark binding_quark;
|
GQuark binding_quark;
|
||||||
|
|
||||||
g_return_if_fail (G_IS_SETTINGS (settings));
|
g_return_if_fail (G_IS_SETTINGS (settings));
|
||||||
|
g_return_if_fail (~flags & G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||||
|
|
||||||
objectclass = G_OBJECT_GET_CLASS (object);
|
objectclass = G_OBJECT_GET_CLASS (object);
|
||||||
|
|
||||||
@ -2408,10 +2438,39 @@ g_settings_bind_with_mapping (GSettings *settings,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((get_mapping == NULL && (flags & G_SETTINGS_BIND_GET)) ||
|
if (get_mapping == g_settings_bind_invert_boolean_get_mapping)
|
||||||
(set_mapping == NULL && (flags & G_SETTINGS_BIND_SET))) &&
|
{
|
||||||
!g_settings_mapping_is_compatible (binding->property->value_type,
|
/* g_settings_bind_invert_boolean_get_mapping() is a private
|
||||||
binding->info.type))
|
* function, so if we are here it means that g_settings_bind() was
|
||||||
|
* called with G_SETTINGS_BIND_INVERT_BOOLEAN.
|
||||||
|
*
|
||||||
|
* Ensure that both sides are boolean.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (binding->property->value_type != G_TYPE_BOOLEAN)
|
||||||
|
{
|
||||||
|
g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN "
|
||||||
|
"was specified, but property `%s' on type `%s' has "
|
||||||
|
"type `%s'", property, G_OBJECT_TYPE_NAME (object),
|
||||||
|
g_type_name ((binding->property->value_type)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_variant_type_equal (binding->info.type, G_VARIANT_TYPE_BOOLEAN))
|
||||||
|
{
|
||||||
|
g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN "
|
||||||
|
"was specified, but key `%s' on schema `%s' has "
|
||||||
|
"type `%s'", key, settings->priv->schema_name,
|
||||||
|
g_variant_type_dup_string (binding->info.type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else 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->info.type))
|
||||||
{
|
{
|
||||||
g_critical ("g_settings_bind: property '%s' on class '%s' has type "
|
g_critical ("g_settings_bind: property '%s' on class '%s' has type "
|
||||||
"'%s' which is not compatible with type '%s' of key '%s' "
|
"'%s' which is not compatible with type '%s' of key '%s' "
|
||||||
|
@ -207,6 +207,9 @@ typedef gboolean (*GSettingsGetMapping) (GVarian
|
|||||||
* @G_SETTINGS_BIND_NO_SENSITIVITY: Do not try to bind a "sensitivity" property to the writability of the setting
|
* @G_SETTINGS_BIND_NO_SENSITIVITY: Do not try to bind a "sensitivity" property to the writability of the setting
|
||||||
* @G_SETTINGS_BIND_GET_NO_CHANGES: When set in addition to #G_SETTINGS_BIND_GET, set the #GObject property
|
* @G_SETTINGS_BIND_GET_NO_CHANGES: When set in addition to #G_SETTINGS_BIND_GET, set the #GObject property
|
||||||
* value initially from the setting, but do not listen for changes of the setting
|
* value initially from the setting, but do not listen for changes of the setting
|
||||||
|
* @G_SETTINGS_BIND_INVERT_BOOLEAN: When passed to g_settings_bind(), uses a pair of mapping functions that invert
|
||||||
|
* the boolean value when mapping between the setting and the property. The setting and property must both
|
||||||
|
* be booleans. You can not pass this flag to g_settings_bind_with_mapping().
|
||||||
*
|
*
|
||||||
* Flags used when creating a binding. These flags determine in which
|
* Flags used when creating a binding. These flags determine in which
|
||||||
* direction the binding works. The default is to synchronize in both
|
* direction the binding works. The default is to synchronize in both
|
||||||
@ -218,7 +221,8 @@ typedef enum
|
|||||||
G_SETTINGS_BIND_GET = (1<<0),
|
G_SETTINGS_BIND_GET = (1<<0),
|
||||||
G_SETTINGS_BIND_SET = (1<<1),
|
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)
|
G_SETTINGS_BIND_GET_NO_CHANGES = (1<<3),
|
||||||
|
G_SETTINGS_BIND_INVERT_BOOLEAN = (1<<4)
|
||||||
} GSettingsBindFlags;
|
} GSettingsBindFlags;
|
||||||
|
|
||||||
void g_settings_bind (GSettings *settings,
|
void g_settings_bind (GSettings *settings,
|
||||||
|
@ -681,6 +681,7 @@ enum
|
|||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_BOOL,
|
PROP_BOOL,
|
||||||
|
PROP_ANTI_BOOL,
|
||||||
PROP_BYTE,
|
PROP_BYTE,
|
||||||
PROP_INT16,
|
PROP_INT16,
|
||||||
PROP_UINT16,
|
PROP_UINT16,
|
||||||
@ -701,6 +702,7 @@ typedef struct
|
|||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
gboolean bool_prop;
|
gboolean bool_prop;
|
||||||
|
gboolean anti_bool_prop;
|
||||||
gchar byte_prop;
|
gchar byte_prop;
|
||||||
gint int16_prop;
|
gint int16_prop;
|
||||||
guint16 uint16_prop;
|
guint16 uint16_prop;
|
||||||
@ -750,6 +752,9 @@ test_object_get_property (GObject *object,
|
|||||||
case PROP_BOOL:
|
case PROP_BOOL:
|
||||||
g_value_set_boolean (value, test_object->bool_prop);
|
g_value_set_boolean (value, test_object->bool_prop);
|
||||||
break;
|
break;
|
||||||
|
case PROP_ANTI_BOOL:
|
||||||
|
g_value_set_boolean (value, test_object->anti_bool_prop);
|
||||||
|
break;
|
||||||
case PROP_BYTE:
|
case PROP_BYTE:
|
||||||
g_value_set_char (value, test_object->byte_prop);
|
g_value_set_char (value, test_object->byte_prop);
|
||||||
break;
|
break;
|
||||||
@ -805,6 +810,9 @@ test_object_set_property (GObject *object,
|
|||||||
case PROP_BOOL:
|
case PROP_BOOL:
|
||||||
test_object->bool_prop = g_value_get_boolean (value);
|
test_object->bool_prop = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_ANTI_BOOL:
|
||||||
|
test_object->anti_bool_prop = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
case PROP_BYTE:
|
case PROP_BYTE:
|
||||||
test_object->byte_prop = g_value_get_char (value);
|
test_object->byte_prop = g_value_get_char (value);
|
||||||
break;
|
break;
|
||||||
@ -883,6 +891,8 @@ test_object_class_init (TestObjectClass *class)
|
|||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_BOOL,
|
g_object_class_install_property (gobject_class, PROP_BOOL,
|
||||||
g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
|
g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ANTI_BOOL,
|
||||||
|
g_param_spec_boolean ("anti-bool", "", "", FALSE, G_PARAM_READWRITE));
|
||||||
g_object_class_install_property (gobject_class, PROP_BYTE,
|
g_object_class_install_property (gobject_class, PROP_BYTE,
|
||||||
g_param_spec_char ("byte", "", "", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE));
|
g_param_spec_char ("byte", "", "", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE));
|
||||||
g_object_class_install_property (gobject_class, PROP_INT16,
|
g_object_class_install_property (gobject_class, PROP_INT16,
|
||||||
@ -942,7 +952,6 @@ test_simple_binding (void)
|
|||||||
obj = test_object_new ();
|
obj = test_object_new ();
|
||||||
|
|
||||||
g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
|
g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
|
||||||
|
|
||||||
g_object_set (obj, "bool", TRUE, NULL);
|
g_object_set (obj, "bool", TRUE, NULL);
|
||||||
g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
|
g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
|
||||||
|
|
||||||
@ -951,6 +960,16 @@ test_simple_binding (void)
|
|||||||
g_object_get (obj, "bool", &b, NULL);
|
g_object_get (obj, "bool", &b, NULL);
|
||||||
g_assert_cmpint (b, ==, FALSE);
|
g_assert_cmpint (b, ==, FALSE);
|
||||||
|
|
||||||
|
g_settings_bind (settings, "anti-bool", obj, "anti-bool",
|
||||||
|
G_SETTINGS_BIND_INVERT_BOOLEAN);
|
||||||
|
g_object_set (obj, "anti-bool", FALSE, NULL);
|
||||||
|
g_assert_cmpint (g_settings_get_boolean (settings, "anti-bool"), ==, TRUE);
|
||||||
|
|
||||||
|
g_settings_set_boolean (settings, "anti-bool", FALSE);
|
||||||
|
b = FALSE;
|
||||||
|
g_object_get (obj, "anti-bool", &b, NULL);
|
||||||
|
g_assert_cmpint (b, ==, TRUE);
|
||||||
|
|
||||||
g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
|
g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
|
||||||
|
|
||||||
g_object_set (obj, "byte", 123, NULL);
|
g_object_set (obj, "byte", 123, NULL);
|
||||||
|
@ -81,6 +81,9 @@
|
|||||||
<key name="bool" type="b">
|
<key name="bool" type="b">
|
||||||
<default>false</default>
|
<default>false</default>
|
||||||
</key>
|
</key>
|
||||||
|
<key name="anti-bool" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
</key>
|
||||||
<key name="byte" type="y">
|
<key name="byte" type="y">
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
</key>
|
</key>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user