[gthumb/ext] [metadata] write comment data in the image as well



commit bcca96eceb2f103030d89d892944e7e707dc5b26
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Sep 6 18:21:10 2009 +0200

    [metadata] write comment data in the image as well
    
    write the metadata in the image as exif/iptc/xmp format
    sync the image embedded data and the .comment metadata

 extensions/comments/gth-edit-comment-page.c        |   35 +++++++-
 .../comments/gth-metadata-provider-comment.c       |   96 +++++++++++++-------
 extensions/comments/main.c                         |   94 +++++++++++++++++++
 extensions/exiv2/exiv2-utils.cpp                   |   62 ++++++++++----
 extensions/exiv2/exiv2.extension.in.in             |    2 +-
 extensions/exiv2/gth-metadata-provider-exiv2.c     |   57 ++++++++++++-
 gthumb/gth-file-properties.c                       |    2 +-
 gthumb/gth-main-default-hooks.c                    |    9 ++
 gthumb/gth-metadata-provider.c                     |    6 ++
 gthumb/gth-string-list.c                           |   22 +++++
 gthumb/gth-string-list.h                           |    2 +
 11 files changed, 330 insertions(+), 57 deletions(-)
---
diff --git a/extensions/comments/gth-edit-comment-page.c b/extensions/comments/gth-edit-comment-page.c
index b30b99f..e574236 100644
--- a/extensions/comments/gth-edit-comment-page.c
+++ b/extensions/comments/gth-edit-comment-page.c
@@ -122,6 +122,7 @@ gth_edit_comment_page_real_update_info (GthEditMetadataPage *base,
 	GtkTextIter          start;
 	GtkTextIter          end;
 	char                *text;
+	GthMetadata         *metadata;
 	int                  i;
 	char               **tagv;
 	GList               *tags;
@@ -129,14 +130,41 @@ gth_edit_comment_page_real_update_info (GthEditMetadataPage *base,
 
 	self = GTH_EDIT_COMMENT_PAGE (base);
 
+	/* comment */
+
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (GET_WIDGET ("note_text")));
 	gtk_text_buffer_get_bounds (buffer, &start, &end);
 	text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
-	g_file_info_set_attribute_string (self->priv->file_data->info, "comment::note", text);
+	metadata = g_object_new (GTH_TYPE_METADATA,
+				 "id", "Embedded::Image::Comment",
+				 "raw", text,
+				 "formatted", text,
+				 NULL);
+	g_file_info_set_attribute_object (self->priv->file_data->info, "Embedded::Image::Comment", G_OBJECT (metadata));
+	g_object_unref (metadata);
 	g_free (text);
 
-	g_file_info_set_attribute_string (self->priv->file_data->info, "comment::place", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("place_entry"))));
-	g_file_info_set_attribute_string (self->priv->file_data->info, "comment::time", gtk_entry_get_text (GTK_ENTRY (self->priv->date_datetime)));
+	/* location */
+
+	metadata = g_object_new (GTH_TYPE_METADATA,
+				 "id", "Embedded::Image::Location",
+				 "raw", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("place_entry"))),
+				 "formatted", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("place_entry"))),
+				 NULL);
+	g_file_info_set_attribute_object (self->priv->file_data->info, "Embedded::Image::Location", G_OBJECT (metadata));
+	g_object_unref (metadata);
+
+	/* date */
+
+	metadata = g_object_new (GTH_TYPE_METADATA,
+				 "id", "Embedded::Image::Date",
+				 "raw", gtk_entry_get_text (GTK_ENTRY (self->priv->date_datetime)),
+				 "formatted", gtk_entry_get_text (GTK_ENTRY (self->priv->date_datetime)),
+				 NULL);
+	g_file_info_set_attribute_object (self->priv->file_data->info, "Embedded::Image::Date", G_OBJECT (metadata));
+	g_object_unref (metadata);
+
+	/* tags */
 
 	tagv = gth_tags_entry_get_tags (GTH_TAGS_ENTRY (self->priv->tags_entry));
 	tags = NULL;
