gimpconfig-register.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* LIBGIMP - The GIMP Library
  2. * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
  3. *
  4. * gimpconfig-register.c
  5. * Copyright (C) 2008-2019 Michael Natterer <mitch@gimp.org>
  6. *
  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.
  11. *
  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. * Lesser General Public License for more details.
  16. *
  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/>.
  20. */
  21. #include "config.h"
  22. #include <cairo.h>
  23. #include <gdk-pixbuf/gdk-pixbuf.h>
  24. #include <gegl-paramspecs.h>
  25. #include "libgimpbase/gimpbase.h"
  26. #include "gimpconfig.h"
  27. /* local function prototypes */
  28. static void gimp_config_class_init (GObjectClass *klass,
  29. GParamSpec **pspecs);
  30. static void gimp_config_set_property (GObject *object,
  31. guint property_id,
  32. const GValue *value,
  33. GParamSpec *pspec);
  34. static void gimp_config_get_property (GObject *object,
  35. guint property_id,
  36. GValue *value,
  37. GParamSpec *pspec);
  38. static GValue * gimp_config_value_get (GObject *object,
  39. GParamSpec *pspec);
  40. static GValue * gimp_config_value_new (GParamSpec *pspec);
  41. static void gimp_config_value_free (GValue *value);
  42. /* public functions */
  43. /**
  44. * gimp_config_type_register:
  45. * @parent_type: type from which this type will be derived
  46. * @type_name: string used as the name of the new type
  47. * @pspecs: (array length=n_pspecs): array of #GParamSpec to install as properties on the new type
  48. * @n_pspecs: the number of param specs in @pspecs
  49. *
  50. * This function is a fancy wrapper around g_type_register_static().
  51. * It creates a new object type as subclass of @parent_type, installs
  52. * @pspecs on it and makes the new type implement the #GimpConfig
  53. * interface.
  54. *
  55. * Returns: the newly registered #GType
  56. *
  57. * Since: 3.0
  58. **/
  59. GType
  60. gimp_config_type_register (GType parent_type,
  61. const gchar *type_name,
  62. GParamSpec **pspecs,
  63. gint n_pspecs)
  64. {
  65. GParamSpec **terminated_pspecs;
  66. GTypeQuery query;
  67. GType config_type;
  68. g_return_val_if_fail (g_type_is_a (parent_type, G_TYPE_OBJECT), G_TYPE_NONE);
  69. g_return_val_if_fail (type_name != NULL, G_TYPE_NONE);
  70. g_return_val_if_fail (pspecs != NULL || n_pspecs == 0, G_TYPE_NONE);
  71. terminated_pspecs = g_new0 (GParamSpec *, n_pspecs + 1);
  72. memcpy (terminated_pspecs, pspecs, sizeof (GParamSpec *) * n_pspecs);
  73. g_type_query (parent_type, &query);
  74. {
  75. GTypeInfo info =
  76. {
  77. query.class_size,
  78. (GBaseInitFunc) NULL,
  79. (GBaseFinalizeFunc) NULL,
  80. (GClassInitFunc) gimp_config_class_init,
  81. NULL, /* class_finalize */
  82. terminated_pspecs,
  83. query.instance_size,
  84. 0, /* n_preallocs */
  85. (GInstanceInitFunc) NULL,
  86. };
  87. config_type = g_type_register_static (parent_type, type_name,
  88. &info, 0);
  89. if (! g_type_is_a (parent_type, GIMP_TYPE_CONFIG))
  90. {
  91. const GInterfaceInfo config_info =
  92. {
  93. NULL, /* interface_init */
  94. NULL, /* interface_finalize */
  95. NULL /* interface_data */
  96. };
  97. g_type_add_interface_static (config_type, GIMP_TYPE_CONFIG,
  98. &config_info);
  99. }
  100. }
  101. return config_type;
  102. }
  103. /* private functions */
  104. static void
  105. gimp_config_class_init (GObjectClass *klass,
  106. GParamSpec **pspecs)
  107. {
  108. gint i;
  109. klass->set_property = gimp_config_set_property;
  110. klass->get_property = gimp_config_get_property;
  111. for (i = 0; pspecs[i] != NULL; i++)
  112. {
  113. GParamSpec *pspec = pspecs[i];
  114. GParamSpec *copy = gimp_config_param_spec_duplicate (pspec);
  115. if (copy)
  116. {
  117. g_object_class_install_property (klass, i + 1, copy);
  118. }
  119. else
  120. {
  121. GType value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
  122. const gchar *type_name = g_type_name (value_type);
  123. /* There are some properties that we don't care to copy because they
  124. * are not serializable anyway (or we don't want them to be).
  125. * GimpContext properties are one such property type. We can find them
  126. * e.g. in some custom GEGL ops, such as "gimp:offset". So we silently
  127. * ignore these.
  128. * We might add more types of properties to the list as we discover
  129. * more cases. We keep warnings for all the other types which we
  130. * explicitly don't support.
  131. */
  132. if (g_strcmp0 (type_name, "GimpContext") != 0 &&
  133. /* Format specs are a GParamSpecPointer. There might be other
  134. * pointer specs we might be able to serialize, but BablFormat are
  135. * not one of these (there might be easy serializable formats, but
  136. * many are not and anyway it's probably not a data which ops or
  137. * plug-ins want to remember across run).
  138. */
  139. ! GEGL_IS_PARAM_SPEC_FORMAT (pspec))
  140. g_warning ("%s: not supported: %s (%s | %s)\n", G_STRFUNC,
  141. g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name, type_name);
  142. }
  143. }
  144. }
  145. static void
  146. gimp_config_set_property (GObject *object,
  147. guint property_id,
  148. const GValue *value,
  149. GParamSpec *pspec)
  150. {
  151. GValue *val = gimp_config_value_get (object, pspec);
  152. g_value_copy (value, val);
  153. }
  154. static void
  155. gimp_config_get_property (GObject *object,
  156. guint property_id,
  157. GValue *value,
  158. GParamSpec *pspec)
  159. {
  160. GValue *val = gimp_config_value_get (object, pspec);
  161. g_value_copy (val, value);
  162. }
  163. static GValue *
  164. gimp_config_value_get (GObject *object,
  165. GParamSpec *pspec)
  166. {
  167. GHashTable *properties;
  168. GValue *value;
  169. properties = g_object_get_data (object, "gimp-config-properties");
  170. if (! properties)
  171. {
  172. properties =
  173. g_hash_table_new_full (g_str_hash,
  174. g_str_equal,
  175. (GDestroyNotify) g_free,
  176. (GDestroyNotify) gimp_config_value_free);
  177. g_object_set_data_full (object, "gimp-config-properties", properties,
  178. (GDestroyNotify) g_hash_table_unref);
  179. }
  180. value = g_hash_table_lookup (properties, pspec->name);
  181. if (! value)
  182. {
  183. value = gimp_config_value_new (pspec);
  184. g_hash_table_insert (properties, g_strdup (pspec->name), value);
  185. }
  186. return value;
  187. }
  188. static GValue *
  189. gimp_config_value_new (GParamSpec *pspec)
  190. {
  191. GValue *value = g_slice_new0 (GValue);
  192. g_value_init (value, pspec->value_type);
  193. g_param_value_set_default (pspec, value);
  194. return value;
  195. }
  196. static void
  197. gimp_config_value_free (GValue *value)
  198. {
  199. g_value_unset (value);
  200. g_slice_free (GValue, value);
  201. }