app: s/sprintf/g_snprintf/ in xcf_save_image()
[gimp.git] / libgimpconfig / gimpconfig-iface.c
blob409f4faebd572efc651a1e61042343b0652ade1a
1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
4 * Config file serialization and deserialization interface
5 * Copyright (C) 2001-2002 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/>.
22 #include "config.h"
24 #include <string.h>
26 #include <gio/gio.h>
28 #include "libgimpbase/gimpbase.h"
30 #include "gimpconfigtypes.h"
32 #include "gimpconfigwriter.h"
33 #include "gimpconfig-iface.h"
34 #include "gimpconfig-deserialize.h"
35 #include "gimpconfig-serialize.h"
36 #include "gimpconfig-params.h"
37 #include "gimpconfig-utils.h"
38 #include "gimpscanner.h"
40 #include "libgimp/libgimp-intl.h"
43 /**
44 * SECTION: gimpconfig-iface
45 * @title: GimpConfig-iface
46 * @short_description: High-level API for libgimpconfig.
48 * High-level API for libgimpconfig.
49 **/
53 * The GimpConfig serialization and deserialization interface.
57 /* local function prototypes */
59 static void gimp_config_iface_default_init (GimpConfigInterface *iface);
60 static void gimp_config_iface_base_init (GimpConfigInterface *iface);
62 static gboolean gimp_config_iface_serialize (GimpConfig *config,
63 GimpConfigWriter *writer,
64 gpointer data);
65 static gboolean gimp_config_iface_deserialize (GimpConfig *config,
66 GScanner *scanner,
67 gint nest_level,
68 gpointer data);
69 static GimpConfig * gimp_config_iface_duplicate (GimpConfig *config);
70 static gboolean gimp_config_iface_equal (GimpConfig *a,
71 GimpConfig *b);
72 static void gimp_config_iface_reset (GimpConfig *config);
73 static gboolean gimp_config_iface_copy (GimpConfig *src,
74 GimpConfig *dest,
75 GParamFlags flags);
78 /* private functions */
81 GType
82 gimp_config_get_type (void)
84 static GType config_iface_type = 0;
86 if (! config_iface_type)
88 const GTypeInfo config_iface_info =
90 sizeof (GimpConfigInterface),
91 (GBaseInitFunc) gimp_config_iface_base_init,
92 (GBaseFinalizeFunc) NULL,
93 (GClassInitFunc) gimp_config_iface_default_init,
94 (GClassFinalizeFunc) NULL,
97 config_iface_type = g_type_register_static (G_TYPE_INTERFACE,
98 "GimpConfigInterface",
99 &config_iface_info,
102 g_type_interface_add_prerequisite (config_iface_type, G_TYPE_OBJECT);
105 return config_iface_type;
108 static void
109 gimp_config_iface_default_init (GimpConfigInterface *iface)
111 iface->serialize = gimp_config_iface_serialize;
112 iface->deserialize = gimp_config_iface_deserialize;
113 iface->duplicate = gimp_config_iface_duplicate;
114 iface->equal = gimp_config_iface_equal;
115 iface->reset = gimp_config_iface_reset;
116 iface->copy = gimp_config_iface_copy;
119 static void
120 gimp_config_iface_base_init (GimpConfigInterface *iface)
122 /* always set these to NULL since we don't want to inherit them
123 * from parent classes
125 iface->serialize_property = NULL;
126 iface->deserialize_property = NULL;
129 static gboolean
130 gimp_config_iface_serialize (GimpConfig *config,
131 GimpConfigWriter *writer,
132 gpointer data)
134 return gimp_config_serialize_properties (config, writer);
137 static gboolean
138 gimp_config_iface_deserialize (GimpConfig *config,
139 GScanner *scanner,
140 gint nest_level,
141 gpointer data)
143 return gimp_config_deserialize_properties (config, scanner, nest_level);
146 static GimpConfig *
147 gimp_config_iface_duplicate (GimpConfig *config)
149 GObject *object = G_OBJECT (config);
150 GObjectClass *klass = G_OBJECT_GET_CLASS (object);
151 GParamSpec **property_specs;
152 guint n_property_specs;
153 gint n_construct_properties = 0;
154 const gchar **construct_names = NULL;
155 GValue *construct_values = NULL;
156 guint i;
157 GObject *dup;
159 property_specs = g_object_class_list_properties (klass, &n_property_specs);
161 construct_names = g_new0 (const gchar *, n_property_specs);
162 construct_values = g_new0 (GValue, n_property_specs);
164 for (i = 0; i < n_property_specs; i++)
166 GParamSpec *prop_spec = property_specs[i];
168 if ((prop_spec->flags & G_PARAM_READABLE) &&
169 (prop_spec->flags & G_PARAM_WRITABLE) &&
170 (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY))
172 construct_names[n_construct_properties] = prop_spec->name;
174 g_value_init (&construct_values[n_construct_properties],
175 prop_spec->value_type);
176 g_object_get_property (object, prop_spec->name,
177 &construct_values[n_construct_properties]);
179 n_construct_properties++;
183 g_free (property_specs);
185 dup = g_object_new_with_properties (G_TYPE_FROM_INSTANCE (object),
186 n_construct_properties,
187 (const gchar **) construct_names,
188 (const GValue *) construct_values);
190 for (i = 0; i < n_construct_properties; i++)
191 g_value_unset (&construct_values[i]);
193 g_free (construct_names);
194 g_free (construct_values);
196 gimp_config_copy (config, GIMP_CONFIG (dup), 0);
198 return GIMP_CONFIG (dup);
201 static gboolean
202 gimp_config_iface_equal (GimpConfig *a,
203 GimpConfig *b)
205 GObjectClass *klass;
206 GParamSpec **property_specs;
207 guint n_property_specs;
208 guint i;
209 gboolean equal = TRUE;
211 klass = G_OBJECT_GET_CLASS (a);
213 property_specs = g_object_class_list_properties (klass, &n_property_specs);
215 for (i = 0; equal && i < n_property_specs; i++)
217 GParamSpec *prop_spec;
218 GValue a_value = G_VALUE_INIT;
219 GValue b_value = G_VALUE_INIT;
221 prop_spec = property_specs[i];
223 if (! (prop_spec->flags & G_PARAM_READABLE))
224 continue;
226 g_value_init (&a_value, prop_spec->value_type);
227 g_value_init (&b_value, prop_spec->value_type);
228 g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value);
229 g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value);
231 if (g_param_values_cmp (prop_spec, &a_value, &b_value))
233 if ((prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) &&
234 G_IS_PARAM_SPEC_OBJECT (prop_spec) &&
235 g_type_interface_peek (g_type_class_peek (prop_spec->value_type),
236 GIMP_TYPE_CONFIG))
238 if (! gimp_config_is_equal_to (g_value_get_object (&a_value),
239 g_value_get_object (&b_value)))
241 equal = FALSE;
244 else
246 equal = FALSE;
250 g_value_unset (&a_value);
251 g_value_unset (&b_value);
254 g_free (property_specs);
256 return equal;
259 static void
260 gimp_config_iface_reset (GimpConfig *config)
262 gimp_config_reset_properties (G_OBJECT (config));
265 static gboolean
266 gimp_config_iface_copy (GimpConfig *src,
267 GimpConfig *dest,
268 GParamFlags flags)
270 return gimp_config_sync (G_OBJECT (src), G_OBJECT (dest), flags);
274 /* public functions */
278 * gimp_config_serialize_to_file:
279 * @config: a #GObject that implements the #GimpConfigInterface.
280 * @filename: the name of the file to write the configuration to.
281 * @header: optional file header (must be ASCII only)
282 * @footer: optional file footer (must be ASCII only)
283 * @data: user data passed to the serialize implementation.
284 * @error: return location for a possible error
286 * Serializes the object properties of @config to the file specified
287 * by @filename. If a file with that name already exists, it is
288 * overwritten. Basically this function opens @filename for you and
289 * calls the serialize function of the @config's #GimpConfigInterface.
291 * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
293 * Since: 2.4
295 gboolean
296 gimp_config_serialize_to_file (GimpConfig *config,
297 const gchar *filename,
298 const gchar *header,
299 const gchar *footer,
300 gpointer data,
301 GError **error)
303 GimpConfigWriter *writer;
305 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
306 g_return_val_if_fail (filename != NULL, FALSE);
307 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
309 writer = gimp_config_writer_new_file (filename, TRUE, header, error);
310 if (!writer)
311 return FALSE;
313 GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
315 return gimp_config_writer_finish (writer, footer, error);
319 * gimp_config_serialize_to_gfile:
320 * @config: a #GObject that implements the #GimpConfigInterface.
321 * @file: the #GFile to write the configuration to.
322 * @header: optional file header (must be ASCII only)
323 * @footer: optional file footer (must be ASCII only)
324 * @data: user data passed to the serialize implementation.
325 * @error: return location for a possible error
327 * Serializes the object properties of @config to the file specified
328 * by @file. If a file with that name already exists, it is
329 * overwritten. Basically this function opens @file for you and calls
330 * the serialize function of the @config's #GimpConfigInterface.
332 * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
334 * Since: 2.10
336 gboolean
337 gimp_config_serialize_to_gfile (GimpConfig *config,
338 GFile *file,
339 const gchar *header,
340 const gchar *footer,
341 gpointer data,
342 GError **error)
344 GimpConfigWriter *writer;
346 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
347 g_return_val_if_fail (G_IS_FILE (file), FALSE);
348 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
350 writer = gimp_config_writer_new_gfile (file, TRUE, header, error);
351 if (!writer)
352 return FALSE;
354 GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
356 return gimp_config_writer_finish (writer, footer, error);
360 * gimp_config_serialize_to_stream:
361 * @config: a #GObject that implements the #GimpConfigInterface.
362 * @output: the #GOutputStream to write the configuration to.
363 * @header: optional file header (must be ASCII only)
364 * @footer: optional file footer (must be ASCII only)
365 * @data: user data passed to the serialize implementation.
366 * @error: return location for a possible error
368 * Serializes the object properties of @config to the stream specified
369 * by @output.
371 * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
373 * Since: 2.10
375 gboolean
376 gimp_config_serialize_to_stream (GimpConfig *config,
377 GOutputStream *output,
378 const gchar *header,
379 const gchar *footer,
380 gpointer data,
381 GError **error)
383 GimpConfigWriter *writer;
385 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
386 g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), FALSE);
387 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
389 writer = gimp_config_writer_new_stream (output, header, error);
390 if (!writer)
391 return FALSE;
393 GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
395 return gimp_config_writer_finish (writer, footer, error);
399 * gimp_config_serialize_to_fd:
400 * @config: a #GObject that implements the #GimpConfigInterface.
401 * @fd: a file descriptor, opened for writing
402 * @data: user data passed to the serialize implementation.
404 * Serializes the object properties of @config to the given file
405 * descriptor.
407 * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
409 * Since: 2.4
411 gboolean
412 gimp_config_serialize_to_fd (GimpConfig *config,
413 gint fd,
414 gpointer data)
416 GimpConfigWriter *writer;
418 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
419 g_return_val_if_fail (fd > 0, FALSE);
421 writer = gimp_config_writer_new_fd (fd);
422 if (!writer)
423 return FALSE;
425 GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
427 return gimp_config_writer_finish (writer, NULL, NULL);
431 * gimp_config_serialize_to_string:
432 * @config: a #GObject that implements the #GimpConfigInterface.
433 * @data: user data passed to the serialize implementation.
435 * Serializes the object properties of @config to a string.
437 * Return value: a newly allocated NUL-terminated string.
439 * Since: 2.4
441 gchar *
442 gimp_config_serialize_to_string (GimpConfig *config,
443 gpointer data)
445 GimpConfigWriter *writer;
446 GString *str;
448 g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
450 str = g_string_new (NULL);
451 writer = gimp_config_writer_new_string (str);
453 GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
455 gimp_config_writer_finish (writer, NULL, NULL);
457 return g_string_free (str, FALSE);
461 * gimp_config_deserialize_file:
462 * @config: a #GObject that implements the #GimpConfigInterface.
463 * @filename: the name of the file to read configuration from.
464 * @data: user data passed to the deserialize implementation.
465 * @error: return location for a possible error
467 * Opens the file specified by @filename, reads configuration data
468 * from it and configures @config accordingly. Basically this function
469 * creates a properly configured #GScanner for you and calls the
470 * deserialize function of the @config's #GimpConfigInterface.
472 * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
474 * Since: 2.4
476 gboolean
477 gimp_config_deserialize_file (GimpConfig *config,
478 const gchar *filename,
479 gpointer data,
480 GError **error)
482 GScanner *scanner;
483 gboolean success;
485 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
486 g_return_val_if_fail (filename != NULL, FALSE);
487 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
489 scanner = gimp_scanner_new_file (filename, error);
490 if (! scanner)
491 return FALSE;
493 g_object_freeze_notify (G_OBJECT (config));
495 success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
496 scanner, 0, data);
498 g_object_thaw_notify (G_OBJECT (config));
500 gimp_scanner_destroy (scanner);
502 if (! success)
503 g_assert (error == NULL || *error != NULL);
505 return success;
509 * gimp_config_deserialize_gfile:
510 * @config: a #GObject that implements the #GimpConfigInterface.
511 * @file: the #GFile to read configuration from.
512 * @data: user data passed to the deserialize implementation.
513 * @error: return location for a possible error
515 * Opens the file specified by @file, reads configuration data from it
516 * and configures @config accordingly. Basically this function creates
517 * a properly configured #GScanner for you and calls the deserialize
518 * function of the @config's #GimpConfigInterface.
520 * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
522 * Since: 2.10
524 gboolean
525 gimp_config_deserialize_gfile (GimpConfig *config,
526 GFile *file,
527 gpointer data,
528 GError **error)
530 GScanner *scanner;
531 gboolean success;
533 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
534 g_return_val_if_fail (G_IS_FILE (file), FALSE);
535 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
537 scanner = gimp_scanner_new_gfile (file, error);
538 if (! scanner)
539 return FALSE;
541 g_object_freeze_notify (G_OBJECT (config));
543 success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
544 scanner, 0, data);
546 g_object_thaw_notify (G_OBJECT (config));
548 gimp_scanner_destroy (scanner);
550 if (! success)
551 g_assert (error == NULL || *error != NULL);
553 return success;
557 * gimp_config_deserialize_stream:
558 * @config: a #GObject that implements the #GimpConfigInterface.
559 * @input: the #GInputStream to read configuration from.
560 * @data: user data passed to the deserialize implementation.
561 * @error: return location for a possible error
563 * Reads configuration data from @input and configures @config
564 * accordingly. Basically this function creates a properly configured
565 * #GScanner for you and calls the deserialize function of the
566 * @config's #GimpConfigInterface.
568 * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
570 * Since: 2.10
572 gboolean
573 gimp_config_deserialize_stream (GimpConfig *config,
574 GInputStream *input,
575 gpointer data,
576 GError **error)
578 GScanner *scanner;
579 gboolean success;
581 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
582 g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE);
583 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
585 scanner = gimp_scanner_new_stream (input, error);
586 if (! scanner)
587 return FALSE;
589 g_object_freeze_notify (G_OBJECT (config));
591 success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
592 scanner, 0, data);
594 g_object_thaw_notify (G_OBJECT (config));
596 gimp_scanner_destroy (scanner);
598 if (! success)
599 g_assert (error == NULL || *error != NULL);
601 return success;
605 * gimp_config_deserialize_string:
606 * @config: a #GObject that implements the #GimpConfigInterface.
607 * @text: string to deserialize (in UTF-8 encoding)
608 * @text_len: length of @text in bytes or -1
609 * @data: client data
610 * @error: return location for a possible error
612 * Configures @config from @text. Basically this function creates a
613 * properly configured #GScanner for you and calls the deserialize
614 * function of the @config's #GimpConfigInterface.
616 * Returns: %TRUE if deserialization succeeded, %FALSE otherwise.
618 * Since: 2.4
620 gboolean
621 gimp_config_deserialize_string (GimpConfig *config,
622 const gchar *text,
623 gint text_len,
624 gpointer data,
625 GError **error)
627 GScanner *scanner;
628 gboolean success;
630 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
631 g_return_val_if_fail (text != NULL || text_len == 0, FALSE);
632 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
634 scanner = gimp_scanner_new_string (text, text_len, error);
636 g_object_freeze_notify (G_OBJECT (config));
638 success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
639 scanner, 0, data);
641 g_object_thaw_notify (G_OBJECT (config));
643 gimp_scanner_destroy (scanner);
645 if (! success)
646 g_assert (error == NULL || *error != NULL);
648 return success;
652 * gimp_config_deserialize_return:
653 * @scanner: a #GScanner
654 * @expected_token: the expected token
655 * @nest_level: the nest level
657 * Returns:
659 * Since: 2.4
661 gboolean
662 gimp_config_deserialize_return (GScanner *scanner,
663 GTokenType expected_token,
664 gint nest_level)
666 GTokenType next_token;
668 g_return_val_if_fail (scanner != NULL, FALSE);
670 next_token = g_scanner_peek_next_token (scanner);
672 if (expected_token != G_TOKEN_LEFT_PAREN)
674 g_scanner_get_next_token (scanner);
675 g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
676 _("fatal parse error"), TRUE);
677 return FALSE;
679 else
681 if (nest_level > 0 && next_token == G_TOKEN_RIGHT_PAREN)
683 return TRUE;
685 else if (next_token != G_TOKEN_EOF)
687 g_scanner_get_next_token (scanner);
688 g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
689 _("fatal parse error"), TRUE);
690 return FALSE;
694 return TRUE;
699 * gimp_config_serialize:
700 * @config: a #GObject that implements the #GimpConfigInterface.
701 * @writer: the #GimpConfigWriter to use.
702 * @data: client data
704 * Serialize the #GimpConfig object.
706 * Returns: %TRUE if serialization succeeded, %FALSE otherwise.
708 * Since: 2.8
710 gboolean
711 gimp_config_serialize (GimpConfig *config,
712 GimpConfigWriter *writer,
713 gpointer data)
715 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
717 return GIMP_CONFIG_GET_INTERFACE (config)->serialize (config,
718 writer,
719 data);
723 * gimp_config_deserialize:
724 * @config: a #GObject that implements the #GimpConfigInterface.
725 * @scanner: the #GScanner to use.
726 * @nest_level: the nest level.
727 * @data: client data.
729 * Deserialize the #GimpConfig object.
731 * Returns: %TRUE if deserialization succeeded, %FALSE otherwise.
733 * Since: 2.8
735 gboolean
736 gimp_config_deserialize (GimpConfig *config,
737 GScanner *scanner,
738 gint nest_level,
739 gpointer data)
741 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
743 return GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
744 scanner,
745 nest_level,
746 data);
750 * gimp_config_duplicate:
751 * @config: a #GObject that implements the #GimpConfigInterface.
753 * Creates a copy of the passed object by copying all object
754 * properties. The default implementation of the #GimpConfigInterface
755 * only works for objects that are completely defined by their
756 * properties.
758 * Return value: the duplicated #GimpConfig object
760 * Since: 2.4
762 gpointer
763 gimp_config_duplicate (GimpConfig *config)
765 g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
767 return GIMP_CONFIG_GET_INTERFACE (config)->duplicate (config);
771 * gimp_config_is_equal_to:
772 * @a: a #GObject that implements the #GimpConfigInterface.
773 * @b: another #GObject of the same type as @a.
775 * Compares the two objects. The default implementation of the
776 * #GimpConfigInterface compares the object properties and thus only
777 * works for objects that are completely defined by their
778 * properties.
780 * Return value: %TRUE if the two objects are equal.
782 * Since: 2.4
784 gboolean
785 gimp_config_is_equal_to (GimpConfig *a,
786 GimpConfig *b)
788 g_return_val_if_fail (GIMP_IS_CONFIG (a), FALSE);
789 g_return_val_if_fail (GIMP_IS_CONFIG (b), FALSE);
790 g_return_val_if_fail (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b),
791 FALSE);
793 return GIMP_CONFIG_GET_INTERFACE (a)->equal (a, b);
797 * gimp_config_reset:
798 * @config: a #GObject that implements the #GimpConfigInterface.
800 * Resets the object to its default state. The default implementation of the
801 * #GimpConfigInterface only works for objects that are completely defined by
802 * their properties.
804 * Since: 2.4
806 void
807 gimp_config_reset (GimpConfig *config)
809 g_return_if_fail (GIMP_IS_CONFIG (config));
811 g_object_freeze_notify (G_OBJECT (config));
813 GIMP_CONFIG_GET_INTERFACE (config)->reset (config);
815 g_object_thaw_notify (G_OBJECT (config));
819 * gimp_config_copy:
820 * @src: a #GObject that implements the #GimpConfigInterface.
821 * @dest: another #GObject of the same type as @a.
822 * @flags: a mask of GParamFlags
824 * Compares all read- and write-able properties from @src and @dest
825 * that have all @flags set. Differing values are then copied from
826 * @src to @dest. If @flags is 0, all differing read/write properties.
828 * Properties marked as "construct-only" are not touched.
830 * Return value: %TRUE if @dest was modified, %FALSE otherwise
832 * Since: 2.6
834 gboolean
835 gimp_config_copy (GimpConfig *src,
836 GimpConfig *dest,
837 GParamFlags flags)
839 gboolean changed;
841 g_return_val_if_fail (GIMP_IS_CONFIG (src), FALSE);
842 g_return_val_if_fail (GIMP_IS_CONFIG (dest), FALSE);
843 g_return_val_if_fail (G_TYPE_FROM_INSTANCE (src) == G_TYPE_FROM_INSTANCE (dest),
844 FALSE);
846 g_object_freeze_notify (G_OBJECT (dest));
848 changed = GIMP_CONFIG_GET_INTERFACE (src)->copy (src, dest, flags);
850 g_object_thaw_notify (G_OBJECT (dest));
852 return changed;