@@ -144,7 +172,6 @@ gth_edit_comment_page_real_update_info (GthEditMetadataPage *base,
 		tags = g_list_prepend (tags, tagv[i]);
 	tags = g_list_reverse (tags);
 	string_list = gth_string_list_new (tags);
-	g_file_info_set_attribute_object (self->priv->file_data->info, "comment::categories", G_OBJECT (string_list));
 	g_file_info_set_attribute_object (self->priv->file_data->info, "Embedded::Image::Keywords", G_OBJECT (string_list));
 
 	g_object_unref (string_list);
diff --git a/extensions/comments/gth-metadata-provider-comment.c b/extensions/comments/gth-metadata-provider-comment.c
index d8c7eba..866c493 100644
--- a/extensions/comments/gth-metadata-provider-comment.c
+++ b/extensions/comments/gth-metadata-provider-comment.c
@@ -112,41 +112,69 @@ gth_metadata_provider_comment_write (GthMetadataProvider *self,
 				     GthFileData         *file_data,
 				     const char          *attributes)
 {
-	if (_g_file_attributes_matches (attributes, "comment::*")) {
-		GthComment    *comment;
-		char          *data;
-		gsize          length;
-		GthStringList *categories;
-		GFile         *comment_file;
-		GFile         *comment_folder;
-
-		comment = gth_comment_new ();
-		gth_comment_set_note (comment, g_file_info_get_attribute_string (file_data->info, "comment::note"));
-		gth_comment_set_place (comment, g_file_info_get_attribute_string (file_data->info, "comment::place"));
-		gth_comment_set_time_from_exif_format (comment, g_file_info_get_attribute_string (file_data->info, "comment::time"));
-
+	GthComment    *comment;
+	GthMetadata   *metadata;
+	const char    *text;
+	char          *data;
+	gsize          length;
+	GthStringList *categories;
+	GFile         *comment_file;
+	GFile         *comment_folder;
+
+	comment = gth_comment_new ();
+
+	/* comment */
+
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Comment");
+	if (metadata == NULL)
+		text = g_file_info_get_attribute_string (file_data->info, "comment::note");
+	else
+		text = gth_metadata_get_raw (metadata);
+	gth_comment_set_note (comment, text);
+
+	/* location */
+
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Location");
+	if (metadata == NULL)
+		text = g_file_info_get_attribute_string (file_data->info, "comment::place");
+	else
+		text = gth_metadata_get_raw (metadata);
+	gth_comment_set_place (comment, text);
+
+	/* time */
+
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Date");
+	if (metadata == NULL)
+		text = g_file_info_get_attribute_string (file_data->info, "comment::time");
+	else
+		text = gth_metadata_get_raw (metadata);
+	gth_comment_set_time_from_exif_format (comment, text);
+
+	/* keywords */
+
+	categories = (GthStringList *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Keywords");
+	if (categories == NULL)
 		categories = (GthStringList *) g_file_info_get_attribute_object (file_data->info, "comment::categories");
-		if (categories != NULL) {
-			GList *list;
-			GList *scan;
-
-			list = gth_string_list_get_list (categories);
-			for (scan = list; scan; scan = scan->next)
-				gth_comment_add_category (comment, (char *) scan->data);
-		}
-
-		data = gth_comment_to_data (comment, &length);
-		comment_file = gth_comment_get_comment_file (file_data->file);
-		comment_folder = g_file_get_parent (comment_file);
-
-		g_file_make_directory (comment_folder, NULL, NULL);
-		g_write_file (comment_file, FALSE, 0, data, length, NULL, NULL);
-
-		g_object_unref (comment_folder);
-		g_object_unref (comment_file);
-		g_free (data);
-		g_object_unref (comment);
+	if (categories != NULL) {
+		GList *list;
+		GList *scan;
+
+		list = gth_string_list_get_list (categories);
+		for (scan = list; scan; scan = scan->next)
+			gth_comment_add_category (comment, (char *) scan->data);
 	}
+
+	data = gth_comment_to_data (comment, &length);
+	comment_file = gth_comment_get_comment_file (file_data->file);
+	comment_folder = g_file_get_parent (comment_file);
+
+	g_file_make_directory (comment_folder, NULL, NULL);
+	g_write_file (comment_file, FALSE, 0, data, length, NULL, NULL);
+
+	g_object_unref (comment_folder);
+	g_object_unref (comment_file);
+	g_free (data);
+	g_object_unref (comment);
 }
 
 
@@ -175,7 +203,7 @@ gth_metadata_provider_constructor (GType                  type,
 	self = GTH_METADATA_PROVIDER (obj);
 
 	g_object_set (self, "readable-attributes", "comment::*", NULL);
-	g_object_set (self, "writable-attributes", "comment::*", NULL);
+	g_object_set (self, "writable-attributes", "comment::*,Embedded::Image::*", NULL);
 
 	return obj;
 }
diff --git a/extensions/comments/main.c b/extensions/comments/main.c
index 8542c54..2afccf7 100644
--- a/extensions/comments/main.c
+++ b/extensions/comments/main.c
@@ -74,6 +74,99 @@ comments__add_sidecars_cb (GFile  *file,
 }
 
 
+void
+comments__read_metadata_ready_cb (GthFileData *file_data,
+				  const char  *attributes)
+{
+	if (_g_file_attributes_matches (attributes, "Embedded::Image::*")
+	    && _g_file_attributes_matches (attributes, "comment::*"))
+	{
+		gboolean       write_comment = FALSE;
+		GthMetadata   *metadata;
+		const char    *text;
+		GthComment    *comment;
+		GPtrArray     *keywords;
+		int            i;
+		GthStringList *categories;
+
+		comment = gth_comment_new ();
+		gth_comment_set_note (comment, g_file_info_get_attribute_string (file_data->info, "comment::note"));
+		gth_comment_set_place (comment, g_file_info_get_attribute_string (file_data->info, "comment::place"));
+		gth_comment_set_time_from_exif_format (comment, g_file_info_get_attribute_string (file_data->info, "comment::time"));
+		keywords = gth_comment_get_categories (comment);
+		for (i = 0; i < keywords->len; i++)
+			gth_comment_add_category (comment, g_ptr_array_index (keywords, i));
+
+		/* sync embedded data and .comment data if required */
+
+		metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Comment");
+		if (metadata != NULL) {
+			text = g_file_info_get_attribute_string (file_data->info, "comment::note");
+			if (g_strcmp0 (gth_metadata_get_raw (metadata), text) != 0) {
+				gth_comment_set_note (comment, gth_metadata_get_raw (metadata));
+				write_comment = TRUE;
+			}
+		}
+
+		metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Location");
+		if (metadata != NULL) {
+			text = g_file_info_get_attribute_string (file_data->info, "comment::place");
+			if (g_strcmp0 (gth_metadata_get_raw (metadata), text) != 0) {
+				gth_comment_set_place (comment, gth_metadata_get_raw (metadata));
+				write_comment = TRUE;
+			}
+		}
+
+		metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Date");
+		if (metadata != NULL) {
+			text = g_file_info_get_attribute_string (file_data->info, "comment::time");
+			if (g_strcmp0 (gth_metadata_get_raw (metadata), text) != 0) {
+				gth_comment_set_time_from_exif_format (comment, gth_metadata_get_raw (metadata));
+				write_comment = TRUE;
+			}
+		}
+
+		categories = (GthStringList *) g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Keywords");
+		if (categories != NULL) {
+			GthStringList *comment_categories;
+
+			comment_categories = (GthStringList *) g_file_info_get_attribute_object (file_data->info, "comment::categories");
+			if (! gth_string_list_equal (categories, comment_categories)) {
+				GList *list;
+				GList *scan;
+
+				gth_comment_clear_categories (comment);
+				list = gth_string_list_get_list (categories);
+				for (scan = list; scan; scan = scan->next)
+					gth_comment_add_category (comment, scan->data);
+				write_comment = TRUE;
+			}
+		}
+
+		if (write_comment) {
+			GFile *comment_file;
+			char  *buffer;
+			gsize  size;
+
+			buffer = gth_comment_to_data (comment, &size);
+			comment_file = gth_comment_get_comment_file (file_data->file);
+			g_write_file (comment_file,
+				      FALSE,
+				      G_FILE_CREATE_NONE,
+				      buffer,
+				      size,
+				      NULL,
+				      NULL);
+
+			g_object_unref (comment_file);
+			g_free (buffer);
+		}
+
+		g_object_unref (comment);
+	}
+}
+
+
 G_MODULE_EXPORT void
 gthumb_extension_activate (void)
 {
@@ -103,6 +196,7 @@ gthumb_extension_activate (void)
 				  "display-name", _("Tag"),
 				  NULL);
 	gth_hook_add_callback ("add-sidecars", 10, G_CALLBACK (comments__add_sidecars_cb), NULL);
+	gth_hook_add_callback ("read-metadata-ready", 10, G_CALLBACK (comments__read_metadata_ready_cb), NULL);
 }
 
 
diff --git a/extensions/exiv2/exiv2-utils.cpp b/extensions/exiv2/exiv2-utils.cpp
index d522ac6..599ebbe 100644
--- a/extensions/exiv2/exiv2-utils.cpp
+++ b/extensions/exiv2/exiv2-utils.cpp
@@ -21,6 +21,7 @@
  */
 
 #include <config.h>
+#include <glib.h>
 #include <exiv2/basicio.hpp>
 #include <exiv2/error.hpp>
 #include <exiv2/image.hpp>
@@ -121,8 +122,8 @@ const char *_ORIENTATION_TAG_NAMES[] = {
 const char *_COMMENT_TAG_NAMES[] = {
 	"Exif::Photo::UserComment",
 	"Exif::Image::ImageDescription",
-	"Xmp::tiff::ImageDescription",
 	"Xmp::dc::description",
+	"Xmp::tiff::ImageDescription",
 	"Iptc::Application2::Caption",
 	"Iptc::Application2::Headline",
 	NULL
@@ -240,22 +241,42 @@ set_attribute_from_tagset (GFileInfo  *info,
 
 
 static void
-set_attributes_from_tagsets (GFileInfo *info)
+set_string_list_attribute_from_tagset (GFileInfo  *info,
+				       const char *attribute,
+				       const char *tagset[])
 {
-	/*set_attribute_from_tagset (info, "Exif::Photo::ExposureTime", _EXPOSURE_TIME_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Photo::ExposureMode", _EXPOSURE_MODE_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Photo::ISOSpeedRatings", _ISOSPEED_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Photo::ApertureValue", _APERTURE_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Photo::FocalLength", _FOCAL_LENGTH_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Photo::ShutterSpeedValue", _SHUTTER_SPEED_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Image::Make", _MAKE_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Image::Model", _MODEL_TAG_NAMES);
-	set_attribute_from_tagset (info, "Exif::Photo::Flash", _FLASH_TAG_NAMES);*/
+	GObject        *metadata;
+	int             i;
+	char           *raw;
+	char          **keywords;
+	GthStringList  *string_list;
 
+	metadata = NULL;
+	for (i = 0; tagset[i] != NULL; i++) {
+		metadata = g_file_info_get_attribute_object (info, tagset[i]);
+		if (metadata != NULL)
+			break;
+	}
+
+	if (metadata == NULL)
+		return;
+
+	g_object_get (metadata, "raw", &raw, NULL);
+	keywords = g_strsplit (raw, " ", -1);
+	string_list = gth_string_list_new_from_strv (keywords);
+	g_file_info_set_attribute_object (info, attribute, G_OBJECT (string_list));
+
+	g_strfreev (keywords);
+	g_free (raw);
+}
+
+static void
+set_attributes_from_tagsets (GFileInfo *info)
+{
 	set_attribute_from_tagset (info, "Embedded::Image::DateTime", _DATE_TAG_NAMES);
 	set_attribute_from_tagset (info, "Embedded::Image::Comment", _COMMENT_TAG_NAMES);
 	set_attribute_from_tagset (info, "Embedded::Image::Location", _LOCATION_TAG_NAMES);
-	set_attribute_from_tagset (info, "Embedded::Image::Keywords", _KEYWORDS_TAG_NAMES);
+	set_string_list_attribute_from_tagset (info, "Embedded::Image::Keywords", _KEYWORDS_TAG_NAMES);
 	set_attribute_from_tagset (info, "Embedded::Image::Orientation", _ORIENTATION_TAG_NAMES);
 }
 
@@ -515,8 +536,9 @@ exiv2_write_metadata_private (Exiv2::Image::AutoPtr  image,
 		try {
 			ed[key] = gth_metadata_get_raw (metadatum);
 		}
-		catch (...) {
+		catch (Exiv2::AnyError& e) {
 			/* we don't care about invalid key errors */
+			g_warning ("%s", e.what());
 		}
 
 		g_free (key);
@@ -597,8 +619,9 @@ exiv2_write_metadata_private (Exiv2::Image::AutoPtr  image,
 		try {
 			id[key] = gth_metadata_get_raw (metadatum);
 		}
-		catch (...) {
+		catch (Exiv2::AnyError& e) {
 			/* we don't care about invalid key errors */
+			g_warning ("%s", e.what());
 		}
 
 		g_free (key);
@@ -621,10 +644,17 @@ exiv2_write_metadata_private (Exiv2::Image::AutoPtr  image,
 			xd.erase (iter);
 
 		try {
-			ed[key] = gth_metadata_get_raw (metadatum);
+			/*if (strcmp (key, "Xmp.dc.description") == 0) {
+				Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::langAlt);
+				v->read(gth_metadata_get_raw (metadatum));
+				xd.add (Exiv2::XmpKey (key), v.get());
+			}
+			else FIXME */
+				xd[key] = gth_metadata_get_raw (metadatum);
 		}
-		catch (...) {
+		catch (Exiv2::AnyError& e) {
 			/* we don't care about invalid key errors */
+			g_warning ("%s", e.what());
 		}
 
 		g_free (key);
diff --git a/extensions/exiv2/exiv2.extension.in.in b/extensions/exiv2/exiv2.extension.in.in
index 66ed4db..93047de 100644
--- a/extensions/exiv2/exiv2.extension.in.in
+++ b/extensions/exiv2/exiv2.extension.in.in
@@ -8,4 +8,4 @@ Version=1.0
 [Loader]
 Type=module
 File=%LIBRARY%
-After=image_rotation
+After=image_rotation;comments
diff --git a/extensions/exiv2/gth-metadata-provider-exiv2.c b/extensions/exiv2/gth-metadata-provider-exiv2.c
index f156881..312da9c 100644
--- a/extensions/exiv2/gth-metadata-provider-exiv2.c
+++ b/extensions/exiv2/gth-metadata-provider-exiv2.c
@@ -82,7 +82,61 @@ gth_metadata_provider_exiv2_write (GthMetadataProvider *self,
 				   GthFileData         *file_data,
 				   const char          *attributes)
 {
-	/* FIXME */
+	void    *buffer = NULL;
+	gsize    size;
+	GError  *error = NULL;
+	GObject *metadata;
+
+	if (! g_load_file_in_buffer (file_data->file, &buffer, &size, &error))
+		return;
+
+	metadata = g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Comment");
+	if (metadata != NULL) {
+		g_file_info_set_attribute_object (file_data->info, "Exif::Photo::UserComment", metadata);
+		g_file_info_set_attribute_object (file_data->info, "Xmp::dc::description", metadata);
+		g_file_info_set_attribute_object (file_data->info, "Iptc::Application2::Headline", metadata);
+	}
+
+	metadata = g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Location");
+	if (metadata != NULL) {
+		g_file_info_set_attribute_object (file_data->info, "Xmp::iptc::Location", metadata);
+		g_file_info_set_attribute_object (file_data->info, "Iptc::Application2::LocationName", metadata);
+	}
+
+	metadata = g_file_info_get_attribute_object (file_data->info, "Embedded::Image::Keywords");
+	if (metadata != NULL) {
+		GthMetadata *meta;
+		char        *raw;
+
+		meta = gth_metadata_new ();
+		raw = gth_file_data_get_attribute_as_string (file_data, "Embedded::Image::Keywords");
+		g_object_set (meta, "id", "Embedded::Image::Keywords", "raw", raw, NULL);
+
+		g_file_info_set_attribute_object (file_data->info, "Xmp::iptc::Keywords", G_OBJECT (meta));
+		g_file_info_set_attribute_object (file_data->info, "Iptc::Application2::Keywords", G_OBJECT (meta));
+
+		g_free (raw);
+		g_object_unref (meta);
+	}
+
+	if (exiv2_write_metadata_to_buffer (&buffer,
+					    &size,
+					    file_data->info,
+					    NULL,
+					    &error))
+	{
+		g_write_file (file_data->file,
+			      FALSE,
+			      G_FILE_CREATE_NONE,
+			      buffer,
+			      size,
+			      NULL,
+			      &error);
+	}
+
+	if (buffer != NULL)
+		g_free (buffer);
+	g_clear_error (&error);
 }
 
 
@@ -111,6 +165,7 @@ gth_metadata_provider_constructor (GType                  type,
 	self = GTH_METADATA_PROVIDER (obj);
 
 	g_object_set (self, "readable-attributes", "Exif::*,Xmp::*,Iptc::*", NULL);
+	g_object_set (self, "writable-attributes", "Exif::*,Xmp::*,Iptc::*,Embedded::Image::*", NULL);
 
 	return obj;
 }
diff --git a/gthumb/gth-file-properties.c b/gthumb/gth-file-properties.c
index c768c94..2766331 100644
--- a/gthumb/gth-file-properties.c
+++ b/gthumb/gth-file-properties.c
@@ -34,7 +34,7 @@
 
 #define GTH_FILE_PROPERTIES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_FILE_PROPERTIES, GthFilePropertiesPrivate))
 #define FONT_SCALE (0.85)
-#define COMMENT_HEIGHT 150
+#define COMMENT_HEIGHT 100
 #define CATEGORY_SIZE 1000
 
 
diff --git a/gthumb/gth-main-default-hooks.c b/gthumb/gth-main-default-hooks.c
index a531586..d3f0b11 100644
--- a/gthumb/gth-main-default-hooks.c
+++ b/gthumb/gth-main-default-hooks.c
@@ -160,6 +160,15 @@ gth_main_register_default_hooks (void)
 	gth_hook_register ("add-sidecars", 2);
 
 	/**
+	 * Called after a file metadata has been read.  Used to syncronize
+	 * embedded metadata with the .comment file.
+	 *
+	 * @file_data (GthFileData *): the file
+	 * @attributes (const char *): the attributes read for the file
+	 */
+	gth_hook_register ("read-metadata-ready", 2);
+
+	/**
 	 * Called when creating the preferences dialog to add other tabs to
 	 * the dialog.
 	 *
diff --git a/gthumb/gth-metadata-provider.c b/gthumb/gth-metadata-provider.c
index f572d48..23564ae 100644
--- a/gthumb/gth-metadata-provider.c
+++ b/gthumb/gth-metadata-provider.c
@@ -354,6 +354,12 @@ read_metadata_thread (gpointer data)
 		g_object_unref (metadata_provider);
 	}
 
+	if (! cancelled)
+		for (scan = rmtd->files; scan; scan = scan->next) {
+			GthFileData *file_data = scan->data;
+			gth_hook_invoke ("read-metadata-ready", file_data, rmtd->attributes);
+		}
+
 	g_mutex_lock (rmtd->mutex);
 	rmtd->thread_done = TRUE;
 	g_mutex_unlock (rmtd->mutex);
diff --git a/gthumb/gth-string-list.c b/gthumb/gth-string-list.c
index 50766a3..368806c 100644
--- a/gthumb/gth-string-list.c
+++ b/gthumb/gth-string-list.c
@@ -20,6 +20,7 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
+#include <string.h>
 #include "glib-utils.h"
 #include "gth-string-list.h"
 
@@ -155,3 +156,24 @@ gth_string_list_join (GthStringList *list,
 	return g_string_free (str, FALSE);
 }
 
+
+gboolean
+gth_string_list_equal (GthStringList  *list1,
+		       GthStringList  *list2)
+{
+	GList *keys1;
+	GList *keys2;
+	GList *scan;
+
+	keys1 = list1->priv->list;
+	keys2 = list2->priv->list;
+
+	if (g_list_length (keys1) != g_list_length (keys2))
+		return FALSE;
+
+	for (scan = keys1; scan; scan = scan->next)
+		if (! g_list_find_custom (keys2, scan->data, (GCompareFunc) strcmp))
+			return FALSE;
+
+	return TRUE;
+}
diff --git a/gthumb/gth-string-list.h b/gthumb/gth-string-list.h
index c49da1f..125c63a 100644
--- a/gthumb/gth-string-list.h
+++ b/gthumb/gth-string-list.h
@@ -55,6 +55,8 @@ GthStringList *   gth_string_list_new_from_ptr_array  (GPtrArray      *array);
 GList *           gth_string_list_get_list            (GthStringList  *list);
 char *            gth_string_list_join                (GthStringList  *list,
 						       const char     *separator);
+gboolean          gth_string_list_equal               (GthStringList  *list1,
+						       GthStringList  *list2);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]