1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* Object properties serialization routines
5
* Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program 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
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
#include <glib-object.h>
26
#include "libgimpbase/gimpbase.h"
27
#include "libgimpmath/gimpmath.h"
28
#include "libgimpcolor/gimpcolor.h"
30
#include "config-types.h"
32
#include "gimpconfig.h"
33
#include "gimpconfig-params.h"
34
#include "gimpconfig-serialize.h"
35
#include "gimpconfig-types.h"
36
#include "gimpconfig-utils.h"
37
#include "gimpconfigwriter.h"
40
static void serialize_unknown_token (const gchar *key,
46
* gimp_config_serialize_properties:
47
* @config: a #GimpConfig.
48
* @writer: a #GimpConfigWriter.
50
* This function writes all object properties to the @writer.
52
* Returns: %TRUE if serialization succeeded, %FALSE otherwise
55
gimp_config_serialize_properties (GimpConfig *config,
56
GimpConfigWriter *writer)
59
GParamSpec **property_specs;
60
guint n_property_specs;
63
g_return_val_if_fail (G_IS_OBJECT (config), FALSE);
65
klass = G_OBJECT_GET_CLASS (config);
67
property_specs = g_object_class_list_properties (klass, &n_property_specs);
72
for (i = 0; i < n_property_specs; i++)
74
GParamSpec *prop_spec = property_specs[i];
76
if (! (prop_spec->flags & GIMP_PARAM_SERIALIZE))
79
if (! gimp_config_serialize_property (config, prop_spec, writer))
83
g_free (property_specs);
89
* gimp_config_serialize_changed_properties:
90
* @config: a #GimpConfig.
91
* @writer: a #GimpConfigWriter.
93
* This function writes all object properties that have been changed from
94
* their default values to the @writer.
96
* Returns: %TRUE if serialization succeeded, %FALSE otherwise
99
gimp_config_serialize_changed_properties (GimpConfig *config,
100
GimpConfigWriter *writer)
103
GParamSpec **property_specs;
104
guint n_property_specs;
106
GValue value = { 0, };
108
g_return_val_if_fail (G_IS_OBJECT (config), FALSE);
110
klass = G_OBJECT_GET_CLASS (config);
112
property_specs = g_object_class_list_properties (klass, &n_property_specs);
114
if (! property_specs)
117
for (i = 0; i < n_property_specs; i++)
119
GParamSpec *prop_spec = property_specs[i];
121
if (! (prop_spec->flags & GIMP_PARAM_SERIALIZE))
124
g_value_init (&value, prop_spec->value_type);
125
g_object_get_property (G_OBJECT (config), prop_spec->name, &value);
127
if (! g_param_value_defaults (prop_spec, &value))
129
if (! gimp_config_serialize_property (config, prop_spec, writer))
133
g_value_unset (&value);
136
g_free (property_specs);
142
* gimp_config_serialize_properties_diff:
143
* @config: a #GimpConfig.
144
* @compare: a #GimpConfig of the same type as @config.
145
* @writer: a #GimpConfigWriter.
147
* This function compares @config and @compare and writes all
148
* properties of @config that have different values than @compare to
151
* Returns: %TRUE if serialization succeeded, %FALSE otherwise
154
gimp_config_serialize_properties_diff (GimpConfig *config,
156
GimpConfigWriter *writer)
162
g_return_val_if_fail (G_IS_OBJECT (config), FALSE);
163
g_return_val_if_fail (G_IS_OBJECT (compare), FALSE);
164
g_return_val_if_fail (G_TYPE_FROM_INSTANCE (config) ==
165
G_TYPE_FROM_INSTANCE (compare), FALSE);
167
klass = G_OBJECT_GET_CLASS (config);
169
diff = gimp_config_diff (config, compare, GIMP_PARAM_SERIALIZE);
174
for (list = diff; list; list = g_list_next (list))
176
GParamSpec *prop_spec = (GParamSpec *) list->data;
178
if (! (prop_spec->flags & GIMP_PARAM_SERIALIZE))
181
if (! gimp_config_serialize_property (config, prop_spec, writer))
192
gimp_config_serialize_property (GimpConfig *config,
193
GParamSpec *param_spec,
194
GimpConfigWriter *writer)
196
GTypeClass *owner_class;
197
GimpConfigInterface *config_iface;
198
GimpConfigInterface *parent_iface = NULL;
199
GValue value = { 0, };
200
gboolean success = FALSE;
202
if (! (param_spec->flags & GIMP_PARAM_SERIALIZE))
205
if (param_spec->flags & GIMP_PARAM_IGNORE)
208
g_value_init (&value, param_spec->value_type);
209
g_object_get_property (G_OBJECT (config), param_spec->name, &value);
211
if (param_spec->flags & GIMP_PARAM_DEFAULTS &&
212
g_param_value_defaults (param_spec, &value))
214
g_value_unset (&value);
218
owner_class = g_type_class_peek (param_spec->owner_type);
220
config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG);
222
/* We must call serialize_property() *only* if the *exact* class
223
* which implements it is param_spec->owner_type's class.
225
* Therefore, we ask param_spec->owner_type's immediate parent class
226
* for it's GimpConfigInterface and check if we get a different pointer.
228
* (if the pointers are the same, param_spec->owner_type's
229
* GimpConfigInterface is inherited from one of it's parent classes
230
* and thus not able to handle param_spec->owner_type's properties).
234
GTypeClass *owner_parent_class;
236
owner_parent_class = g_type_class_peek_parent (owner_class),
238
parent_iface = g_type_interface_peek (owner_parent_class,
243
config_iface != parent_iface && /* see comment above */
244
config_iface->serialize_property &&
245
config_iface->serialize_property (config,
246
param_spec->param_id,
247
(const GValue *) &value,
254
/* If there is no serialize_property() method *or* if it returned
255
* FALSE, continue with the default implementation
260
if (G_VALUE_HOLDS_OBJECT (&value))
262
GimpConfigInterface *config_iface = NULL;
263
GimpConfig *prop_object;
265
prop_object = g_value_get_object (&value);
268
config_iface = GIMP_CONFIG_GET_INTERFACE (prop_object);
274
gimp_config_writer_open (writer, param_spec->name);
276
/* if the object property is not GIMP_PARAM_AGGREGATE,
277
* deserializing will need to know the exact type
278
* in order to create the object
280
if (! (param_spec->flags & GIMP_PARAM_AGGREGATE))
282
GType object_type = G_TYPE_FROM_INSTANCE (prop_object);
284
gimp_config_writer_string (writer, g_type_name (object_type));
287
success = config_iface->serialize (prop_object, writer, NULL);
290
gimp_config_writer_close (writer);
292
gimp_config_writer_revert (writer);
295
else if (! G_VALUE_HOLDS_OBJECT (&value))
297
GString *str = g_string_new (NULL);
299
success = gimp_config_serialize_value (&value, str, TRUE);
303
gimp_config_writer_open (writer, param_spec->name);
304
gimp_config_writer_print (writer, str->str, str->len);
305
gimp_config_writer_close (writer);
308
g_string_free (str, TRUE);
313
/* don't warn for empty string properties */
314
if (G_VALUE_HOLDS_STRING (&value))
320
g_warning ("couldn't serialize property %s::%s of type %s",
321
g_type_name (G_TYPE_FROM_INSTANCE (config)),
323
g_type_name (param_spec->value_type));
328
g_value_unset (&value);
334
* gimp_config_serialize_value:
337
* @escaped: whether to escape string values.
339
* This utility function appends a string representation of #GValue to @str.
341
* Return value: %TRUE if serialization succeeded, %FALSE otherwise.
344
gimp_config_serialize_value (const GValue *value,
348
if (G_VALUE_HOLDS_BOOLEAN (value))
352
bool = g_value_get_boolean (value);
353
g_string_append (str, bool ? "yes" : "no");
357
if (G_VALUE_HOLDS_ENUM (value))
359
GEnumClass *enum_class = g_type_class_peek (G_VALUE_TYPE (value));
360
GEnumValue *enum_value = g_enum_get_value (enum_class,
361
g_value_get_enum (value));
363
if (enum_value && enum_value->value_nick)
365
g_string_append (str, enum_value->value_nick);
370
g_warning ("Couldn't get nick for enum_value of %s",
371
G_ENUM_CLASS_TYPE_NAME (enum_class));
376
if (G_VALUE_HOLDS_STRING (value))
378
const gchar *cstr = g_value_get_string (value);
384
gimp_config_string_append_escaped (str, cstr);
386
g_string_append (str, cstr);
391
if (G_VALUE_HOLDS_DOUBLE (value) || G_VALUE_HOLDS_FLOAT (value))
394
gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
396
if (G_VALUE_HOLDS_DOUBLE (value))
397
v_double = g_value_get_double (value);
399
v_double = (gdouble) g_value_get_float (value);
401
g_ascii_formatd (buf, sizeof (buf), "%f", v_double);
402
g_string_append (str, buf);
406
if (GIMP_VALUE_HOLDS_RGB (value))
409
gchar buf[4][G_ASCII_DTOSTR_BUF_SIZE];
411
rgb = g_value_get_boxed (value);
413
g_ascii_formatd (buf[0], G_ASCII_DTOSTR_BUF_SIZE, "%f", rgb->r);
414
g_ascii_formatd (buf[1], G_ASCII_DTOSTR_BUF_SIZE, "%f", rgb->g);
415
g_ascii_formatd (buf[2], G_ASCII_DTOSTR_BUF_SIZE, "%f", rgb->b);
416
g_ascii_formatd (buf[3], G_ASCII_DTOSTR_BUF_SIZE, "%f", rgb->a);
418
g_string_append_printf (str, "(color-rgba %s %s %s %s)",
419
buf[0], buf[1], buf[2], buf[3]);
423
if (GIMP_VALUE_HOLDS_MATRIX2 (value))
426
gchar buf[4][G_ASCII_DTOSTR_BUF_SIZE];
429
trafo = g_value_get_boxed (value);
431
for (i = 0, k = 0; i < 2; i++)
432
for (j = 0; j < 2; j++, k++)
433
g_ascii_formatd (buf[k],
434
G_ASCII_DTOSTR_BUF_SIZE, "%f", trafo->coeff[i][j]);
436
g_string_append_printf (str, "(matrix %s %s %s %s)",
437
buf[0], buf[1], buf[2], buf[3]);
441
if (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY)
445
array = g_value_get_boxed (value);
451
g_string_append_printf (str, "%d", array->n_values);
453
for (i = 0; i < array->n_values; i++)
455
g_string_append (str, " ");
457
if (! gimp_config_serialize_value (g_value_array_get_nth (array,
465
g_string_append (str, "NULL");
471
if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_STRING))
473
GValue tmp_value = { 0, };
475
g_value_init (&tmp_value, G_TYPE_STRING);
476
g_value_transform (value, &tmp_value);
478
g_string_append (str, g_value_get_string (&tmp_value));
480
g_value_unset (&tmp_value);
489
* gimp_config_serialize_unknown_tokens:
490
* @config: a #GimpConfig.
491
* @writer: a #GimpConfigWriter.
493
* Writes all unknown tokens attached to @config to the @writer. See
494
* gimp_config_add_unknown_token().
496
* Returns: %TRUE if serialization succeeded, %FALSE otherwise
499
gimp_config_serialize_unknown_tokens (GimpConfig *config,
500
GimpConfigWriter *writer)
502
g_return_val_if_fail (G_IS_OBJECT (config), FALSE);
504
gimp_config_writer_linefeed (writer);
505
gimp_config_foreach_unknown_token (config, serialize_unknown_token, writer);
511
serialize_unknown_token (const gchar *key,
515
GimpConfigWriter *writer = data;
517
gimp_config_writer_open (writer, key);
518
gimp_config_writer_string (writer, value);
519
gimp_config_writer_close (writer);