libgimp, libgimpconfig: GimpResource can now be (de)serialized.

I add a new class method deserialize_create() to GimpConfigInterface which
returns the GimpConfig object per deserialization, instead of modifying an
existing bare object.

This matters for cases like our GimpResource (and later our GimpItem) classes
which are fully managed by libgimp and should be unique objects per actual
resource. It should even be possible to compare the pointer itself for identity.
That's why we need to let GimpResource create the object (in reality request it
to the infra and only ref it) through this new class method.

With this commit and the previous ones, all GimpResource are now properly stored
as plug-in settings (e.g. the "film" plug-in has a font setting which is now
properly remembered).

These identifiers are not portable (across various installations and therefore
not for XCF either), but at least they are reasonably identifying data on a same
installation (unlike GimpResource's int ID which is only valid within a single
session) which makes them very fine for plug-in settings storage.

When a data file disappears, we fallback to the context default data instead.
This commit is contained in:
Jehan 2023-07-20 01:48:59 +02:00
parent 38c717b149
commit ce0a84003c
4 changed files with 107 additions and 4 deletions

View File

@ -112,6 +112,8 @@ typedef struct _GimpResourcePrivate
} GimpResourcePrivate; } GimpResourcePrivate;
static void gimp_resource_config_iface_init (GimpConfigInterface *iface);
static void gimp_resource_set_property (GObject *object, static void gimp_resource_set_property (GObject *object,
guint property_id, guint property_id,
const GValue *value, const GValue *value,
@ -121,8 +123,21 @@ static void gimp_resource_get_property (GObject *object,
GValue *value, GValue *value,
GParamSpec *pspec); GParamSpec *pspec);
static gboolean gimp_resource_serialize (GimpConfig *config,
GimpConfigWriter *writer,
gpointer data);
static GimpConfig *
gimp_resource_deserialize_create (GType type,
GScanner *scanner,
gint nest_level,
gpointer data);
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GimpResource, gimp_resource, G_TYPE_OBJECT)
G_DEFINE_TYPE_EXTENDED (GimpResource, gimp_resource, G_TYPE_OBJECT,
G_TYPE_FLAG_ABSTRACT,
G_ADD_PRIVATE (GimpResource)
G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
gimp_resource_config_iface_init))
#define parent_class gimp_resource_parent_class #define parent_class gimp_resource_parent_class
@ -148,6 +163,13 @@ gimp_resource_class_init (GimpResourceClass *klass)
g_object_class_install_properties (object_class, N_PROPS, props); g_object_class_install_properties (object_class, N_PROPS, props);
} }
static void
gimp_resource_config_iface_init (GimpConfigInterface *iface)
{
iface->serialize = gimp_resource_serialize;
iface->deserialize_create = gimp_resource_deserialize_create;
}
static void static void
gimp_resource_init (GimpResource *resource) gimp_resource_init (GimpResource *resource)
{ {
@ -195,6 +217,63 @@ gimp_resource_get_property (GObject *object,
} }
} }
static gboolean
gimp_resource_serialize (GimpConfig *config,
GimpConfigWriter *writer,
gpointer data)
{
GimpResource *resource;
gchar *name;
gchar *collection;
gboolean is_internal;
g_return_val_if_fail (GIMP_IS_RESOURCE (config), FALSE);
resource = GIMP_RESOURCE (config);
is_internal = _gimp_resource_get_identifiers (resource, &name, &collection);
if (is_internal)
gimp_config_writer_identifier (writer, "internal");
gimp_config_writer_string (writer, name);
gimp_config_writer_string (writer, collection);
g_free (name);
g_free (collection);
return TRUE;
}
static GimpConfig *
gimp_resource_deserialize_create (GType type,
GScanner *scanner,
gint nest_level,
gpointer data)
{
GimpResource *resource = NULL;
gchar *name = NULL;
gchar *collection = NULL;
gboolean is_internal = FALSE;
if (gimp_scanner_parse_identifier (scanner, "internal"))
is_internal = TRUE;
if (gimp_scanner_parse_string (scanner, &name) &&
gimp_scanner_parse_string (scanner, &collection))
resource = _gimp_resource_get_by_identifiers (g_type_name (type), name, collection, is_internal);
if (resource == NULL)
/* Default to context resource. */
resource = _gimp_context_get_resource (g_type_name (type));
if (resource)
g_object_ref (resource);
g_free (collection);
g_free (name);;
return GIMP_CONFIG (resource);;
}
/** /**
* gimp_resource_get_id: * gimp_resource_get_id:
* @resource: The resource. * @resource: The resource.

View File

@ -781,8 +781,28 @@ gimp_config_deserialize_object (GValue *value,
if (! config_iface) if (! config_iface)
return gimp_config_deserialize_any (value, prop_spec, scanner); return gimp_config_deserialize_any (value, prop_spec, scanner);
if (! config_iface->deserialize (prop_object, scanner, nest_level + 1, NULL)) if (config_iface->deserialize_create != NULL)
{
/* Some class may prefer to create themselves their objects, for instance
* to maintain unicity of objects (in libgimp in particular, the various
* GimpItem or GimpResource are managed by the lib. A single item or
* resource must be represented for a single object across the whole
* processus.
*/
GimpConfig *created_object;
created_object = config_iface->deserialize_create (G_TYPE_FROM_INSTANCE (prop_object),
scanner, nest_level + 1, NULL);
if (created_object == NULL)
return G_TOKEN_NONE; return G_TOKEN_NONE;
else
g_value_take_object (value, created_object);
}
else if (! config_iface->deserialize (prop_object, scanner, nest_level + 1, NULL))
{
return G_TOKEN_NONE;
}
return G_TOKEN_RIGHT_PAREN; return G_TOKEN_RIGHT_PAREN;
} }

View File

@ -454,7 +454,7 @@ gimp_config_serialize_to_parasite (GimpConfig *config,
/** /**
* gimp_config_deserialize_file: * gimp_config_deserialize_file:
* @config: an oObject that implements the #GimpConfigInterface. * @config: an object that implements the #GimpConfigInterface.
* @file: the file to read configuration from. * @file: the file to read configuration from.
* @data: user data passed to the deserialize implementation. * @data: user data passed to the deserialize implementation.
* @error: return location for a possible error * @error: return location for a possible error

View File

@ -44,6 +44,10 @@ struct _GimpConfigInterface
GScanner *scanner, GScanner *scanner,
gint nest_level, gint nest_level,
gpointer data); gpointer data);
GimpConfig * (* deserialize_create) (GType type,
GScanner *scanner,
gint nest_level,
gpointer data);
gboolean (* serialize_property) (GimpConfig *config, gboolean (* serialize_property) (GimpConfig *config,
guint property_id, guint property_id,
const GValue *value, const GValue *value,