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 e_bind_properties_transfer (GObject *src_object, GParamSpec *src_pspec, GObject *dst_object, GParamSpec *dst_pspec, GlideBindingTransform transform, gpointer user_data) { const gchar *src_name; const gchar *dst_name; gboolean result; GValue src_value = { 0, }; GValue dst_value = { 0, }; src_name = g_param_spec_get_name (src_pspec); dst_name = g_param_spec_get_name (dst_pspec); g_value_init (&src_value, G_PARAM_SPEC_VALUE_TYPE (src_pspec)); g_object_get_property (src_object, src_name, &src_value); g_value_init (&dst_value, G_PARAM_SPEC_VALUE_TYPE (dst_pspec)); result = (*transform) (&src_value, &dst_value, user_data); g_value_unset (&src_value); g_return_if_fail (result); g_param_value_validate (dst_pspec, &dst_value); g_object_set_property (dst_object, dst_name, &dst_value); g_value_unset (&dst_value); }
/* --- functions --- */ void _bst_skin_config_init (void) { BstSkinConfig *skin_config; GValue *value; SfiRec *rec; g_return_if_fail (global_skin_config == NULL); /* global config record description */ pspec_skin_config = sfi_pspec_rec ("beast-skin-config-v1", NULL, NULL, bst_skin_config_fields, SFI_PARAM_STANDARD); g_param_spec_ref (pspec_skin_config); g_param_spec_sink (pspec_skin_config); /* create empty config record */ rec = sfi_rec_new (); value = sfi_value_rec (rec); /* fill out missing values with defaults */ g_param_value_validate (pspec_skin_config, value); /* install global config */ skin_config = bst_skin_config_from_rec (rec); global_skin_config = skin_config; /* cleanup */ sfi_value_free (value); sfi_rec_unref (rec); }
static VALUE value_validate_body(struct validate_arg* arg) { VALUE ret; gboolean b; rbgobj_rvalue_to_gvalue(arg->obj, arg->value); b = g_param_value_validate(arg->pspec, arg->value); ret = rbgobj_gvalue_to_rvalue(arg->value); return rb_ary_new3(2, CBOOL2RVAL(b), ret); }
static void test_param_spec_char (void) { GParamSpec *pspec; GValue value = { 0, }; gboolean modified; pspec = g_param_spec_char ("char", "nick", "blurb", 20, 40, 30, G_PARAM_READWRITE); //g_param_spec_ref_force_floating(pspec); //g_assert(g_param_spec_is_floating(pspec)); g_param_spec_ref_sink(pspec); g_assert (strcmp (g_param_spec_get_name (pspec), "char") == 0); g_assert (strcmp (g_param_spec_get_nick (pspec), "nick") == 0); g_assert (strcmp (g_param_spec_get_blurb (pspec), "blurb") == 0); g_value_init (&value, G_TYPE_CHAR); g_value_set_char (&value, 30); g_assert (g_param_value_defaults (pspec, &value)); g_value_set_char (&value, 0); modified = g_param_value_validate (pspec, &value); g_assert (modified && g_value_get_char (&value) == 20); g_value_set_char (&value, 20); modified = g_param_value_validate (pspec, &value); g_assert (!modified && g_value_get_char (&value) == 20); g_value_set_char (&value, 40); modified = g_param_value_validate (pspec, &value); g_assert (!modified && g_value_get_char (&value) == 40); g_value_set_char (&value, 60); modified = g_param_value_validate (pspec, &value); g_assert (modified && g_value_get_char (&value) == 40); g_param_spec_unref (pspec); }
static void test_param_spec_gtype (void) { GParamSpec *pspec; GValue value = { 0, }; gboolean modified; pspec = g_param_spec_gtype ("gtype", "nick", "blurb", G_TYPE_PARAM, G_PARAM_READWRITE); g_value_init (&value, G_TYPE_GTYPE); g_value_set_gtype (&value, G_TYPE_PARAM); g_assert (g_param_value_defaults (pspec, &value)); g_value_set_gtype (&value, G_TYPE_INT); modified = g_param_value_validate (pspec, &value); g_assert (modified && g_value_get_gtype (&value) == G_TYPE_PARAM); g_value_set_gtype (&value, G_TYPE_PARAM_INT); modified = g_param_value_validate (pspec, &value); g_assert (!modified && g_value_get_gtype (&value) == G_TYPE_PARAM_INT); }
static inline void tidy_stylable_set_property_internal (TidyStylable *stylable, GParamSpec *pspec, const GValue *value, GObjectNotifyQueue *nqueue) { GValue tmp_value = { 0, }; g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (!g_value_transform (value, &tmp_value)) g_warning ("unable to set property `%s' of type `%s' from value of type `%s'", pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), G_VALUE_TYPE_NAME (value)); else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION)) { gchar *contents = g_strdup_value_contents (value); g_warning ("value \"%s\" of type `%s' is invalid or out of range for property `%s' of type `%s'", contents, G_VALUE_TYPE_NAME (value), pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec))); g_free (contents); } else { TidyStyle *style = tidy_stylable_get_style (stylable); gchar *real_name; real_name = g_strconcat (g_param_spec_get_qdata (pspec, quark_real_owner), "::", pspec->name, NULL); if (!tidy_style_has_property (style, real_name)) tidy_style_add_property (style, real_name, G_PARAM_SPEC_VALUE_TYPE (pspec)); tidy_style_set_property (style, real_name, &tmp_value); g_object_notify_queue_add (G_OBJECT (stylable), nqueue, pspec); g_free (real_name); } g_value_unset (&tmp_value); }
static gboolean param_value_array_validate (GParamSpec *pspec, GValue *value) { GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec); GValueArray *value_array = value->data[0].v_pointer; guint changed = 0; if (!value->data[0].v_pointer && aspec->fixed_n_elements) value->data[0].v_pointer = g_value_array_new (aspec->fixed_n_elements); if (value->data[0].v_pointer) { /* ensure array size validity */ changed += value_array_ensure_size (value_array, aspec->fixed_n_elements); /* ensure array values validity against a present element spec */ if (aspec->element_spec) { GParamSpec *element_spec = aspec->element_spec; guint i; for (i = 0; i < value_array->n_values; i++) { GValue *element = value_array->values + i; /* need to fixup value type, or ensure that the array value is initialized at all */ if (!g_value_type_compatible (G_VALUE_TYPE (element), G_PARAM_SPEC_VALUE_TYPE (element_spec))) { if (G_VALUE_TYPE (element) != 0) g_value_unset (element); g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec)); g_param_value_set_default (element_spec, element); changed++; } /* validate array value against element_spec */ changed += g_param_value_validate (element_spec, element); } } } return changed; }
static gboolean set_prop(GeglNode *t, const gchar *port, GParamSpec *paramspec, GValue *value) { GType target_type = G_PARAM_SPEC_VALUE_TYPE(paramspec); GValue dest_value = {0,}; gboolean success; g_value_init(&dest_value, target_type); success = g_param_value_convert(paramspec, value, &dest_value, FALSE); if (success) { gegl_node_set_property(t, port, &dest_value); return TRUE; } if (gvalue_from_string(value, target_type, &dest_value)) { g_param_value_validate(paramspec, &dest_value); gegl_node_set_property(t, port, &dest_value); return TRUE; } return FALSE; }
static void on_target_notify (GObject *gobject, GParamSpec *pspec, GBinding *binding) { const gchar *p_name; GValue from_value = G_VALUE_INIT; GValue to_value = G_VALUE_INIT; gboolean res; if (binding->is_frozen) return; p_name = g_intern_string (pspec->name); if (p_name != binding->target_property) return; g_value_init (&from_value, G_PARAM_SPEC_VALUE_TYPE (binding->target_pspec)); g_value_init (&to_value, G_PARAM_SPEC_VALUE_TYPE (binding->source_pspec)); g_object_get_property (binding->target, binding->target_pspec->name, &from_value); res = binding->transform_t2s (binding, &from_value, &to_value, binding->transform_data); if (res) { binding->is_frozen = TRUE; g_param_value_validate (binding->source_pspec, &to_value); g_object_set_property (binding->source, binding->source_pspec->name, &to_value); binding->is_frozen = FALSE; } g_value_unset (&from_value); g_value_unset (&to_value); }
/* --- functions --- */ void _bst_msg_absorb_config_init (void) { g_return_if_fail (global_msg_absorb_config == NULL); /* global config record description */ pspec_msg_absorb_config = sfi_pspec_seq ("beast-msg-absorb-config-v1", NULL, NULL, sfi_pspec_rec ("mstring", NULL, NULL, bst_msg_absorb_string_fields, SFI_PARAM_STANDARD), SFI_PARAM_STANDARD); g_param_spec_ref (pspec_msg_absorb_config); g_param_spec_sink (pspec_msg_absorb_config); /* create empty config record */ SfiSeq *seq = sfi_seq_new (); GValue *value = sfi_value_seq (seq); /* fill out missing values with defaults */ g_param_value_validate (pspec_msg_absorb_config, value); /* install global config */ BstMsgAbsorbStringSeq *mconfig = bst_msg_absorb_string_seq_from_seq (seq); global_msg_absorb_config = mconfig; /* cleanup */ sfi_value_free (value); sfi_seq_unref (seq); }
P_INVOKE void bp_set_volume (BansheePlayer *player, gdouble volume) { GParamSpec *volume_spec; GValue value = { 0, }; GstElement *v; g_return_if_fail (IS_BANSHEE_PLAYER (player)); // playbin will either control the volume property of the audiosinks real // sink element case the audiosink doesn't have one it will control a // volume element it created itself. // Unfortunately if playbin creates a volume element it will be before our // audiosink and thus before our equalizer and replaygain, which is // undesirable because of latency issues (Most likely they insert too many // queues). So only use the playbin volume support when we know our sink // supports volume control if (player->audiosink_has_volume) { v = player->playbin; } else { v = player->volume; } g_return_if_fail (GST_IS_ELEMENT(v)); player->current_volume = CLAMP (volume, 0.0, 1.0); volume_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (v), "volume"); g_value_init (&value, G_TYPE_DOUBLE); g_value_set_double (&value, player->current_volume); g_param_value_validate (volume_spec, &value); g_object_set_property (G_OBJECT (v), "volume", &value); g_value_unset (&value); _bp_rgvolume_print_volume(player); }
static void gimp_operation_tool_color_picked (GimpImageMapTool *im_tool, gpointer identifier, gdouble x, gdouble y, const Babl *sample_format, const GimpRGB *color) { GimpOperationTool *tool = GIMP_OPERATION_TOOL (im_tool); gchar **pspecs; pspecs = g_strsplit (identifier, ":", 2); if (pspecs[1]) { GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool); GimpDrawable *drawable = GIMP_TOOL (im_tool)->drawable; GObjectClass *object_class = G_OBJECT_GET_CLASS (im_tool->config); GParamSpec *pspec_x; GParamSpec *pspec_y; gint width = 1; gint height = 1; if (drawable) { gint off_x, off_y; gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); x -= off_x; y -= off_y; switch (options->region) { case GIMP_IMAGE_MAP_REGION_SELECTION: if (gimp_item_mask_intersect (GIMP_ITEM (drawable), &off_x, &off_y, &width, &height)) { x -= off_x; y -= off_y; } break; case GIMP_IMAGE_MAP_REGION_DRAWABLE: width = gimp_item_get_width (GIMP_ITEM (drawable)); height = gimp_item_get_height (GIMP_ITEM (drawable)); break; } } pspec_x = g_object_class_find_property (object_class, pspecs[0]); pspec_y = g_object_class_find_property (object_class, pspecs[1]); if (pspec_x && pspec_y && G_PARAM_SPEC_TYPE (pspec_x) == G_PARAM_SPEC_TYPE (pspec_y)) { GValue value_x = G_VALUE_INIT; GValue value_y = G_VALUE_INIT; g_value_init (&value_x, G_PARAM_SPEC_VALUE_TYPE (pspec_x)); g_value_init (&value_y, G_PARAM_SPEC_VALUE_TYPE (pspec_y)); #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v) if (HAS_KEY (pspec_x, "unit", "relative-coordinate") && HAS_KEY (pspec_y, "unit", "relative-coordinate")) { x /= (gdouble) width; y /= (gdouble) height; } if (G_IS_PARAM_SPEC_INT (pspec_x)) { g_value_set_int (&value_x, x); g_value_set_int (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (im_tool->config, pspecs[0], g_value_get_int (&value_x), pspecs[1], g_value_get_int (&value_y), NULL); } else if (G_IS_PARAM_SPEC_DOUBLE (pspec_x)) { g_value_set_double (&value_x, x); g_value_set_double (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (im_tool->config, pspecs[0], g_value_get_double (&value_x), pspecs[1], g_value_get_double (&value_y), NULL); } else { g_warning ("%s: unhandled param spec of type %s", G_STRFUNC, G_PARAM_SPEC_TYPE_NAME (pspec_x)); } g_value_unset (&value_x); g_value_unset (&value_y); } } else { g_object_set (im_tool->config, pspecs[0], color, NULL); } g_strfreev (pspecs); }
static gboolean gimp_procedure_validate_args (GimpProcedure *procedure, GParamSpec **param_specs, gint n_param_specs, GValueArray *args, gboolean return_vals, GError **error) { gint i; for (i = 0; i < MIN (args->n_values, n_param_specs); i++) { GValue *arg = &args->values[i]; GParamSpec *pspec = param_specs[i]; GType arg_type = G_VALUE_TYPE (arg); GType spec_type = G_PARAM_SPEC_VALUE_TYPE (pspec); if (arg_type != spec_type) { if (return_vals) { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_RETURN_VALUE, _("Procedure '%s' returned a wrong value type " "for return value '%s' (#%d). " "Expected %s, got %s."), gimp_object_get_name (procedure), g_param_spec_get_name (pspec), i + 1, g_type_name (spec_type), g_type_name (arg_type)); } else { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_ARGUMENT, _("Procedure '%s' has been called with a " "wrong value type for argument '%s' (#%d). " "Expected %s, got %s."), gimp_object_get_name (procedure), g_param_spec_get_name (pspec), i + 1, g_type_name (spec_type), g_type_name (arg_type)); } return FALSE; } else if (! (pspec->flags & GIMP_PARAM_NO_VALIDATE)) { GValue string_value = { 0, }; g_value_init (&string_value, G_TYPE_STRING); if (g_value_type_transformable (arg_type, G_TYPE_STRING)) g_value_transform (arg, &string_value); else g_value_set_static_string (&string_value, "<not transformable to string>"); if (g_param_value_validate (pspec, arg)) { if (GIMP_IS_PARAM_SPEC_DRAWABLE_ID (pspec) && g_value_get_int (arg) == -1) { if (return_vals) { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_RETURN_VALUE, _("Procedure '%s' returned an " "invalid ID for argument '%s'. " "Most likely a plug-in is trying " "to work on a layer that doesn't " "exist any longer."), gimp_object_get_name (procedure), g_param_spec_get_name (pspec)); } else { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_ARGUMENT, _("Procedure '%s' has been called with an " "invalid ID for argument '%s'. " "Most likely a plug-in is trying " "to work on a layer that doesn't " "exist any longer."), gimp_object_get_name (procedure), g_param_spec_get_name (pspec)); } } else if (GIMP_IS_PARAM_SPEC_IMAGE_ID (pspec) && g_value_get_int (arg) == -1) { if (return_vals) { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_RETURN_VALUE, _("Procedure '%s' returned an " "invalid ID for argument '%s'. " "Most likely a plug-in is trying " "to work on an image that doesn't " "exist any longer."), gimp_object_get_name (procedure), g_param_spec_get_name (pspec)); } else { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_ARGUMENT, _("Procedure '%s' has been called with an " "invalid ID for argument '%s'. " "Most likely a plug-in is trying " "to work on an image that doesn't " "exist any longer."), gimp_object_get_name (procedure), g_param_spec_get_name (pspec)); } } else { const gchar *value = g_value_get_string (&string_value); if (value == NULL) value = "(null)"; if (return_vals) { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_RETURN_VALUE, _("Procedure '%s' returned " "'%s' as return value '%s' " "(#%d, type %s). " "This value is out of range."), gimp_object_get_name (procedure), value, g_param_spec_get_name (pspec), i + 1, g_type_name (spec_type)); } else { g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_ARGUMENT, _("Procedure '%s' has been called with " "value '%s' for argument '%s' " "(#%d, type %s). " "This value is out of range."), gimp_object_get_name (procedure), value, g_param_spec_get_name (pspec), i + 1, g_type_name (spec_type)); } } return FALSE; } g_value_unset (&string_value); } } return TRUE; }
static void gimp_operation_tool_color_picked (GimpFilterTool *filter_tool, gpointer identifier, gdouble x, gdouble y, const Babl *sample_format, const GimpRGB *color) { gchar **pspecs = g_strsplit (identifier, ":", 2); if (pspecs[1]) { GObjectClass *object_class = G_OBJECT_GET_CLASS (filter_tool->config); GParamSpec *pspec_x; GParamSpec *pspec_y; gint off_x, off_y; GeglRectangle area; gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area); x -= off_x + area.x; y -= off_y + area.y; pspec_x = g_object_class_find_property (object_class, pspecs[0]); pspec_y = g_object_class_find_property (object_class, pspecs[1]); if (pspec_x && pspec_y && G_PARAM_SPEC_TYPE (pspec_x) == G_PARAM_SPEC_TYPE (pspec_y)) { GValue value_x = G_VALUE_INIT; GValue value_y = G_VALUE_INIT; g_value_init (&value_x, G_PARAM_SPEC_VALUE_TYPE (pspec_x)); g_value_init (&value_y, G_PARAM_SPEC_VALUE_TYPE (pspec_y)); #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v) if (HAS_KEY (pspec_x, "unit", "relative-coordinate") && HAS_KEY (pspec_y, "unit", "relative-coordinate")) { x /= (gdouble) area.width; y /= (gdouble) area.height; } if (G_IS_PARAM_SPEC_INT (pspec_x)) { g_value_set_int (&value_x, x); g_value_set_int (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (filter_tool->config, pspecs[0], g_value_get_int (&value_x), pspecs[1], g_value_get_int (&value_y), NULL); } else if (G_IS_PARAM_SPEC_DOUBLE (pspec_x)) { g_value_set_double (&value_x, x); g_value_set_double (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (filter_tool->config, pspecs[0], g_value_get_double (&value_x), pspecs[1], g_value_get_double (&value_y), NULL); } else { g_warning ("%s: unhandled param spec of type %s", G_STRFUNC, G_PARAM_SPEC_TYPE_NAME (pspec_x)); } g_value_unset (&value_x); g_value_unset (&value_y); } } else { g_object_set (filter_tool->config, pspecs[0], color, NULL); } g_strfreev (pspecs); }
/** * nm_g_object_set_property: * @object: the target object * @property_name: the property name * @value: the #GValue to set * @error: (allow-none): optional error argument * * A reimplementation of g_object_set_property(), but instead * returning an error instead of logging a warning. All g_object_set*() * versions in glib require you to not pass invalid types or they will * log a g_warning() -- without reporting an error. We don't want that, * so we need to hack error checking around it. * * Returns: whether the value was successfully set. */ gboolean nm_g_object_set_property (GObject *object, const gchar *property_name, const GValue *value, GError **error) { GParamSpec *pspec; nm_auto_unset_gvalue GValue tmp_value = G_VALUE_INIT; GObjectClass *klass; g_return_val_if_fail (G_IS_OBJECT (object), FALSE); g_return_val_if_fail (property_name != NULL, FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE); g_return_val_if_fail (!error || !*error, FALSE); /* g_object_class_find_property() does g_param_spec_get_redirect_target(), * where we differ from a plain g_object_set_property(). */ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name); if (!pspec) { g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("object class '%s' has no property named '%s'"), G_OBJECT_TYPE_NAME (object), property_name); return FALSE; } if (!(pspec->flags & G_PARAM_WRITABLE)) { g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("property '%s' of object class '%s' is not writable"), pspec->name, G_OBJECT_TYPE_NAME (object)); return FALSE; } if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY)) { g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("construct property \"%s\" for object '%s' can't be set after construction"), pspec->name, G_OBJECT_TYPE_NAME (object)); return FALSE; } klass = g_type_class_peek (pspec->owner_type); if (klass == NULL) { g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("'%s::%s' is not a valid property name; '%s' is not a GObject subtype"), g_type_name (pspec->owner_type), pspec->name, g_type_name (pspec->owner_type)); return FALSE; } /* provide a copy to work from, convert (if necessary) and validate */ g_value_init (&tmp_value, pspec->value_type); if (!g_value_transform (value, &tmp_value)) { g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("unable to set property '%s' of type '%s' from value of type '%s'"), pspec->name, g_type_name (pspec->value_type), G_VALUE_TYPE_NAME (value)); return FALSE; } if ( g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION)) { gs_free char *contents = g_strdup_value_contents (value); g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("value \"%s\" of type '%s' is invalid or out of range for property '%s' of type '%s'"), contents, G_VALUE_TYPE_NAME (value), pspec->name, g_type_name (pspec->value_type)); return FALSE; } g_object_set_property (object, property_name, &tmp_value); return TRUE; }
static void terminal_profile_gsettings_notify_cb (GSettings *settings, gchar *key, gpointer user_data) { TerminalProfile *profile = TERMINAL_PROFILE (user_data); TerminalProfilePrivate *priv = profile->priv; TerminalProfileClass *klass; GVariant *settings_value; GParamSpec *pspec; GValue value = { 0, }; gboolean equal; gboolean force_set = FALSE; if (!key) return; _terminal_debug_print (TERMINAL_DEBUG_PROFILE, "GSettings notification for key %s [%s]\n", key, g_settings_is_writable (settings, key) ? "writable" : "LOCKED"); klass = TERMINAL_PROFILE_GET_CLASS (profile); pspec = g_hash_table_lookup (klass->gsettings_keys, key); if (!pspec) return; /* ignore unknown keys, for future extensibility */ priv->locked[pspec->param_id] = !g_settings_is_writable (settings, key); settings_value = g_settings_get_value (settings, key); if (!settings_value) return; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) { if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_BOOLEAN)) goto out; g_value_set_boolean (&value, g_variant_get_boolean (settings_value)); } else if (G_IS_PARAM_SPEC_STRING (pspec)) { if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_STRING)) goto out; g_value_set_string (&value, g_variant_get_string (settings_value, NULL)); } else if (G_IS_PARAM_SPEC_ENUM (pspec)) { if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_STRING)) goto out; g_value_set_enum (&value, g_settings_get_enum (settings, key)); } else if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_COLOR) { GdkColor color; if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_STRING)) goto out; if (!gdk_color_parse (g_variant_get_string (settings_value, NULL), &color)) goto out; g_value_set_boxed (&value, &color); } else if (G_PARAM_SPEC_VALUE_TYPE (pspec) == PANGO_TYPE_FONT_DESCRIPTION) { if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_STRING)) goto out; g_value_take_boxed (&value, pango_font_description_from_string (g_variant_get_string (settings_value, NULL))); } else if (G_IS_PARAM_SPEC_DOUBLE (pspec)) { if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_DOUBLE)) goto out; g_value_set_double (&value, g_variant_get_double (settings_value)); } else if (G_IS_PARAM_SPEC_INT (pspec)) { if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_INT16) && !g_variant_is_of_type (settings_value, G_VARIANT_TYPE_INT32) && !g_variant_is_of_type (settings_value, G_VARIANT_TYPE_INT64)) goto out; g_value_set_int (&value, g_settings_get_int(settings, key)); } else if (G_IS_PARAM_SPEC_VALUE_ARRAY (pspec) && G_PARAM_SPEC_VALUE_TYPE (G_PARAM_SPEC_VALUE_ARRAY (pspec)->element_spec) == GDK_TYPE_COLOR) { char **color_strings; GdkColor *colors; int n_colors, i; if (!g_variant_is_of_type (settings_value, G_VARIANT_TYPE_STRING)) goto out; color_strings = g_strsplit (g_variant_get_string (settings_value, NULL), ":", -1); if (!color_strings) goto out; n_colors = g_strv_length (color_strings); colors = g_new0 (GdkColor, n_colors); for (i = 0; i < n_colors; ++i) { if (!gdk_color_parse (color_strings[i], &colors[i])) continue; /* ignore errors */ } g_strfreev (color_strings); /* We continue even with a palette size != TERMINAL_PALETTE_SIZE, * so we can change the palette size in future versions without * causing too many issues. */ set_value_from_palette (&value, colors, n_colors); g_free (colors); } else { g_printerr ("Unhandled value type %s of pspec %s\n", g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), pspec->name); goto out; } if (g_param_value_validate (pspec, &value)) { _terminal_debug_print (TERMINAL_DEBUG_PROFILE, "Invalid value in GSettings for key %s was changed to comply with pspec %s\n", key, pspec->name); force_set = TRUE; } /* Only set the property if the value is different than our current value, * so we don't go into an infinite loop. */ equal = values_equal (pspec, &value, g_value_array_get_nth (priv->properties, pspec->param_id)); #ifdef MATE_ENABLE_DEBUG _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_PROFILE) { if (!equal) _terminal_debug_print (TERMINAL_DEBUG_PROFILE, "Setting property %s to a different value\n" " now: %s\n" " new: %s\n", pspec->name, g_strdup_value_contents (g_value_array_get_nth (priv->properties, pspec->param_id)), g_strdup_value_contents (&value)); } #endif if (!equal || force_set) { priv->gsettings_notification_pspec = pspec; g_object_set_property (G_OBJECT (profile), pspec->name, &value); priv->gsettings_notification_pspec = NULL; } out: /* FIXME: if we arrive here through goto in the error cases, * should we maybe reset the property to its default value? */ g_value_unset (&value); g_variant_unref (settings_value); }