[gimp] libgimp, plug-ins: add an "(edit)" link next to "Metadata" frame in…



commit c1c2b8e30499037cf4718f44a9e08920779b6f2a
Author: Jehan <jehan girinstud io>
Date:   Thu Dec 17 18:48:46 2020 +0100

    libgimp, plug-ins: add an "(edit)" link next to "Metadata" frame in…
    
    … GimpSaveProcedureDialog.
    
    See issue #6092 and the discussion with Jacob. Basically we are trying
    to improve the metadata situation with more edit abilities and
    awareness, while in the same time having the export dialogs less of a
    mess (the "Comment" input in particular will most likely move to the
    metadata editor itself; I left it for now, until the move is done).
    
    The "(edit)" link will basically just run "plug-in-metadata-editor".
    
    Also as a side note: I realized that gimp_pdb_run_procedure() runs
    procedures synchronously and wait for a result, which is fine for quick
    non-interactive plug-ins, but freezes the calling process otherwise.
    Actually even when we want synchronous result, we should allow for GUI
    events to be processed (otherwise the OS just thinks the calling export
    plug-in is a zombie and proposes to kill it). This API should probably
    be improved (and an alternative async version added as well).

 libgimp/gimpsaveproceduredialog.c   | 108 ++++++++++++++++++++++++++++++++----
 libgimp/gimpsaveproceduredialog.h   |   3 +-
 plug-ins/common/file-png.c          |   3 +-
 plug-ins/file-jpeg/jpeg-save.c      |   3 +-
 plug-ins/file-tiff/file-tiff-save.c |   3 +-
 5 files changed, 106 insertions(+), 14 deletions(-)
---
diff --git a/libgimp/gimpsaveproceduredialog.c b/libgimp/gimpsaveproceduredialog.c
index 4c1cff3f18..d97e86076a 100644
--- a/libgimp/gimpsaveproceduredialog.c
+++ b/libgimp/gimpsaveproceduredialog.c
@@ -33,7 +33,11 @@
 
 struct _GimpSaveProcedureDialogPrivate
 {
-  GList *additional_metadata;
+  GList     *additional_metadata;
+  GimpImage *image;
+
+  GThread   *metadata_thread;
+  GMutex     metadata_thread_mutex;
 };
 
 
@@ -44,6 +48,11 @@ static void   gimp_save_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
                                                     GimpProcedureConfig *config,
                                                     GList               *properties);
 
+static gpointer gimp_save_procedure_dialog_edit_metadata_thread   (gpointer                 data);
+static gboolean gimp_save_procedure_dialog_activate_edit_metadata (GtkLinkButton           *link,
+                                                                   GimpSaveProcedureDialog *dialog);
+
+
 G_DEFINE_TYPE_WITH_PRIVATE (GimpSaveProcedureDialog, gimp_save_procedure_dialog, GIMP_TYPE_PROCEDURE_DIALOG)
 
 #define parent_class gimp_save_procedure_dialog_parent_class
@@ -67,6 +76,9 @@ gimp_save_procedure_dialog_init (GimpSaveProcedureDialog *dialog)
   dialog->priv = gimp_save_procedure_dialog_get_instance_private (dialog);
 
   dialog->priv->additional_metadata = NULL;
+  dialog->priv->image               = NULL;
+  dialog->priv->metadata_thread     = NULL;
+  g_mutex_init (&dialog->priv->metadata_thread_mutex);
 }
 
 static void
@@ -76,6 +88,8 @@ gimp_save_procedure_dialog_dispose (GObject *object)
 
   g_list_free_full (dialog->priv->additional_metadata, g_free);
   dialog->priv->additional_metadata = NULL;
