diff --git a/app/pdb/drawable-filter-cmds.c b/app/pdb/drawable-filter-cmds.c index c71db38af4..8283e2479f 100644 --- a/app/pdb/drawable-filter-cmds.c +++ b/app/pdb/drawable-filter-cmds.c @@ -39,6 +39,7 @@ #include "core/gimpimage-undo-push.h" #include "core/gimpitem.h" #include "core/gimpparamspecs.h" +#include "gegl/gimp-gegl-utils.h" #include "operations/gimp-operation-config.h" #include "operations/gimpoperationsettings.h" @@ -61,7 +62,7 @@ validate_operation_name (const gchar *operation_name, op_type = gegl_operation_gtype_from_name (operation_name); - /* Using the same rules as in xcf_load_effect() for plug-in created + /* Using the same rules as in xcf_load_effect () for plug-in created * effects. */ if (g_type_is_a (op_type, GEGL_TYPE_OPERATION_SINK)) @@ -707,6 +708,202 @@ drawable_filter_delete_invoker (GimpProcedure *procedure, error ? *error : NULL); } +static GimpValueArray * +drawable_filter_operation_get_available_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + gchar **names = NULL; + + GList *ops = NULL; + GStrvBuilder *builder = NULL; + + ops = gimp_gegl_get_op_classes (FALSE); + builder = g_strv_builder_new (); + + for (GList *op = ops; op != NULL; op = op->next) + { + GeglOperationClass *op_klass = op->data; + + if (!validate_operation_name (op_klass->name, NULL)) + continue; + + g_strv_builder_add (builder, op_klass->name); + } + + names = g_strv_builder_end (builder); + + g_list_free (ops); + g_strv_builder_unref (builder); + + return_vals = gimp_procedure_get_return_values (procedure, TRUE, NULL); + g_value_take_boxed (gimp_value_array_index (return_vals, 1), names); + + return return_vals; +} + +static GimpValueArray * +drawable_filter_operation_get_details_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpValueArray *return_vals; + const gchar *operation_name; + gchar **propnames = NULL; + GimpValueArray *propvalues = NULL; + + operation_name = g_value_get_string (gimp_value_array_index (args, 0)); + + if (success) + { + if (validate_operation_name (operation_name, error)) + { + GStrvBuilder *names_builder = NULL; + GeglOperationClass *klass = NULL; + gchar *license = NULL; + GType op_type; + GValue value = G_VALUE_INIT; + + /* Comes from gegl/operation/gegl-operations.h which is not public. */ + GType gegl_operation_gtype_from_name (const gchar *name); + + names_builder = g_strv_builder_new (); + propvalues = gimp_value_array_new (0); + + op_type = gegl_operation_gtype_from_name (operation_name); + klass = g_type_class_ref (op_type); + + g_value_init (&value, G_TYPE_STRING); + + g_strv_builder_add (names_builder, "title"); + g_value_take_string (&value, g_strdup (gegl_operation_class_get_key (klass, "title"))); + gimp_value_array_append (propvalues, &value); + + g_strv_builder_add (names_builder, "description"); + g_value_take_string (&value, g_strdup (gegl_operation_class_get_key (klass, "description"))); + gimp_value_array_append (propvalues, &value); + + g_strv_builder_add (names_builder, "categories"); + g_value_take_string (&value, g_strdup (gegl_operation_class_get_key (klass, "categories"))); + gimp_value_array_append (propvalues, &value); + + license = g_strdup (gegl_operation_class_get_key (klass, "license")); + if (license == NULL) + license = g_strdup ("unknown"); + + g_strv_builder_add (names_builder, "license"); + g_value_take_string (&value, license); + gimp_value_array_append (propvalues, &value); + + propnames = g_strv_builder_end (names_builder); + + g_strv_builder_unref (names_builder); + } + else + { + success = FALSE; + } + } + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + if (success) + { + g_value_take_boxed (gimp_value_array_index (return_vals, 1), propnames); + g_value_take_boxed (gimp_value_array_index (return_vals, 2), propvalues); + } + + return return_vals; +} + +static GimpValueArray * +drawable_filter_operation_get_pspecs_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpValueArray *return_vals; + const gchar *operation_name; + GimpValueArray *pspecs = NULL; + + operation_name = g_value_get_string (gimp_value_array_index (args, 0)); + + if (success) + { + if (validate_operation_name (operation_name, error)) + { + GParamSpec **specs = NULL; + guint n_specs = 0; + guint n_parent_specs = 0; + + if (gimp_operation_config_is_custom (gimp, operation_name)) + { + GObjectClass *op_config_klass = NULL; + GObjectClass *op_parent_klass = NULL; + GType op_config_type; + GType op_parent_type; + + op_config_type = gimp_operation_config_get_type (gimp, operation_name, NULL, GIMP_TYPE_OPERATION_SETTINGS); + op_config_klass = g_type_class_ref (op_config_type); + specs = g_object_class_list_properties (op_config_klass, &n_specs); + g_type_class_unref (op_config_klass); + + op_parent_type = g_type_parent (op_config_type); + op_parent_klass = g_type_class_ref (op_parent_type); + g_free (g_object_class_list_properties (op_parent_klass, &n_parent_specs)); + g_type_class_unref (op_parent_klass); + + n_specs -= n_parent_specs; + } + else + { + specs = gegl_operation_list_properties (operation_name, &n_specs); + } + + pspecs = gimp_value_array_new (n_specs); + + for (gint i = 0; i < n_specs; i++) + { + GParamSpec *pspec = specs[n_parent_specs + i]; + GValue value = G_VALUE_INIT; + + g_value_init (&value, G_TYPE_PARAM); + + g_value_set_param (&value, g_param_spec_ref (pspec)); + gimp_value_array_append (pspecs, &value); + + g_value_unset (&value); + } + + g_free (specs); + } + else + { + success = FALSE; + } + } + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + if (success) + g_value_take_boxed (gimp_value_array_index (return_vals, 1), pspecs); + + return return_vals; +} + void register_drawable_filter_procs (GimpPDB *pdb) { @@ -1171,4 +1368,97 @@ register_drawable_filter_procs (GimpPDB *pdb) GIMP_PARAM_READWRITE)); gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + + /* + * gimp-drawable-filter-operation-get-available + */ + procedure = gimp_procedure_new (drawable_filter_operation_get_available_invoker, FALSE); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-drawable-filter-operation-get-available"); + gimp_procedure_set_static_help (procedure, + "Get a list of all available GEGL operation names for drawable filters.", + "This procedure returns a list of all GEGL operation names available for use with drawable filters.", + NULL); + gimp_procedure_set_static_attribution (procedure, + "Ondřej Míchal ", + "Ondřej Míchal", + "2025"); + gimp_procedure_add_return_value (procedure, + g_param_spec_boxed ("names", + "names", + "The list of GEGL operation names", + G_TYPE_STRV, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-drawable-filter-operation-get-details + */ + procedure = gimp_procedure_new (drawable_filter_operation_get_details_invoker, FALSE); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-drawable-filter-operation-get-details"); + gimp_procedure_set_static_help (procedure, + "Get information about a GEGL operation.", + "This procedure returns information about a GEGL operation. The content of the list of information can vary across versions and currently can contain:\n" + "- a human-readable title of the operation, - a description of the operation's behaviour, - the categories the operation belongs to, and - the license of the operation.\n" + "An operation can belong to no categories or to multiple categories. Multiple categories are separated by the ':' character.\n" + "Some operation's license is not specifically set. In such cases, the returned license is 'unknown'.", + NULL); + gimp_procedure_set_static_attribution (procedure, + "Ondřej Míchal ", + "Ondřej Míchal", + "2025"); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("operation-name", + "operation name", + "The GEGL operation's name", + FALSE, FALSE, FALSE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + g_param_spec_boxed ("propnames", + "propnames", + "The names of properties", + G_TYPE_STRV, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + gimp_param_spec_value_array ("propvalues", + "propvalues", + "The values of properties in the same order", + NULL, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-drawable-filter-operation-get-pspecs + */ + procedure = gimp_procedure_new (drawable_filter_operation_get_pspecs_invoker, FALSE); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-drawable-filter-operation-get-pspecs"); + gimp_procedure_set_static_help (procedure, + "Get information for all parameters of a GEGL operation.", + "This procedure returns a list of all parameters used to configure a GEGL operation.\n" + "Each parameter is represented by GParamSpec.", + NULL); + gimp_procedure_set_static_attribution (procedure, + "Ondřej Míchal ", + "Ondřej Míchal", + "2025"); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("operation-name", + "operation name", + "The GEGL operation's name", + FALSE, FALSE, FALSE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + gimp_param_spec_value_array ("pspecs", + "pspecs", + "List of all parameters of the GEGL operation", + NULL, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); } diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c index 704577eca0..124df49769 100644 --- a/app/pdb/internal-procs.c +++ b/app/pdb/internal-procs.c @@ -30,7 +30,7 @@ #include "internal-procs.h" -/* 718 procedures registered total */ +/* 721 procedures registered total */ void internal_procs_init (GimpPDB *pdb) diff --git a/libgimp/gimp.def b/libgimp/gimp.def index a5532405e3..836bfaa87e 100644 --- a/libgimp/gimp.def +++ b/libgimp/gimp.def @@ -227,6 +227,9 @@ EXPORTS gimp_drawable_filter_id_is_valid gimp_drawable_filter_is_valid gimp_drawable_filter_new + gimp_drawable_filter_operation_get_available + gimp_drawable_filter_operation_get_details + gimp_drawable_filter_operation_get_pspecs gimp_drawable_filter_set_aux_input gimp_drawable_filter_set_blend_mode gimp_drawable_filter_set_opacity diff --git a/libgimp/gimpdrawablefilter_pdb.c b/libgimp/gimpdrawablefilter_pdb.c index 8cc4b7367f..6ccc70cc9c 100644 --- a/libgimp/gimpdrawablefilter_pdb.c +++ b/libgimp/gimpdrawablefilter_pdb.c @@ -573,3 +573,137 @@ gimp_drawable_filter_delete (GimpDrawableFilter *filter) return success; } + +/** + * gimp_drawable_filter_operation_get_available: + * + * Get a list of all available GEGL operation names for drawable + * filters. + * + * This procedure returns a list of all GEGL operation names available + * for use with drawable filters. + * + * Returns: (array zero-terminated=1) (transfer full): + * The list of GEGL operation names. + * The returned value must be freed with g_strfreev(). + * + * Since: 3.2 + **/ +gchar ** +gimp_drawable_filter_operation_get_available (void) +{ + GimpValueArray *args; + GimpValueArray *return_vals; + gchar **names = NULL; + + args = gimp_value_array_new_from_types (NULL, + G_TYPE_NONE); + + return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (), + "gimp-drawable-filter-operation-get-available", + args); + gimp_value_array_unref (args); + + if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS) + names = GIMP_VALUES_DUP_STRV (return_vals, 1); + + gimp_value_array_unref (return_vals); + + return names; +} + +/** + * gimp_drawable_filter_operation_get_details: + * @operation_name: The GEGL operation's name. + * @propnames: (out) (array zero-terminated=1) (transfer full): The names of properties. + * @propvalues: (out): The values of properties in the same order. + * + * Get information about a GEGL operation. + * + * This procedure returns information about a GEGL operation. The + * content of the list of information can vary across versions and + * currently can contain: + * - a human-readable title of the operation, - a description of the + * operation's behaviour, - the categories the operation belongs to, + * and - the license of the operation. + * An operation can belong to no categories or to multiple categories. + * Multiple categories are separated by the ':' character. + * Some operation's license is not specifically set. In such cases, the + * returned license is 'unknown'. + * + * Returns: TRUE on success. + * + * Since: 3.2 + **/ +gboolean +gimp_drawable_filter_operation_get_details (const gchar *operation_name, + gchar ***propnames, + GimpValueArray **propvalues) +{ + GimpValueArray *args; + GimpValueArray *return_vals; + gboolean success = TRUE; + + args = gimp_value_array_new_from_types (NULL, + G_TYPE_STRING, operation_name, + G_TYPE_NONE); + + return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (), + "gimp-drawable-filter-operation-get-details", + args); + gimp_value_array_unref (args); + + *propnames = NULL; + *propvalues = NULL; + + success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS; + + if (success) + { + *propnames = GIMP_VALUES_DUP_STRV (return_vals, 1); + *propvalues = g_value_dup_boxed (gimp_value_array_index (return_vals, 2)); + } + + gimp_value_array_unref (return_vals); + + return success; +} + +/** + * gimp_drawable_filter_operation_get_pspecs: + * @operation_name: The GEGL operation's name. + * + * Get information for all parameters of a GEGL operation. + * + * This procedure returns a list of all parameters used to configure a + * GEGL operation. + * Each parameter is represented by GParamSpec. + * + * Returns: List of all parameters of the GEGL operation. + * The returned value must be freed with g_free(). + * + * Since: 3.2 + **/ +GimpValueArray * +gimp_drawable_filter_operation_get_pspecs (const gchar *operation_name) +{ + GimpValueArray *args; + GimpValueArray *return_vals; + GimpValueArray *pspecs = NULL; + + args = gimp_value_array_new_from_types (NULL, + G_TYPE_STRING, operation_name, + G_TYPE_NONE); + + return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (), + "gimp-drawable-filter-operation-get-pspecs", + args); + gimp_value_array_unref (args); + + if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS) + pspecs = g_value_dup_boxed (gimp_value_array_index (return_vals, 1)); + + gimp_value_array_unref (return_vals); + + return pspecs; +} diff --git a/libgimp/gimpdrawablefilter_pdb.h b/libgimp/gimpdrawablefilter_pdb.h index 3ef1f57953..02ab767476 100644 --- a/libgimp/gimpdrawablefilter_pdb.h +++ b/libgimp/gimpdrawablefilter_pdb.h @@ -31,32 +31,37 @@ G_BEGIN_DECLS /* For information look into the C source or the html documentation */ -gboolean gimp_drawable_filter_id_is_valid (gint filter_id); -GimpDrawableFilter* gimp_drawable_filter_new (GimpDrawable *drawable, - const gchar *operation_name, - const gchar *name); -gchar* gimp_drawable_filter_get_name (GimpDrawableFilter *filter); -gchar* gimp_drawable_filter_get_operation_name (GimpDrawableFilter *filter); -gboolean gimp_drawable_filter_get_visible (GimpDrawableFilter *filter); -gboolean gimp_drawable_filter_set_visible (GimpDrawableFilter *filter, - gboolean visible); -gdouble gimp_drawable_filter_get_opacity (GimpDrawableFilter *filter); -GimpLayerMode gimp_drawable_filter_get_blend_mode (GimpDrawableFilter *filter); -G_GNUC_INTERNAL gboolean _gimp_drawable_filter_update (GimpDrawableFilter *filter, - const gchar **propnames, - const GimpValueArray *propvalues, - gdouble opacity, - GimpLayerMode blend_mode, - GimpLayerColorSpace blend_space, - GimpLayerCompositeMode composite_mode, - GimpLayerColorSpace composite_space, - const gchar **auxinputnames, - const GimpDrawable **auxinputs); -G_GNUC_INTERNAL gint _gimp_drawable_filter_get_number_arguments (GimpDrawableFilter *filter); -G_GNUC_INTERNAL GParamSpec* _gimp_drawable_filter_get_pspec (GimpDrawableFilter *filter, - gint arg_num); -G_GNUC_INTERNAL gchar** _gimp_drawable_filter_get_arguments (GimpDrawableFilter *filter, - GimpValueArray **values); -gboolean gimp_drawable_filter_delete (GimpDrawableFilter *filter); +gboolean gimp_drawable_filter_id_is_valid (gint filter_id); +GimpDrawableFilter* gimp_drawable_filter_new (GimpDrawable *drawable, + const gchar *operation_name, + const gchar *name); +gchar* gimp_drawable_filter_get_name (GimpDrawableFilter *filter); +gchar* gimp_drawable_filter_get_operation_name (GimpDrawableFilter *filter); +gboolean gimp_drawable_filter_get_visible (GimpDrawableFilter *filter); +gboolean gimp_drawable_filter_set_visible (GimpDrawableFilter *filter, + gboolean visible); +gdouble gimp_drawable_filter_get_opacity (GimpDrawableFilter *filter); +GimpLayerMode gimp_drawable_filter_get_blend_mode (GimpDrawableFilter *filter); +G_GNUC_INTERNAL gboolean _gimp_drawable_filter_update (GimpDrawableFilter *filter, + const gchar **propnames, + const GimpValueArray *propvalues, + gdouble opacity, + GimpLayerMode blend_mode, + GimpLayerColorSpace blend_space, + GimpLayerCompositeMode composite_mode, + GimpLayerColorSpace composite_space, + const gchar **auxinputnames, + const GimpDrawable **auxinputs); +G_GNUC_INTERNAL gint _gimp_drawable_filter_get_number_arguments (GimpDrawableFilter *filter); +G_GNUC_INTERNAL GParamSpec* _gimp_drawable_filter_get_pspec (GimpDrawableFilter *filter, + gint arg_num); +G_GNUC_INTERNAL gchar** _gimp_drawable_filter_get_arguments (GimpDrawableFilter *filter, + GimpValueArray **values); +gboolean gimp_drawable_filter_delete (GimpDrawableFilter *filter); +gchar** gimp_drawable_filter_operation_get_available (void); +gboolean gimp_drawable_filter_operation_get_details (const gchar *operation_name, + gchar ***propnames, + GimpValueArray **propvalues); +GimpValueArray* gimp_drawable_filter_operation_get_pspecs (const gchar *operation_name); G_END_DECLS diff --git a/pdb/groups/drawable_filter.pdb b/pdb/groups/drawable_filter.pdb index 46dc1a44a3..5cae11c4a1 100644 --- a/pdb/groups/drawable_filter.pdb +++ b/pdb/groups/drawable_filter.pdb @@ -645,6 +645,230 @@ CODE ); } +sub drawable_filter_operation_get_available { + $blurb = 'Get a list of all available GEGL operation names for drawable filters.'; + + $help = <<'HELP'; +This procedure returns a list of all GEGL operation names available for use +with drawable filters. +HELP + + &martymichal_pdb_misc('2025', '3.2'); + + @outargs = ( + { + name => 'names', type => 'strv', + desc => 'The list of GEGL operation names', + } + ); + + %invoke = ( + code => <<'CODE' +{ + GList *ops = NULL; + GStrvBuilder *builder = NULL; + + ops = gimp_gegl_get_op_classes (FALSE); + builder = g_strv_builder_new (); + + for (GList *op = ops; op != NULL; op = op->next) + { + GeglOperationClass *op_klass = op->data; + + if (!validate_operation_name (op_klass->name, NULL)) + continue; + + g_strv_builder_add (builder, op_klass->name); + } + + names = g_strv_builder_end (builder); + + g_list_free (ops); + g_strv_builder_unref (builder); +} +CODE + ); +} + +sub drawable_filter_operation_get_details { + $blurb = 'Get information about a GEGL operation.'; + + $help = <<'HELP'; +This procedure returns information about a GEGL operation. The content of the +list of information can vary across versions and currently can contain: + +- a human-readable title of the operation, +- a description of the operation's behaviour, +- the categories the operation belongs to, and +- the license of the operation. + +An operation can belong to no categories or to multiple categories. Multiple +categories are separated by the ':' character. + +Some operation's license is not specifically set. In such cases, the returned +license is 'unknown'. +HELP + + &martymichal_pdb_misc('2025', '3.2'); + + @inargs = ( + { + name => 'operation_name', type => 'string', + desc => 'The GEGL operation\'s name', + } + ); + + @outargs = ( + { + name => 'propnames', type => 'strv', void_ret => 1, + desc => 'The names of properties', + }, + { + name => 'propvalues', type => 'valuearray', + desc => 'The values of properties in the same order', + }, + ); + + %invoke = ( + code => <<'CODE' +{ +if (validate_operation_name (operation_name, error)) + { + GStrvBuilder *names_builder = NULL; + GeglOperationClass *klass = NULL; + gchar *license = NULL; + GType op_type; + GValue value = G_VALUE_INIT; + + /* Comes from gegl/operation/gegl-operations.h which is not public. */ + GType gegl_operation_gtype_from_name (const gchar *name); + + names_builder = g_strv_builder_new (); + propvalues = gimp_value_array_new (0); + + op_type = gegl_operation_gtype_from_name (operation_name); + klass = g_type_class_ref (op_type); + + g_value_init (&value, G_TYPE_STRING); + + g_strv_builder_add (names_builder, "title"); + g_value_take_string (&value, g_strdup (gegl_operation_class_get_key (klass, "title"))); + gimp_value_array_append (propvalues, &value); + + g_strv_builder_add (names_builder, "description"); + g_value_take_string (&value, g_strdup (gegl_operation_class_get_key (klass, "description"))); + gimp_value_array_append (propvalues, &value); + + g_strv_builder_add (names_builder, "categories"); + g_value_take_string (&value, g_strdup (gegl_operation_class_get_key (klass, "categories"))); + gimp_value_array_append (propvalues, &value); + + license = g_strdup (gegl_operation_class_get_key (klass, "license")); + if (license == NULL) + license = g_strdup ("unknown"); + + g_strv_builder_add (names_builder, "license"); + g_value_take_string (&value, license); + gimp_value_array_append (propvalues, &value); + + propnames = g_strv_builder_end (names_builder); + + g_strv_builder_unref (names_builder); + } + else + { + success = FALSE; + } +} +CODE + ); +} + +sub drawable_filter_operation_get_pspecs { + $blurb = 'Get information for all parameters of a GEGL operation.'; + + $help = <<'HELP'; +This procedure returns a list of all parameters used to configure a GEGL +operation. + +Each parameter is represented by GParamSpec. +HELP + + &martymichal_pdb_misc('2025', '3.2'); + + @inargs = ( + { + name => 'operation_name', type => 'string', + desc => 'The GEGL operation\'s name', + } + ); + + @outargs = ( + { + name => 'pspecs', type => 'valuearray', + desc => "List of all parameters of the GEGL operation", + } + ); + + %invoke = ( + code => <<'CODE' +{ + if (validate_operation_name (operation_name, error)) + { + GParamSpec **specs = NULL; + guint n_specs = 0; + guint n_parent_specs = 0; + + if (gimp_operation_config_is_custom (gimp, operation_name)) + { + GObjectClass *op_config_klass = NULL; + GObjectClass *op_parent_klass = NULL; + GType op_config_type; + GType op_parent_type; + + op_config_type = gimp_operation_config_get_type (gimp, operation_name, NULL, GIMP_TYPE_OPERATION_SETTINGS); + op_config_klass = g_type_class_ref (op_config_type); + specs = g_object_class_list_properties (op_config_klass, &n_specs); + g_type_class_unref (op_config_klass); + + op_parent_type = g_type_parent (op_config_type); + op_parent_klass = g_type_class_ref (op_parent_type); + g_free (g_object_class_list_properties (op_parent_klass, &n_parent_specs)); + g_type_class_unref (op_parent_klass); + + n_specs -= n_parent_specs; + } + else + { + specs = gegl_operation_list_properties (operation_name, &n_specs); + } + + pspecs = gimp_value_array_new (n_specs); + + for (gint i = 0; i < n_specs; i++) + { + GParamSpec *pspec = specs[n_parent_specs + i]; + GValue value = G_VALUE_INIT; + + g_value_init (&value, G_TYPE_PARAM); + + g_value_set_param (&value, g_param_spec_ref (pspec)); + gimp_value_array_append (pspecs, &value); + + g_value_unset (&value); + } + + g_free (specs); + } + else + { + success = FALSE; + } +} +CODE + ); +} + $extra{app}->{code} = <<'CODE'; static gboolean validate_operation_name (const gchar *operation_name, @@ -657,7 +881,7 @@ validate_operation_name (const gchar *operation_name, op_type = gegl_operation_gtype_from_name (operation_name); - /* Using the same rules as in xcf_load_effect() for plug-in created + /* Using the same rules as in xcf_load_effect () for plug-in created * effects. */ if (g_type_is_a (op_type, GEGL_TYPE_OPERATION_SINK)) @@ -706,6 +930,7 @@ CODE "core/gimpdrawable-filters.h" "core/gimpimage-undo-push.h" "core/gimpitem.h" + "gegl/gimp-gegl-utils.h" "operations/gimp-operation-config.h" "operations/gimpoperationsettings.h" "gimppdberror.h" @@ -723,7 +948,10 @@ CODE drawable_filter_get_number_arguments drawable_filter_get_pspec drawable_filter_get_arguments - drawable_filter_delete); + drawable_filter_delete + drawable_filter_operation_get_available + drawable_filter_operation_get_details + drawable_filter_operation_get_pspecs); %exports = (app => [@procs], lib => [@procs]); diff --git a/pdb/stddefs.pdb b/pdb/stddefs.pdb index 73f8b241bd..5213fa1d01 100644 --- a/pdb/stddefs.pdb +++ b/pdb/stddefs.pdb @@ -125,6 +125,10 @@ sub martin_pdb_misc { contrib_pdb_misc('Martin Nordholts', '', @_); } +sub martymichal_pdb_misc { + contrib_pdb_misc('Ondřej Míchal', 'harrymichal@seznam.cz', @_); +} + sub mitch_pdb_misc { contrib_pdb_misc('Michael Natterer', 'mitch@gimp.org', @_); }