diff --git a/app/config/gimpcoreconfig.c b/app/config/gimpcoreconfig.c index 691b728a7e..a4591055d6 100644 --- a/app/config/gimpcoreconfig.c +++ b/app/config/gimpcoreconfig.c @@ -121,6 +121,7 @@ enum PROP_EXPORT_METADATA_EXIF, PROP_EXPORT_METADATA_XMP, PROP_EXPORT_METADATA_IPTC, + PROP_EXPORT_UPDATE_METADATA, PROP_DEBUG_POLICY, PROP_CHECK_UPDATES, PROP_CHECK_UPDATE_TIMESTAMP, @@ -793,6 +794,13 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass) TRUE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_EXPORT_UPDATE_METADATA, + "export-update-metadata", + "Update metadata automatically", + EXPORT_UPDATE_METADATA_BLURB, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_ENUM (object_class, PROP_DEBUG_POLICY, "debug-policy", "Try generating backtrace upon errors", @@ -1194,6 +1202,9 @@ gimp_core_config_set_property (GObject *object, case PROP_EXPORT_METADATA_IPTC: core_config->export_metadata_iptc = g_value_get_boolean (value); break; + case PROP_EXPORT_UPDATE_METADATA: + core_config->export_update_metadata = g_value_get_boolean (value); + break; case PROP_DEBUG_POLICY: core_config->debug_policy = g_value_get_enum (value); break; @@ -1462,6 +1473,9 @@ gimp_core_config_get_property (GObject *object, case PROP_EXPORT_METADATA_IPTC: g_value_set_boolean (value, core_config->export_metadata_iptc); break; + case PROP_EXPORT_UPDATE_METADATA: + g_value_set_boolean (value, core_config->export_update_metadata); + break; case PROP_DEBUG_POLICY: g_value_set_enum (value, core_config->debug_policy); break; diff --git a/app/config/gimpcoreconfig.h b/app/config/gimpcoreconfig.h index 39543ae94b..134f447041 100644 --- a/app/config/gimpcoreconfig.h +++ b/app/config/gimpcoreconfig.h @@ -104,6 +104,7 @@ struct _GimpCoreConfig gboolean export_metadata_exif; gboolean export_metadata_xmp; gboolean export_metadata_iptc; + gboolean export_update_metadata; GimpDebugPolicy debug_policy; #ifdef G_OS_WIN32 GimpWin32PointerInputAPI win32_pointer_input_api; diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h index bd143ec7b4..ca5fabe0f5 100644 --- a/app/config/gimprc-blurbs.h +++ b/app/config/gimprc-blurbs.h @@ -257,6 +257,15 @@ _("Export XMP metadata by default.") #define EXPORT_METADATA_IPTC_BLURB \ _("Export IPTC metadata by default.") +/* Translators: tooltip for configuration option (checkbox). + * It determines what metadata is updated when exporting. + */ +#define EXPORT_UPDATE_METADATA_BLURB \ +_("When enabled, add and update metadata automatically. When disabled, " \ + "only the minimum necessary metadata changes are made, without changing " \ + "modification date, synchronizing tags, or updating the software and " \ + "change history metadata.") + #define GENERATE_BACKTRACE_BLURB \ _("Try generating debug data for bug reporting when appropriate.") diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c index f084405fcb..c46a03d090 100644 --- a/app/dialogs/preferences-dialog.c +++ b/app/dialogs/preferences-dialog.c @@ -1589,6 +1589,9 @@ prefs_dialog_new (Gimp *gimp, */ _("Export _IPTC metadata by default when available"), GTK_BOX (vbox2)); + button = prefs_check_button_add (object, "export-update-metadata", + _("Update metadata automatically"), + GTK_BOX (vbox2)); hbox = prefs_hint_box_new (GIMP_ICON_DIALOG_WARNING, _("Metadata can contain sensitive information.")); gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); diff --git a/app/plug-in/gimppluginmanager-call.c b/app/plug-in/gimppluginmanager-call.c index a736776bd2..73a497816f 100644 --- a/app/plug-in/gimppluginmanager-call.c +++ b/app/plug-in/gimppluginmanager-call.c @@ -242,6 +242,7 @@ gimp_plug_in_manager_call_run (GimpPlugInManager *manager, config.export_exif = core_config->export_metadata_exif; config.export_xmp = core_config->export_metadata_xmp; config.export_iptc = core_config->export_metadata_iptc; + config.update_metadata = core_config->export_update_metadata; config.default_display_id = display_id; config.app_name = (gchar *) g_get_application_name (); config.wm_class = (gchar *) gimp_get_program_class (manager->gimp); diff --git a/libgimp/gimp.c b/libgimp/gimp.c index 5c900aca5b..b768bc4295 100644 --- a/libgimp/gimp.c +++ b/libgimp/gimp.c @@ -129,6 +129,7 @@ static gboolean _export_exif = FALSE; static gboolean _export_xmp = FALSE; static gboolean _export_iptc = FALSE; static gboolean _export_thumbnail = TRUE; +static gboolean _update_metadata = TRUE; static gint32 _num_processors = 1; static GimpCheckSize _check_size = GIMP_CHECK_SIZE_MEDIUM_CHECKS; static GimpCheckType _check_type = GIMP_CHECK_TYPE_GRAY_CHECKS; @@ -747,6 +748,28 @@ gimp_export_thumbnail (void) return _export_thumbnail; } +/** + * gimp_update_metadata: + * + * Returns whether file plug-ins should update the + * image's metadata. + * + * Note that metadata that reflects the image characteristics + * will still be updated even if this is set to FALSE. This only + * concerns metadata changes that are nonessential, like setting + * GIMP in Exif.Image.Software, synchronizing the comment with its + * equivalent metadata tags, etc. + * + * Returns: TRUE if preferences are set to update the metadata. + * + * Since: 3.1 + **/ +gboolean +gimp_update_metadata (void) +{ + return _update_metadata; +} + /** * gimp_get_num_processors: * @@ -1090,6 +1113,7 @@ _gimp_config (GPConfig *config) _export_exif = config->export_exif ? TRUE : FALSE; _export_xmp = config->export_xmp ? TRUE : FALSE; _export_iptc = config->export_iptc ? TRUE : FALSE; + _update_metadata = config->update_metadata ? TRUE : FALSE; _export_comment = config->export_comment; _num_processors = config->num_processors; _default_display_id = config->default_display_id; diff --git a/libgimp/gimp.def b/libgimp/gimp.def index 836bfaa87e..789b84ae2b 100644 --- a/libgimp/gimp.def +++ b/libgimp/gimp.def @@ -1061,6 +1061,7 @@ EXPORTS gimp_tile_width gimp_trc_type_get_type gimp_unit_new + gimp_update_metadata gimp_user_time gimp_vector_load_procedure_extract_dimensions gimp_vector_load_procedure_get_type diff --git a/libgimp/gimp.h b/libgimp/gimp.h index 64391e8056..482bae2fe7 100644 --- a/libgimp/gimp.h +++ b/libgimp/gimp.h @@ -186,6 +186,7 @@ gboolean gimp_export_exif (void) G_GNUC_CONST; gboolean gimp_export_xmp (void) G_GNUC_CONST; gboolean gimp_export_iptc (void) G_GNUC_CONST; gboolean gimp_export_thumbnail (void) G_GNUC_CONST; +gboolean gimp_update_metadata (void) G_GNUC_CONST; gint gimp_get_num_processors (void) G_GNUC_CONST; GimpCheckSize gimp_check_size (void) G_GNUC_CONST; GimpCheckType gimp_check_type (void) G_GNUC_CONST; diff --git a/libgimp/gimpimagemetadata-save.c b/libgimp/gimpimagemetadata-save.c index 8f191053c0..ae384bc8b7 100644 --- a/libgimp/gimpimagemetadata-save.c +++ b/libgimp/gimpimagemetadata-save.c @@ -132,63 +132,69 @@ gimp_image_metadata_save_prepare (GimpImage *image, gimp_parasite_free (comment_parasite); } + if (! gimp_update_metadata ()) + *suggested_flags &= ~GIMP_METADATA_UPDATE; + /* Exif */ if (! gimp_export_exif () || ! gexiv2_metadata_has_exif (g2metadata)) *suggested_flags &= ~GIMP_METADATA_SAVE_EXIF; - if (comment) + if (gimp_update_metadata ()) { + if (comment) + { + gexiv2_metadata_try_set_tag_string (g2metadata, + "Exif.Photo.UserComment", + comment, &error); + if (error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Exif.Photo.UserComment", error->message); + g_clear_error (&error); + } + + gexiv2_metadata_try_set_tag_string (g2metadata, + "Exif.Image.ImageDescription", + comment, &error); + if (error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Exif.Image.ImageDescription", error->message); + g_clear_error (&error); + } + } + + g_snprintf (buffer, sizeof (buffer), + "%d:%02d:%02d %02d:%02d:%02d", + g_date_time_get_year (datetime), + g_date_time_get_month (datetime), + g_date_time_get_day_of_month (datetime), + g_date_time_get_hour (datetime), + g_date_time_get_minute (datetime), + g_date_time_get_second (datetime)); gexiv2_metadata_try_set_tag_string (g2metadata, - "Exif.Photo.UserComment", - comment, &error); + "Exif.Image.DateTime", + buffer, &error); if (error) { g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Exif.Photo.UserComment", error->message); + G_STRFUNC, "Exif.Image.DateTime", error->message); g_clear_error (&error); } gexiv2_metadata_try_set_tag_string (g2metadata, - "Exif.Image.ImageDescription", - comment, &error); + "Exif.Image.Software", + PACKAGE_STRING, &error); if (error) { g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Exif.Image.ImageDescription", error->message); + G_STRFUNC, "Exif.Image.Software", error->message); g_clear_error (&error); } } - g_snprintf (buffer, sizeof (buffer), - "%d:%02d:%02d %02d:%02d:%02d", - g_date_time_get_year (datetime), - g_date_time_get_month (datetime), - g_date_time_get_day_of_month (datetime), - g_date_time_get_hour (datetime), - g_date_time_get_minute (datetime), - g_date_time_get_second (datetime)); - gexiv2_metadata_try_set_tag_string (g2metadata, - "Exif.Image.DateTime", - buffer, &error); - if (error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Exif.Image.DateTime", error->message); - g_clear_error (&error); - } - - gexiv2_metadata_try_set_tag_string (g2metadata, - "Exif.Image.Software", - PACKAGE_STRING, &error); - if (error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Exif.Image.Software", error->message); - g_clear_error (&error); - } - gimp_metadata_set_pixel_size (metadata, image_width, image_height); @@ -212,26 +218,29 @@ gimp_image_metadata_save_prepare (GimpImage *image, g_clear_error (&error); } - /* XMP uses datetime in ISO 8601 format */ - datetime_buf = g_date_time_format (datetime, "%Y:%m:%dT%T\%:z"); + if (gimp_update_metadata ()) + { + /* XMP uses datetime in ISO 8601 format */ + datetime_buf = g_date_time_format (datetime, "%Y:%m:%dT%T\%:z"); - gexiv2_metadata_try_set_tag_string (g2metadata, - "Xmp.xmp.ModifyDate", - datetime_buf, &error); - if (error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.xmp.ModifyDate", error->message); - g_clear_error (&error); - } - gexiv2_metadata_try_set_tag_string (g2metadata, - "Xmp.xmp.MetadataDate", - datetime_buf, &error); - if (error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.xmp.MetadataDate", error->message); - g_clear_error (&error); + gexiv2_metadata_try_set_tag_string (g2metadata, + "Xmp.xmp.ModifyDate", + datetime_buf, &error); + if (error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.xmp.ModifyDate", error->message); + g_clear_error (&error); + } + gexiv2_metadata_try_set_tag_string (g2metadata, + "Xmp.xmp.MetadataDate", + datetime_buf, &error); + if (error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.xmp.MetadataDate", error->message); + g_clear_error (&error); + } } if (! g_strcmp0 (mime_type, "image/tiff")) @@ -260,14 +269,17 @@ gimp_image_metadata_save_prepare (GimpImage *image, g_clear_error (&error); } - gexiv2_metadata_try_set_tag_string (g2metadata, - "Xmp.tiff.DateTime", - datetime_buf, &error); - if (error) + if (gimp_update_metadata ()) { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.tiff.DateTime", error->message); - g_clear_error (&error); + gexiv2_metadata_try_set_tag_string (g2metadata, + "Xmp.tiff.DateTime", + datetime_buf, &error); + if (error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.tiff.DateTime", error->message); + g_clear_error (&error); + } } } @@ -320,6 +332,9 @@ gimp_image_metadata_save_prepare (GimpImage *image, if (! gimp_export_thumbnail ()) *suggested_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL; + + if (! gimp_update_metadata ()) + *suggested_flags &= ~GIMP_METADATA_UPDATE; } /* Color profile */ @@ -748,72 +763,75 @@ gimp_image_metadata_save_filter (GimpImage *image, GList *exclude_list = NULL; GList *list; - gettimeofday (&timer_usec, NULL); - timestamp_usec = ((gint64) timer_usec.tv_sec) * 1000000ll + - (gint64) timer_usec.tv_usec; - g_snprintf (ts, sizeof (ts), "%" G_GINT64_FORMAT, timestamp_usec); - - gimp_metadata_add_xmp_history (metadata, ""); - - gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), - "Xmp.GIMP.TimeStamp", - ts, &code_error); - if (code_error) + if (gimp_update_metadata ()) { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.GIMP.TimeStamp", code_error->message); - g_clear_error (&code_error); - } + gettimeofday (&timer_usec, NULL); + timestamp_usec = ((gint64) timer_usec.tv_sec) * 1000000ll + + (gint64) timer_usec.tv_usec; + g_snprintf (ts, sizeof (ts), "%" G_GINT64_FORMAT, timestamp_usec); - gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), - "Xmp.xmp.CreatorTool", - N_("GIMP"), &code_error); - if (code_error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.xmp.CreatorTool", code_error->message); - g_clear_error (&code_error); - } + gimp_metadata_add_xmp_history (metadata, ""); - gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), - "Xmp.GIMP.Version", - GIMP_VERSION, &code_error); - if (code_error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.GIMP.Version", code_error->message); - g_clear_error (&code_error); - } + gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), + "Xmp.GIMP.TimeStamp", + ts, &code_error); + if (code_error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.GIMP.TimeStamp", code_error->message); + g_clear_error (&code_error); + } - gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), - "Xmp.GIMP.API", - GIMP_API_VERSION, &code_error); - if (code_error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.GIMP.API", code_error->message); - g_clear_error (&code_error); - } + gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), + "Xmp.xmp.CreatorTool", + N_("GIMP"), &code_error); + if (code_error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.xmp.CreatorTool", code_error->message); + g_clear_error (&code_error); + } - gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), - "Xmp.GIMP.Platform", + gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), + "Xmp.GIMP.Version", + GIMP_VERSION, &code_error); + if (code_error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.GIMP.Version", code_error->message); + g_clear_error (&code_error); + } + + gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), + "Xmp.GIMP.API", + GIMP_API_VERSION, &code_error); + if (code_error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.GIMP.API", code_error->message); + g_clear_error (&code_error); + } + + gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata), + "Xmp.GIMP.Platform", #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) - "Windows", + "Windows", #elif defined(__linux__) - "Linux", + "Linux", #elif defined(__APPLE__) && defined(__MACH__) - "Mac OS", + "Mac OS", #elif defined(unix) || defined(__unix__) || defined(__unix) - "Unix", + "Unix", #else - "Unknown", + "Unknown", #endif - &code_error); - if (code_error) - { - g_warning ("%s: failed to set metadata '%s': %s\n", - G_STRFUNC, "Xmp.GIMP.Platform", code_error->message); - g_clear_error (&code_error); + &code_error); + if (code_error) + { + g_warning ("%s: failed to set metadata '%s': %s\n", + G_STRFUNC, "Xmp.GIMP.Platform", code_error->message); + g_clear_error (&code_error); + } } xmp_data = gexiv2_metadata_get_xmp_tags (GEXIV2_METADATA (metadata)); diff --git a/libgimpbase/gimpmetadata.h b/libgimpbase/gimpmetadata.h index 02860c907b..5f37292c9d 100644 --- a/libgimpbase/gimpmetadata.h +++ b/libgimpbase/gimpmetadata.h @@ -65,6 +65,8 @@ typedef enum * Since: 2.10.10 * @GIMP_METADATA_SAVE_COMMENT: Save the image's comment * Since: 3.0 + * @GIMP_METADATA_UPDATE: Update metadata automatically + * Since: 3.1 * @GIMP_METADATA_SAVE_ALL: Save all of the above * * What kinds of metadata to save when exporting images. @@ -77,6 +79,7 @@ typedef enum GIMP_METADATA_SAVE_THUMBNAIL = 1 << 3, GIMP_METADATA_SAVE_COLOR_PROFILE = 1 << 4, GIMP_METADATA_SAVE_COMMENT = 1 << 5, + GIMP_METADATA_UPDATE = 1 << 6, GIMP_METADATA_SAVE_ALL = 0xffffffff } GimpMetadataSaveFlags; diff --git a/libgimpbase/gimpprotocol.c b/libgimpbase/gimpprotocol.c index 5d740997d0..58821a6dad 100644 --- a/libgimpbase/gimpprotocol.c +++ b/libgimpbase/gimpprotocol.c @@ -540,6 +540,10 @@ _gp_config_read (GIOChannel *channel, (guint8 *) &config->export_iptc, 1, user_data)) goto cleanup; + if (! _gimp_wire_read_int8 (channel, + (guint8 *) &config->update_metadata, 1, + user_data)) + goto cleanup; if (! _gimp_wire_read_int32 (channel, (guint32 *) &config->default_display_id, 1, user_data)) @@ -667,6 +671,10 @@ _gp_config_write (GIOChannel *channel, (const guint8 *) &config->export_iptc, 1, user_data)) return; + if (! _gimp_wire_write_int8 (channel, + (const guint8 *) &config->update_metadata, 1, + user_data)) + return; if (! _gimp_wire_write_int32 (channel, (const guint32 *) &config->default_display_id, 1, user_data)) diff --git a/libgimpbase/gimpprotocol.h b/libgimpbase/gimpprotocol.h index c5427991f5..8944805d9b 100644 --- a/libgimpbase/gimpprotocol.h +++ b/libgimpbase/gimpprotocol.h @@ -130,6 +130,7 @@ struct _GPConfig gint8 export_exif; gint8 export_xmp; gint8 export_iptc; + gint8 update_metadata; gint32 default_display_id; gchar *app_name; gchar *wm_class;