1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
4 * Utility functions for GimpConfig.
5 * Copyright (C) 2001-2003 Sven Neumann <sven@gimp.org>
7 * This library is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <https://www.gnu.org/licenses/>.
26 #include "libgimpbase/gimpbase.h"
28 #include "gimpconfigtypes.h"
30 #include "gimpconfigwriter.h"
31 #include "gimpconfig-iface.h"
32 #include "gimpconfig-params.h"
33 #include "gimpconfig-utils.h"
37 * SECTION: gimpconfig-utils
38 * @title: GimpConfig-utils
39 * @short_description: Miscellaneous utility functions for libgimpconfig.
41 * Miscellaneous utility functions for libgimpconfig.
46 gimp_config_diff_property (GObject
*a
,
48 GParamSpec
*prop_spec
)
50 GValue a_value
= G_VALUE_INIT
;
51 GValue b_value
= G_VALUE_INIT
;
52 gboolean retval
= FALSE
;
54 g_value_init (&a_value
, prop_spec
->value_type
);
55 g_value_init (&b_value
, prop_spec
->value_type
);
57 g_object_get_property (a
, prop_spec
->name
, &a_value
);
58 g_object_get_property (b
, prop_spec
->name
, &b_value
);
60 if (g_param_values_cmp (prop_spec
, &a_value
, &b_value
))
62 if ((prop_spec
->flags
& GIMP_CONFIG_PARAM_AGGREGATE
) &&
63 G_IS_PARAM_SPEC_OBJECT (prop_spec
) &&
64 g_type_interface_peek (g_type_class_peek (prop_spec
->value_type
),
67 if (! gimp_config_is_equal_to (g_value_get_object (&a_value
),
68 g_value_get_object (&b_value
)))
79 g_value_unset (&a_value
);
80 g_value_unset (&b_value
);
86 gimp_config_diff_same (GObject
*a
,
90 GParamSpec
**param_specs
;
95 param_specs
= g_object_class_list_properties (G_OBJECT_GET_CLASS (a
),
98 for (i
= 0; i
< n_param_specs
; i
++)
100 GParamSpec
*prop_spec
= param_specs
[i
];
102 if (! flags
|| ((prop_spec
->flags
& flags
) == flags
))
104 if (gimp_config_diff_property (a
, b
, prop_spec
))
105 list
= g_list_prepend (list
, prop_spec
);
109 g_free (param_specs
);
115 gimp_config_diff_other (GObject
*a
,
119 GParamSpec
**param_specs
;
124 param_specs
= g_object_class_list_properties (G_OBJECT_GET_CLASS (a
),
127 for (i
= 0; i
< n_param_specs
; i
++)
129 GParamSpec
*a_spec
= param_specs
[i
];
130 GParamSpec
*b_spec
= g_object_class_find_property (G_OBJECT_GET_CLASS (b
),
134 (a_spec
->value_type
== b_spec
->value_type
) &&
135 (! flags
|| (a_spec
->flags
& b_spec
->flags
& flags
) == flags
))
137 if (gimp_config_diff_property (a
, b
, b_spec
))
138 list
= g_list_prepend (list
, b_spec
);
142 g_free (param_specs
);
151 * @b: another #GObject object
152 * @flags: a mask of GParamFlags
154 * Compares all properties of @a and @b that have all @flags set. If
155 * @flags is 0, all properties are compared.
157 * If the two objects are not of the same type, only properties that
158 * exist in both object classes and are of the same value_type are
161 * Return value: a GList of differing GParamSpecs.
166 gimp_config_diff (GObject
*a
,
172 g_return_val_if_fail (G_IS_OBJECT (a
), NULL
);
173 g_return_val_if_fail (G_IS_OBJECT (b
), NULL
);
175 if (G_TYPE_FROM_INSTANCE (a
) == G_TYPE_FROM_INSTANCE (b
))
176 diff
= gimp_config_diff_same (a
, b
, flags
);
178 diff
= gimp_config_diff_other (a
, b
, flags
);
180 return g_list_reverse (diff
);
186 * @dest: another #GObject
187 * @flags: a mask of GParamFlags
189 * Compares all read- and write-able properties from @src and @dest
190 * that have all @flags set. Differing values are then copied from
191 * @src to @dest. If @flags is 0, all differing read/write properties.
193 * Properties marked as "construct-only" are not touched.
195 * If the two objects are not of the same type, only properties that
196 * exist in both object classes and are of the same value_type are
199 * Return value: %TRUE if @dest was modified, %FALSE otherwise
204 gimp_config_sync (GObject
*src
,
211 g_return_val_if_fail (G_IS_OBJECT (src
), FALSE
);
212 g_return_val_if_fail (G_IS_OBJECT (dest
), FALSE
);
214 /* we use the internal versions here for a number of reasons:
215 * - it saves a g_list_reverse()
216 * - it avoids duplicated parameter checks
218 if (G_TYPE_FROM_INSTANCE (src
) == G_TYPE_FROM_INSTANCE (dest
))
219 diff
= gimp_config_diff_same (src
, dest
, (flags
| G_PARAM_READWRITE
));
221 diff
= gimp_config_diff_other (src
, dest
, flags
);
226 g_object_freeze_notify (G_OBJECT (dest
));
228 for (list
= diff
; list
; list
= list
->next
)
230 GParamSpec
*prop_spec
= list
->data
;
232 if (! (prop_spec
->flags
& G_PARAM_CONSTRUCT_ONLY
))
234 GValue value
= G_VALUE_INIT
;
236 g_value_init (&value
, prop_spec
->value_type
);
238 g_object_get_property (src
, prop_spec
->name
, &value
);
239 g_object_set_property (dest
, prop_spec
->name
, &value
);
241 g_value_unset (&value
);
245 g_object_thaw_notify (G_OBJECT (dest
));
253 * gimp_config_reset_properties:
254 * @object: a #GObject
256 * Resets all writable properties of @object to the default values as
257 * defined in their #GParamSpec. Properties marked as "construct-only"
260 * If you want to reset a #GimpConfig object, please use gimp_config_reset().
265 gimp_config_reset_properties (GObject
*object
)
268 GParamSpec
**property_specs
;
269 guint n_property_specs
;
272 g_return_if_fail (G_IS_OBJECT (object
));
274 klass
= G_OBJECT_GET_CLASS (object
);
276 property_specs
= g_object_class_list_properties (klass
, &n_property_specs
);
280 g_object_freeze_notify (object
);
282 for (i
= 0; i
< n_property_specs
; i
++)
284 GParamSpec
*prop_spec
;
285 GValue value
= G_VALUE_INIT
;
287 prop_spec
= property_specs
[i
];
289 if ((prop_spec
->flags
& G_PARAM_WRITABLE
) &&
290 ! (prop_spec
->flags
& G_PARAM_CONSTRUCT_ONLY
))
292 if (G_IS_PARAM_SPEC_OBJECT (prop_spec
))
294 if ((prop_spec
->flags
& GIMP_CONFIG_PARAM_SERIALIZE
) &&
295 (prop_spec
->flags
& GIMP_CONFIG_PARAM_AGGREGATE
) &&
296 g_type_interface_peek (g_type_class_peek (prop_spec
->value_type
),
299 g_value_init (&value
, prop_spec
->value_type
);
301 g_object_get_property (object
, prop_spec
->name
, &value
);
303 gimp_config_reset (g_value_get_object (&value
));
305 g_value_unset (&value
);
310 GValue default_value
= G_VALUE_INIT
;
312 g_value_init (&default_value
, prop_spec
->value_type
);
313 g_value_init (&value
, prop_spec
->value_type
);
315 g_param_value_set_default (prop_spec
, &default_value
);
316 g_object_get_property (object
, prop_spec
->name
, &value
);
318 if (g_param_values_cmp (prop_spec
, &default_value
, &value
))
320 g_object_set_property (object
, prop_spec
->name
,
324 g_value_unset (&value
);
325 g_value_unset (&default_value
);
330 g_object_thaw_notify (object
);
332 g_free (property_specs
);
337 * gimp_config_reset_property:
338 * @object: a #GObject
339 * @property_name: name of the property to reset
341 * Resets the property named @property_name to its default value. The
342 * property must be writable and must not be marked as "construct-only".
347 gimp_config_reset_property (GObject
*object
,
348 const gchar
*property_name
)
351 GParamSpec
*prop_spec
;
353 g_return_if_fail (G_IS_OBJECT (object
));
354 g_return_if_fail (property_name
!= NULL
);
356 klass
= G_OBJECT_GET_CLASS (object
);
358 prop_spec
= g_object_class_find_property (klass
, property_name
);
363 if ((prop_spec
->flags
& G_PARAM_WRITABLE
) &&
364 ! (prop_spec
->flags
& G_PARAM_CONSTRUCT_ONLY
))
366 GValue value
= G_VALUE_INIT
;
368 if (G_IS_PARAM_SPEC_OBJECT (prop_spec
))
370 if ((prop_spec
->flags
& GIMP_CONFIG_PARAM_SERIALIZE
) &&
371 (prop_spec
->flags
& GIMP_CONFIG_PARAM_AGGREGATE
) &&
372 g_type_interface_peek (g_type_class_peek (prop_spec
->value_type
),
375 g_value_init (&value
, prop_spec
->value_type
);
377 g_object_get_property (object
, prop_spec
->name
, &value
);
379 gimp_config_reset (g_value_get_object (&value
));
381 g_value_unset (&value
);
386 g_value_init (&value
, prop_spec
->value_type
);
387 g_param_value_set_default (prop_spec
, &value
);
389 g_object_set_property (object
, prop_spec
->name
, &value
);
391 g_value_unset (&value
);
398 * GimpConfig string utilities
402 * gimp_config_string_append_escaped:
403 * @string: pointer to a #GString
404 * @val: a string to append or %NULL
406 * Escapes and quotes @val and appends it to @string. The escape
407 * algorithm is different from the one used by g_strescape() since it
408 * leaves non-ASCII characters intact and thus preserves UTF-8
409 * strings. Only control characters and quotes are being escaped.
414 gimp_config_string_append_escaped (GString
*string
,
417 g_return_if_fail (string
!= NULL
);
422 gchar buf
[4] = { '\\', 0, 0, 0 };
425 g_string_append_c (string
, '\"');
427 for (p
= (const guchar
*) val
, len
= 0; *p
; p
++)
429 if (*p
< ' ' || *p
== '\\' || *p
== '\"')
431 g_string_append_len (string
, val
, len
);
458 buf
[1] = '0' + (((*p
) >> 6) & 07);
459 buf
[2] = '0' + (((*p
) >> 3) & 07);
460 buf
[3] = '0' + ((*p
) & 07);
464 g_string_append_len (string
, buf
, len
);
466 val
= (const gchar
*) p
+ 1;
475 g_string_append_len (string
, val
, len
);
476 g_string_append_c (string
, '\"');
480 g_string_append_len (string
, "\"\"", 2);