mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 01:13:24 +00:00

New libgimpbase functions: - gimp_param_spec_choice_get_choice - gimp_param_spec_choice_get_default Now the only GParamSpec in libgimpbase whose struct is visible is GimpParamSpecObject. This can't change since it is derived into param specs defined in libgimp and therefore needs to be visible.
1436 lines
47 KiB
C
1436 lines
47 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimpprocedureconfig.c
|
|
* Copyright (C) 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 "gimp.h"
|
|
#include "gimpimagemetadata.h"
|
|
|
|
#include "gimpprocedureconfig-private.h"
|
|
|
|
|
|
/**
|
|
* GimpProcedureConfig:
|
|
*
|
|
* The base class for [class@Procedure] specific config objects and the main
|
|
* interface to manage aspects of [class@Procedure]'s arguments such as
|
|
* persistency of the last used arguments across GIMP sessions.
|
|
*
|
|
* A procedure config is created by a [class@Procedure] using
|
|
* [method@Procedure.create_config] and its properties match the
|
|
* procedure's arguments and auxiliary arguments in number, order and
|
|
* type.
|
|
*
|
|
* It implements the [struct@Config] interface and therefore has all its
|
|
* serialization and deserialization features.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_PROCEDURE,
|
|
N_PROPS
|
|
};
|
|
|
|
|
|
typedef struct _GimpProcedureConfigPrivate
|
|
{
|
|
GimpProcedure *procedure;
|
|
|
|
GimpImage *image;
|
|
GimpRunMode run_mode;
|
|
|
|
GimpMetadata *metadata;
|
|
gchar *mime_type;
|
|
GimpMetadataSaveFlags metadata_flags;
|
|
gboolean metadata_saved;
|
|
} GimpProcedureConfigPrivate;
|
|
|
|
#define GET_PRIVATE(obj) ((GimpProcedureConfigPrivate *) gimp_procedure_config_get_instance_private ((GimpProcedureConfig *) (obj)))
|
|
|
|
|
|
static void gimp_procedure_config_constructed (GObject *object);
|
|
static void gimp_procedure_config_dispose (GObject *object);
|
|
static void gimp_procedure_config_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void gimp_procedure_config_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
|
|
static void gimp_procedure_config_set_values (GimpProcedureConfig *config,
|
|
const GimpValueArray *values);
|
|
|
|
static gboolean gimp_procedure_config_load_last (GimpProcedureConfig *config,
|
|
GError **error);
|
|
static gboolean gimp_procedure_config_save_last (GimpProcedureConfig *config,
|
|
GError **error);
|
|
|
|
static gboolean gimp_procedure_config_load_parasite (GimpProcedureConfig *config,
|
|
GimpImage *image,
|
|
GError **error);
|
|
static gboolean gimp_procedure_config_save_parasite (GimpProcedureConfig *config,
|
|
GimpImage *image,
|
|
GError **error);
|
|
|
|
static GFile * gimp_procedure_config_get_file (GimpProcedureConfig *config,
|
|
const gchar *extension);
|
|
static gchar * gimp_procedure_config_parasite_name (GimpProcedureConfig *config,
|
|
const gchar *suffix);
|
|
|
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GimpProcedureConfig, gimp_procedure_config,
|
|
G_TYPE_OBJECT)
|
|
|
|
#define parent_class gimp_procedure_config_parent_class
|
|
|
|
static GParamSpec *props[N_PROPS] = { NULL, };
|
|
|
|
static const struct
|
|
{
|
|
const gchar *name;
|
|
GimpMetadataSaveFlags flag;
|
|
}
|
|
metadata_properties[] =
|
|
{
|
|
{ "include-exif", GIMP_METADATA_SAVE_EXIF },
|
|
{ "include-xmp", GIMP_METADATA_SAVE_XMP },
|
|
{ "include-iptc", GIMP_METADATA_SAVE_IPTC },
|
|
{ "include-thumbnail", GIMP_METADATA_SAVE_THUMBNAIL },
|
|
{ "include-color-profile", GIMP_METADATA_SAVE_COLOR_PROFILE },
|
|
{ "include-comment", GIMP_METADATA_SAVE_COMMENT }
|
|
};
|
|
|
|
|
|
static void
|
|
gimp_procedure_config_class_init (GimpProcedureConfigClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->constructed = gimp_procedure_config_constructed;
|
|
object_class->dispose = gimp_procedure_config_dispose;
|
|
object_class->set_property = gimp_procedure_config_set_property;
|
|
object_class->get_property = gimp_procedure_config_get_property;
|
|
|
|
props[PROP_PROCEDURE] =
|
|
g_param_spec_object ("procedure",
|
|
"Procedure",
|
|
"The procedure this config object is used for",
|
|
GIMP_TYPE_PROCEDURE,
|
|
GIMP_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY);
|
|
|
|
g_object_class_install_properties (object_class, N_PROPS, props);
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_init (GimpProcedureConfig *config)
|
|
{
|
|
GET_PRIVATE (config)->run_mode = -1;
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_constructed (GObject *object)
|
|
{
|
|
GimpProcedureConfig *config = GIMP_PROCEDURE_CONFIG (object);
|
|
|
|
G_OBJECT_CLASS (parent_class)->constructed (object);
|
|
|
|
g_assert (GIMP_IS_PROCEDURE (GET_PRIVATE (config)->procedure));
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_dispose (GObject *object)
|
|
{
|
|
GimpProcedureConfig *config = GIMP_PROCEDURE_CONFIG (object);
|
|
GimpProcedureConfigPrivate *priv = GET_PRIVATE (config);
|
|
|
|
g_clear_object (&priv->procedure);
|
|
g_clear_object (&priv->metadata);
|
|
g_clear_pointer (&priv->mime_type, g_free);
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpProcedureConfig *config = GIMP_PROCEDURE_CONFIG (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_PROCEDURE:
|
|
GET_PRIVATE (config)->procedure = g_value_dup_object (value);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpProcedureConfig *config = GIMP_PROCEDURE_CONFIG (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_PROCEDURE:
|
|
g_value_set_object (value, GET_PRIVATE (config)->procedure);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* public functions */
|
|
|
|
/**
|
|
* gimp_procedure_config_get_procedure:
|
|
* @config: a procedure config
|
|
*
|
|
* This function returns the [class@Procedure] which created @config, see
|
|
* [method@Procedure.create_config].
|
|
*
|
|
* Returns: (transfer none): The procedure which created this config.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GimpProcedure *
|
|
gimp_procedure_config_get_procedure (GimpProcedureConfig *config)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), NULL);
|
|
|
|
return GET_PRIVATE (config)->procedure;
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_get_parasite (GimpProcedureConfig *config,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpParasite *parasite;
|
|
gchar *value = NULL;
|
|
|
|
/* for now we only support strings */
|
|
if (! GET_PRIVATE (config)->image ||
|
|
! G_IS_PARAM_SPEC_STRING (pspec))
|
|
return;
|
|
|
|
parasite = gimp_image_get_parasite (GET_PRIVATE (config)->image,
|
|
pspec->name);
|
|
|
|
if (parasite)
|
|
{
|
|
guint32 parasite_size;
|
|
|
|
value = (gchar *) gimp_parasite_get_data (parasite, ¶site_size);
|
|
value = g_strndup (value, parasite_size);
|
|
gimp_parasite_free (parasite);
|
|
|
|
if (value && ! strlen (value))
|
|
g_clear_pointer (&value, g_free);
|
|
}
|
|
|
|
if (! value)
|
|
{
|
|
/* special case "gimp-comment" here, yes this is bad hack */
|
|
if (! strcmp (pspec->name, "gimp-comment"))
|
|
{
|
|
value = gimp_get_default_comment ();
|
|
}
|
|
}
|
|
|
|
if (value && strlen (value))
|
|
g_object_set (config,
|
|
pspec->name, value,
|
|
NULL);
|
|
|
|
g_free (value);
|
|
}
|
|
|
|
static void
|
|
gimp_procedure_config_set_parasite (GimpProcedureConfig *config,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpProcedureConfigPrivate *priv = GET_PRIVATE (config);
|
|
GimpParasite *parasite;
|
|
gchar *value;
|
|
|
|
/* for now we only support strings */
|
|
if (! priv->image || ! G_IS_PARAM_SPEC_STRING (pspec))
|
|
return;
|
|
|
|
g_object_get (config,
|
|
pspec->name, &value,
|
|
NULL);
|
|
|
|
parasite = gimp_image_get_parasite (priv->image, pspec->name);
|
|
|
|
if (parasite)
|
|
{
|
|
/* it there is a parasite, always override it if its value was
|
|
* changed
|
|
*/
|
|
gchar *image_value;
|
|
guint32 parasite_size;
|
|
|
|
image_value = (gchar *) gimp_parasite_get_data (parasite, ¶site_size);
|
|
image_value = g_strndup (image_value, parasite_size);
|
|
gimp_parasite_free (parasite);
|
|
|
|
if (g_strcmp0 (value, image_value))
|
|
{
|
|
if (value && strlen (value))
|
|
{
|
|
parasite = gimp_parasite_new (pspec->name,
|
|
GIMP_PARASITE_PERSISTENT,
|
|
strlen (value) + 1,
|
|
value);
|
|
gimp_image_attach_parasite (priv->image, parasite);
|
|
gimp_parasite_free (parasite);
|
|
}
|
|
else
|
|
{
|
|
gimp_image_detach_parasite (priv->image, pspec->name);
|
|
}
|
|
}
|
|
|
|
g_free (image_value);
|
|
}
|
|
else
|
|
{
|
|
/* otherwise, set the parasite if the value was changed from
|
|
* the default value
|
|
*/
|
|
gchar *default_value = NULL;
|
|
|
|
/* special case "gimp-comment" here, yes this is bad hack */
|
|
if (! strcmp (pspec->name, "gimp-comment"))
|
|
{
|
|
default_value = gimp_get_default_comment ();
|
|
}
|
|
|
|
if (g_strcmp0 (value, default_value) &&
|
|
value && strlen (value))
|
|
{
|
|
parasite = gimp_parasite_new (pspec->name,
|
|
GIMP_PARASITE_PERSISTENT,
|
|
strlen (value) + 1,
|
|
value);
|
|
gimp_image_attach_parasite (priv->image, parasite);
|
|
gimp_parasite_free (parasite);
|
|
}
|
|
|
|
g_free (default_value);
|
|
}
|
|
|
|
g_free (value);
|
|
}
|
|
|
|
/**
|
|
* gimp_procedure_config_save_metadata:
|
|
* @config: a #GimpProcedureConfig
|
|
* @exported_image: the image that was actually exported
|
|
* @file: the file @exported_image was written to
|
|
*
|
|
* *Note: There is normally no need to call this function because it's
|
|
* already called by [class@ExportProcedure] after the `run()` callback.*
|
|
*
|
|
* *Only use this function if the [class@Metadata] passed as argument of a
|
|
* [class@ExportProcedure]'s run() method needs to be written at a specific
|
|
* point of the export, other than its end.*
|
|
*
|
|
* This function syncs back @config's export properties to the
|
|
* metadata's [flags@MetadataSaveFlags] and writes the metadata to
|
|
* @file.
|
|
*
|
|
* The metadata is only ever written once. If this function has been
|
|
* called explicitly, it will do nothing when called a second time at the end of
|
|
* the `run()` callback.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
gimp_procedure_config_save_metadata (GimpProcedureConfig *config,
|
|
GimpImage *exported_image,
|
|
GFile *file)
|
|
{
|
|
GimpProcedureConfigPrivate *priv = GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (GIMP_IS_PROCEDURE_CONFIG (config));
|
|
g_return_if_fail (GIMP_IS_IMAGE (exported_image));
|
|
g_return_if_fail (G_IS_FILE (file));
|
|
|
|
if (priv->metadata && ! priv->metadata_saved)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_GET_CLASS (config);
|
|
GError *error = NULL;
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (metadata_properties); i++)
|
|
{
|
|
const gchar *prop_name = metadata_properties[i].name;
|
|
GimpMetadataSaveFlags prop_flag = metadata_properties[i].flag;
|
|
GParamSpec *pspec;
|
|
gboolean value;
|
|
|
|
pspec = g_object_class_find_property (object_class, prop_name);
|
|
if (pspec)
|
|
{
|
|
g_object_get (config,
|
|
prop_name, &value,
|
|
NULL);
|
|
|
|
if (value)
|
|
priv->metadata_flags |= prop_flag;
|
|
else
|
|
priv->metadata_flags &= ~prop_flag;
|
|
}
|
|
else
|
|
{
|
|
priv->metadata_flags &= ~prop_flag;
|
|
}
|
|
}
|
|
|
|
if (! _gimp_image_metadata_save_finish (exported_image,
|
|
priv->mime_type,
|
|
priv->metadata,
|
|
priv->metadata_flags,
|
|
file, &error))
|
|
{
|
|
if (error)
|
|
{
|
|
/* Even though a failure to write metadata is not enough
|
|
reason to say we failed to save the image, we should
|
|
still notify the user about the problem. */
|
|
g_message ("%s: saving metadata failed: %s",
|
|
G_STRFUNC, error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
priv->metadata_saved = TRUE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gimp_procedure_config_get_core_object_array:
|
|
* @config: a #GimpProcedureConfig
|
|
* @property_name: the name of a #GimpParamSpecCoreObjectArray param spec.
|
|
*
|
|
* A function for bindings to get a [type@CoreObjectArray] property. Getting
|
|
* these with [method@GObject.Object.get] or [method@GObject.Object.get_property] won't
|
|
* [work for the time being](https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/492)
|
|
* so all our boxed array types must be set and get using alternative
|
|
* functions instead.
|
|
*
|
|
* C plug-ins should just use [method@GObject.Object.get].
|
|
*
|
|
* Returns: (array zero-terminated) (transfer container): an array of #GObjects.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GObject **
|
|
gimp_procedure_config_get_core_object_array (GimpProcedureConfig *config,
|
|
const gchar *property_name)
|
|
{
|
|
GObject **objects = NULL;
|
|
GParamSpec *param_spec;
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), property_name);
|
|
|
|
if (! param_spec)
|
|
{
|
|
g_warning ("%s: %s has no property named '%s'",
|
|
G_STRFUNC,
|
|
g_type_name (G_TYPE_FROM_INSTANCE (config)),
|
|
property_name);
|
|
return objects;
|
|
}
|
|
|
|
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY))
|
|
{
|
|
g_warning ("%s: property '%s' of %s is not a GimpParamCoreObjectArray.",
|
|
G_STRFUNC,
|
|
param_spec->name,
|
|
g_type_name (param_spec->owner_type));
|
|
return objects;
|
|
}
|
|
|
|
g_object_get (config,
|
|
property_name, &objects,
|
|
NULL);
|
|
|
|
return objects;
|
|
}
|
|
|
|
/**
|
|
* gimp_procedure_config_set_core_object_array:
|
|
* @config: a #GimpProcedureConfig
|
|
* @property_name: the name of a #GimpParamSpecCoreObjectArray param spec.
|
|
* @objects: (array length=n_objects) (transfer none): an array of #GObjects.
|
|
* @n_objects: the numbers of @objects.
|
|
*
|
|
* A function for bindings to set a [type@CoreObjectArray] property. Setting
|
|
* these with [method@GObject.Object.set] or [method@GObject.Object.set_property] won't
|
|
* [work for the time being](https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/492)
|
|
* so all our boxed array types must be set and get using alternative
|
|
* functions instead.
|
|
*
|
|
* C plug-ins should just use [method@GObject.Object.set].
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
gimp_procedure_config_set_core_object_array (GimpProcedureConfig *config,
|
|
const gchar *property_name,
|
|
GObject **objects,
|
|
gsize n_objects)
|
|
{
|
|
GObject **null_objects;
|
|
GParamSpec *param_spec;
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config),
|
|
property_name);
|
|
|
|
if (! param_spec)
|
|
{
|
|
g_warning ("%s: %s has no property named '%s'",
|
|
G_STRFUNC,
|
|
g_type_name (G_TYPE_FROM_INSTANCE (config)),
|
|
property_name);
|
|
return;
|
|
}
|
|
|
|
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY))
|
|
{
|
|
g_warning ("%s: property '%s' of %s is not a GimpParamCoreObjectArray.",
|
|
G_STRFUNC,
|
|
param_spec->name,
|
|
g_type_name (param_spec->owner_type));
|
|
return;
|
|
}
|
|
|
|
null_objects = g_new0 (GObject *, n_objects + 1);
|
|
|
|
for (gint i = 0; i < n_objects; i++)
|
|
null_objects[i] = objects[i];
|
|
|
|
g_object_set (config,
|
|
property_name, null_objects,
|
|
NULL);
|
|
|
|
g_free (null_objects);
|
|
}
|
|
|
|
/**
|
|
* gimp_procedure_config_get_color_array:
|
|
* @config: a #GimpProcedureConfig
|
|
* @property_name: the name of a #GParamSpecBoxed param spec with [type@ColorArray] value type.
|
|
*
|
|
* A function for bindings to get a [type@ColorArray] property. Getting
|
|
* these with [method@GObject.Object.get] or [method@GObject.Object.get_property] won't
|
|
* [work for the time being](https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/492)
|
|
* so all our boxed array types must be set and get using these
|
|
* alternative functions instead.
|
|
*
|
|
* C plug-ins should just use [method@GObject.Object.get].
|
|
*
|
|
* Returns: (array zero-terminated) (transfer full): an array of #GObjects.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GeglColor **
|
|
gimp_procedure_config_get_color_array (GimpProcedureConfig *config,
|
|
const gchar *property_name)
|
|
{
|
|
GeglColor **colors = NULL;
|
|
GParamSpec *param_spec;
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), property_name);
|
|
|
|
if (! param_spec)
|
|
{
|
|
g_warning ("%s: %s has no property named '%s'",
|
|
G_STRFUNC,
|
|
g_type_name (G_TYPE_FROM_INSTANCE (config)),
|
|
property_name);
|
|
return colors;
|
|
}
|
|
|
|
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), G_TYPE_PARAM_BOXED) ||
|
|
! g_type_is_a (param_spec->value_type, GIMP_TYPE_COLOR_ARRAY))
|
|
{
|
|
g_warning ("%s: property '%s' of %s is not a GimpColorArray boxed type.",
|
|
G_STRFUNC,
|
|
param_spec->name,
|
|
g_type_name (param_spec->owner_type));
|
|
return colors;
|
|
}
|
|
|
|
g_object_get (config,
|
|
property_name, &colors,
|
|
NULL);
|
|
|
|
return colors;
|
|
}
|
|
|
|
/**
|
|
* gimp_procedure_config_set_color_array:
|
|
* @config: a #GimpProcedureConfig
|
|
* @property_name: the name of a #GParamSpecBoxed param spec with [type@ColorArray] value type.
|
|
* @colors: (array length=n_colors) (transfer none): an array of [class@Gegl.Color].
|
|
* @n_colors: the numbers of @colors.
|
|
*
|
|
* A function for bindings to set a [type@ColorArray] property. Setting
|
|
* these with [method@GObject.Object.set] or [method@GObject.Object.set_property] won't
|
|
* [work for the time being](https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/492)
|
|
* so all our boxed array types must be set and get using these
|
|
* alternative functions instead.
|
|
*
|
|
* C plug-ins should just use [method@GObject.Object.set].
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
gimp_procedure_config_set_color_array (GimpProcedureConfig *config,
|
|
const gchar *property_name,
|
|
GeglColor **colors,
|
|
gsize n_colors)
|
|
{
|
|
GeglColor **null_colors;
|
|
GParamSpec *param_spec;
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), property_name);
|
|
|
|
if (! param_spec)
|
|
{
|
|
g_warning ("%s: %s has no property named '%s'",
|
|
G_STRFUNC,
|
|
g_type_name (G_TYPE_FROM_INSTANCE (config)),
|
|
property_name);
|
|
return;
|
|
}
|
|
|
|
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), G_TYPE_PARAM_BOXED) ||
|
|
! g_type_is_a (param_spec->value_type, GIMP_TYPE_COLOR_ARRAY))
|
|
{
|
|
g_warning ("%s: property '%s' of %s is not a GimpColorArray boxed type.",
|
|
G_STRFUNC,
|
|
param_spec->name,
|
|
g_type_name (param_spec->owner_type));
|
|
return;
|
|
}
|
|
|
|
null_colors = g_new0 (GeglColor *, n_colors + 1);
|
|
|
|
for (gint i = 0; i < n_colors; i++)
|
|
null_colors[i] = colors[i];
|
|
|
|
g_object_set (config,
|
|
property_name, null_colors,
|
|
NULL);
|
|
|
|
g_free (null_colors);
|
|
}
|
|
|
|
/**
|
|
* gimp_procedure_config_get_choice_id:
|
|
* @config: a #GimpProcedureConfig
|
|
* @property_name: the name of a #GimpParamSpecChoice property.
|
|
*
|
|
* A utility function which will get the current string value of a
|
|
* #GimpParamSpecChoice property in @config and convert it to the
|
|
* integer ID mapped to this value.
|
|
* This makes it easy to work with an Enum type locally, within a plug-in code.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
gint
|
|
gimp_procedure_config_get_choice_id (GimpProcedureConfig *config,
|
|
const gchar *property_name)
|
|
{
|
|
GParamSpec *param_spec;
|
|
GimpChoice *choice;
|
|
gchar *value = NULL;
|
|
gint id;
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config),
|
|
property_name);
|
|
|
|
if (! param_spec)
|
|
{
|
|
g_warning ("%s: %s has no property named '%s'",
|
|
G_STRFUNC,
|
|
g_type_name (G_TYPE_FROM_INSTANCE (config)),
|
|
property_name);
|
|
return 0;
|
|
}
|
|
|
|
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), GIMP_TYPE_PARAM_CHOICE))
|
|
{
|
|
g_warning ("%s: property '%s' of %s is a %s, not a GimpParamSpecChoice.",
|
|
G_STRFUNC,
|
|
param_spec->name,
|
|
g_type_name (G_TYPE_FROM_INSTANCE (param_spec)),
|
|
g_type_name (param_spec->owner_type));
|
|
return 0;
|
|
}
|
|
|
|
choice = gimp_param_spec_choice_get_choice (param_spec);
|
|
g_object_get (config,
|
|
property_name, &value,
|
|
NULL);
|
|
id = gimp_choice_get_id (choice, value);
|
|
|
|
g_free (value);
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
/* Functions only used by GimpProcedure classes */
|
|
|
|
/**
|
|
* _gimp_procedure_config_get_values:
|
|
* @config: a #GimpProcedureConfig
|
|
* @values: a #GimpValueArray
|
|
*
|
|
* Gets the values from @config's properties and stores them in
|
|
* @values.
|
|
*
|
|
* See [method@ProcedureConfig.set_values].
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
_gimp_procedure_config_get_values (GimpProcedureConfig *config,
|
|
GimpValueArray *values)
|
|
{
|
|
GParamSpec **pspecs;
|
|
guint n_pspecs;
|
|
gint n_aux_args;
|
|
gint n_values;
|
|
gint i;
|
|
|
|
g_return_if_fail (GIMP_IS_PROCEDURE_CONFIG (config));
|
|
g_return_if_fail (values != NULL);
|
|
|
|
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
|
|
&n_pspecs);
|
|
gimp_procedure_get_aux_arguments (GET_PRIVATE (config)->procedure, &n_aux_args);
|
|
n_values = gimp_value_array_length (values);
|
|
|
|
/* The config will have 1 additional property: "procedure". */
|
|
g_return_if_fail (n_pspecs == n_values + n_aux_args + 1);
|
|
|
|
for (i = 0; i < n_values; i++)
|
|
{
|
|
GParamSpec *pspec = pspecs[i + 1];
|
|
GValue *value = gimp_value_array_index (values, i);
|
|
|
|
g_object_get_property (G_OBJECT (config), pspec->name, value);
|
|
}
|
|
|
|
g_free (pspecs);
|
|
}
|
|
|
|
/**
|
|
* _gimp_procedure_config_begin_run:
|
|
* @config: a #GimpProcedureConfig
|
|
* @image: (nullable): a #GimpImage or %NULL
|
|
* @run_mode: the #GimpRunMode passed to a [class@Procedure]'s run()
|
|
* @args: the #GimpValueArray passed to a [class@Procedure]'s run()
|
|
* @editable_properties: whether you may tweak the properties for
|
|
* metadata export.
|
|
*
|
|
* Populates @config with values for a [class@Procedure]'s run(),
|
|
* depending on @run_mode.
|
|
*
|
|
* If @run_mode is %GIMP_RUN_INTERACTIVE or %GIMP_RUN_WITH_LAST_VALS,
|
|
* the saved values from the procedure's last run() are loaded and set
|
|
* on @config. If @image is not %NULL, the last used values for this
|
|
* image are tried first, and if no image-specific values are found
|
|
* the globally saved last used values are used. If no saved last used
|
|
* values are found, the procedure's default argument values are used.
|
|
*
|
|
* If @run_mode is %GIMP_RUN_NONINTERACTIVE, the contents of @args are
|
|
* set on @config using [method@ProcedureConfig.set_values].
|
|
*
|
|
* After setting @config's properties like described above, arguments
|
|
* and auxiliary arguments are automatically synced from image
|
|
* parasites of the same name if they were set to
|
|
* %GIMP_ARGUMENT_SYNC_PARASITE with [class@Procedure.set_argument_sync]:
|
|
*
|
|
* String properties are set to the value of the image parasite if
|
|
* @run_mode is %GIMP_RUN_INTERACTIVE or %GIMP_RUN_WITH_LAST_VALS, or
|
|
* if the corresponding argument is an auxiliary argument. As a
|
|
* special case, a property named "gimp-comment" will default to
|
|
* [func@get_default_comment] if there is no "gimp-comment" parasite.
|
|
*
|
|
* After calling this function, the @args passed to run() should be
|
|
* left alone and @config be treated as the procedure's arguments, with
|
|
* some exception, such as metadata export properties (which may be
|
|
* overwritten for safety measure), and only if @editable_properties is
|
|
* returned as %TRUE, which should only happen in interactive @run_mode
|
|
* when this is the first run with @image in particular (i.e. there is
|
|
* no config parasite on @image stored for this procedure). In
|
|
* particular, in non-interactive, we will use exactly @args; and in
|
|
* last-vals run, or if a config parasite was found on image, we will
|
|
* use exactly the last-run arguments.
|
|
*
|
|
* It is possible to get @config's resulting values back into @args by
|
|
* calling [method@ProcedureConfig.get_values], as long as modified
|
|
* @args are written back to @config using [method@ProcedureConfig.set_values]
|
|
* before the call to [method@ProcedureConfig.end_run].
|
|
*
|
|
* This function should be used at the beginning of a procedure's
|
|
* run() and be paired with a call to [method@ProcedureConfig.end_run]
|
|
* at the end of run().
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
_gimp_procedure_config_begin_run (GimpProcedureConfig *config,
|
|
GimpImage *image,
|
|
GimpRunMode run_mode,
|
|
const GimpValueArray *args,
|
|
gboolean *editable_properties)
|
|
{
|
|
GimpProcedureConfigPrivate *priv;
|
|
GParamSpec *run_mode_pspec;
|
|
GParamSpec **pspecs;
|
|
guint n_pspecs;
|
|
gint i;
|
|
gboolean loaded = FALSE;
|
|
GError *error = NULL;
|
|
|
|
g_return_if_fail (GIMP_IS_PROCEDURE_CONFIG (config));
|
|
g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
|
|
g_return_if_fail (args != NULL);
|
|
|
|
priv = GET_PRIVATE (config);
|
|
|
|
priv->image = image;
|
|
priv->run_mode = run_mode;
|
|
|
|
if (editable_properties)
|
|
*editable_properties = FALSE;
|
|
|
|
gimp_procedure_config_set_values (config, args);
|
|
|
|
switch (run_mode)
|
|
{
|
|
case GIMP_RUN_INTERACTIVE :
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
if (image)
|
|
{
|
|
loaded = gimp_procedure_config_load_parasite (config, image,
|
|
&error);
|
|
if (! loaded && error)
|
|
{
|
|
g_printerr ("Loading last used values from parasite failed: %s\n",
|
|
error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
}
|
|
|
|
if (! loaded)
|
|
{
|
|
if (! gimp_procedure_config_load_last (config, &error) && error)
|
|
{
|
|
g_printerr ("Loading last used values from disk failed: %s\n",
|
|
error->message);
|
|
g_clear_error (&error);
|
|
|
|
if (editable_properties)
|
|
*editable_properties = TRUE;
|
|
}
|
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE && editable_properties)
|
|
*editable_properties = TRUE;
|
|
}
|
|
break;
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
|
break;
|
|
}
|
|
|
|
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
|
|
&n_pspecs);
|
|
|
|
for (i = 0; i < n_pspecs; i++)
|
|
{
|
|
GParamSpec *pspec = pspecs[i];
|
|
|
|
/* skip our own properties */
|
|
if (pspec->owner_type == GIMP_TYPE_PROCEDURE_CONFIG)
|
|
continue;
|
|
|
|
switch (gimp_procedure_get_argument_sync (priv->procedure, pspec->name))
|
|
{
|
|
case GIMP_ARGUMENT_SYNC_PARASITE:
|
|
/* we sync the property from the image parasite if it is an
|
|
* aux argument, or if we run interactively, because the
|
|
* parasite should be global to the image and not depend on
|
|
* whatever parasite another image had when last using this
|
|
* procedure
|
|
*/
|
|
if (gimp_procedure_find_aux_argument (priv->procedure,
|
|
pspec->name) ||
|
|
(run_mode != GIMP_RUN_NONINTERACTIVE))
|
|
{
|
|
gimp_procedure_config_get_parasite (config, pspec);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Always set the run-mode in the end, which should be influenced neither by
|
|
* the default property value, nor last run's value.
|
|
*/
|
|
run_mode_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), "run-mode");
|
|
if (run_mode_pspec != NULL && G_IS_PARAM_SPEC_ENUM (run_mode_pspec))
|
|
g_object_set (config, "run-mode", run_mode, NULL);
|
|
|
|
g_free (pspecs);
|
|
}
|
|
|
|
/**
|
|
* _gimp_procedure_config_end_run:
|
|
* @config: a #GimpProcedureConfig
|
|
* @status: the return status of the [class@Procedure]'s run()
|
|
*
|
|
* This function is the counterpart of
|
|
* [method@ProcedureConfig.begin_run] and must always be called in
|
|
* pairs in a procedure's run(), before returning return values.
|
|
*
|
|
* If the @run_mode passed to [method@ProcedureConfig.end_run] was
|
|
* %GIMP_RUN_INTERACTIVE, @config is saved as last used values to be
|
|
* used when the procedure runs again. Additionally, if the #GimpImage
|
|
* passed to [method@ProcedureConfig.begin_run] was not %NULL, @config is
|
|
* attached to @image as last used values for this image using a
|
|
* #GimpParasite and [method@Image.attach_parasite].
|
|
*
|
|
* If @run_mode was not %GIMP_RUN_NONINTERACTIVE, this function also
|
|
* conveniently calls [func@displays_flush], which is what most
|
|
* procedures want and doesn't do any harm if called redundantly.
|
|
*
|
|
* After a %GIMP_RUN_INTERACTIVE run, %GIMP_ARGUMENT_SYNC_PARASITE
|
|
* values that have been changed are written back to their
|
|
* corresponding image parasite.
|
|
*
|
|
* See [method@ProcedureConfig.begin_run].
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
_gimp_procedure_config_end_run (GimpProcedureConfig *config,
|
|
GimpPDBStatusType status)
|
|
{
|
|
GimpProcedureConfigPrivate *priv;
|
|
|
|
g_return_if_fail (GIMP_IS_PROCEDURE_CONFIG (config));
|
|
|
|
priv = GET_PRIVATE (config);
|
|
|
|
if (priv->run_mode != GIMP_RUN_NONINTERACTIVE)
|
|
gimp_displays_flush ();
|
|
|
|
if (status == GIMP_PDB_SUCCESS &&
|
|
priv->run_mode == GIMP_RUN_INTERACTIVE)
|
|
{
|
|
GParamSpec **pspecs;
|
|
guint n_pspecs;
|
|
gint i;
|
|
GError *error = NULL;
|
|
|
|
if (priv->image)
|
|
gimp_procedure_config_save_parasite (config, priv->image,
|
|
NULL);
|
|
|
|
if (! gimp_procedure_config_save_last (config, &error))
|
|
{
|
|
g_printerr ("Saving last used values to disk failed: %s\n",
|
|
error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
|
|
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
|
|
&n_pspecs);
|
|
|
|
for (i = 0; i < n_pspecs; i++)
|
|
{
|
|
GParamSpec *pspec = pspecs[i];
|
|
|
|
/* skip our own properties */
|
|
if (pspec->owner_type == GIMP_TYPE_PROCEDURE_CONFIG)
|
|
continue;
|
|
|
|
switch (gimp_procedure_get_argument_sync (priv->procedure,
|
|
pspec->name))
|
|
{
|
|
case GIMP_ARGUMENT_SYNC_PARASITE:
|
|
gimp_procedure_config_set_parasite (config, pspec);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_free (pspecs);
|
|
}
|
|
|
|
priv->image = NULL;
|
|
priv->run_mode = -1;
|
|
}
|
|
|
|
/**
|
|
* _gimp_procedure_config_begin_export:
|
|
* @config: a #GimpProcedureConfig
|
|
* @original_image: the image passed to run()
|
|
* @run_mode: the #GimpRunMode passed to a [class@Procedure]'s run()
|
|
* @args: the value array passed to a [class@Procedure]'s run()
|
|
* @mime_type: (nullable): exported file format's mime type, or %NULL.
|
|
*
|
|
* This is a variant of [method@ProcedureConfig.begin_run] to be used
|
|
* by file export procedures using [class@ExportProcedure]. It must be
|
|
* paired with a call to [method@ProcedureConfig.end_export] at the end
|
|
* of run().
|
|
*
|
|
* It does everything [method@ProcedureConfig.begin_run] does but
|
|
* provides additional features to automate file export:
|
|
*
|
|
* If @mime_type is non-%NULL, exporting metadata is handled
|
|
* automatically, by calling [method@Image.metadata_save_prepare] and
|
|
* syncing its returned [flags@MetadataSaveFlags] with @config's
|
|
* properties. (The corresponding [method@Image.metadata_save_finish]
|
|
* will be called by [method@ProcedureConfig.end_export]).
|
|
*
|
|
* The following boolean arguments of the used [class@ExportProcedure] are
|
|
* synced. The procedure can but must not provide these arguments.
|
|
*
|
|
* - "include-exif" for %GIMP_METADATA_SAVE_EXIF.
|
|
* - "include-xmp" for %GIMP_METADATA_SAVE_XMP.
|
|
* - "include-iptc" for %GIMP_METADATA_SAVE_IPTC.
|
|
* - "include-thumbnail" for %GIMP_METADATA_SAVE_THUMBNAIL.
|
|
* - "include-color-profile" for %GIMP_METADATA_SAVE_COLOR_PROFILE.
|
|
* - "include-comment" for %GIMP_METADATA_SAVE_COMMENT.
|
|
*
|
|
* The values from the [flags@MetadataSaveFlags] will only ever be used
|
|
* to set these properties to %FALSE, overriding the user's saved
|
|
* default values for the procedure, but NOT overriding the last used
|
|
* values from exporting @original_image or the last used values from
|
|
* exporting any other image using this procedure.
|
|
*
|
|
* If @mime_type is %NULL, [class@Metadata] handling is skipped. The
|
|
* procedure can still have all of the above listed boolean arguments,
|
|
* but must take care of their default values itself. The easiest way
|
|
* to do this is by simply using [func@export_comment], [func@export_exif] etc.
|
|
* as default values for these arguments when adding them using
|
|
* gimp_procedure_add_boolean_argument() or
|
|
* gimp_procedure_add_boolean_aux_argument().
|
|
*
|
|
* Returns: (transfer none) (nullable): The metadata to be used
|
|
* for this export, or %NULL if @original_image doesn't have
|
|
* metadata.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GimpMetadata *
|
|
_gimp_procedure_config_begin_export (GimpProcedureConfig *config,
|
|
GimpImage *original_image,
|
|
GimpRunMode run_mode,
|
|
const GimpValueArray *args,
|
|
const gchar *mime_type)
|
|
{
|
|
GimpProcedureConfigPrivate *priv;
|
|
GObjectClass *object_class;
|
|
gboolean editable_properties;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), NULL);
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (original_image), NULL);
|
|
g_return_val_if_fail (args != NULL, NULL);
|
|
|
|
priv = GET_PRIVATE (config);
|
|
|
|
object_class = G_OBJECT_GET_CLASS (config);
|
|
|
|
/* This must be run before we process the metadata, because we may
|
|
* overwrite various metadata export properties when they are globally
|
|
* disabled in Preferences, for security reasons.
|
|
*/
|
|
_gimp_procedure_config_begin_run (config, original_image, run_mode, args,
|
|
&editable_properties);
|
|
|
|
if (mime_type)
|
|
{
|
|
GimpMetadataSaveFlags metadata_flags;
|
|
gint i;
|
|
|
|
priv->metadata =
|
|
gimp_image_metadata_save_prepare (original_image,
|
|
mime_type,
|
|
&metadata_flags);
|
|
|
|
if (priv->metadata)
|
|
{
|
|
priv->mime_type = g_strdup (mime_type);
|
|
priv->metadata_flags = metadata_flags;
|
|
}
|
|
|
|
if (editable_properties)
|
|
for (i = 0; i < G_N_ELEMENTS (metadata_properties); i++)
|
|
{
|
|
/* we only disable properties based on metadata flags here
|
|
* and never enable them, so we don't override the user's
|
|
* saved default values that are passed to us via "args"
|
|
*/
|
|
if (! (metadata_flags & metadata_properties[i].flag))
|
|
{
|
|
const gchar *prop_name = metadata_properties[i].name;
|
|
GParamSpec *pspec;
|
|
|
|
pspec = g_object_class_find_property (object_class, prop_name);
|
|
if (pspec)
|
|
g_object_set (config,
|
|
prop_name, FALSE,
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
return priv->metadata;
|
|
}
|
|
|
|
/**
|
|
* _gimp_procedure_config_end_export:
|
|
* @config: a #GimpProcedureConfig
|
|
* @exported_image: the image that was actually exported
|
|
* @file: the #GFile @exported_image was written to
|
|
* @status: the return status of the [class@Procedure]'s run()
|
|
*
|
|
* This is a variant of [method@ProcedureConfig.end_run] to be used by
|
|
* file export procedures using [class@ExportProcedure]. It must be paired
|
|
* with a call to [method@ProcedureConfig.begin_export] at the
|
|
* beginning of run().
|
|
*
|
|
* It does everything [method@ProcedureConfig.begin_run] does but
|
|
* provides additional features to automate file export:
|
|
*
|
|
* If @status is %GIMP_PDB_SUCCESS, and
|
|
* [method@ProcedureConfig.begin_export] returned a [class@Metadata], this
|
|
* function calls [method@ProcedureConfig.save_metadata], which syncs
|
|
* back @config's export properties to the metadata's
|
|
* [flags@MetadataSaveFlags] and writes metadata to @file using
|
|
* [method@Image.metadata_save_finish].
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
_gimp_procedure_config_end_export (GimpProcedureConfig *config,
|
|
GimpImage *exported_image,
|
|
GFile *file,
|
|
GimpPDBStatusType status)
|
|
{
|
|
GimpProcedureConfigPrivate *priv;
|
|
|
|
g_return_if_fail (GIMP_IS_PROCEDURE_CONFIG (config));
|
|
g_return_if_fail (GIMP_IS_IMAGE (exported_image));
|
|
g_return_if_fail (G_IS_FILE (file));
|
|
|
|
priv = GET_PRIVATE (config);
|
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
{
|
|
gimp_procedure_config_save_metadata (config, exported_image, file);
|
|
}
|
|
|
|
g_clear_object (&priv->metadata);
|
|
g_clear_pointer (&priv->mime_type, g_free);
|
|
priv->metadata_flags = 0;
|
|
priv->metadata_saved = FALSE;
|
|
|
|
_gimp_procedure_config_end_run (config, status);
|
|
}
|
|
|
|
gboolean
|
|
gimp_procedure_config_has_default (GimpProcedureConfig *config)
|
|
{
|
|
GFile *file;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
|
|
file = gimp_procedure_config_get_file (config, ".default");
|
|
|
|
success = g_file_query_exists (file, NULL);
|
|
g_object_unref (file);
|
|
|
|
return success;
|
|
}
|
|
|
|
gboolean
|
|
gimp_procedure_config_load_default (GimpProcedureConfig *config,
|
|
GError **error)
|
|
{
|
|
GFile *file;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
file = gimp_procedure_config_get_file (config, ".default");
|
|
|
|
success = gimp_config_deserialize_file (GIMP_CONFIG (config),
|
|
file,
|
|
NULL, error);
|
|
|
|
if (! success && error && (*error)->code == GIMP_CONFIG_ERROR_OPEN_ENOENT)
|
|
{
|
|
g_clear_error (error);
|
|
}
|
|
|
|
g_object_unref (file);
|
|
|
|
return success;
|
|
}
|
|
|
|
gboolean
|
|
gimp_procedure_config_save_default (GimpProcedureConfig *config,
|
|
GError **error)
|
|
{
|
|
GFile *file;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
file = gimp_procedure_config_get_file (config, ".default");
|
|
|
|
success = gimp_config_serialize_to_file (GIMP_CONFIG (config),
|
|
file,
|
|
"settings",
|
|
"end of settings",
|
|
NULL, error);
|
|
|
|
g_object_unref (file);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
/**
|
|
* gimp_procedure_config_set_values:
|
|
* @config: a #GimpProcedureConfig
|
|
* @values: a #GimpValueArray
|
|
*
|
|
* Sets the values from @values on @config's properties.
|
|
*
|
|
* The number, order and types of values in @values must match the
|
|
* number, order and types of @config's properties.
|
|
*
|
|
* This function is meant to be used on @values which are passed as
|
|
* arguments to the run() function of the [class@Procedure] which created
|
|
* this @config. See [method@Procedure.create_config].
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
static void
|
|
gimp_procedure_config_set_values (GimpProcedureConfig *config,
|
|
const GimpValueArray *values)
|
|
{
|
|
GParamSpec **pspecs;
|
|
guint n_pspecs;
|
|
gint n_aux_args;
|
|
gint n_values;
|
|
gint i;
|
|
|
|
g_return_if_fail (GIMP_IS_PROCEDURE_CONFIG (config));
|
|
g_return_if_fail (values != NULL);
|
|
|
|
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
|
|
&n_pspecs);
|
|
gimp_procedure_get_aux_arguments (GET_PRIVATE (config)->procedure,
|
|
&n_aux_args);
|
|
n_values = gimp_value_array_length (values);
|
|
|
|
/* The first property is the procedure, all others are arguments. */
|
|
g_return_if_fail (n_pspecs == n_values + n_aux_args + 1);
|
|
|
|
for (i = 0; i < n_values; i++)
|
|
{
|
|
GParamSpec *pspec = pspecs[i + 1];
|
|
GValue *value = gimp_value_array_index (values, i);
|
|
|
|
g_object_set_property (G_OBJECT (config), pspec->name, value);
|
|
}
|
|
|
|
g_free (pspecs);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_procedure_config_load_last (GimpProcedureConfig *config,
|
|
GError **error)
|
|
{
|
|
GFile *file;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
file = gimp_procedure_config_get_file (config, ".last");
|
|
|
|
success = gimp_config_deserialize_file (GIMP_CONFIG (config),
|
|
file,
|
|
NULL, error);
|
|
|
|
if (! success && (*error)->code == GIMP_CONFIG_ERROR_OPEN_ENOENT)
|
|
{
|
|
g_clear_error (error);
|
|
}
|
|
|
|
g_object_unref (file);
|
|
|
|
return success;
|
|
}
|
|
|
|
static gboolean
|
|
gimp_procedure_config_save_last (GimpProcedureConfig *config,
|
|
GError **error)
|
|
{
|
|
GFile *file;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
file = gimp_procedure_config_get_file (config, ".last");
|
|
|
|
success = gimp_config_serialize_to_file (GIMP_CONFIG (config),
|
|
file,
|
|
"settings",
|
|
"end of settings",
|
|
NULL, error);
|
|
|
|
g_object_unref (file);
|
|
|
|
return success;
|
|
}
|
|
|
|
static gboolean
|
|
gimp_procedure_config_load_parasite (GimpProcedureConfig *config,
|
|
GimpImage *image,
|
|
GError **error)
|
|
{
|
|
gchar *name;
|
|
GimpParasite *parasite;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
name = gimp_procedure_config_parasite_name (config, "-last");
|
|
parasite = gimp_image_get_parasite (image, name);
|
|
g_free (name);
|
|
|
|
if (! parasite)
|
|
return FALSE;
|
|
|
|
success = gimp_config_deserialize_parasite (GIMP_CONFIG (config),
|
|
parasite,
|
|
NULL, error);
|
|
gimp_parasite_free (parasite);
|
|
|
|
return success;
|
|
}
|
|
|
|
static gboolean
|
|
gimp_procedure_config_save_parasite (GimpProcedureConfig *config,
|
|
GimpImage *image,
|
|
GError **error)
|
|
{
|
|
gchar *name;
|
|
GimpParasite *parasite;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), FALSE);
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
name = gimp_procedure_config_parasite_name (config, "-last");
|
|
parasite = gimp_config_serialize_to_parasite (GIMP_CONFIG (config),
|
|
name,
|
|
GIMP_PARASITE_PERSISTENT,
|
|
NULL);
|
|
g_free (name);
|
|
|
|
if (! parasite)
|
|
return FALSE;
|
|
|
|
gimp_image_attach_parasite (image, parasite);
|
|
gimp_parasite_free (parasite);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GFile *
|
|
gimp_procedure_config_get_file (GimpProcedureConfig *config,
|
|
const gchar *extension)
|
|
{
|
|
GFile *file;
|
|
gchar *basename;
|
|
|
|
basename = g_strconcat (G_OBJECT_TYPE_NAME (config), extension, NULL);
|
|
file = gimp_directory_file ("plug-in-settings", basename, NULL);
|
|
g_free (basename);
|
|
|
|
return file;
|
|
}
|
|
|
|
static gchar *
|
|
gimp_procedure_config_parasite_name (GimpProcedureConfig *config,
|
|
const gchar *suffix)
|
|
{
|
|
return g_strconcat (G_OBJECT_TYPE_NAME (config), suffix, NULL);
|
|
}
|