[gimp] libgimp: implement argument sync in GimpProcedureConfig



commit 48b04e72573f5a0e62685e1518a851aee3806afa
Author: Michael Natterer <mitch gimp org>
Date:   Mon Jun 15 22:59:12 2020 +0200

    libgimp: implement argument sync in GimpProcedureConfig
    
    In begin_run() and end_run(), sync string properties set to
    GIMP_ARGUMENT_SYNC_PARASITE with image parasites of the same name,
    exactly the way "gimp-comment" was handled by begin_export() and
    end_export(). Remove the "gimp-comment" handling code from
    begin_export() and end_export().

 libgimp/gimpprocedureconfig.c | 347 ++++++++++++++++++++++++++----------------
 1 file changed, 212 insertions(+), 135 deletions(-)
---
diff --git a/libgimp/gimpprocedureconfig.c b/libgimp/gimpprocedureconfig.c
index 369665c26f..26c9ab9d8e 100644
--- a/libgimp/gimpprocedureconfig.c
+++ b/libgimp/gimpprocedureconfig.c
@@ -310,6 +310,128 @@ gimp_procedure_config_get_values (GimpProcedureConfig  *config,
   g_free (pspecs);
 }
 
+static void
+gimp_procedure_config_get_parasite (GimpProcedureConfig *config,
+                                    GParamSpec          *pspec)
+{
+  GimpParasite *parasite;
+  gchar        *value = NULL;
+
+  /*  for now we only support strings  */
+  if (! config->priv->image ||
+      ! G_IS_PARAM_SPEC_STRING (pspec))
+    return;
+
+  parasite = gimp_image_get_parasite (config->priv->image, pspec->name);
+
+  if (parasite)
+    {
+      value = g_strndup (gimp_parasite_data (parasite),
+                         gimp_parasite_data_size (parasite));
+      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)
+{
+  GimpParasite *parasite;
+  gchar        *value;
+
+  /*  for now we only support strings  */
+  if (! config->priv->image ||
+      ! G_IS_PARAM_SPEC_STRING (pspec))
+    return;
+
+  g_object_get (config,
+                pspec->name, &value,
+                NULL);
+
+  parasite = gimp_image_get_parasite (config->priv->image, pspec->name);
+
+  if (parasite)
+    {
+      /*  it there is a parasite, always override it if its value was
+       *  changed
+       */
+      gchar *image_value;
+
+      image_value = g_strndup (gimp_parasite_data (parasite),
+                               gimp_parasite_data_size (parasite));
+      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 (config->priv->image,
+                                          parasite);
+              gimp_parasite_free (parasite);
+            }
+          else
+            {
+              gimp_image_detach_parasite (config->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 (config->priv->image,
+                                      parasite);
+          gimp_parasite_free (parasite);
+        }
+
+      g_free (default_value);
+    }
+
+  g_free (value);
+}
+
 /**
  * gimp_procedure_config_begin_run:
  * @config:   a #GimpProcedureConfig
@@ -330,6 +452,18 @@ gimp_procedure_config_get_values (GimpProcedureConfig  *config,
  * If @run_mode is %GIMP_RUN_NONINTERACTIVE, the contents of @args are
  * set on @config using gimp_procedure_config_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
+ * gimp_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 propery named "gimp-comment" will default to
+ * gimp_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.
  *
@@ -351,8 +485,11 @@ gimp_procedure_config_begin_run (GimpProcedureConfig  *config,
                                  GimpRunMode           run_mode,
                                  const GimpValueArray *args)
 {
-  gboolean  loaded = FALSE;
-  GError   *error  = NULL;
+  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));
@@ -390,6 +527,42 @@ gimp_procedure_config_begin_run (GimpProcedureConfig  *config,
       gimp_procedure_config_set_values (config, args);
       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 (config->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 (config->priv->procedure,
+                                                pspec->name) ||
+              (run_mode != GIMP_RUN_NONINTERACTIVE))
+            {
+              gimp_procedure_config_get_parasite (config, pspec);
+            }
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  g_free (pspecs);
 }
 
 /**
@@ -412,6 +585,10 @@ gimp_procedure_config_begin_run (GimpProcedureConfig  *config,
  * conveniently calls gimp_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 gimp_procedure_config_begin_run().
  *
  * Since: 3.0
@@ -425,10 +602,13 @@ gimp_procedure_config_end_run (GimpProcedureConfig *config,
   if (config->priv->run_mode != GIMP_RUN_NONINTERACTIVE)
     gimp_displays_flush ();
 
-  if (status                 == GIMP_PDB_SUCCESS &&
+  if (status == GIMP_PDB_SUCCESS &&
       config->priv->run_mode == GIMP_RUN_INTERACTIVE)
     {
-      GError *error = NULL;
+      GParamSpec **pspecs;
+      guint        n_pspecs;
+      gint         i;
+      GError      *error = NULL;
 
       if (config->priv->image)
         gimp_procedure_config_save_parasite (config, config->priv->image,
@@ -440,6 +620,31 @@ gimp_procedure_config_end_run (GimpProcedureConfig *config,
                       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 (config->priv->procedure,
+                                                    pspec->name))
+            {
+            case GIMP_ARGUMENT_SYNC_PARASITE:
+              gimp_procedure_config_set_parasite (config, pspec);
+              break;
+
+            default:
+              break;
+            }
+        }
+
+      g_free (pspecs);
     }
 
   config->priv->image    = NULL;
@@ -497,18 +702,9 @@ gimp_procedure_config_end_run (GimpProcedureConfig *config,
  * adding them using GIMP_PROC_ARG_BOOLEAN() or
  * GIMP_PROC_AUX_ARG_BOOLEAN().
  *
- * Additionally, some procedure arguments are handled automatically
- * regardless of whether @mime_type is %NULL or not:
- *
- * If the procedure has a "comment" argument, it is synced with the
- * image's "gimp-comment" parasite, unless @run_mode is
- * %GIMP_RUN_NONINTERACTIVE and the argument is not an auxiliary
- * argument. If there is no "gimp-comment" parasite, the "comment"
- * argument is initialized with the default comment returned by
- * gimp_get_default_comment().
- *
- * Returns: (transfer none) (nullable): The #GimpMetadata to be used for this
- *          export, or %NULL if @original_image doesn't have metadata.
+ * Returns: (transfer none) (nullable): The #GimpMetadata to be used
+ *          for this export, or %NULL if @original_image doesn't have
+ *          metadata.
  *
  * Since: 3.0
  **/
@@ -565,45 +761,6 @@ gimp_procedure_config_begin_export (GimpProcedureConfig  *config,
 
   gimp_procedure_config_begin_run (config, original_image, run_mode, args);
 
-  if (g_object_class_find_property (object_class, "comment"))
-    {
-      /*  we set the comment property from the image comment if it is
-       *  an aux argument, or if we run interactively, because the
-       *  image comment should be global and not depend on whatever
-       *  comment another image had when last using this export
-       *  procedure
-       */
-      if (gimp_procedure_find_aux_argument (config->priv->procedure,
-                                            "comment") ||
-          (run_mode != GIMP_RUN_NONINTERACTIVE))
-        {
-          GimpParasite *parasite;
-          gchar        *comment = NULL;
-
-          parasite = gimp_image_get_parasite (original_image, "gimp-comment");
-          if (parasite)
-            {
-              comment = g_strndup (gimp_parasite_data (parasite),
-                                   gimp_parasite_data_size (parasite));
-
-              if (comment && ! strlen (comment))
-                g_clear_pointer (&comment, g_free);
-
-              gimp_parasite_free (parasite);
-            }
-
-          if (! comment)
-            comment = gimp_get_default_comment ();
-
-          if (comment && strlen (comment))
-            g_object_set (config,
-                          "comment", comment,
-                          NULL);
-
-          g_free (comment);
-        }
-    }
-
   return config->priv->metadata;
 }
 
@@ -629,10 +786,6 @@ gimp_procedure_config_begin_export (GimpProcedureConfig  *config,
  * #GimpMetadataSaveFlags and writes metadata to @file using
  * gimp_image_metadata_save_finish().
  *
- * If the procedure has a "comment" argument, and it was modified
- * during an interactive run, it is synced back to the original
- * image's "gimp-comment" parasite.
- *
  * Since: 3.0
  **/
 void
@@ -647,82 +800,6 @@ gimp_procedure_config_end_export (GimpProcedureConfig *config,
 
   if (status == GIMP_PDB_SUCCESS)
     {
-      GObjectClass *object_class = G_OBJECT_GET_CLASS (config);
-
-      /*  we write the comment back to the image if it was modified
-       *  during an interactive export
-       */
-      if (g_object_class_find_property (object_class, "comment") &&
-          config->priv->run_mode == GIMP_RUN_INTERACTIVE)
-        {
-          GimpParasite *parasite;
-          gchar        *comment;
-
-          g_object_get (config,
-                        "comment", &comment,
-                        NULL);
-
-          parasite = gimp_image_get_parasite (config->priv->image,
-                                              "gimp-comment");
-          if (parasite)
-            {
-              /*  it there is an image comment, always override it if
-               *  the comment was changed
-               */
-              gchar *image_comment;
-
-              image_comment = g_strndup (gimp_parasite_data (parasite),
-                                         gimp_parasite_data_size (parasite));
-              gimp_parasite_free (parasite);
-
-              if (g_strcmp0 (comment, image_comment))
-                {
-                  if (comment && strlen (comment))
-                    {
-                      parasite = gimp_parasite_new ("gimp-comment",
-                                                    GIMP_PARASITE_PERSISTENT,
-                                                    strlen (comment) + 1,
-                                                    comment);
-                      gimp_image_attach_parasite (config->priv->image,
-                                                  parasite);
-                      gimp_parasite_free (parasite);
-                    }
-                  else
-                    {
-                      gimp_image_detach_parasite (config->priv->image,
-                                                  "gimp-comment");
-                    }
-                }
-
-              g_free (image_comment);
-            }
-          else
-            {
-              /*  otherwise, set an image comment if the comment was
-               *  changed from the default comment
-               */
-              gchar *default_comment;
-
-              default_comment = gimp_get_default_comment ();
-
-              if (g_strcmp0 (comment, default_comment) &&
-                  comment && strlen (comment))
-                {
-                  parasite = gimp_parasite_new ("gimp-comment",
-                                                GIMP_PARASITE_PERSISTENT,
-                                                strlen (comment) + 1,
-                                                comment);
-                  gimp_image_attach_parasite (config->priv->image,
-                                              parasite);
-                  gimp_parasite_free (parasite);
-                }
-
-              g_free (default_comment);
-            }
-
-          g_free (comment);
-        }
-
       gimp_procedure_config_save_metadata (config, exported_image, file);
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]