+  g_clear_pointer (&dialog->priv->metadata_thread, g_thread_unref);
+  g_mutex_clear (&dialog->priv->metadata_thread_mutex);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -132,16 +146,45 @@ gimp_save_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
       g_list_length (save_dialog->priv->additional_metadata) > 0 ||
       gimp_save_procedure_get_support_comment   (save_procedure))
     {
-      GtkWidget *frame;
-      GtkWidget *grid;
-      GtkWidget *widget;
-      gint       n_metadata;
-      gint       left = 0;
-      gint       top  = 0;
-
-      frame = gimp_frame_new (_("Metadata"));
+      GtkWidget      *frame;
+      GtkWidget      *frame_title;
+      GtkWidget      *grid;
+      GtkWidget      *widget;
+      GtkWidget      *label;
+      GtkWidget      *link;
+      PangoAttrList  *attrs;
+      PangoAttribute *attr;
+      gint            n_metadata;
+      gint            left = 0;
+      gint            top  = 0;
+
+      frame = gimp_frame_new (NULL);
       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
 
+      /* Metadata frame title: a label and an edit link. */
+      frame_title = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+
+      label = gtk_label_new (_("Metadata"));
+      attrs = pango_attr_list_new ();
+      attr  = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+      pango_attr_list_insert (attrs, attr);
+      gtk_label_set_attributes (GTK_LABEL (label), attrs);
+      pango_attr_list_unref (attrs);
+      gtk_box_pack_start (GTK_BOX (frame_title), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+
+      link = gtk_link_button_new_with_label (_("Edit Metadata"), _("(edit)"));
+      gtk_link_button_set_visited (GTK_LINK_BUTTON (link), FALSE);
+      g_signal_connect (link, "activate-link",
+                        G_CALLBACK (gimp_save_procedure_dialog_activate_edit_metadata),
+                        dialog);
+      gtk_box_pack_start (GTK_BOX (frame_title), link, FALSE, FALSE, 0);
+      gtk_widget_show (link);
+
+      gtk_frame_set_label_widget (GTK_FRAME (frame), frame_title);
+      gtk_widget_show (frame_title);
+
+      /* Metadata frame contents in a grid.. */
       grid = gtk_grid_new ();
       gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
       gtk_widget_set_vexpand (grid, TRUE);
@@ -276,9 +319,52 @@ gimp_save_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
     }
 }
 
+static gpointer
+gimp_save_procedure_dialog_edit_metadata_thread (gpointer data)
+{
+  GimpSaveProcedureDialog *dialog = data;
+
+  gimp_pdb_run_procedure (gimp_get_pdb (),    "plug-in-metadata-editor",
+                          GIMP_TYPE_RUN_MODE, GIMP_RUN_INTERACTIVE,
+                          GIMP_TYPE_IMAGE,    dialog->priv->image,
+                          G_TYPE_NONE);
+
+  g_mutex_lock (&dialog->priv->metadata_thread_mutex);
+  g_thread_unref (dialog->priv->metadata_thread);
+  dialog->priv->metadata_thread = NULL;
+  g_mutex_unlock (&dialog->priv->metadata_thread_mutex);
+
+  return NULL;
+}
+
+static gboolean
+gimp_save_procedure_dialog_activate_edit_metadata (GtkLinkButton           *link,
+                                                   GimpSaveProcedureDialog *dialog)
+{
+  gtk_link_button_set_visited (link, TRUE);
+
+  g_mutex_lock (&dialog->priv->metadata_thread_mutex);
+
+  if (! dialog->priv->metadata_thread)
+    /* Only run if not already running. */
+    dialog->priv->metadata_thread = g_thread_try_new ("Edit Metadata",
+                                                      gimp_save_procedure_dialog_edit_metadata_thread,
+                                                      dialog, NULL);
+
+  g_mutex_unlock (&dialog->priv->metadata_thread_mutex);
+
+  /* Stop propagation as the URI is bogus. */
+  return TRUE;
+}
+
+
+/* Public Functions */
+
+
 GtkWidget *
 gimp_save_procedure_dialog_new (GimpSaveProcedure   *procedure,
-                                GimpProcedureConfig *config)
+                                GimpProcedureConfig *config,
+                                GimpImage           *image)
 {
   GtkWidget   *dialog;
   gchar       *title;
@@ -290,6 +376,7 @@ gimp_save_procedure_dialog_new (GimpSaveProcedure   *procedure,
   g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), NULL);
   g_return_val_if_fail (gimp_procedure_config_get_procedure (config) ==
                         GIMP_PROCEDURE (procedure), NULL);
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
 
   format_name = gimp_file_procedure_get_format_name (GIMP_FILE_PROCEDURE (procedure));
   if (! format_name)
