diff --git a/plug-ins/metadata/metadata-viewer.c b/plug-ins/metadata/metadata-viewer.c index c0be370d1d..76b016a829 100644 --- a/plug-ins/metadata/metadata-viewer.c +++ b/plug-ins/metadata/metadata-viewer.c @@ -39,6 +39,15 @@ #define IPTC_PREFIX "Iptc." #define XMP_PREFIX "Xmp." +/* The length at which to truncate tag values, in characters. */ +#define TAG_VALUE_MAX_SIZE 1024 + +/* The length at which to truncate raw data (i.e., tag values + * of type "Byte" or "Undefined"), in bytes. + */ +#define RAW_DATA_MAX_SIZE 16 + + enum { C_XMP_TAG = 0, @@ -63,18 +72,25 @@ enum /* local function prototypes */ -static void query (void); -static void run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals); - -static gboolean metadata_viewer_dialog (gint32 image_id, - GExiv2Metadata *metadata); -static void metadata_dialog_set_metadata (GExiv2Metadata *metadata, - GtkBuilder *builder); +static void query (void); +static void run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals); +static gboolean metadata_viewer_dialog (gint32 image_id, + GExiv2Metadata *metadata); +static void metadata_dialog_set_metadata (GExiv2Metadata *metadata, + GtkBuilder *builder); +static void metadata_dialog_append_tags (GExiv2Metadata *metadata, + gchar **tags, + GtkListStore *store, + gint tag_column, + gint value_column); +static gchar * metadata_dialog_format_tag_value (GExiv2Metadata *metadata, + const gchar *tag, + gboolean truncate); /* local variables */ @@ -205,7 +221,7 @@ metadata_viewer_dialog (gint32 image_id, "gimp-metadata-viewer-dialog", NULL, 0, gimp_standard_help_func, PLUG_IN_PROC, - GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + _("_Close"), GTK_RESPONSE_CLOSE, NULL); gtk_widget_set_size_request(dialog, 460, 340); @@ -237,66 +253,154 @@ static void metadata_dialog_set_metadata (GExiv2Metadata *metadata, GtkBuilder *builder) { - GtkListStore *exif_store; - GtkListStore *xmp_store; - GtkListStore *iptc_store; - gchar **exif_data; - gchar **iptc_data; - gchar **xmp_data; - gchar *value; - gchar *value_utf; - GtkTreeIter iter; - gint i; + gchar **tags; + GtkListStore *store; - exif_store = GTK_LIST_STORE (gtk_builder_get_object (builder, - "exif-liststore")); - xmp_store = GTK_LIST_STORE (gtk_builder_get_object (builder, - "xmp-liststore")); - iptc_store = GTK_LIST_STORE (gtk_builder_get_object (builder, - "iptc-liststore")); + /* load exif tags */ + tags = gexiv2_metadata_get_exif_tags (metadata); + store = GTK_LIST_STORE (gtk_builder_get_object (builder, "exif-liststore")); - exif_data = gexiv2_metadata_get_exif_tags (metadata); + metadata_dialog_append_tags (metadata, tags, store, C_EXIF_TAG, C_EXIF_VALUE); - for (i = 0; exif_data[i] != NULL; i++) + g_strfreev (tags); + + /* load xmp tags */ + tags = gexiv2_metadata_get_xmp_tags (metadata); + store = GTK_LIST_STORE (gtk_builder_get_object (builder, "xmp-liststore")); + + metadata_dialog_append_tags (metadata, tags, store, C_XMP_TAG, C_XMP_VALUE); + + g_strfreev (tags); + + /* load iptc tags */ + tags = gexiv2_metadata_get_iptc_tags (metadata); + store = GTK_LIST_STORE (gtk_builder_get_object (builder, "iptc-liststore")); + + metadata_dialog_append_tags (metadata, tags, store, C_IPTC_TAG, C_IPTC_VALUE); + + g_strfreev (tags); +} + +static void +metadata_dialog_append_tags (GExiv2Metadata *metadata, + gchar **tags, + GtkListStore *store, + gint tag_column, + gint value_column) +{ + GtkTreeIter iter; + const gchar *tag; + + while ((tag = *tags++)) { - gtk_list_store_append (exif_store, &iter); - value = gexiv2_metadata_get_tag_interpreted_string (metadata, - exif_data[i]); - value_utf = g_locale_to_utf8 (value, -1, NULL, NULL, NULL); + const gchar *tag_label; + gchar *value; - gtk_list_store_set (exif_store, &iter, - C_EXIF_TAG, exif_data[i], - C_EXIF_VALUE, value_utf, + tag_label = gexiv2_metadata_get_tag_label (tag); + + /* skip private tags */ + if (g_strcmp0 (tag_label, "") == 0 || g_strcmp0 (tag_label, NULL) == 0) + continue; + + gtk_list_store_append (store, &iter); + + value = metadata_dialog_format_tag_value (metadata, tag, + /* truncate = */ TRUE); + + gtk_list_store_set (store, &iter, + tag_column, tag, + value_column, value, -1); - } - xmp_data = gexiv2_metadata_get_xmp_tags (metadata); - - for (i = 0; xmp_data[i] != NULL; i++) - { - gtk_list_store_append (xmp_store, &iter); - value = gexiv2_metadata_get_tag_interpreted_string (metadata, - xmp_data[i]); - value_utf = g_locale_to_utf8 (value, -1, NULL, NULL, NULL); - - gtk_list_store_set (xmp_store, &iter, - C_XMP_TAG, xmp_data[i], - C_XMP_VALUE, value_utf, - -1); - } - - iptc_data = gexiv2_metadata_get_iptc_tags (metadata); - - for (i = 0; iptc_data[i] != NULL; i++) - { - gtk_list_store_append (iptc_store, &iter); - value = gexiv2_metadata_get_tag_interpreted_string (metadata, - iptc_data[i]); - value_utf = g_locale_to_utf8 (value, -1, NULL, NULL, NULL); - - gtk_list_store_set (iptc_store, &iter, - C_IPTC_TAG, iptc_data[i], - C_IPTC_VALUE, value_utf, - -1); + g_free (value); } } + +static gchar * +metadata_dialog_format_tag_value (GExiv2Metadata *metadata, + const gchar *tag, + gboolean truncate) +{ + const gchar *tag_type; + gchar *result; + + tag_type = gexiv2_metadata_get_tag_type (tag); + + if (g_strcmp0 (tag_type, "Byte") != 0 && + g_strcmp0 (tag_type, "Undefined") != 0 && + g_strcmp0 (tag_type, NULL) != 0) + { + gchar *value; + gchar *value_utf8; + glong size; + + value = gexiv2_metadata_get_tag_interpreted_string (metadata, tag); + value_utf8 = g_locale_to_utf8 (value, -1, NULL, NULL, NULL); + + g_free (value); + + size = g_utf8_strlen (value_utf8, -1); + + if (! truncate || size <= TAG_VALUE_MAX_SIZE) + { + result = value_utf8; + } + else + { + gchar *value_utf8_trunc; + GString *str; + + value_utf8_trunc = g_utf8_substring (value_utf8, + 0, TAG_VALUE_MAX_SIZE); + + g_free (value_utf8); + + str = g_string_new (value_utf8_trunc); + + g_free (value_utf8_trunc); + + g_string_append (str, "... "); + g_string_append_printf (str, + _("(%lu more character(s))"), + size - TAG_VALUE_MAX_SIZE); + + result = g_string_free (str, FALSE); + } + } + else + { + GBytes *bytes; + const guchar *data; + gsize size; + gsize display_size; + GString *str; + gint i; + + bytes = gexiv2_metadata_get_tag_raw (metadata, tag); + data = g_bytes_get_data (bytes, &size); + + if (! truncate) + display_size = size; + else + display_size = MIN (size, RAW_DATA_MAX_SIZE); + + str = g_string_sized_new (3 * display_size); + + for (i = 0; i < display_size; i++) + g_string_append_printf (str, i == 0 ? "%02x" : " %02x", data[i]); + + if (display_size < size) + { + g_string_append (str, " ... "); + g_string_append_printf (str, + _("(%llu more byte(s))"), + (unsigned long long) (size - display_size)); + } + + result = g_string_free (str, FALSE); + + g_bytes_unref (bytes); + } + + return result; +}