Issue #12568: support GIMP's GEGL operations with a custom config argument…

… in new filter API.
This commit is contained in:
Jehan
2025-01-27 13:17:49 +01:00
parent 79b200335c
commit 679220d8f5
6 changed files with 291 additions and 65 deletions

View File

@ -38,6 +38,8 @@
#include "core-types.h" #include "core-types.h"
#include "operations/gimp-operation-config.h"
#include "gegl/gimp-babl.h" #include "gegl/gimp-babl.h"
#include "gegl/gimpapplicator.h" #include "gegl/gimpapplicator.h"
#include "gegl/gimp-gegl-utils.h" #include "gegl/gimp-gegl-utils.h"
@ -769,9 +771,12 @@ gimp_drawable_filter_set_preview_split (GimpDrawableFilter *filter,
} }
} }
/* This function is mostly for usage by libgimp API. The idea is to have /* This function is **ONLY** for usage by libgimp API. The idea is to have
* a single function which updates a bunch of settings in a single call * a single function which updates a bunch of settings in a single call
* and in particular a single rendering update. * and in particular a single rendering update.
*
* Also it does some funky config object switch for custom operations
* which is only needed libgimp-side.
*/ */
gboolean gboolean
gimp_drawable_filter_update (GimpDrawableFilter *filter, gimp_drawable_filter_update (GimpDrawableFilter *filter,
@ -786,8 +791,12 @@ gimp_drawable_filter_update (GimpDrawableFilter *filter,
const GimpDrawable **auxinputs, const GimpDrawable **auxinputs,
GError **error) GError **error)
{ {
GimpImage *image;
GimpObject *settings = NULL;
GeglNode *node = NULL;
GParamSpec **pspecs; GParamSpec **pspecs;
gchar *opname; gchar *opname;
guint n_parent_pspecs = 0;
guint n_pspecs; guint n_pspecs;
gint n_values; gint n_values;
gint n_auxinputs; gint n_auxinputs;
@ -822,14 +831,55 @@ gimp_drawable_filter_update (GimpDrawableFilter *filter,
gegl_node_get (filter->operation, "operation", &opname, NULL); gegl_node_get (filter->operation, "operation", &opname, NULL);
pspecs = gegl_operation_list_properties (opname, &n_pspecs); image = gimp_item_get_image (GIMP_ITEM (filter->drawable));
for (gint i = 0; i < n_pspecs; i++) node = gimp_drawable_filter_get_operation (filter);
if (gimp_operation_config_is_custom (image->gimp, opname))
{ {
GObjectClass *klass;
GObjectClass *parent_klass;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_pspecs));
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &n_pspecs);
}
else
{
pspecs = gegl_operation_list_properties (opname, &n_pspecs);
}
for (gint i = n_parent_pspecs; i < n_pspecs; i++)
{
GParamSpec *target_pspec;
GParamSpec *pspec = pspecs[i]; GParamSpec *pspec = pspecs[i];
GValue old_value = G_VALUE_INIT; GValue old_value = G_VALUE_INIT;
gint j; gint j;
gegl_node_get_property (filter->operation, pspec->name, &old_value); if (settings)
target_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), pspec->name);
else
target_pspec = gegl_node_find_property (node, pspec->name);
if (! target_pspec)
{
/* If this ever happens, this is more likely a bug in our
* PDB code, unless someone tried to call the PDB procedure
* directly with bad data.
*/
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
/* TODO: localize after string freeze. */
"GEGL operation '%s' has been called with a "
"non-existent argument name '%s' (#%d).",
opname, pspec->name, i);
break;
}
if (settings)
g_object_get_property (G_OBJECT (settings), pspec->name, &old_value);
else
gegl_node_get_property (node, pspec->name, &old_value);
for (j = 0; j < n_values; j++) for (j = 0; j < n_values; j++)
if (g_strcmp0 (pspec->name, propnames[j]) == 0) if (g_strcmp0 (pspec->name, propnames[j]) == 0)
@ -897,7 +947,10 @@ gimp_drawable_filter_update (GimpDrawableFilter *filter,
if (g_param_values_cmp (pspec, new_value, &old_value) != 0) if (g_param_values_cmp (pspec, new_value, &old_value) != 0)
{ {
gegl_node_set_property (filter->operation, pspec->name, new_value); if (settings)
g_object_set_property (G_OBJECT (settings), pspec->name, new_value);
else
gegl_node_set_property (node, pspec->name, new_value);
changed = TRUE; changed = TRUE;
} }
@ -913,7 +966,10 @@ gimp_drawable_filter_update (GimpDrawableFilter *filter,
g_value_init (&default_value, pspec->value_type); g_value_init (&default_value, pspec->value_type);
g_param_value_set_default (pspec, &default_value); g_param_value_set_default (pspec, &default_value);
gegl_node_set_property (filter->operation, pspec->name, &default_value); if (settings)
g_object_set_property (G_OBJECT (settings), pspec->name, &default_value);
else
gegl_node_set_property (node, pspec->name, &default_value);
changed = TRUE; changed = TRUE;
g_value_unset (&default_value); g_value_unset (&default_value);
@ -951,7 +1007,7 @@ gimp_drawable_filter_update (GimpDrawableFilter *filter,
GeglNode *src_node; GeglNode *src_node;
GeglBuffer *buffer; GeglBuffer *buffer;
if (! gegl_node_has_pad (filter->operation, auxinputnames[i])) if (! gegl_node_has_pad (node, auxinputnames[i]))
{ {
g_set_error (error, GIMP_ERROR, GIMP_FAILED, g_set_error (error, GIMP_ERROR, GIMP_FAILED,
/* TODO: localize after string freeze. */ /* TODO: localize after string freeze. */
@ -964,18 +1020,22 @@ gimp_drawable_filter_update (GimpDrawableFilter *filter,
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (auxinputs[i])); buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (auxinputs[i]));
g_object_ref (buffer); g_object_ref (buffer);
src_node = gegl_node_new_child (gegl_node_get_parent (filter->operation), src_node = gegl_node_new_child (gegl_node_get_parent (node),
"operation", "gegl:buffer-source", "operation", "gegl:buffer-source",
"buffer", buffer, "buffer", buffer,
NULL); NULL);
g_object_unref (buffer); g_object_unref (buffer);
gegl_node_connect (src_node, "output", filter->operation, auxinputnames[i]); gegl_node_connect (src_node, "output", node, auxinputnames[i]);
} }
} }
if (settings)
gegl_node_set (node, "config", settings, NULL);
g_object_thaw_notify (G_OBJECT (filter)); g_object_thaw_notify (G_OBJECT (filter));
g_clear_object (&settings);
g_free (pspecs); g_free (pspecs);
g_free (opname); g_free (opname);

View File

@ -39,6 +39,8 @@
#include "core/gimpimage-undo-push.h" #include "core/gimpimage-undo-push.h"
#include "core/gimpitem.h" #include "core/gimpitem.h"
#include "core/gimpparamspecs.h" #include "core/gimpparamspecs.h"
#include "operations/gimp-operation-config.h"
#include "operations/gimpoperationsettings.h"
#include "gimppdb.h" #include "gimppdb.h"
#include "gimppdberror.h" #include "gimppdberror.h"
@ -387,18 +389,46 @@ drawable_filter_get_number_arguments_invoker (GimpProcedure *procedure,
{ {
gboolean success = TRUE; gboolean success = TRUE;
GimpValueArray *return_vals; GimpValueArray *return_vals;
const gchar *operation_name; GimpDrawableFilter *filter;
gint num_args = 0; gint num_args = 0;
operation_name = g_value_get_string (gimp_value_array_index (args, 0)); filter = g_value_get_object (gimp_value_array_index (args, 0));
if (success) if (success)
{ {
if (gegl_has_operation (operation_name)) GeglNode *node;
const gchar *opname;
node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node);
if (gegl_has_operation (opname))
{ {
guint n_properties; guint n_properties;
g_free (gegl_operation_list_properties (operation_name, &n_properties)); if (gimp_operation_config_is_custom (gimp, opname))
{
GimpObject *settings = NULL;
GObjectClass *klass;
GObjectClass *parent_klass;
guint n_parent_properties;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_properties));
g_free (g_object_class_list_properties (klass, &n_properties));
g_clear_object (&settings);
n_properties -= n_parent_properties;
}
else
{
g_free (gegl_operation_list_properties (opname, &n_properties));
}
num_args = (gint) n_properties; num_args = (gint) n_properties;
} }
else else
@ -426,25 +456,49 @@ drawable_filter_get_pspec_invoker (GimpProcedure *procedure,
{ {
gboolean success = TRUE; gboolean success = TRUE;
GimpValueArray *return_vals; GimpValueArray *return_vals;
const gchar *operation_name; GimpDrawableFilter *filter;
gint arg_num; gint arg_num;
GParamSpec *param_spec = NULL; GParamSpec *param_spec = NULL;
operation_name = g_value_get_string (gimp_value_array_index (args, 0)); filter = g_value_get_object (gimp_value_array_index (args, 0));
arg_num = g_value_get_int (gimp_value_array_index (args, 1)); arg_num = g_value_get_int (gimp_value_array_index (args, 1));
if (success) if (success)
{ {
if (gegl_has_operation (operation_name)) GimpObject *settings = NULL;
GeglNode *node;
const gchar *opname;
node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node);
if (gegl_has_operation (opname))
{ {
GParamSpec **specs; GParamSpec **specs;
guint n_properties; guint n_properties;
guint n_parent_properties = 0;
specs = gegl_operation_list_properties (operation_name, &n_properties); if (gimp_operation_config_is_custom (gimp, opname))
if (arg_num >= 0 && arg_num < n_properties)
{ {
param_spec = g_param_spec_ref (specs[arg_num]); GObjectClass *klass;
GObjectClass *parent_klass;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_properties));
}
if (settings != NULL)
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &n_properties);
else
specs = gegl_operation_list_properties (opname, &n_properties);
if (arg_num >= 0 && n_parent_properties + arg_num < n_properties)
{
param_spec = g_param_spec_ref (specs[n_parent_properties + arg_num]);
} }
else else
{ {
@ -457,6 +511,8 @@ drawable_filter_get_pspec_invoker (GimpProcedure *procedure,
{ {
success = FALSE; success = FALSE;
} }
g_clear_object (&settings);
} }
return_vals = gimp_procedure_get_return_values (procedure, success, return_vals = gimp_procedure_get_return_values (procedure, success,
@ -490,23 +546,50 @@ drawable_filter_get_arguments_invoker (GimpProcedure *procedure,
const gchar *opname; const gchar *opname;
GParamSpec **specs; GParamSpec **specs;
guint n_specs; guint n_specs;
guint n_parent_properties = 0;
GStrvBuilder *names_builder; GStrvBuilder *names_builder;
GimpObject *settings = NULL;
node = gimp_drawable_filter_get_operation (filter); node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node); opname = gegl_node_get_operation (node);
specs = gegl_operation_list_properties (opname, &n_specs); if (gegl_has_operation (opname) &&
gimp_operation_config_is_custom (gimp, opname))
{
GObjectClass *klass;
GObjectClass *parent_klass;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_properties));
}
if (settings != NULL)
{
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &n_specs);
n_specs -= n_parent_properties;
}
else
{
specs = gegl_operation_list_properties (opname, &n_specs);
}
names_builder = g_strv_builder_new (); names_builder = g_strv_builder_new ();
values = gimp_value_array_new (n_specs); values = gimp_value_array_new (n_specs);
for (gint i = 0; i < n_specs; i++) for (gint i = 0; i < n_specs; i++)
{ {
GParamSpec *pspec = specs[i]; GParamSpec *pspec = specs[n_parent_properties + i];
GValue value = G_VALUE_INIT; GValue value = G_VALUE_INIT;
g_value_init (&value, pspec->value_type); g_value_init (&value, pspec->value_type);
gegl_node_get_property (node, pspec->name, &value); if (settings != NULL)
g_object_get_property (G_OBJECT (settings), pspec->name, &value);
else
gegl_node_get_property (node, pspec->name, &value);
if (GEGL_IS_PARAM_SPEC_ENUM (pspec)) if (GEGL_IS_PARAM_SPEC_ENUM (pspec))
{ {
@ -553,6 +636,7 @@ drawable_filter_get_arguments_invoker (GimpProcedure *procedure,
g_strv_builder_unref (names_builder); g_strv_builder_unref (names_builder);
g_free (specs); g_free (specs);
g_clear_object (&settings);
} }
return_vals = gimp_procedure_get_return_values (procedure, success, return_vals = gimp_procedure_get_return_values (procedure, success,
@ -958,12 +1042,11 @@ register_drawable_filter_procs (GimpPDB *pdb)
"Jehan", "Jehan",
"2024"); "2024");
gimp_procedure_add_argument (procedure, gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("operation-name", gimp_param_spec_drawable_filter ("filter",
"operation name", "filter",
"The procedure name", "The filter",
FALSE, FALSE, TRUE, FALSE,
NULL, GIMP_PARAM_READWRITE));
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure, gimp_procedure_add_return_value (procedure,
g_param_spec_int ("num-args", g_param_spec_int ("num-args",
"num args", "num args",
@ -988,12 +1071,11 @@ register_drawable_filter_procs (GimpPDB *pdb)
"Jehan", "Jehan",
"2024"); "2024");
gimp_procedure_add_argument (procedure, gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("operation-name", gimp_param_spec_drawable_filter ("filter",
"operation name", "filter",
"The procedure name", "The filter",
FALSE, FALSE, TRUE, FALSE,
NULL, GIMP_PARAM_READWRITE));
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure, gimp_procedure_add_argument (procedure,
g_param_spec_int ("arg-num", g_param_spec_int ("arg-num",
"arg num", "arg num",

View File

@ -323,7 +323,7 @@ gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
canonical_name = gimp_canonicalize_identifier (op_name); canonical_name = gimp_canonicalize_identifier (op_name);
config_type_name = g_strdup_printf ("GimpDrawableFilterConfig-%s", canonical_name); config_type_name = g_strdup_printf ("GimpDrawableFilterConfig-%s", canonical_name);
config_type = g_type_from_name (config_type_name); config_type = g_type_from_name (config_type_name);
n_args = _gimp_drawable_filter_get_number_arguments (op_name); n_args = _gimp_drawable_filter_get_number_arguments (filter);
if (! config_type) if (! config_type)
{ {
@ -335,7 +335,7 @@ gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
{ {
GParamSpec *pspec; GParamSpec *pspec;
pspec = _gimp_drawable_filter_get_pspec (op_name, i); pspec = _gimp_drawable_filter_get_pspec (filter, i);
config_args[i] = pspec; config_args[i] = pspec;
} }

View File

@ -416,7 +416,7 @@ _gimp_drawable_filter_update (GimpDrawableFilter *filter,
/** /**
* _gimp_drawable_filter_get_number_arguments: * _gimp_drawable_filter_get_number_arguments:
* @operation_name: The procedure name. * @filter: The filter.
* *
* Queries for the number of arguments on the specified filter. * Queries for the number of arguments on the specified filter.
* *
@ -430,14 +430,14 @@ _gimp_drawable_filter_update (GimpDrawableFilter *filter,
* Since: 3.0 * Since: 3.0
**/ **/
gint gint
_gimp_drawable_filter_get_number_arguments (const gchar *operation_name) _gimp_drawable_filter_get_number_arguments (GimpDrawableFilter *filter)
{ {
GimpValueArray *args; GimpValueArray *args;
GimpValueArray *return_vals; GimpValueArray *return_vals;
gint num_args = 0; gint num_args = 0;
args = gimp_value_array_new_from_types (NULL, args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, operation_name, GIMP_TYPE_DRAWABLE_FILTER, filter,
G_TYPE_NONE); G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (), return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
@ -455,7 +455,7 @@ _gimp_drawable_filter_get_number_arguments (const gchar *operation_name)
/** /**
* _gimp_drawable_filter_get_pspec: * _gimp_drawable_filter_get_pspec:
* @operation_name: The procedure name. * @filter: The filter.
* @arg_num: The argument number. * @arg_num: The argument number.
* *
* Queries for information on the specified filter's argument. * Queries for information on the specified filter's argument.
@ -468,15 +468,15 @@ _gimp_drawable_filter_get_number_arguments (const gchar *operation_name)
* Since: 3.0 * Since: 3.0
**/ **/
GParamSpec * GParamSpec *
_gimp_drawable_filter_get_pspec (const gchar *operation_name, _gimp_drawable_filter_get_pspec (GimpDrawableFilter *filter,
gint arg_num) gint arg_num)
{ {
GimpValueArray *args; GimpValueArray *args;
GimpValueArray *return_vals; GimpValueArray *return_vals;
GParamSpec *param_spec = NULL; GParamSpec *param_spec = NULL;
args = gimp_value_array_new_from_types (NULL, args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, operation_name, GIMP_TYPE_DRAWABLE_FILTER, filter,
G_TYPE_INT, arg_num, G_TYPE_INT, arg_num,
G_TYPE_NONE); G_TYPE_NONE);

View File

@ -53,8 +53,8 @@ G_GNUC_INTERNAL gboolean _gimp_drawable_filter_update (GimpDraw
GimpLayerColorSpace composite_space, GimpLayerColorSpace composite_space,
const gchar **auxinputnames, const gchar **auxinputnames,
const GimpDrawable **auxinputs); const GimpDrawable **auxinputs);
G_GNUC_INTERNAL gint _gimp_drawable_filter_get_number_arguments (const gchar *operation_name); G_GNUC_INTERNAL gint _gimp_drawable_filter_get_number_arguments (GimpDrawableFilter *filter);
G_GNUC_INTERNAL GParamSpec* _gimp_drawable_filter_get_pspec (const gchar *operation_name, G_GNUC_INTERNAL GParamSpec* _gimp_drawable_filter_get_pspec (GimpDrawableFilter *filter,
gint arg_num); gint arg_num);
G_GNUC_INTERNAL gchar** _gimp_drawable_filter_get_arguments (GimpDrawableFilter *filter, G_GNUC_INTERNAL gchar** _gimp_drawable_filter_get_arguments (GimpDrawableFilter *filter,
GimpValueArray **values); GimpValueArray **values);

View File

@ -372,8 +372,8 @@ HELP
$lib_private = 1; $lib_private = 1;
@inargs = ( @inargs = (
{ name => 'operation_name', type => 'string', non_empty => 1, { name => 'filter', type => 'filter',
desc => 'The procedure name' } desc => 'The filter' }
); );
@outargs = ( @outargs = (
@ -384,11 +384,39 @@ HELP
%invoke = ( %invoke = (
code => <<'CODE' code => <<'CODE'
{ {
if (gegl_has_operation (operation_name)) GeglNode *node;
const gchar *opname;
node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node);
if (gegl_has_operation (opname))
{ {
guint n_properties; guint n_properties;
g_free (gegl_operation_list_properties (operation_name, &n_properties)); if (gimp_operation_config_is_custom (gimp, opname))
{
GimpObject *settings = NULL;
GObjectClass *klass;
GObjectClass *parent_klass;
guint n_parent_properties;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_properties));
g_free (g_object_class_list_properties (klass, &n_properties));
g_clear_object (&settings);
n_properties -= n_parent_properties;
}
else
{
g_free (gegl_operation_list_properties (opname, &n_properties));
}
num_args = (gint) n_properties; num_args = (gint) n_properties;
} }
else else
@ -414,8 +442,8 @@ HELP
$lib_private = 1; $lib_private = 1;
@inargs = ( @inargs = (
{ name => 'operation_name', type => 'string', non_empty => 1, { name => 'filter', type => 'filter',
desc => 'The procedure name' }, desc => 'The filter' },
{ name => 'arg_num', type => 'int32', { name => 'arg_num', type => 'int32',
desc => 'The argument number' } desc => 'The argument number' }
); );
@ -426,18 +454,42 @@ HELP
); );
%invoke = ( %invoke = (
code => <<CODE code => <<'CODE'
{ {
if (gegl_has_operation (operation_name)) GimpObject *settings = NULL;
GeglNode *node;
const gchar *opname;
node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node);
if (gegl_has_operation (opname))
{ {
GParamSpec **specs; GParamSpec **specs;
guint n_properties; guint n_properties;
guint n_parent_properties = 0;
specs = gegl_operation_list_properties (operation_name, &n_properties); if (gimp_operation_config_is_custom (gimp, opname))
if (arg_num >= 0 && arg_num < n_properties)
{ {
param_spec = g_param_spec_ref (specs[arg_num]); GObjectClass *klass;
GObjectClass *parent_klass;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_properties));
}
if (settings != NULL)
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &n_properties);
else
specs = gegl_operation_list_properties (opname, &n_properties);
if (arg_num >= 0 && n_parent_properties + arg_num < n_properties)
{
param_spec = g_param_spec_ref (specs[n_parent_properties + arg_num]);
} }
else else
{ {
@ -450,6 +502,8 @@ HELP
{ {
success = FALSE; success = FALSE;
} }
g_clear_object (&settings);
} }
CODE CODE
); );
@ -486,23 +540,50 @@ HELP
const gchar *opname; const gchar *opname;
GParamSpec **specs; GParamSpec **specs;
guint n_specs; guint n_specs;
guint n_parent_properties = 0;
GStrvBuilder *names_builder; GStrvBuilder *names_builder;
GimpObject *settings = NULL;
node = gimp_drawable_filter_get_operation (filter); node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node); opname = gegl_node_get_operation (node);
specs = gegl_operation_list_properties (opname, &n_specs); if (gegl_has_operation (opname) &&
gimp_operation_config_is_custom (gimp, opname))
{
GObjectClass *klass;
GObjectClass *parent_klass;
gegl_node_get (node,
"config", &settings,
NULL);
klass = G_OBJECT_GET_CLASS (settings);
parent_klass = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
g_free (g_object_class_list_properties (parent_klass, &n_parent_properties));
}
if (settings != NULL)
{
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &n_specs);
n_specs -= n_parent_properties;
}
else
{
specs = gegl_operation_list_properties (opname, &n_specs);
}
names_builder = g_strv_builder_new (); names_builder = g_strv_builder_new ();
values = gimp_value_array_new (n_specs); values = gimp_value_array_new (n_specs);
for (gint i = 0; i < n_specs; i++) for (gint i = 0; i < n_specs; i++)
{ {
GParamSpec *pspec = specs[i]; GParamSpec *pspec = specs[n_parent_properties + i];
GValue value = G_VALUE_INIT; GValue value = G_VALUE_INIT;
g_value_init (&value, pspec->value_type); g_value_init (&value, pspec->value_type);
gegl_node_get_property (node, pspec->name, &value); if (settings != NULL)
g_object_get_property (G_OBJECT (settings), pspec->name, &value);
else
gegl_node_get_property (node, pspec->name, &value);
if (GEGL_IS_PARAM_SPEC_ENUM (pspec)) if (GEGL_IS_PARAM_SPEC_ENUM (pspec))
{ {
@ -549,6 +630,7 @@ HELP
g_strv_builder_unref (names_builder); g_strv_builder_unref (names_builder);
g_free (specs); g_free (specs);
g_clear_object (&settings);
} }
CODE CODE
); );
@ -600,6 +682,8 @@ CODE
"core/gimpdrawable-filters.h" "core/gimpdrawable-filters.h"
"core/gimpimage-undo-push.h" "core/gimpimage-undo-push.h"
"core/gimpitem.h" "core/gimpitem.h"
"operations/gimp-operation-config.h"
"operations/gimpoperationsettings.h"
"gimppdberror.h" "gimppdberror.h"
"gimp-intl.h"); "gimp-intl.h");