@@ -317,6 +404,7 @@ gimp_save_procedure_dialog_new (GimpSaveProcedure   *procedure,
                          "help-id",        help_id,
                          "use-header-bar", use_header_bar,
                          NULL);
+  GIMP_SAVE_PROCEDURE_DIALOG (dialog)->priv->image = image;
   g_free (title);
 
   return dialog;
diff --git a/libgimp/gimpsaveproceduredialog.h b/libgimp/gimpsaveproceduredialog.h
index 77edd24ccb..80f25031b9 100644
--- a/libgimp/gimpsaveproceduredialog.h
+++ b/libgimp/gimpsaveproceduredialog.h
@@ -67,7 +67,8 @@ struct _GimpSaveProcedureDialogClass
 GType       gimp_save_procedure_dialog_get_type          (void) G_GNUC_CONST;
 
 GtkWidget * gimp_save_procedure_dialog_new               (GimpSaveProcedure   *procedure,
-                                                          GimpProcedureConfig *config);
+                                                          GimpProcedureConfig *config,
+                                                          GimpImage           *image);
 
 void        gimp_save_procedure_dialog_add_metadata      (GimpSaveProcedureDialog *dialog,
                                                           const gchar             *property);
diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
index 63e2c91110..32e6fb53a4 100644
--- a/plug-ins/common/file-png.c
+++ b/plug-ins/common/file-png.c
@@ -2167,7 +2167,8 @@ save_dialog (GimpImage     *image,
   gboolean      run;
 
   dialog = gimp_save_procedure_dialog_new (GIMP_SAVE_PROCEDURE (procedure),
-                                           GIMP_PROCEDURE_CONFIG (config));
+                                           GIMP_PROCEDURE_CONFIG (config),
+                                           image);
 
   gimp_procedure_dialog_get_widget (GIMP_PROCEDURE_DIALOG (dialog),
                                     "compression", GIMP_TYPE_SCALE_ENTRY);
diff --git a/plug-ins/file-jpeg/jpeg-save.c b/plug-ins/file-jpeg/jpeg-save.c
index 8fa030b32b..96db28ece2 100644
--- a/plug-ins/file-jpeg/jpeg-save.c
+++ b/plug-ins/file-jpeg/jpeg-save.c
@@ -796,7 +796,8 @@ save_dialog (GimpProcedure       *procedure,
                 NULL);
 
   dialog = gimp_save_procedure_dialog_new (GIMP_SAVE_PROCEDURE (procedure),
-                                           GIMP_PROCEDURE_CONFIG (config));
+                                           GIMP_PROCEDURE_CONFIG (config),
+                                           gimp_item_get_image (GIMP_ITEM (drawable)));
 
   /* custom quantization tables - now used also for original quality */
   widget = gimp_procedure_dialog_get_widget (GIMP_PROCEDURE_DIALOG (dialog),
diff --git a/plug-ins/file-tiff/file-tiff-save.c b/plug-ins/file-tiff/file-tiff-save.c
index 45ce1c5336..161b896a69 100644
--- a/plug-ins/file-tiff/file-tiff-save.c
+++ b/plug-ins/file-tiff/file-tiff-save.c
@@ -1283,7 +1283,8 @@ save_dialog (GimpImage     *image,
   gboolean         run;
 
   dialog = gimp_save_procedure_dialog_new (GIMP_SAVE_PROCEDURE (procedure),
-                                           GIMP_PROCEDURE_CONFIG (config));
+                                           GIMP_PROCEDURE_CONFIG (config),
+                                           image);
 
   store =
     gimp_int_store_new (_("None"),              GIMP_COMPRESSION_NONE,


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