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 *
drawable_filter_get_argument_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
drawable_filter_get_pspec_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpValueArray *return_vals;
@ -463,6 +463,105 @@ drawable_filter_get_argument_invoker (GimpProcedure *procedure,
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 *
drawable_filter_delete_invoker (GimpProcedure *procedure,
Gimp *gimp,
@ -858,11 +957,11 @@ register_drawable_filter_procs (GimpPDB *pdb)
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-drawable-filter-get-argument");
"gimp-drawable-filter-get-pspec");
gimp_procedure_set_static_help (procedure,
"Queries for information on the specified 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);
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
*/

View file

@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 733 procedures registered total */
/* 734 procedures registered total */
void
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.
*
* 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
* core application. Use [method@Gimp.Drawable.update] to trigger an
* actual update.
* Further changes to the config's properties are not synced back
* immediately with the core application. Use
* [method@Gimp.Drawable.update] to trigger an actual update.
*
* Returns: (transfer none): The #GimpDrawableFilterConfig. Further
* calls will return the same object.
*
* Since: 3.0
**/
GimpDrawableFilterConfig *
gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
{
gchar *config_type_name;
gchar *op_name;
gchar *canonical_name;
GType config_type;
gint n_args;
gchar **argnames;
GimpValueArray *values;
gchar *config_type_name;
gchar *op_name;
gchar *canonical_name;
GType config_type;
gint n_args;
g_return_val_if_fail (GIMP_IS_DRAWABLE_FILTER (filter), NULL);
@ -298,7 +305,7 @@ gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
{
GParamSpec *pspec;
pspec = _gimp_drawable_filter_get_argument (op_name, i);
pspec = _gimp_drawable_filter_get_pspec (op_name, i);
config_args[i] = pspec;
}
@ -313,6 +320,14 @@ gimp_drawable_filter_get_config (GimpDrawableFilter *filter)
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;
}

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.
* @arg_num: The argument number.
*
@ -462,8 +462,8 @@ _gimp_drawable_filter_get_number_arguments (const gchar *operation_name)
* Since: 3.0
**/
GParamSpec *
_gimp_drawable_filter_get_argument (const gchar *operation_name,
gint arg_num)
_gimp_drawable_filter_get_pspec (const gchar *operation_name,
gint arg_num)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@ -475,7 +475,7 @@ _gimp_drawable_filter_get_argument (const gchar *operation_name,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-drawable-filter-get-argument",
"gimp-drawable-filter-get-pspec",
args);
gimp_value_array_unref (args);
@ -487,6 +487,49 @@ _gimp_drawable_filter_get_argument (const gchar *operation_name,
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:
* @filter: The filter to delete.

View file

@ -52,8 +52,10 @@ G_GNUC_INTERNAL gboolean _gimp_drawable_filter_update (GimpDraw
GimpLayerCompositeMode composite_mode,
GimpLayerColorSpace composite_space);
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);
G_GNUC_INTERNAL gchar** _gimp_drawable_filter_get_arguments (GimpDrawableFilter *filter,
GimpValueArray **values);
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;
Queries for information on the specified filter's argument.
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 {
$blurb = 'Delete a drawable filter.';
@ -509,7 +608,8 @@ CODE
drawable_filter_get_blend_mode
drawable_filter_update
drawable_filter_get_number_arguments
drawable_filter_get_argument
drawable_filter_get_pspec
drawable_filter_get_arguments
drawable_filter_delete);
%exports = (app => [@procs], lib => [@procs]);