[gimp] libgimpconfig: add gimp_config_type_register()
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimpconfig: add gimp_config_type_register()
- Date: Mon, 16 Sep 2019 08:52:00 +0000 (UTC)
commit 3598722020cb298dedd60088079bc24c8b5e6bc9
Author: Michael Natterer <mitch gimp org>
Date: Mon Sep 16 10:45:22 2019 +0200
libgimpconfig: add gimp_config_type_register()
which implements a generalized (not GEGL operation specific) version
of the dynamic config type creation code from gimp-operation-config.c.
app/operations/gimp-operation-config.c | 238 +++++------------------------
libgimpconfig/Makefile.gi | 2 +
libgimpconfig/gimpconfig-register.c | 269 +++++++++++++++++++++++++++++++++
libgimpconfig/gimpconfig-register.h | 42 +++++
libgimpconfig/gimpconfig.def | 3 +-
libgimpconfig/gimpconfig.h | 11 +-
libgimpconfig/meson.build | 4 +-
7 files changed, 360 insertions(+), 209 deletions(-)
---
diff --git a/app/operations/gimp-operation-config.c b/app/operations/gimp-operation-config.c
index f4ff88a095..efa08a3b1d 100644
--- a/app/operations/gimp-operation-config.c
+++ b/app/operations/gimp-operation-config.c
@@ -86,166 +86,6 @@ gimp_operation_config_get_container_table (Gimp *gimp)
return config_containers;
}
-static GValue *
-gimp_operation_config_value_new (GParamSpec *pspec)
-{
- GValue *value = g_slice_new0 (GValue);
-
- g_value_init (value, pspec->value_type);
- g_param_value_set_default (pspec, value);
-
- return value;
-}
-
-static void
-gimp_operation_config_value_free (GValue *value)
-{
- g_value_unset (value);
- g_slice_free (GValue, value);
-}
-
-static GHashTable *
-gimp_operation_config_get_properties (GObject *object)
-{
- GHashTable *properties = g_object_get_data (object, "properties");
-
- if (! properties)
- {
- properties = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) gimp_operation_config_value_free);
-
- g_object_set_data_full (object, "properties", properties,
- (GDestroyNotify) g_hash_table_unref);
- }
-
- return properties;
-}
-
-static GValue *
-gimp_operation_config_value_get (GObject *object,
- GParamSpec *pspec)
-{
- GHashTable *properties = gimp_operation_config_get_properties (object);
- GValue *value;
-
- value = g_hash_table_lookup (properties, pspec->name);
-
- if (! value)
- {
- value = gimp_operation_config_value_new (pspec);
- g_hash_table_insert (properties, g_strdup (pspec->name), value);
- }
-
- return value;
-}
-
-static void
-gimp_operation_config_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GValue *val = gimp_operation_config_value_get (object, pspec);
-
- g_value_copy (value, val);
-}
-
-static void
-gimp_operation_config_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GValue *val = gimp_operation_config_value_get (object, pspec);
-
- g_value_copy (val, value);
-}
-
-static void
-gimp_operation_config_class_init (GObjectClass *klass,
- const gchar *operation)
-{
- GParamSpec **pspecs;
- guint n_pspecs;
- gint i;
-
- klass->set_property = gimp_operation_config_set_property;
- klass->get_property = gimp_operation_config_get_property;
-
- pspecs = gegl_operation_list_properties (operation, &n_pspecs);
-
- for (i = 0; i < n_pspecs; i++)
- {
- GParamSpec *pspec = pspecs[i];
-
- if ((pspec->flags & G_PARAM_READABLE) &&
- (pspec->flags & G_PARAM_WRITABLE) &&
- strcmp (pspec->name, "input") &&
- strcmp (pspec->name, "output"))
- {
- GParamSpec *copy = gimp_config_param_spec_duplicate (pspec);
-
- if (copy)
- {
- g_object_class_install_property (klass, i + 1, copy);
- }
- else if (! G_IS_PARAM_SPEC_OBJECT (pspec) &&
- ! G_IS_PARAM_SPEC_POINTER (pspec))
- {
- /* silently ignore object properties */
-
- g_warning ("%s: not supported: %s (%s)\n", G_STRFUNC,
- g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name);
- }
- }
- }
-
- g_free (pspecs);
-}
-
-static gboolean
-gimp_operation_config_equal (GimpConfig *a,
- GimpConfig *b)
-{
- GList *diff;
- gboolean equal = TRUE;
-
- diff = gimp_config_diff (G_OBJECT (a), G_OBJECT (b),
- GIMP_CONFIG_PARAM_SERIALIZE);
-
- if (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b))
- {
- GList *list;
-
- for (list = diff; list; list = g_list_next (list))
- {
- GParamSpec *pspec = list->data;
-
- if (pspec->owner_type == G_TYPE_FROM_INSTANCE (a))
- {
- equal = FALSE;
- break;
- }
- }
- }
- else if (diff)
- {
- equal = FALSE;
- }
-
- g_list_free (diff);
-
- return equal;
-}
-
-static void
-gimp_operation_config_config_iface_init (GimpConfigInterface *iface)
-{
- iface->equal = gimp_operation_config_equal;
-}
-
/* public functions */
@@ -265,7 +105,7 @@ gimp_operation_config_register (Gimp *gimp,
g_hash_table_insert (config_types,
g_strdup (operation),
(gpointer) config_type);
- }
+}
GType
gimp_operation_config_get_type (Gimp *gimp,
@@ -278,6 +118,8 @@ gimp_operation_config_get_type (Gimp *gimp,
g_return_val_if_fail (GIMP_IS_GIMP (gimp), G_TYPE_NONE);
g_return_val_if_fail (operation != NULL, G_TYPE_NONE);
+ g_return_val_if_fail (g_type_is_a (parent_type, GIMP_TYPE_OBJECT),
+ G_TYPE_NONE);
config_types = gimp_operation_config_get_type_table (gimp);
@@ -285,59 +127,51 @@ gimp_operation_config_get_type (Gimp *gimp,
if (! config_type)
{
- GTypeQuery query;
+ GParamSpec **pspecs;
+ guint n_pspecs;
+ gchar *type_name;
+ gint i, j;
- g_return_val_if_fail (g_type_is_a (parent_type, GIMP_TYPE_OBJECT),
- G_TYPE_NONE);
+ pspecs = gegl_operation_list_properties (operation, &n_pspecs);
- g_type_query (parent_type, &query);
-
- {
- GTypeInfo info =
- {
- query.class_size,
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) gimp_operation_config_class_init,
- NULL, /* class_finalize */
- operation,
- query.instance_size,
- 0, /* n_preallocs */
- (GInstanceInitFunc) NULL,
- };
-
- const GInterfaceInfo config_info =
+ for (i = 0, j = 0; i < n_pspecs; i++)
{
- (GInterfaceInitFunc) gimp_operation_config_config_iface_init,
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
+ GParamSpec *pspec = pspecs[i];
- gchar *type_name = g_strdup_printf ("GimpGegl-%s-config",
- operation);
+ if ((pspec->flags & G_PARAM_READABLE) &&
+ (pspec->flags & G_PARAM_WRITABLE) &&
+ strcmp (pspec->name, "input") &&
+ strcmp (pspec->name, "output"))
+ {
+ pspecs[j] = pspec;
+ j++;
+ }
+ }
- g_strcanon (type_name,
- G_CSET_DIGITS "-" G_CSET_a_2_z G_CSET_A_2_Z, '-');
+ n_pspecs = j;
- config_type = g_type_register_static (parent_type, type_name,
- &info, 0);
+ type_name = g_strdup_printf ("GimpGegl-%s-config", operation);
- g_free (type_name);
+ g_strcanon (type_name,
+ G_CSET_DIGITS "-" G_CSET_a_2_z G_CSET_A_2_Z, '-');
- g_type_add_interface_static (config_type, GIMP_TYPE_CONFIG,
- &config_info);
+ config_type = gimp_config_type_register (parent_type,
+ type_name,
+ pspecs, n_pspecs);
- if (icon_name && g_type_is_a (config_type, GIMP_TYPE_VIEWABLE))
- {
- GimpViewableClass *viewable_class = g_type_class_ref (config_type);
+ g_free (pspecs);
+ g_free (type_name);
- viewable_class->default_icon_name = g_strdup (icon_name);
+ if (icon_name && g_type_is_a (config_type, GIMP_TYPE_VIEWABLE))
+ {
+ GimpViewableClass *viewable_class = g_type_class_ref (config_type);
- g_type_class_unref (viewable_class);
- }
+ viewable_class->default_icon_name = g_strdup (icon_name);
+
+ g_type_class_unref (viewable_class);
+ }
- gimp_operation_config_register (gimp, operation, config_type);
- }
+ gimp_operation_config_register (gimp, operation, config_type);
}
return config_type;
diff --git a/libgimpconfig/Makefile.gi b/libgimpconfig/Makefile.gi
index bd83600014..532b790d19 100644
--- a/libgimpconfig/Makefile.gi
+++ b/libgimpconfig/Makefile.gi
@@ -8,6 +8,7 @@ libgimpconfig_introspectable_headers = \
../libgimpconfig/gimpconfig-error.h \
../libgimpconfig/gimpconfig-params.h \
../libgimpconfig/gimpconfig-path.h \
+ ../libgimpconfig/gimpconfig-register.h \
../libgimpconfig/gimpconfig-serialize.h \
../libgimpconfig/gimpconfig-utils.h \
../libgimpconfig/gimpconfigwriter.h \
@@ -20,6 +21,7 @@ libgimpconfig_introspectable = \
../libgimpconfig/gimpconfig-error.c \
../libgimpconfig/gimpconfig-path.c \
../libgimpconfig/gimpconfig-params.c \
+ ../libgimpconfig/gimpconfig-register.c \
../libgimpconfig/gimpconfig-serialize.c \
../libgimpconfig/gimpconfig-utils.c \
../libgimpconfig/gimpconfigwriter.c \
diff --git a/libgimpconfig/gimpconfig-register.c b/libgimpconfig/gimpconfig-register.c
new file mode 100644
index 0000000000..4eaef927f4
--- /dev/null
+++ b/libgimpconfig/gimpconfig-register.c
@@ -0,0 +1,269 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpconfig-register.c
+ * Copyright (C) 2008-2019 Michael Natterer <mitch gimp org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "gimpconfig.h"
+
+
+/* local function prototypes */
+
+static void gimp_config_class_init (GObjectClass *klass,
+ GParamSpec **pspecs);
+static void gimp_config_config_iface_init (GimpConfigInterface *iface);
+
+static void gimp_config_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_config_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static gboolean gimp_config_equal (GimpConfig *a,
+ GimpConfig *b);
+
+static GValue * gimp_config_value_get (GObject *object,
+ GParamSpec *pspec);
+static GValue * gimp_config_value_new (GParamSpec *pspec);
+static void gimp_config_value_free (GValue *value);
+
+
+/* public functions */
+
+/**
+ * gimp_config_type_register:
+ * @parent_type: type from which this type will be derived
+ * @type_name: string used as the name of the new type
+ * @pspecs: array of #GParamSpec to install as properties on the new type
+ * @n_pspecs: the number of param specs in @pspecs
+ *
+ * This function is a fancy wrapper around g_type_register_static().
+ * It creates a new object type as subclass of @parent_type, installs
+ * @pspecs on it and makes the new type implement the #GimpConfig
+ * interface.
+ *
+ * Returns: the newly registered #GType
+ *
+ * Since: 3.0
+ **/
+GType
+gimp_config_type_register (GType parent_type,
+ const gchar *type_name,
+ GParamSpec **pspecs,
+ gint n_pspecs)
+{
+ GParamSpec **terminated_pspecs;
+ GTypeQuery query;
+ GType config_type;
+
+ g_return_val_if_fail (g_type_is_a (parent_type, G_TYPE_OBJECT), G_TYPE_NONE);
+ g_return_val_if_fail (type_name != NULL, G_TYPE_NONE);
+ g_return_val_if_fail (pspecs != NULL, G_TYPE_NONE);
+ g_return_val_if_fail (n_pspecs > 0, G_TYPE_NONE);
+
+ terminated_pspecs = g_new0 (GParamSpec *, n_pspecs + 1);
+
+ memcpy (terminated_pspecs, pspecs, sizeof (GParamSpec *) * n_pspecs);
+
+ g_type_query (parent_type, &query);
+
+ {
+ GTypeInfo info =
+ {
+ query.class_size,
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gimp_config_class_init,
+ NULL, /* class_finalize */
+ terminated_pspecs,
+ query.instance_size,
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ };
+
+ const GInterfaceInfo config_info =
+ {
+ (GInterfaceInitFunc) gimp_config_config_iface_init,
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+
+ config_type = g_type_register_static (parent_type, type_name,
+ &info, 0);
+
+ g_type_add_interface_static (config_type, GIMP_TYPE_CONFIG,
+ &config_info);
+ }
+
+ return config_type;
+}
+
+
+/* private functions */
+
+static void
+gimp_config_class_init (GObjectClass *klass,
+ GParamSpec **pspecs)
+{
+ gint i;
+
+ klass->set_property = gimp_config_set_property;
+ klass->get_property = gimp_config_get_property;
+
+ for (i = 0; pspecs[i] != NULL; i++)
+ {
+ GParamSpec *pspec = pspecs[i];
+ GParamSpec *copy = gimp_config_param_spec_duplicate (pspec);
+
+ if (copy)
+ {
+ g_object_class_install_property (klass, i + 1, copy);
+ }
+ else if (! G_IS_PARAM_SPEC_OBJECT (pspec) &&
+ ! G_IS_PARAM_SPEC_POINTER (pspec))
+ {
+ /* silently ignore object properties */
+
+ g_warning ("%s: not supported: %s (%s)\n", G_STRFUNC,
+ g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name);
+ }
+ }
+}
+
+static void
+gimp_config_config_iface_init (GimpConfigInterface *iface)
+{
+ iface->equal = gimp_config_equal;
+}
+
+static void
+gimp_config_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GValue *val = gimp_config_value_get (object, pspec);
+
+ g_value_copy (value, val);
+}
+
+static void
+gimp_config_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GValue *val = gimp_config_value_get (object, pspec);
+
+ g_value_copy (val, value);
+}
+
+static gboolean
+gimp_config_equal (GimpConfig *a,
+ GimpConfig *b)
+{
+ GList *diff;
+ gboolean equal = TRUE;
+
+ diff = gimp_config_diff (G_OBJECT (a), G_OBJECT (b),
+ GIMP_CONFIG_PARAM_SERIALIZE);
+
+ if (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b))
+ {
+ GList *list;
+
+ for (list = diff; list; list = g_list_next (list))
+ {
+ GParamSpec *pspec = list->data;
+
+ if (pspec->owner_type == G_TYPE_FROM_INSTANCE (a))
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ }
+ else if (diff)
+ {
+ equal = FALSE;
+ }
+
+ g_list_free (diff);
+
+ return equal;
+}
+
+static GValue *
+gimp_config_value_get (GObject *object,
+ GParamSpec *pspec)
+{
+ GHashTable *properties;
+ GValue *value;
+
+ properties = g_object_get_data (object, "gimp-config-properties");
+
+ if (! properties)
+ {
+ properties =
+ g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) gimp_config_value_free);
+
+ g_object_set_data_full (object, "gimp-config-properties", properties,
+ (GDestroyNotify) g_hash_table_unref);
+ }
+
+ value = g_hash_table_lookup (properties, pspec->name);
+
+ if (! value)
+ {
+ value = gimp_config_value_new (pspec);
+ g_hash_table_insert (properties, g_strdup (pspec->name), value);
+ }
+
+ return value;
+}
+
+static GValue *
+gimp_config_value_new (GParamSpec *pspec)
+{
+ GValue *value = g_slice_new0 (GValue);
+
+ g_value_init (value, pspec->value_type);
+ g_param_value_set_default (pspec, value);
+
+ return value;
+}
+
+static void
+gimp_config_value_free (GValue *value)
+{
+ g_value_unset (value);
+ g_slice_free (GValue, value);
+}
diff --git a/libgimpconfig/gimpconfig-register.h b/libgimpconfig/gimpconfig-register.h
new file mode 100644
index 0000000000..9cfd722a45
--- /dev/null
+++ b/libgimpconfig/gimpconfig-register.h
@@ -0,0 +1,42 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpconfig-register.c
+ * Copyright (C) 2008-2019 Michael Natterer <mitch gimp org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_CONFIG_H_INSIDE__) && !defined (GIMP_CONFIG_COMPILATION)
+#error "Only <libgimpconfig/gimpconfig.h> can be included directly."
+#endif
+
+#ifndef __GIMP_CONFIG_REGISTER_H__
+#define __GIMP_CONFIG_REGISTER_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+GType gimp_config_type_register (GType parent_type,
+ const gchar *type_name,
+ GParamSpec **pspecs,
+ gint n_pspecs);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_CONFIG_REGISTER_H__ */
diff --git a/libgimpconfig/gimpconfig.def b/libgimpconfig/gimpconfig.def
index d1d8d69363..81371a8d0a 100644
--- a/libgimpconfig/gimpconfig.def
+++ b/libgimpconfig/gimpconfig.def
@@ -35,11 +35,11 @@ EXPORTS
gimp_config_error_quark
gimp_config_get_type
gimp_config_is_equal_to
+ gimp_config_param_spec_duplicate
gimp_config_path_expand
gimp_config_path_expand_to_files
gimp_config_path_get_type
gimp_config_path_unexpand
- gimp_config_param_spec_duplicate
gimp_config_reset
gimp_config_reset_properties
gimp_config_reset_property
@@ -56,6 +56,7 @@ EXPORTS
gimp_config_serialize_value
gimp_config_string_append_escaped
gimp_config_sync
+ gimp_config_type_register
gimp_config_writer_close
gimp_config_writer_comment
gimp_config_writer_comment_mode
diff --git a/libgimpconfig/gimpconfig.h b/libgimpconfig/gimpconfig.h
index 1b2bb8e383..ae9f87fc3c 100644
--- a/libgimpconfig/gimpconfig.h
+++ b/libgimpconfig/gimpconfig.h
@@ -23,14 +23,15 @@
#include <libgimpconfig/gimpconfigtypes.h>
-#include <libgimpconfig/gimpconfigwriter.h>
-#include <libgimpconfig/gimpconfig-iface.h>
-#include <libgimpconfig/gimpconfig-error.h>
-#include <libgimpconfig/gimpconfig-serialize.h>
#include <libgimpconfig/gimpconfig-deserialize.h>
-#include <libgimpconfig/gimpconfig-utils.h>
+#include <libgimpconfig/gimpconfig-error.h>
+#include <libgimpconfig/gimpconfig-iface.h>
#include <libgimpconfig/gimpconfig-params.h>
#include <libgimpconfig/gimpconfig-path.h>
+#include <libgimpconfig/gimpconfig-register.h>
+#include <libgimpconfig/gimpconfig-serialize.h>
+#include <libgimpconfig/gimpconfig-utils.h>
+#include <libgimpconfig/gimpconfigwriter.h>
#include <libgimpconfig/gimpscanner.h>
#include <libgimpconfig/gimpcolorconfig.h>
diff --git a/libgimpconfig/meson.build b/libgimpconfig/meson.build
index e2af1f3dae..ce95f4a884 100644
--- a/libgimpconfig/meson.build
+++ b/libgimpconfig/meson.build
@@ -19,8 +19,9 @@ libgimpconfig_sources_introspectable = files(
'gimpconfig-deserialize.c',
'gimpconfig-error.c',
'gimpconfig-iface.c',
- 'gimpconfig-path.c',
'gimpconfig-params.c',
+ 'gimpconfig-path.c',
+ 'gimpconfig-register.c',
'gimpconfig-serialize.c',
'gimpconfig-utils.c',
'gimpconfigwriter.c',
@@ -39,6 +40,7 @@ libgimpconfig_headers_introspectable = files(
'gimpconfig-iface.h',
'gimpconfig-params.h',
'gimpconfig-path.h',
+ 'gimpconfig-register.h',
'gimpconfig-serialize.h',
'gimpconfig-utils.h',
'gimpconfigenums.h',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]