Bug 769112 - The metadata windows takes a lot of CPU.

The new metadata viewer is based on a version of the old metadata
plugin that still contained this bug, and a few other bugs that've
been fixed since then.  Reapply those fixes to the new plugin.

This is essentially an adaptation of commits
f8e291bf31,
ce9e7feabd,
38c79600f1,
and 801bd8fb3f.
This commit is contained in:
Ell
2017-07-08 08:48:47 -04:00
parent 8294ca9d21
commit 8c2ca36ac7

View File

@ -39,6 +39,15 @@
#define IPTC_PREFIX "Iptc." #define IPTC_PREFIX "Iptc."
#define XMP_PREFIX "Xmp." #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 enum
{ {
C_XMP_TAG = 0, C_XMP_TAG = 0,
@ -63,18 +72,25 @@ enum
/* local function prototypes */ /* local function prototypes */
static void query (void); static void query (void);
static void run (const gchar *name, static void run (const gchar *name,
gint nparams, gint nparams,
const GimpParam *param, const GimpParam *param,
gint *nreturn_vals, gint *nreturn_vals,
GimpParam **return_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 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 */ /* local variables */
@ -205,7 +221,7 @@ metadata_viewer_dialog (gint32 image_id,
"gimp-metadata-viewer-dialog", "gimp-metadata-viewer-dialog",
NULL, 0, NULL, 0,
gimp_standard_help_func, PLUG_IN_PROC, gimp_standard_help_func, PLUG_IN_PROC,
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, _("_Close"), GTK_RESPONSE_CLOSE,
NULL); NULL);
gtk_widget_set_size_request(dialog, 460, 340); gtk_widget_set_size_request(dialog, 460, 340);
@ -237,66 +253,154 @@ static void
metadata_dialog_set_metadata (GExiv2Metadata *metadata, metadata_dialog_set_metadata (GExiv2Metadata *metadata,
GtkBuilder *builder) GtkBuilder *builder)
{ {
GtkListStore *exif_store; gchar **tags;
GtkListStore *xmp_store; GtkListStore *store;
GtkListStore *iptc_store;
gchar **exif_data;
gchar **iptc_data;
gchar **xmp_data;
gchar *value;
gchar *value_utf;
GtkTreeIter iter;
gint i;
exif_store = GTK_LIST_STORE (gtk_builder_get_object (builder, /* load exif tags */
"exif-liststore")); tags = gexiv2_metadata_get_exif_tags (metadata);
xmp_store = GTK_LIST_STORE (gtk_builder_get_object (builder, store = GTK_LIST_STORE (gtk_builder_get_object (builder, "exif-liststore"));
"xmp-liststore"));
iptc_store = GTK_LIST_STORE (gtk_builder_get_object (builder,
"iptc-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); const gchar *tag_label;
value = gexiv2_metadata_get_tag_interpreted_string (metadata, gchar *value;
exif_data[i]);
value_utf = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
gtk_list_store_set (exif_store, &iter, tag_label = gexiv2_metadata_get_tag_label (tag);
C_EXIF_TAG, exif_data[i],
C_EXIF_VALUE, value_utf, /* 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); -1);
}
xmp_data = gexiv2_metadata_get_xmp_tags (metadata); g_free (value);
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);
} }
} }
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;
}