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 commitsf8e291bf31,ce9e7feabd,38c79600f1, and801bd8fb3f.
This commit is contained in:
@ -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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user