static GObject* base_object_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { /* The constructor is the one place where a GParamSpecOverride is visible * to the outside world, so we do a bunch of checks here */ GValue value1 = { 0, }; GValue value2 = { 0, }; GParamSpec *pspec; g_assert (n_construct_properties == 1); pspec = construct_properties->pspec; /* Check we got the param spec we expected */ g_assert (G_IS_PARAM_SPEC_OVERRIDE (pspec)); g_assert (pspec->param_id == BASE_PROP1); g_assert (strcmp (g_param_spec_get_name (pspec), "prop1") == 0); g_assert (g_param_spec_get_redirect_target (pspec) == iface_spec1); /* Test redirection of the nick and blurb to the redirect target */ g_assert (strcmp (g_param_spec_get_nick (pspec), "Prop1") == 0); g_assert (strcmp (g_param_spec_get_blurb (pspec), "Property 1") == 0); /* Test forwarding of the various GParamSpec methods to the redirect target */ g_value_init (&value1, G_TYPE_INT); g_value_init (&value2, G_TYPE_INT); g_param_value_set_default (pspec, &value1); g_assert (g_value_get_int (&value1) == 42); g_value_reset (&value1); g_value_set_int (&value1, 0x10000); g_assert (g_param_value_validate (pspec, &value1)); g_assert (g_value_get_int (&value1) == 0xFFFF); g_assert (!g_param_value_validate (pspec, &value1)); g_value_reset (&value1); g_value_set_int (&value1, 1); g_value_set_int (&value2, 2); g_assert (g_param_values_cmp (pspec, &value1, &value2) < 0); g_assert (g_param_values_cmp (pspec, &value2, &value1) > 0); g_value_unset (&value1); g_value_unset (&value2); return base_parent_class->constructor (type, n_construct_properties, construct_properties); }
static void gimp_global_config_notify (GObject *global_config, GParamSpec *param_spec, GObject *edit_config) { GValue global_value = { 0, }; GValue edit_value = { 0, }; g_value_init (&global_value, param_spec->value_type); g_value_init (&edit_value, param_spec->value_type); g_object_get_property (global_config, param_spec->name, &global_value); g_object_get_property (edit_config, param_spec->name, &edit_value); if (g_param_values_cmp (param_spec, &global_value, &edit_value)) { g_signal_handlers_block_by_func (edit_config, gimp_edit_config_notify, global_config); g_object_set_property (edit_config, param_spec->name, &global_value); g_signal_handlers_unblock_by_func (edit_config, gimp_edit_config_notify, global_config); } g_value_unset (&global_value); g_value_unset (&edit_value); }
static gboolean gimp_config_iface_equal (GimpConfig *a, GimpConfig *b) { GObjectClass *klass; GParamSpec **property_specs; guint n_property_specs; guint i; gboolean equal = TRUE; klass = G_OBJECT_GET_CLASS (a); property_specs = g_object_class_list_properties (klass, &n_property_specs); for (i = 0; equal && i < n_property_specs; i++) { GParamSpec *prop_spec; GValue a_value = G_VALUE_INIT; GValue b_value = G_VALUE_INIT; prop_spec = property_specs[i]; if (! (prop_spec->flags & G_PARAM_READABLE)) continue; g_value_init (&a_value, prop_spec->value_type); g_value_init (&b_value, prop_spec->value_type); g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value); g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value); if (g_param_values_cmp (prop_spec, &a_value, &b_value)) { if ((prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) && G_IS_PARAM_SPEC_OBJECT (prop_spec) && g_type_interface_peek (g_type_class_peek (prop_spec->value_type), GIMP_TYPE_CONFIG)) { if (! gimp_config_is_equal_to (g_value_get_object (&a_value), g_value_get_object (&b_value))) { equal = FALSE; } } else { equal = FALSE; } } g_value_unset (&a_value); g_value_unset (&b_value); } g_free (property_specs); return equal; }
static void gimp_edit_config_notify (GObject *edit_config, GParamSpec *param_spec, GObject *global_config) { GValue edit_value = { 0, }; GValue global_value = { 0, }; g_value_init (&edit_value, param_spec->value_type); g_value_init (&global_value, param_spec->value_type); g_object_get_property (edit_config, param_spec->name, &edit_value); g_object_get_property (global_config, param_spec->name, &global_value); if (g_param_values_cmp (param_spec, &edit_value, &global_value)) { if (param_spec->flags & GIMP_CONFIG_PARAM_RESTART) { #ifdef GIMP_CONFIG_DEBUG g_print ("NOT Applying edit_config change of '%s' to global_config " "because it needs restart\n", param_spec->name); #endif } else { #ifdef GIMP_CONFIG_DEBUG g_print ("Applying edit_config change of '%s' to global_config\n", param_spec->name); #endif g_signal_handlers_block_by_func (global_config, gimp_global_config_notify, edit_config); g_object_set_property (global_config, param_spec->name, &edit_value); g_signal_handlers_unblock_by_func (global_config, gimp_global_config_notify, edit_config); } } g_value_unset (&edit_value); g_value_unset (&global_value); }
static int values_equal (GParamSpec *pspec, const GValue *va, const GValue *vb) { /* g_param_values_cmp isn't good enough for some types, since e.g. * it compares colours and font descriptions by pointer value, not * with the correct compare functions. Providing extra * PangoParamSpecFontDescription and GdkParamSpecColor wouldn't * have fixed this either, since it's unclear how to _order_ them. * Luckily we only need to check them for equality here. */ if (g_param_values_cmp (pspec, va, vb) == 0) return TRUE; if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_COLOR) return gdk_color_equal (g_value_get_boxed (va), g_value_get_boxed (vb)); if (G_PARAM_SPEC_VALUE_TYPE (pspec) == PANGO_TYPE_FONT_DESCRIPTION) return pango_font_description_equal (g_value_get_boxed (va), g_value_get_boxed (vb)); if (G_IS_PARAM_SPEC_VALUE_ARRAY (pspec) && G_PARAM_SPEC_VALUE_TYPE (G_PARAM_SPEC_VALUE_ARRAY (pspec)->element_spec) == GDK_TYPE_COLOR) { GValueArray *ara, *arb; guint i; ara = g_value_get_boxed (va); arb = g_value_get_boxed (vb); if (!ara || !arb || ara->n_values != arb->n_values) return FALSE; for (i = 0; i < ara->n_values; ++i) if (!gdk_color_equal (g_value_get_boxed (g_value_array_get_nth (ara, i)), g_value_get_boxed (g_value_array_get_nth (arb, i)))) return FALSE; return TRUE; } return FALSE; }
static gint param_value_array_values_cmp (GParamSpec *pspec, const GValue *value1, const GValue *value2) { GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec); GValueArray *value_array1 = value1->data[0].v_pointer; GValueArray *value_array2 = value2->data[0].v_pointer; if (!value_array1 || !value_array2) return value_array2 ? -1 : value_array1 != value_array2; if (value_array1->n_values != value_array2->n_values) return value_array1->n_values < value_array2->n_values ? -1 : 1; else if (!aspec->element_spec) { /* we need an element specification for comparisons, so there's not much * to compare here, try to at least provide stable lesser/greater result */ return value_array1->n_values < value_array2->n_values ? -1 : value_array1->n_values > value_array2->n_values; } else /* value_array1->n_values == value_array2->n_values */ { guint i; for (i = 0; i < value_array1->n_values; i++) { GValue *element1 = value_array1->values + i; GValue *element2 = value_array2->values + i; gint cmp; /* need corresponding element types, provide stable result otherwise */ if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2)) return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1; cmp = g_param_values_cmp (aspec->element_spec, element1, element2); if (cmp) return cmp; } return 0; } }
static void thunar_preferences_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { ThunarPreferences *preferences = THUNAR_PREFERENCES (object); GValue *dst; dst = preferences->values + prop_id; if (G_UNLIKELY (!G_IS_VALUE (dst))) { g_value_init (dst, pspec->value_type); g_param_value_set_default (pspec, dst); } if (g_param_values_cmp (pspec, value, dst) != 0) { g_value_copy (value, dst); thunar_preferences_queue_store (preferences); } }
static VALUE values_compare(VALUE self, VALUE a, VALUE b) { GParamSpec* pspec = rbgobj_get_param_spec(self); GType type = G_PARAM_SPEC_VALUE_TYPE(pspec); GValue v1 = {0,}; GValue v2 = {0,}; gint result; g_value_init(&v1, type); g_value_init(&v2, type); /* FIXME: use rb_ensure to ensure following g_value_unset() call*/ rbgobj_rvalue_to_gvalue(a, &v1); rbgobj_rvalue_to_gvalue(b, &v2); result = g_param_values_cmp(pspec, &v1, &v2); g_value_unset(&v1); g_value_unset(&v2); return INT2NUM(result); }