[gimp] libgimp: new metadata support concept in GimpSaveProcedure and new…
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimp: new metadata support concept in GimpSaveProcedure and new…
- Date: Mon, 23 Nov 2020 01:23:44 +0000 (UTC)
commit 3918a0a04c1c3df2bc6944dfab22cc20b14bc092
Author: Jehan <jehan girinstud io>
Date: Sat Nov 21 01:15:15 2020 +0100
libgimp: new metadata support concept in GimpSaveProcedure and new…
… class GimpSaveProcedureDialog.
The idea is that we have basically the same code in most file format
plug-ins to handle various generic metadata, yet usually with slight
differences here and there. Even behavior is sometimes a bit different
even though there is no reason for the logics to be different from one
format to another.
So I move the metadata support logics into GimpSaveProcedure (and
GimpProcedureConfig still keeps the main export logics). The GUI logics
is now in a new GimpSaveProcedureDialog. So export plug-ins will now get
the creation of generic metadata nearly for free. All they have to do is
to tell what kind of metadata the GimpSaveProcedure supports with the
gimp_save_procedure_set_support_*() functions.
Then consistency will apply:
- If a format supports a given metadata, they will always have an
auxiliary argument with the same name across plug-ins.
- The label and tooltips will also be always the same in the GUI.
- Order of metadata widgets will also stay consistent.
- The widgets will work the same (no more "Comment" text view missing in
one plug-in but present in another, or with an entry here, and a text
view there, and so on).
Also adding gimp_save_procedure_dialog_add_metadata() to allow plug-ins
to "declare" one of their options as a metadata option, and therefore
have it packed within the "Metadata" block which is now created (for
instance for PNG/TIFF/JPEG specific metadata). This allows a nicer
organization of dialogs.
libgimp/Makefile.gi | 2 +
libgimp/gimp.def | 12 +
libgimp/gimpproceduredialog.c | 214 +++++++++------
libgimp/gimpproceduredialog.h | 5 +
libgimp/gimpsaveprocedure.c | 554 ++++++++++++++++++++++++++++++++++++++
libgimp/gimpsaveprocedure.h | 20 ++
libgimp/gimpsaveproceduredialog.c | 296 ++++++++++++++++++++
libgimp/gimpsaveproceduredialog.h | 79 ++++++
libgimp/gimpui.def | 3 +
libgimp/gimpui.h | 1 +
libgimp/gimpuitypes.h | 1 +
libgimp/meson.build | 2 +
12 files changed, 1100 insertions(+), 89 deletions(-)
---
diff --git a/libgimp/Makefile.gi b/libgimp/Makefile.gi
index 2cf4510561..7e25a01dab 100644
--- a/libgimp/Makefile.gi
+++ b/libgimp/Makefile.gi
@@ -190,6 +190,7 @@ libgimpui_introspectable_headers = \
../libgimp/gimpproceduredialog.h \
../libgimp/gimpprocview.h \
../libgimp/gimpprogressbar.h \
+ ../libgimp/gimpsaveproceduredialog.h \
../libgimp/gimpselectbutton.h \
../libgimp/gimpzoompreview.h
@@ -209,6 +210,7 @@ libgimpui_introspectable = \
../libgimp/gimpprocbrowserdialog.c \
../libgimp/gimpproceduredialog.c \
../libgimp/gimpprocview.c \
+ ../libgimp/gimpsaveproceduredialog.c \
../libgimp/gimpprogressbar.c \
../libgimp/gimpselectbutton.c \
../libgimp/gimpzoompreview.c
diff --git a/libgimp/gimp.def b/libgimp/gimp.def
index 4a01a64880..32fa15e3bb 100644
--- a/libgimp/gimp.def
+++ b/libgimp/gimp.def
@@ -759,8 +759,20 @@ EXPORTS
gimp_progress_uninstall
gimp_progress_update
gimp_quit
+ gimp_save_procedure_get_support_comment
+ gimp_save_procedure_get_support_exif
+ gimp_save_procedure_get_support_iptc
+ gimp_save_procedure_get_support_profile
+ gimp_save_procedure_get_support_thumbnail
+ gimp_save_procedure_get_support_xmp
gimp_save_procedure_get_type
gimp_save_procedure_new
+ gimp_save_procedure_set_support_comment
+ gimp_save_procedure_set_support_exif
+ gimp_save_procedure_set_support_iptc
+ gimp_save_procedure_set_support_profile
+ gimp_save_procedure_set_support_thumbnail
+ gimp_save_procedure_set_support_xmp
gimp_selection_all
gimp_selection_border
gimp_selection_bounds
diff --git a/libgimp/gimpproceduredialog.c b/libgimp/gimpproceduredialog.c
index c91f4a139e..47e292482c 100644
--- a/libgimp/gimpproceduredialog.c
+++ b/libgimp/gimpproceduredialog.c
@@ -60,6 +60,7 @@ struct _GimpProcedureDialogPrivate
};
+static void gimp_procedure_dialog_constructed (GObject *object);
static void gimp_procedure_dialog_dispose (GObject *object);
static void gimp_procedure_dialog_set_property (GObject *object,
guint property_id,
@@ -70,6 +71,11 @@ static void gimp_procedure_dialog_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
+static void gimp_procedure_dialog_real_fill_list (GimpProcedureDialog *dialog,
+ GimpProcedure *procedure,
+ GimpProcedureConfig *config,
+ GList *properties);
+
static void gimp_procedure_dialog_reset_initial (GtkWidget *button,
GimpProcedureDialog *dialog);
static void gimp_procedure_dialog_reset_factory (GtkWidget *button,
@@ -102,16 +108,20 @@ gimp_procedure_dialog_class_init (GimpProcedureDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = gimp_procedure_dialog_constructed;
object_class->dispose = gimp_procedure_dialog_dispose;
object_class->get_property = gimp_procedure_dialog_get_property;
object_class->set_property = gimp_procedure_dialog_set_property;
+ klass->fill_list = gimp_procedure_dialog_real_fill_list;
+
props[PROP_PROCEDURE] =
g_param_spec_object ("procedure",
"Procedure",
"The GimpProcedure this dialog is used with",
GIMP_TYPE_PROCEDURE,
- GIMP_PARAM_READWRITE);
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT);
props[PROP_CONFIG] =
g_param_spec_object ("config",
@@ -135,6 +145,86 @@ gimp_procedure_dialog_init (GimpProcedureDialog *dialog)
dialog->priv->label_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
}
+static void
+gimp_procedure_dialog_constructed (GObject *object)
+{
+ GimpProcedureDialog *dialog;
+ GimpProcedure *procedure;
+ const gchar *ok_label;
+ GtkWidget *hbox;
+ GtkWidget *button;
+ GtkWidget *content_area;
+ gchar *role;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ dialog = GIMP_PROCEDURE_DIALOG (object);
+ procedure = dialog->priv->procedure;
+
+ role = g_strdup_printf ("gimp-%s", gimp_procedure_get_name (procedure));
+ g_object_set (object,
+ "role", role,
+ NULL);
+ g_free (role);
+
+ if (GIMP_IS_LOAD_PROCEDURE (procedure))
+ ok_label = _("_Open");
+ else if (GIMP_IS_SAVE_PROCEDURE (procedure))
+ ok_label = _("_Export");
+ else
+ ok_label = _("_OK");
+
+ button = gimp_dialog_add_button (GIMP_DIALOG (dialog),
+ _("_Reset"), RESPONSE_RESET);
+ gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "reset");
+ button = gimp_dialog_add_button (GIMP_DIALOG (dialog),
+ _("_Cancel"), GTK_RESPONSE_CANCEL);
+ gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "cancel");
+ button = gimp_dialog_add_button (GIMP_DIALOG (dialog),
+ ok_label, GTK_RESPONSE_OK);
+ gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "ok");
+
+ gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ RESPONSE_RESET,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gimp_window_set_transient (GTK_WINDOW (dialog));
+
+ /* Main content area. */
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_container_set_border_width (GTK_CONTAINER (content_area), 12);
+ gtk_box_set_spacing (GTK_BOX (content_area), 3);
+
+ /* Bottom box buttons with small additional padding. */
+ hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_set_spacing (GTK_BOX (hbox), 6);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_START);
+ gtk_box_pack_end (GTK_BOX (content_area), hbox, FALSE, FALSE, 0);
+ gtk_container_child_set (GTK_CONTAINER (content_area), hbox,
+ "padding", 3, NULL);
+ gtk_widget_show (hbox);
+
+ button = gtk_button_new_with_mnemonic (_("_Load Defaults"));
+ gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "load-defaults");
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (gimp_procedure_dialog_load_defaults),
+ dialog);
+
+ button = gtk_button_new_with_mnemonic (_("_Save Defaults"));
+ gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "save-defaults");
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (gimp_procedure_dialog_save_defaults),
+ dialog);
+}
+
static void
gimp_procedure_dialog_dispose (GObject *object)
{
@@ -207,19 +297,43 @@ gimp_procedure_dialog_get_property (GObject *object,
}
}
+static void
+gimp_procedure_dialog_real_fill_list (GimpProcedureDialog *dialog,
+ GimpProcedure *procedure,
+ GimpProcedureConfig *config,
+ GList *properties)
+{
+ GtkWidget *content_area;
+ GList *iter;
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ for (iter = properties; iter; iter = iter->next)
+ {
+ GtkWidget *widget;
+
+ widget = gimp_procedure_dialog_get_widget (dialog, iter->data, G_TYPE_NONE);
+ if (widget)
+ {
+ /* Reference the widget because the hash table will
+ * unreference it anyway when getting destroyed so we don't
+ * want to give the only reference to the parent widget.
+ */
+ g_object_ref (widget);
+ gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+ }
+ }
+}
+
GtkWidget *
gimp_procedure_dialog_new (GimpProcedure *procedure,
GimpProcedureConfig *config,
const gchar *title)
{
GtkWidget *dialog;
- gchar *role;
const gchar *help_id;
- const gchar *ok_label;
gboolean use_header_bar;
- GtkWidget *hbox;
- GtkWidget *button;
- GtkWidget *content_area;
g_return_val_if_fail (GIMP_IS_PROCEDURE (procedure), NULL);
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), NULL);
@@ -227,8 +341,6 @@ gimp_procedure_dialog_new (GimpProcedure *procedure,
procedure, NULL);
g_return_val_if_fail (title != NULL, NULL);
- role = g_strdup_printf ("gimp-%s", gimp_procedure_get_name (procedure));
-
help_id = gimp_procedure_get_help_id (procedure);
g_object_get (gtk_settings_get_default (),
@@ -239,71 +351,11 @@ gimp_procedure_dialog_new (GimpProcedure *procedure,
"procedure", procedure,
"config", config,
"title", title,
- "role", role,
"help-func", gimp_standard_help_func,
"help-id", help_id,
"use-header-bar", use_header_bar,
NULL);
- g_free (role);
-
- if (GIMP_IS_LOAD_PROCEDURE (procedure))
- ok_label = _("_Open");
- else if (GIMP_IS_SAVE_PROCEDURE (procedure))
- ok_label = _("_Export");
- else
- ok_label = _("_OK");
-
- button = gimp_dialog_add_button (GIMP_DIALOG (dialog),
- _("_Reset"), RESPONSE_RESET);
- gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "reset");
- button = gimp_dialog_add_button (GIMP_DIALOG (dialog),
- _("_Cancel"), GTK_RESPONSE_CANCEL);
- gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "cancel");
- button = gimp_dialog_add_button (GIMP_DIALOG (dialog),
- ok_label, GTK_RESPONSE_OK);
- gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "ok");
-
- gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
- GTK_RESPONSE_OK,
- RESPONSE_RESET,
- GTK_RESPONSE_CANCEL,
- -1);
-
- gimp_window_set_transient (GTK_WINDOW (dialog));
-
- /* Main content area. */
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
- gtk_container_set_border_width (GTK_CONTAINER (content_area), 12);
- gtk_box_set_spacing (GTK_BOX (content_area), 3);
-
- /* Bottom box buttons with small additional padding. */
- hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
- gtk_box_set_spacing (GTK_BOX (hbox), 6);
- gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_START);
- gtk_box_pack_end (GTK_BOX (content_area), hbox, FALSE, FALSE, 0);
- gtk_container_child_set (GTK_CONTAINER (content_area), hbox,
- "padding", 3, NULL);
- gtk_widget_show (hbox);
-
- button = gtk_button_new_with_mnemonic (_("_Load Defaults"));
- gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "load-defaults");
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- gtk_widget_show (button);
-
- g_signal_connect (button, "clicked",
- G_CALLBACK (gimp_procedure_dialog_load_defaults),
- dialog);
-
- button = gtk_button_new_with_mnemonic (_("_Save Defaults"));
- gimp_procedure_dialog_check_mnemonic (GIMP_PROCEDURE_DIALOG (dialog), button, NULL, "save-defaults");
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- gtk_widget_show (button);
-
- g_signal_connect (button, "clicked",
- G_CALLBACK (gimp_procedure_dialog_save_defaults),
- dialog);
-
return GTK_WIDGET (dialog);
}
@@ -664,11 +716,7 @@ void
gimp_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
GList *properties)
{
- GtkWidget *content_area;
- GList *iter;
- gboolean free_properties = FALSE;
-
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gboolean free_properties = FALSE;
if (! properties)
{
@@ -698,22 +746,10 @@ gimp_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
free_properties = TRUE;
}
- for (iter = properties; iter; iter = iter->next)
- {
- GtkWidget *widget;
-
- widget = gimp_procedure_dialog_get_widget (dialog, iter->data, G_TYPE_NONE);
- if (widget)
- {
- /* Reference the widget because the hash table will
- * unreference it anyway when getting destroyed so we don't
- * want to give the only reference to the parent widget.
- */
- g_object_ref (widget);
- gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
- gtk_widget_show (widget);
- }
- }
+ GIMP_PROCEDURE_DIALOG_GET_CLASS (dialog)->fill_list (dialog,
+ dialog->priv->procedure,
+ dialog->priv->config,
+ properties);
if (free_properties)
g_list_free (properties);
diff --git a/libgimp/gimpproceduredialog.h b/libgimp/gimpproceduredialog.h
index 95497faf9c..8825f93d7c 100644
--- a/libgimp/gimpproceduredialog.h
+++ b/libgimp/gimpproceduredialog.h
@@ -52,6 +52,11 @@ struct _GimpProcedureDialogClass
{
GimpDialogClass parent_class;
+ void (* fill_list) (GimpProcedureDialog *dialog,
+ GimpProcedure *procedure,
+ GimpProcedureConfig *config,
+ GList *properties);
+
/* Padding for future expansion */
void (*_gimp_reserved1) (void);
void (*_gimp_reserved2) (void);
diff --git a/libgimp/gimpsaveprocedure.c b/libgimp/gimpsaveprocedure.c
index c2032ab96b..8443949997 100644
--- a/libgimp/gimpsaveprocedure.c
+++ b/libgimp/gimpsaveprocedure.c
@@ -26,16 +26,43 @@
#include "gimppdb_pdb.h"
+enum
+{
+ PROP_0,
+ PROP_SUPPORTS_EXIF,
+ PROP_SUPPORTS_IPTC,
+ PROP_SUPPORTS_XMP,
+ PROP_SUPPORTS_PROFILE,
+ PROP_SUPPORTS_THUMBNAIL,
+ PROP_SUPPORTS_COMMENT,
+ N_PROPS
+};
+
struct _GimpSaveProcedurePrivate
{
GimpRunSaveFunc run_func;
gpointer run_data;
GDestroyNotify run_data_destroy;
+
+ gboolean supports_exif;
+ gboolean supports_iptc;
+ gboolean supports_xmp;
+ gboolean supports_profile;
+ gboolean supports_thumbnail;
+ gboolean supports_comment;
};
static void gimp_save_procedure_constructed (GObject *object);
static void gimp_save_procedure_finalize (GObject *object);
+static void gimp_save_procedure_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_save_procedure_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
static void gimp_save_procedure_install (GimpProcedure *procedure);
static GimpValueArray *
@@ -46,12 +73,15 @@ static GimpProcedureConfig *
GParamSpec **args,
gint n_args);
+static void gimp_save_procedure_add_metadata (GimpSaveProcedure *save_procedure);
+
G_DEFINE_TYPE_WITH_PRIVATE (GimpSaveProcedure, gimp_save_procedure,
GIMP_TYPE_FILE_PROCEDURE)
#define parent_class gimp_save_procedure_parent_class
+static GParamSpec *props[N_PROPS] = { NULL, };
static void
gimp_save_procedure_class_init (GimpSaveProcedureClass *klass)
@@ -61,10 +91,93 @@ gimp_save_procedure_class_init (GimpSaveProcedureClass *klass)
object_class->constructed = gimp_save_procedure_constructed;
object_class->finalize = gimp_save_procedure_finalize;
+ object_class->get_property = gimp_save_procedure_get_property;
+ object_class->set_property = gimp_save_procedure_set_property;
procedure_class->install = gimp_save_procedure_install;
procedure_class->run = gimp_save_procedure_run;
procedure_class->create_config = gimp_save_procedure_create_config;
+
+ /**
+ * GimpSaveProcedure:exif:
+ *
+ * Whether the save procedure supports EXIF.
+ *
+ * Since: 3.0.0
+ */
+ props[PROP_SUPPORTS_EXIF] = g_param_spec_boolean ("supports-exif",
+ "Supports EXIF metadata storage",
+ NULL,
+ FALSE,
+ G_PARAM_CONSTRUCT |
+ GIMP_PARAM_READWRITE);
+ /**
+ * GimpSaveProcedure:iptc:
+ *
+ * Whether the save procedure supports IPTC.
+ *
+ * Since: 3.0.0
+ */
+ props[PROP_SUPPORTS_IPTC] = g_param_spec_boolean ("supports-iptc",
+ "Supports IPTC metadata storage",
+ NULL,
+ FALSE,
+ G_PARAM_CONSTRUCT |
+ GIMP_PARAM_READWRITE);
+ /**
+ * GimpSaveProcedure:xmpp:
+ *
+ * Whether the save procedure supports XMP.
+ *
+ * Since: 3.0.0
+ */
+ props[PROP_SUPPORTS_XMP] = g_param_spec_boolean ("supports-xmp",
+ "Supports XMP metadata storage",
+ NULL,
+ FALSE,
+ G_PARAM_CONSTRUCT |
+ GIMP_PARAM_READWRITE);
+ /**
+ * GimpSaveProcedure:profile:
+ *
+ * Whether the save procedure supports ICC color profiles.
+ *
+ * Since: 3.0.0
+ */
+ props[PROP_SUPPORTS_PROFILE] = g_param_spec_boolean ("supports-profile",
+ "Supports color profile storage",
+ NULL,
+ FALSE,
+ G_PARAM_CONSTRUCT |
+ GIMP_PARAM_READWRITE);
+ /**
+ * GimpSaveProcedure:thumbnail:
+ *
+ * Whether the save procedure supports storing a thumbnail.
+ *
+ * Since: 3.0.0
+ */
+ props[PROP_SUPPORTS_THUMBNAIL] = g_param_spec_boolean ("supports-thumbnail",
+ "Supports thumbnail storage",
+ NULL,
+ FALSE,
+ G_PARAM_CONSTRUCT |
+ GIMP_PARAM_READWRITE);
+ /**
+ * GimpSaveProcedure:comment:
+ *
+ * Whether the save procedure supports storing a comment.
+ *
+ * Since: 3.0.0
+ */
+ props[PROP_SUPPORTS_COMMENT] = g_param_spec_boolean ("supports-comment",
+ "Supports comment storage",
+ NULL,
+ FALSE,
+ G_PARAM_CONSTRUCT |
+ GIMP_PARAM_READWRITE);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
}
static void
@@ -115,6 +228,76 @@ gimp_save_procedure_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static void
+gimp_save_procedure_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpSaveProcedure *procedure = GIMP_SAVE_PROCEDURE (object);
+
+ switch (property_id)
+ {
+ case PROP_SUPPORTS_EXIF:
+ procedure->priv->supports_exif = g_value_get_boolean (value);
+ break;
+ case PROP_SUPPORTS_IPTC:
+ procedure->priv->supports_iptc = g_value_get_boolean (value);
+ break;
+ case PROP_SUPPORTS_XMP:
+ procedure->priv->supports_xmp = g_value_get_boolean (value);
+ break;
+ case PROP_SUPPORTS_PROFILE:
+ procedure->priv->supports_profile = g_value_get_boolean (value);
+ break;
+ case PROP_SUPPORTS_THUMBNAIL:
+ procedure->priv->supports_thumbnail = g_value_get_boolean (value);
+ break;
+ case PROP_SUPPORTS_COMMENT:
+ procedure->priv->supports_comment = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_save_procedure_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpSaveProcedure *procedure = GIMP_SAVE_PROCEDURE (object);
+
+ switch (property_id)
+ {
+ case PROP_SUPPORTS_EXIF:
+ g_value_set_boolean (value, procedure->priv->supports_exif);
+ break;
+ case PROP_SUPPORTS_IPTC:
+ g_value_set_boolean (value, procedure->priv->supports_iptc);
+ break;
+ case PROP_SUPPORTS_XMP:
+ g_value_set_boolean (value, procedure->priv->supports_xmp);
+ break;
+ case PROP_SUPPORTS_PROFILE:
+ g_value_set_boolean (value, procedure->priv->supports_profile);
+ break;
+ case PROP_SUPPORTS_THUMBNAIL:
+ g_value_set_boolean (value, procedure->priv->supports_thumbnail);
+ break;
+ case PROP_SUPPORTS_COMMENT:
+ g_value_set_boolean (value, procedure->priv->supports_comment);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
static void
gimp_save_procedure_install (GimpProcedure *procedure)
{
@@ -122,6 +305,7 @@ gimp_save_procedure_install (GimpProcedure *procedure)
const gchar *mime_types;
gint priority;
+ gimp_save_procedure_add_metadata (GIMP_SAVE_PROCEDURE (procedure));
GIMP_PROCEDURE_CLASS (parent_class)->install (procedure);
_gimp_pdb_set_file_proc_save_handler (gimp_procedure_get_name (procedure),
@@ -191,6 +375,8 @@ gimp_save_procedure_create_config (GimpProcedure *procedure,
GParamSpec **args,
gint n_args)
{
+ gimp_save_procedure_add_metadata (GIMP_SAVE_PROCEDURE (procedure));
+
if (n_args > ARG_OFFSET)
{
args += ARG_OFFSET;
@@ -207,6 +393,60 @@ gimp_save_procedure_create_config (GimpProcedure *procedure,
n_args);
}
+static void
+gimp_save_procedure_add_metadata (GimpSaveProcedure *save_procedure)
+{
+ GimpProcedure *procedure = GIMP_PROCEDURE (save_procedure);
+
+ if (save_procedure->priv->supports_exif)
+ GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-exif",
+ "Save Exif",
+ "Save Exif (Exchangeable image file format) metadata",
+ gimp_export_exif (),
+ G_PARAM_READWRITE);
+ if (save_procedure->priv->supports_iptc)
+ GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-iptc",
+ "Save IPTC",
+ "Save IPTC (International Press Telecommunications Council) metadata",
+ gimp_export_iptc (),
+ G_PARAM_READWRITE);
+ if (save_procedure->priv->supports_xmp)
+ GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-xmp",
+ "Save XMP",
+ "Save XMP (Extensible Metadata Platform) metadata",
+ gimp_export_xmp (),
+ G_PARAM_READWRITE);
+ if (save_procedure->priv->supports_profile)
+ GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-color-profile",
+ "Save color profile",
+ "Save the ICC color profile as metadata",
+ gimp_export_color_profile (),
+ G_PARAM_READWRITE);
+ if (save_procedure->priv->supports_thumbnail)
+ GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-thumbnail",
+ "Save thumbnail",
+ "Save a smaller representation of the image as metadata",
+ TRUE,
+ G_PARAM_READWRITE);
+ if (save_procedure->priv->supports_comment)
+ {
+ GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-comment",
+ "Save comment",
+ "Save a comment as metadata",
+ gimp_export_comment (),
+ G_PARAM_READWRITE);
+ GIMP_PROC_AUX_ARG_STRING (procedure, "gimp-comment",
+ "Comment",
+ "Image comment",
+ gimp_get_default_comment (),
+ G_PARAM_READWRITE);
+
+ gimp_procedure_set_argument_sync (procedure, "gimp-comment",
+ GIMP_ARGUMENT_SYNC_PARASITE);
+ }
+
+}
+
/* public functions */
@@ -271,3 +511,317 @@ gimp_save_procedure_new (GimpPlugIn *plug_in,
return GIMP_PROCEDURE (procedure);
}
+
+/**
+ * gimp_save_procedure_set_support_exif:
+ * @procedure: a #GimpProcedure.
+ * @supports: whether Exif metadata are supported.
+ *
+ * Determine whether @procedure supports saving Exif data. By default,
+ * it won't (so there is usually no reason to run this function with
+ * %FALSE).
+ * This will have several consequence:
+ * - Automatically adds a standard auxiliary argument "save-exif" in the
+ * end of the argument list of @procedure, with relevant blurb and
+ * description.
+ * - If used with other gimp_save_procedure_set_support_*() functions,
+ * they will always be ordered the same (the order of the calls don't
+ * matter), keeping all save procedures consistent.
+ * - Generated GimpSaveProcedureDialog will contain the metadata
+ * options, once again always in the same order and with consistent
+ * GUI style across plug-ins.
+ * - API from #GimpProcedureConfig will automatically process these
+ * properties to decide whether to save a given metadata or not.
+ *
+ * Note that since this is an auxiliary argument, it won't be part of
+ * the PDB arguments. By default, the value will be gimp_export_exif().
+ * Since: 3.0
+ **/
+void
+gimp_save_procedure_set_support_exif (GimpSaveProcedure *procedure,
+ gboolean supports)
+{
+ g_return_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure));
+
+ g_object_set (procedure,
+ "supports-exif", supports,
+ NULL);
+}
+
+/**
+ * gimp_save_procedure_set_support_iptc:
+ * @procedure: a #GimpProcedure.
+ * @supports: whether IPTC metadata are supported.
+ *
+ * Determine whether @procedure supports saving IPTC data. By default,
+ * it won't (so there is usually no reason to run this function with
+ * %FALSE).
+ * This will have several consequence:
+ * - Automatically adds a standard auxiliary argument "save-iptc" in the
+ * end of the argument list of @procedure, with relevant blurb and
+ * description.
+ * - If used with other gimp_save_procedure_set_support_*() functions,
+ * they will always be ordered the same (the order of the calls don't
+ * matter), keeping all save procedures consistent.
+ * - Generated GimpSaveProcedureDialog will contain the metadata
+ * options, once again always in the same order and with consistent
+ * GUI style across plug-ins.
+ * - API from #GimpProcedureConfig will automatically process these
+ * properties to decide whether to save a given metadata or not.
+ *
+ * Note that since this is an auxiliary argument, it won't be part of
+ * the PDB arguments. By default, the value will be gimp_export_iptc().
+ * Since: 3.0
+ **/
+void
+gimp_save_procedure_set_support_iptc (GimpSaveProcedure *procedure,
+ gboolean supports)
+{
+ g_return_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure));
+
+ g_object_set (procedure,
+ "supports-iptc", supports,
+ NULL);
+}
+
+/**
+ * gimp_save_procedure_set_support_xmp:
+ * @procedure: a #GimpProcedure.
+ * @supports: whether XMP metadata are supported.
+ *
+ * Determine whether @procedure supports saving XMP data. By default,
+ * it won't (so there is usually no reason to run this function with
+ * %FALSE).
+ * This will have several consequence:
+ * - Automatically adds a standard auxiliary argument "save-xmp" in the
+ * end of the argument list of @procedure, with relevant blurb and
+ * description.
+ * - If used with other gimp_save_procedure_set_support_*() functions,
+ * they will always be ordered the same (the order of the calls don't
+ * matter), keeping all save procedures consistent.
+ * - Generated GimpSaveProcedureDialog will contain the metadata
+ * options, once again always in the same order and with consistent
+ * GUI style across plug-ins.
+ * - API from #GimpProcedureConfig will automatically process these
+ * properties to decide whether to save a given metadata or not.
+ *
+ * Note that since this is an auxiliary argument, it won't be part of
+ * the PDB arguments. By default, the value will be gimp_export_xmp().
+ * Since: 3.0
+ **/
+void
+gimp_save_procedure_set_support_xmp (GimpSaveProcedure *procedure,
+ gboolean supports)
+{
+ g_return_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure));
+
+ g_object_set (procedure,
+ "supports-xmp", supports,
+ NULL);
+}
+
+/**
+ * gimp_save_procedure_set_support_profile:
+ * @procedure: a #GimpProcedure.
+ * @supports: whether color profiles can be stored.
+ *
+ * Determine whether @procedure supports saving ICC color profiles. By
+ * default, it won't (so there is usually no reason to run this function
+ * with %FALSE).
+ * This will have several consequence:
+ * - Automatically adds a standard auxiliary argument
+ * "save-color-profile" in the end of the argument list of @procedure,
+ * with relevant blurb and description.
+ * - If used with other gimp_save_procedure_set_support_*() functions,
+ * they will always be ordered the same (the order of the calls don't
+ * matter), keeping all save procedures consistent.
+ * - Generated GimpSaveProcedureDialog will contain the metadata
+ * options, once again always in the same order and with consistent
+ * GUI style across plug-ins.
+ * - API from #GimpProcedureConfig will automatically process these
+ * properties to decide whether to save a given metadata or not.
+ *
+ * Note that since this is an auxiliary argument, it won't be part of
+ * the PDB arguments. By default, the value will be
+ * gimp_export_color_profile().
+ * Since: 3.0
+ **/
+void
+gimp_save_procedure_set_support_profile (GimpSaveProcedure *procedure,
+ gboolean supports)
+{
+ g_return_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure));
+
+ g_object_set (procedure,
+ "supports-profile", supports,
+ NULL);
+}
+
+/**
+ * gimp_save_procedure_set_support_thumbnail:
+ * @procedure: a #GimpProcedure.
+ * @supports: whether a thumbnail can be stored.
+ *
+ * Determine whether @procedure supports saving a thumbnail. By default,
+ * it won't (so there is usually no reason to run this function with
+ * %FALSE).
+ * This will have several consequence:
+ * - Automatically adds a standard auxiliary argument "save-thumbnail"
+ * in the end of the argument list of @procedure, with relevant blurb
+ * and description.
+ * - If used with other gimp_save_procedure_set_support_*() functions,
+ * they will always be ordered the same (the order of the calls don't
+ * matter), keeping all save procedures consistent.
+ * - Generated GimpSaveProcedureDialog will contain the metadata
+ * options, once again always in the same order and with consistent
+ * GUI style across plug-ins.
+ * - API from #GimpProcedureConfig will automatically process these
+ * properties to decide whether to save a given metadata or not.
+ *
+ * Note that since this is an auxiliary argument, it won't be part of
+ * the PDB arguments. By default, the value will be %TRUE.
+ * Since: 3.0
+ **/
+void
+gimp_save_procedure_set_support_thumbnail (GimpSaveProcedure *procedure,
+ gboolean supports)
+{
+ g_return_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure));
+
+ g_object_set (procedure,
+ "supports-thumbnail", supports,
+ NULL);
+}
+
+/**
+ * gimp_save_procedure_set_support_comment:
+ * @procedure: a #GimpProcedure.
+ * @supports: whether a comment can be stored.
+ *
+ * Determine whether @procedure supports saving a comment. By default,
+ * it won't (so there is usually no reason to run this function with
+ * %FALSE).
+ * This will have several consequence:
+ * - Automatically adds a standard auxiliary argument "save-comment"
+ * in the end of the argument list of @procedure, with relevant blurb
+ * and description.
+ * - If used with other gimp_save_procedure_set_support_*() functions,
+ * they will always be ordered the same (the order of the calls don't
+ * matter), keeping all save procedures consistent.
+ * - Generated GimpSaveProcedureDialog will contain the metadata
+ * options, once again always in the same order and with consistent
+ * GUI style across plug-ins.
+ * - API from #GimpProcedureConfig will automatically process these
+ * properties to decide whether to save a given metadata or not.
+ *
+ * Note that since this is an auxiliary argument, it won't be part of
+ * the PDB arguments. By default, the value will be
+ * gimp_export_comment().
+ * Since: 3.0
+ **/
+void
+gimp_save_procedure_set_support_comment (GimpSaveProcedure *procedure,
+ gboolean supports)
+{
+ g_return_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure));
+
+ g_object_set (procedure,
+ "supports-comment", supports,
+ NULL);
+}
+
+/**
+ * gimp_save_procedure_get_support_exif:
+ * @procedure: a #GimpProcedure.
+ *
+ * Returns: %TRUE if @procedure supports Exif saving.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_save_procedure_get_support_exif (GimpSaveProcedure *procedure)
+{
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), FALSE);
+
+ return procedure->priv->supports_exif;
+}
+
+/**
+ * gimp_save_procedure_get_support_iptc:
+ * @procedure: a #GimpProcedure.
+ *
+ * Returns: %TRUE if @procedure supports IPTC saving.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_save_procedure_get_support_iptc (GimpSaveProcedure *procedure)
+{
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), FALSE);
+
+ return procedure->priv->supports_iptc;
+}
+
+/**
+ * gimp_save_procedure_get_support_xmp:
+ * @procedure: a #GimpProcedure.
+ *
+ * Returns: %TRUE if @procedure supports XMP saving.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_save_procedure_get_support_xmp (GimpSaveProcedure *procedure)
+{
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), FALSE);
+
+ return procedure->priv->supports_xmp;
+}
+
+/**
+ * gimp_save_procedure_get_support_profile:
+ * @procedure: a #GimpProcedure.
+ *
+ * Returns: %TRUE if @procedure supports ICC color profile saving.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_save_procedure_get_support_profile (GimpSaveProcedure *procedure)
+{
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), FALSE);
+
+ return procedure->priv->supports_profile;
+}
+
+/**
+ * gimp_save_procedure_get_support_thumbnail:
+ * @procedure: a #GimpProcedure.
+ *
+ * Returns: %TRUE if @procedure supports thumbnail saving.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_save_procedure_get_support_thumbnail (GimpSaveProcedure *procedure)
+{
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), FALSE);
+
+ return procedure->priv->supports_thumbnail;
+}
+
+/**
+ * gimp_save_procedure_get_support_comment:
+ * @procedure: a #GimpProcedure.
+ *
+ * Returns: %TRUE if @procedure supports comment saving.
+ *
+ * Since: 3.0
+ **/
+gboolean
+gimp_save_procedure_get_support_comment (GimpSaveProcedure *procedure)
+{
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), FALSE);
+
+ return procedure->priv->supports_comment;
+}
diff --git a/libgimp/gimpsaveprocedure.h b/libgimp/gimpsaveprocedure.h
index c15c0b82cb..40d3a4cfbd 100644
--- a/libgimp/gimpsaveprocedure.h
+++ b/libgimp/gimpsaveprocedure.h
@@ -91,6 +91,26 @@ GimpProcedure * gimp_save_procedure_new (GimpPlugIn *plug_in,
gpointer run_data,
GDestroyNotify run_data_destroy);
+void gimp_save_procedure_set_support_exif (GimpSaveProcedure *procedure,
+ gboolean supports);
+void gimp_save_procedure_set_support_iptc (GimpSaveProcedure *procedure,
+ gboolean supports);
+void gimp_save_procedure_set_support_xmp (GimpSaveProcedure *procedure,
+ gboolean supports);
+void gimp_save_procedure_set_support_profile (GimpSaveProcedure *procedure,
+ gboolean supports);
+void gimp_save_procedure_set_support_thumbnail (GimpSaveProcedure *procedure,
+ gboolean supports);
+void gimp_save_procedure_set_support_comment (GimpSaveProcedure *procedure,
+ gboolean supports);
+
+gboolean gimp_save_procedure_get_support_exif (GimpSaveProcedure *procedure);
+gboolean gimp_save_procedure_get_support_iptc (GimpSaveProcedure *procedure);
+gboolean gimp_save_procedure_get_support_xmp (GimpSaveProcedure *procedure);
+gboolean gimp_save_procedure_get_support_profile (GimpSaveProcedure *procedure);
+gboolean gimp_save_procedure_get_support_thumbnail (GimpSaveProcedure *procedure);
+gboolean gimp_save_procedure_get_support_comment (GimpSaveProcedure *procedure);
+
G_END_DECLS
diff --git a/libgimp/gimpsaveproceduredialog.c b/libgimp/gimpsaveproceduredialog.c
new file mode 100644
index 0000000000..efec13ef66
--- /dev/null
+++ b/libgimp/gimpsaveproceduredialog.c
@@ -0,0 +1,296 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpsaveproceduredialog.c
+ * Copyright (C) 2020 Jehan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "gimp.h"
+#include "gimpui.h"
+
+#include "libgimp-intl.h"
+
+
+struct _GimpSaveProcedureDialogPrivate
+{
+ GList *additional_metadata;
+};
+
+
+static void gimp_save_procedure_dialog_dispose (GObject *object);
+
+static void gimp_save_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
+ GimpProcedure *procedure,
+ GimpProcedureConfig *config,
+ GList *properties);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpSaveProcedureDialog, gimp_save_procedure_dialog, GIMP_TYPE_PROCEDURE_DIALOG)
+
+#define parent_class gimp_save_procedure_dialog_parent_class
+
+static void
+gimp_save_procedure_dialog_class_init (GimpSaveProcedureDialogClass *klass)
+{
+ GObjectClass *object_class;
+ GimpProcedureDialogClass *proc_dialog_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ proc_dialog_class = GIMP_PROCEDURE_DIALOG_CLASS (klass);
+
+ object_class->dispose = gimp_save_procedure_dialog_dispose;
+ proc_dialog_class->fill_list = gimp_save_procedure_dialog_fill_list;
+}
+
+static void
+gimp_save_procedure_dialog_init (GimpSaveProcedureDialog *dialog)
+{
+ dialog->priv = gimp_save_procedure_dialog_get_instance_private (dialog);
+
+ dialog->priv->additional_metadata = NULL;
+}
+
+static void
+gimp_save_procedure_dialog_dispose (GObject *object)
+{
+ GimpSaveProcedureDialog *dialog = GIMP_SAVE_PROCEDURE_DIALOG (object);
+
+ g_list_free_full (dialog->priv->additional_metadata, g_free);
+ dialog->priv->additional_metadata = NULL;
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_save_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
+ GimpProcedure *procedure,
+ GimpProcedureConfig *config,
+ GList *properties)
+{
+ GimpSaveProcedureDialog *save_dialog;
+ GimpSaveProcedure *save_procedure;
+ GtkWidget *content_area;
+ GList *properties2 = NULL;
+ GList *iter;
+ gint n_checkboxes;
+
+ save_dialog = GIMP_SAVE_PROCEDURE_DIALOG (dialog);
+ save_procedure = GIMP_SAVE_PROCEDURE (procedure);
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ for (iter = properties; iter; iter = iter->next)
+ {
+ gchar *propname = iter->data;
+
+ if ((gimp_save_procedure_get_support_exif (save_procedure) &&
+ g_strcmp0 (propname, "save-exif") == 0) ||
+ (gimp_save_procedure_get_support_iptc (save_procedure) &&
+ g_strcmp0 (propname, "save-iptc") == 0) ||
+ (gimp_save_procedure_get_support_xmp (save_procedure) &&
+ g_strcmp0 (propname, "save-xmp") == 0) ||
+ (gimp_save_procedure_get_support_profile (save_procedure) &&
+ g_strcmp0 (propname, "save-color-profile") == 0) ||
+ (gimp_save_procedure_get_support_thumbnail (save_procedure) &&
+ g_strcmp0 (propname, "save-thumbnail") == 0) ||
+ (gimp_save_procedure_get_support_comment (save_procedure) &&
+ (g_strcmp0 (propname, "save-comment") == 0 ||
+ g_strcmp0 (propname, "gimp-comment") == 0)) ||
+ g_list_find (save_dialog->priv->additional_metadata, propname))
+ /* Ignoring the standards and custom metadata. */
+ continue;
+
+ properties2 = g_list_prepend (properties2, propname);
+ }
+ properties2 = g_list_reverse (properties2);
+ GIMP_PROCEDURE_DIALOG_CLASS (parent_class)->fill_list (dialog, procedure, config, properties2);
+ g_list_free (properties2);
+
+ n_checkboxes = gimp_save_procedure_get_support_exif (save_procedure) +
+ gimp_save_procedure_get_support_iptc (save_procedure) +
+ gimp_save_procedure_get_support_xmp (save_procedure) +
+ gimp_save_procedure_get_support_profile (save_procedure) +
+ gimp_save_procedure_get_support_thumbnail (save_procedure);
+
+ if (n_checkboxes != 0 ||
+ g_list_length (save_dialog->priv->additional_metadata) > 0 ||
+ gimp_save_procedure_get_support_comment (save_procedure))
+ {
+ GtkWidget *frame;
+ GtkWidget *box;
+ GtkWidget *flowbox;
+ GtkWidget *widget;
+
+ frame = gimp_frame_new (_("Metadata"));
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
+ gtk_container_add (GTK_CONTAINER (frame), box);
+ gtk_widget_show (box);
+
+ flowbox = gtk_flow_box_new ();
+ if (n_checkboxes + g_list_length (save_dialog->priv->additional_metadata) > 3)
+ {
+ gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (flowbox), 2);
+ gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (flowbox), 2);
+ }
+ gtk_box_pack_start (GTK_BOX (box), flowbox, TRUE, TRUE, 0);
+ gtk_widget_show (flowbox);
+
+ if (gimp_save_procedure_get_support_exif (save_procedure))
+ {
+ widget = gimp_prop_check_button_new (G_OBJECT (config),
+ "save-exif", NULL);
+ gtk_container_add (GTK_CONTAINER (flowbox), widget);
+ gtk_widget_show (widget);
+ }
+ if (gimp_save_procedure_get_support_iptc (save_procedure))
+ {
+ widget = gimp_prop_check_button_new (G_OBJECT (config),
+ "save-iptc", NULL);
+ gtk_container_add (GTK_CONTAINER (flowbox), widget);
+ gtk_widget_show (widget);
+ }
+ if (gimp_save_procedure_get_support_xmp (save_procedure))
+ {
+ widget = gimp_prop_check_button_new (G_OBJECT (config),
+ "save-xmp", NULL);
+ gtk_container_add (GTK_CONTAINER (flowbox), widget);
+ gtk_widget_show (widget);
+ }
+ if (gimp_save_procedure_get_support_profile (save_procedure))
+ {
+ widget = gimp_prop_check_button_new (G_OBJECT (config),
+ "save-color-profile", NULL);
+ gtk_container_add (GTK_CONTAINER (flowbox), widget);
+ gtk_widget_show (widget);
+ }
+ if (gimp_save_procedure_get_support_thumbnail (save_procedure))
+ {
+ widget = gimp_prop_check_button_new (G_OBJECT (config),
+ "save-thumbnail", NULL);
+ gtk_container_add (GTK_CONTAINER (flowbox), widget);
+ gtk_widget_show (widget);
+ }
+
+ for (iter = save_dialog->priv->additional_metadata; iter; iter = iter->next)
+ {
+ widget = gimp_procedure_dialog_get_widget (dialog, iter->data, G_TYPE_NONE);
+ g_object_ref (widget);
+ gtk_container_add (GTK_CONTAINER (flowbox), widget);
+ gtk_widget_show (widget);
+ }
+
+ if (gimp_save_procedure_get_support_comment (save_procedure))
+ {
+ GtkTextBuffer *buffer;
+ const gchar *tooltip;
+ GtkWidget *frame2;
+ GtkWidget *title;
+ GParamSpec *pspec;
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config),
+ "gimp-comment");
+
+ frame2 = gimp_frame_new (NULL);
+ title = gimp_prop_check_button_new (G_OBJECT (config),
+ "save-comment", NULL);
+ gtk_frame_set_label_widget (GTK_FRAME (frame2), title);
+ gtk_widget_show (title);
+
+ buffer = gimp_prop_text_buffer_new (G_OBJECT (config),
+ "gimp-comment", -1);
+ widget = gtk_text_view_new_with_buffer (buffer);
+ gtk_text_view_set_top_margin (GTK_TEXT_VIEW (widget), 3);
+ gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (widget), 3);
+ gtk_text_view_set_left_margin (GTK_TEXT_VIEW (widget), 3);
+ gtk_text_view_set_right_margin (GTK_TEXT_VIEW (widget), 3);
+ g_object_unref (buffer);
+
+ tooltip = g_param_spec_get_blurb (pspec);
+ if (tooltip)
+ gimp_help_set_help_data (widget, tooltip, NULL);
+
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_widget_set_vexpand (widget, TRUE);
+ gtk_container_add (GTK_CONTAINER (frame2), widget);
+ gtk_widget_show (widget);
+
+ /* Why do I put the text view inside a flowbox? This is a
+ * bit ugly as this is only to allow the text view title
+ * checkbox to be aligned with other checkboxes while
+ * still taking double the width. Probably should have I
+ * gone with a GtkGrid on this one.
+ */
+ flowbox = gtk_flow_box_new ();
+ gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (flowbox), 1);
+ gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (flowbox), 1);
+ gtk_box_pack_start (GTK_BOX (box), flowbox, TRUE, TRUE, 0);
+ gtk_widget_show (flowbox);
+
+ gtk_container_add (GTK_CONTAINER (flowbox), frame2);
+ gtk_widget_show (frame2);
+ }
+ gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+ }
+}
+
+GtkWidget *
+gimp_save_procedure_dialog_new (GimpSaveProcedure *procedure,
+ GimpProcedureConfig *config,
+ const gchar *title)
+{
+ GtkWidget *dialog;
+ const gchar *help_id;
+ gboolean use_header_bar;
+
+ g_return_val_if_fail (GIMP_IS_SAVE_PROCEDURE (procedure), NULL);
+ 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 (title != NULL, NULL);
+
+ help_id = gimp_procedure_get_help_id (GIMP_PROCEDURE (procedure));
+
+ g_object_get (gtk_settings_get_default (),
+ "gtk-dialogs-use-header", &use_header_bar,
+ NULL);
+
+ dialog = g_object_new (GIMP_TYPE_SAVE_PROCEDURE_DIALOG,
+ "procedure", procedure,
+ "config", config,
+ "title", title,
+ "help-func", gimp_standard_help_func,
+ "help-id", help_id,
+ "use-header-bar", use_header_bar,
+ NULL);
+
+ return dialog;
+}
+
+void
+gimp_save_procedure_dialog_add_metadata (GimpSaveProcedureDialog *dialog,
+ const gchar *property)
+{
+ if (! g_list_find (dialog->priv->additional_metadata, property))
+ dialog->priv->additional_metadata = g_list_append (dialog->priv->additional_metadata,
+ g_strdup (property));
+}
diff --git a/libgimp/gimpsaveproceduredialog.h b/libgimp/gimpsaveproceduredialog.h
new file mode 100644
index 0000000000..e97b4111f3
--- /dev/null
+++ b/libgimp/gimpsaveproceduredialog.h
@@ -0,0 +1,79 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpsaveproceduredialog.h
+ * Copyright (C) 2020 Jehan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
+#error "Only <libgimp/gimpui.h> can be included directly."
+#endif
+
+#ifndef __GIMP_SAVE_PROCEDURE_DIALOG_H__
+#define __GIMP_SAVE_PROCEDURE_DIALOG_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+#define GIMP_TYPE_SAVE_PROCEDURE_DIALOG (gimp_save_procedure_dialog_get_type ())
+#define GIMP_SAVE_PROCEDURE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GIMP_TYPE_SAVE_PROCEDURE_DIALOG, GimpSaveProcedureDialog))
+#define GIMP_SAVE_PROCEDURE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GIMP_TYPE_SAVE_PROCEDURE_DIALOG, GimpSaveProcedureDialogClass))
+#define GIMP_IS_SAVE_PROCEDURE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GIMP_TYPE_SAVE_PROCEDURE_DIALOG))
+#define GIMP_IS_SAVE_PROCEDURE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GIMP_TYPE_SAVE_PROCEDURE_DIALOG))
+#define GIMP_SAVE_PROCEDURE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GIMP_TYPE_SAVE_PROCEDURE_DIALOG, GimpSaveProcedureDialogClass))
+
+
+typedef struct _GimpSaveProcedureDialogClass GimpSaveProcedureDialogClass;
+typedef struct _GimpSaveProcedureDialogPrivate GimpSaveProcedureDialogPrivate;
+
+struct _GimpSaveProcedureDialog
+{
+ GimpProcedureDialog parent_instance;
+
+ GimpSaveProcedureDialogPrivate *priv;
+};
+
+struct _GimpSaveProcedureDialogClass
+{
+ GimpProcedureDialogClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gimp_reserved1) (void);
+ void (*_gimp_reserved2) (void);
+ void (*_gimp_reserved3) (void);
+ void (*_gimp_reserved4) (void);
+ void (*_gimp_reserved5) (void);
+ void (*_gimp_reserved6) (void);
+ void (*_gimp_reserved7) (void);
+ void (*_gimp_reserved8) (void);
+};
+
+
+GType gimp_save_procedure_dialog_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_save_procedure_dialog_new (GimpSaveProcedure *procedure,
+ GimpProcedureConfig *config,
+ const gchar *title);
+
+void gimp_save_procedure_dialog_add_metadata (GimpSaveProcedureDialog *dialog,
+ const gchar *property);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_SAVE_PROCEDURE_DIALOG_H__ */
diff --git a/libgimp/gimpui.def b/libgimp/gimpui.def
index 8410deb48c..e61530fc74 100644
--- a/libgimp/gimpui.def
+++ b/libgimp/gimpui.def
@@ -52,6 +52,9 @@ EXPORTS
gimp_procedure_dialog_run
gimp_progress_bar_get_type
gimp_progress_bar_new
+ gimp_save_procedure_dialog_add_metadata
+ gimp_save_procedure_dialog_get_type
+ gimp_save_procedure_dialog_new
gimp_select_button_close_popup
gimp_select_button_get_type
gimp_ui_get_display_window
diff --git a/libgimp/gimpui.h b/libgimp/gimpui.h
index ab53ca5f26..83789509cb 100644
--- a/libgimp/gimpui.h
+++ b/libgimp/gimpui.h
@@ -43,6 +43,7 @@
#include <libgimp/gimpproceduredialog.h>
#include <libgimp/gimpprocview.h>
#include <libgimp/gimpprogressbar.h>
+#include <libgimp/gimpsaveproceduredialog.h>
#include <libgimp/gimpselectbutton.h>
#include <libgimp/gimpzoompreview.h>
diff --git a/libgimp/gimpuitypes.h b/libgimp/gimpuitypes.h
index aa168d760a..e361b6f7ee 100644
--- a/libgimp/gimpuitypes.h
+++ b/libgimp/gimpuitypes.h
@@ -29,6 +29,7 @@ G_BEGIN_DECLS
typedef struct _GimpProcedureDialog GimpProcedureDialog;
+typedef struct _GimpSaveProcedureDialog GimpSaveProcedureDialog;
typedef struct _GimpAspectPreview GimpAspectPreview;
typedef struct _GimpDrawablePreview GimpDrawablePreview;
diff --git a/libgimp/meson.build b/libgimp/meson.build
index 2126649c9b..9e7b4fbbe3 100644
--- a/libgimp/meson.build
+++ b/libgimp/meson.build
@@ -242,6 +242,7 @@ libgimpui_sources_introspectable = [
'gimpproceduredialog.c',
'gimpprocview.c',
'gimpprogressbar.c',
+ 'gimpsaveproceduredialog.c',
'gimpselectbutton.c',
'gimpui.c',
'gimpzoompreview.c',
@@ -272,6 +273,7 @@ libgimpui_headers_introspectable = [
'gimpproceduredialog.h',
'gimpprocview.h',
'gimpprogressbar.h',
+ 'gimpsaveproceduredialog.h',
'gimpselectbutton.h',
'gimpzoompreview.h',
]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]