app, libgimp, pdb: make sure default values of a filter's config are right.

When calling gimp_drawable_filter_get_config() the first time, we don't
want the config's properties to be at default values, but instead to be
set same as they are on core app.

On further calls though, we don't touch the values, because they may be
out-of-sync until the next call to gimp_drawable_filter_update().
This commit is contained in:
Jehan 2024-12-13 17:08:27 +01:00
parent 4c07529553
commit 3da53852df
6 changed files with 321 additions and 27 deletions

View file

@ -412,12 +412,12 @@ drawable_filter_get_number_arguments_invoker (GimpProcedure *procedure,
} }
static GimpValueArray * static GimpValueArray *
drawable_filter_get_argument_invoker (GimpProcedure *procedure, drawable_filter_get_pspec_invoker (GimpProcedure *procedure,
Gimp *gimp, Gimp *gimp,
GimpContext *context, GimpContext *context,
GimpProgress *progress, GimpProgress *progress,
const GimpValueArray *args, const GimpValueArray *args,
GError **error) GError **error)
{ {
gboolean success = TRUE; gboolean success = TRUE;
GimpValueArray *return_vals; GimpValueArray *return_vals;
@ -463,6 +463,105 @@ drawable_filter_get_argument_invoker (GimpProcedure *procedure,
return return_vals; return return_vals;
} }
static GimpValueArray *
drawable_filter_get_arguments_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpValueArray *return_vals;
GimpDrawableFilter *filter;
gchar **argnames = NULL;
GimpValueArray *values = NULL;
filter = g_value_get_object (gimp_value_array_index (args, 0));
if (success)
{
GeglNode *node;
const gchar *opname;
GParamSpec **specs;
guint n_specs;
GStrvBuilder *names_builder;
node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node);
specs = gegl_operation_list_properties (opname, &n_specs);
names_builder = g_strv_builder_new ();
values = gimp_value_array_new (n_specs);
for (gint i = 0; i < n_specs; i++)
{
GParamSpec *pspec = specs[i];
GValue value = G_VALUE_INIT;
g_value_init (&value, pspec->value_type);
gegl_node_get_property (node, pspec->name, &value);
if (GEGL_IS_PARAM_SPEC_ENUM (pspec))
{
/* Special-casing GeglParamEnum which are passed as string to
* libgimp.
*/
GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
GEnumClass *enum_class = espec->enum_class;
GValue string_value = G_VALUE_INIT;
gint int_enum = g_value_get_enum (&value);
g_value_init (&string_value, G_TYPE_STRING);
for (gint j = 0; j < enum_class->n_values; j++)
{
GEnumValue enum_value = enum_class->values[j];
if (enum_value.value < enum_class->minimum || enum_value.value > enum_class->maximum)
continue;
if (enum_value.value == espec->default_value)
g_value_set_string (&string_value, enum_value.value_nick);
}
for (gint j = 0; j < enum_class->n_values; j++)
{
GEnumValue enum_value = enum_class->values[j];
if (enum_value.value == int_enum)
g_value_set_string (&string_value, enum_value.value_nick);
}
gimp_value_array_append (values, &string_value);
g_value_unset (&string_value);
}
else
{
gimp_value_array_append (values, &value);
}
g_strv_builder_add (names_builder, pspec->name);
g_value_unset (&value);
}
argnames = g_strv_builder_end (names_builder);
g_strv_builder_unref (names_builder);
g_free (specs);
}
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), argnames);
g_value_take_boxed (gimp_value_array_index (return_vals, 2), values);
}
return return_vals;
}
static GimpValueArray * static GimpValueArray *
drawable_filter_delete_invoker (GimpProcedure *procedure, drawable_filter_delete_invoker (GimpProcedure *procedure,
Gimp *gimp, Gimp *gimp,
@ -858,11 +957,11 @@ register_drawable_filter_procs (GimpPDB *pdb)
g_object_unref (procedure); g_object_unref (procedure);
/* /*
* gimp-drawable-filter-get-argument * gimp-drawable-filter-get-pspec
*/ */
procedure = gimp_procedure_new (drawable_filter_get_argument_invoker); procedure = gimp_procedure_new (drawable_filter_get_pspec_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure), gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-filter-get-argument"); "gimp-drawable-filter-get-pspec");
gimp_procedure_set_static_help (procedure, gimp_procedure_set_static_help (procedure,
"Queries for information on the specified filter's argument.", "Queries for information on the specified filter's argument.",
"This procedure returns the #GParamSpec of filter's argument.", "This procedure returns the #GParamSpec of filter's argument.",
@ -893,6 +992,41 @@ register_drawable_filter_procs (GimpPDB *pdb)
gimp_pdb_register_procedure (pdb, procedure); gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure); g_object_unref (procedure);
/*
* gimp-drawable-filter-get-arguments
*/
procedure = gimp_procedure_new (drawable_filter_get_arguments_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-filter-get-arguments");
gimp_procedure_set_static_help (procedure,
"Returns the currently set filter arguments.",
"This procedure returns the filter's arguments.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Jehan",
"Jehan",
"2024");
gimp_procedure_add_argument (procedure,
gimp_param_spec_drawable_filter ("filter",
"filter",
"The filter",
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_boxed ("argnames",
"argnames",
"The names of the arguments",
G_TYPE_STRV,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_value_array ("values",
"values",
"The values of the arguments in same order",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/* /*
* gimp-drawable-filter-delete * gimp-drawable-filter-delete
*/ */

View file

@ -30,7 +30,7 @@
#include "internal-procs.h" #include "internal-procs.h"
/* 733 procedures registered total */ /* 734 procedures registered total */
void void
internal_procs_init (GimpPDB *pdb) internal_procs_init (GimpPDB *pdb)

View file

@ -260,22 +260,29 @@ gimp_drawable_filter_set_blend_mode (GimpDrawableFilter *filter,
* *
* Get the #GimpConfig with properties that match @filter's arguments. * Get the #GimpConfig with properties that match @filter's arguments.
* *
* Returns: (transfer none): The new #GimpConfig. * The config object will be created at the first call of this method
* and its properties will be synced with the settings of this filter as
* set in the core application.
* *
* Changes to @config's properties are not synced immediately with the * Further changes to the config's properties are not synced back
* core application. Use [method@Gimp.Drawable.update] to trigger an * immediately with the core application. Use
* actual update. * [method@Gimp.Drawable.update] to trigger an actual update.
*
* Returns: (transfer none): The #GimpDrawableFilterConfig. Further
* calls will return the same object.
* *
* Since: 3.0 * Since: 3.0
**/ **/
GimpDrawableFilterConfig * GimpDrawableFilterConfig *
gimp_drawable_filter_get_config (GimpDrawableFilter *filter) gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
{ {
gchar *config_type_name; gchar **argnames;
gchar *op_name; GimpValueArray *values;
gchar *canonical_name; gchar *config_type_name;
GType config_type; gchar *op_name;
gint n_args; gchar *canonical_name;
GType config_type;
gint n_args;
g_return_val_if_fail (GIMP_IS_DRAWABLE_FILTER (filter), NULL); g_return_val_if_fail (GIMP_IS_DRAWABLE_FILTER (filter), NULL);
@ -298,7 +305,7 @@ gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
{ {
GParamSpec *pspec; GParamSpec *pspec;
pspec = _gimp_drawable_filter_get_argument (op_name, i); pspec = _gimp_drawable_filter_get_pspec (op_name, i);
config_args[i] = pspec; config_args[i] = pspec;
} }
@ -313,6 +320,14 @@ gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
filter->config = g_object_new (config_type, NULL); filter->config = g_object_new (config_type, NULL);
argnames = _gimp_drawable_filter_get_arguments (filter, &values);
for (gint i = 0; argnames[i] != NULL; i++)
g_object_set_property (G_OBJECT (filter->config), argnames[i],
gimp_value_array_index (values, i));
g_strfreev (argnames);
gimp_value_array_unref (values);
return filter->config; return filter->config;
} }

View file

@ -448,7 +448,7 @@ _gimp_drawable_filter_get_number_arguments (const gchar *operation_name)
} }
/** /**
* _gimp_drawable_filter_get_argument: * _gimp_drawable_filter_get_pspec:
* @operation_name: The procedure name. * @operation_name: The procedure name.
* @arg_num: The argument number. * @arg_num: The argument number.
* *
@ -462,8 +462,8 @@ _gimp_drawable_filter_get_number_arguments (const gchar *operation_name)
* Since: 3.0 * Since: 3.0
**/ **/
GParamSpec * GParamSpec *
_gimp_drawable_filter_get_argument (const gchar *operation_name, _gimp_drawable_filter_get_pspec (const gchar *operation_name,
gint arg_num) gint arg_num)
{ {
GimpValueArray *args; GimpValueArray *args;
GimpValueArray *return_vals; GimpValueArray *return_vals;
@ -475,7 +475,7 @@ _gimp_drawable_filter_get_argument (const gchar *operation_name,
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 (),
"gimp-drawable-filter-get-argument", "gimp-drawable-filter-get-pspec",
args); args);
gimp_value_array_unref (args); gimp_value_array_unref (args);
@ -487,6 +487,49 @@ _gimp_drawable_filter_get_argument (const gchar *operation_name,
return param_spec; return param_spec;
} }
/**
* _gimp_drawable_filter_get_arguments:
* @filter: The filter.
* @values: (out): The values of the arguments in same order.
*
* Returns the currently set filter arguments.
*
* This procedure returns the filter's arguments.
*
* Returns: (array zero-terminated=1) (transfer full):
* The names of the arguments.
* The returned value must be freed with g_strfreev().
*
* Since: 3.0
**/
gchar **
_gimp_drawable_filter_get_arguments (GimpDrawableFilter *filter,
GimpValueArray **values)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gchar **argnames = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_DRAWABLE_FILTER, filter,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-drawable-filter-get-arguments",
args);
gimp_value_array_unref (args);
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
{
argnames = GIMP_VALUES_DUP_STRV (return_vals, 1);
*values = g_value_dup_boxed (gimp_value_array_index (return_vals, 2));
}
gimp_value_array_unref (return_vals);
return argnames;
}
/** /**
* gimp_drawable_filter_delete: * gimp_drawable_filter_delete:
* @filter: The filter to delete. * @filter: The filter to delete.

View file

@ -52,8 +52,10 @@ G_GNUC_INTERNAL gboolean _gimp_drawable_filter_update (GimpDraw
GimpLayerCompositeMode composite_mode, GimpLayerCompositeMode composite_mode,
GimpLayerColorSpace composite_space); GimpLayerColorSpace composite_space);
G_GNUC_INTERNAL gint _gimp_drawable_filter_get_number_arguments (const gchar *operation_name); G_GNUC_INTERNAL gint _gimp_drawable_filter_get_number_arguments (const gchar *operation_name);
G_GNUC_INTERNAL GParamSpec* _gimp_drawable_filter_get_argument (const gchar *operation_name, G_GNUC_INTERNAL GParamSpec* _gimp_drawable_filter_get_pspec (const gchar *operation_name,
gint arg_num); 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_delete (GimpDrawableFilter *filter);

View file

@ -395,7 +395,7 @@ CODE
); );
} }
sub drawable_filter_get_argument { sub drawable_filter_get_pspec {
$blurb = <<BLURB; $blurb = <<BLURB;
Queries for information on the specified filter's argument. Queries for information on the specified filter's argument.
BLURB BLURB
@ -450,6 +450,105 @@ CODE
); );
} }
sub drawable_filter_get_arguments {
$blurb = <<BLURB;
Returns the currently set filter arguments.
BLURB
$help = <<HELP;
This procedure returns the filter's arguments.
HELP
&jehan_pdb_misc('2024', '3.0');
$lib_private = 1;
@inargs = (
{ name => 'filter', type => 'filter', desc => 'The filter' },
);
@outargs = (
{ name => 'argnames', type => 'strv',
desc => "The names of the arguments" },
{ name => 'values', type => 'valuearray',
desc => "The values of the arguments in same order" }
);
%invoke = (
code => <<'CODE'
{
GeglNode *node;
const gchar *opname;
GParamSpec **specs;
guint n_specs;
GStrvBuilder *names_builder;
node = gimp_drawable_filter_get_operation (filter);
opname = gegl_node_get_operation (node);
specs = gegl_operation_list_properties (opname, &n_specs);
names_builder = g_strv_builder_new ();
values = gimp_value_array_new (n_specs);
for (gint i = 0; i < n_specs; i++)
{
GParamSpec *pspec = specs[i];
GValue value = G_VALUE_INIT;
g_value_init (&value, pspec->value_type);
gegl_node_get_property (node, pspec->name, &value);
if (GEGL_IS_PARAM_SPEC_ENUM (pspec))
{
/* Special-casing GeglParamEnum which are passed as string to
* libgimp.
*/
GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
GEnumClass *enum_class = espec->enum_class;
GValue string_value = G_VALUE_INIT;
gint int_enum = g_value_get_enum (&value);
g_value_init (&string_value, G_TYPE_STRING);
for (gint j = 0; j < enum_class->n_values; j++)
{
GEnumValue enum_value = enum_class->values[j];
if (enum_value.value < enum_class->minimum || enum_value.value > enum_class->maximum)
continue;
if (enum_value.value == espec->default_value)
g_value_set_string (&string_value, enum_value.value_nick);
}
for (gint j = 0; j < enum_class->n_values; j++)
{
GEnumValue enum_value = enum_class->values[j];
if (enum_value.value == int_enum)
g_value_set_string (&string_value, enum_value.value_nick);
}
gimp_value_array_append (values, &string_value);
g_value_unset (&string_value);
}
else
{
gimp_value_array_append (values, &value);
}
g_strv_builder_add (names_builder, pspec->name);
g_value_unset (&value);
}
argnames = g_strv_builder_end (names_builder);
g_strv_builder_unref (names_builder);
g_free (specs);
}
CODE
);
}
sub drawable_filter_delete { sub drawable_filter_delete {
$blurb = 'Delete a drawable filter.'; $blurb = 'Delete a drawable filter.';
@ -509,7 +608,8 @@ CODE
drawable_filter_get_blend_mode drawable_filter_get_blend_mode
drawable_filter_update drawable_filter_update
drawable_filter_get_number_arguments drawable_filter_get_number_arguments
drawable_filter_get_argument drawable_filter_get_pspec
drawable_filter_get_arguments
drawable_filter_delete); drawable_filter_delete);
%exports = (app => [@procs], lib => [@procs]); %exports = (app => [@procs], lib => [@procs]);