[gthumb] Fixed saving of IPTC keyworks



commit b97ba810a202ac9f4077087c77893d61904c325d
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Aug 19 21:48:00 2010 +0200

    Fixed saving of IPTC keyworks
    
    Added support for multiple Xpm and Iptc metadata with the same key.
    
    [bug #627096]

 extensions/exiv2_tools/exiv2-utils.cpp             |  294 +++++++++++++++-----
 .../exiv2_tools/gth-metadata-provider-exiv2.c      |   14 +-
 gthumb/gth-string-list.c                           |    8 +
 gthumb/gth-string-list.h                           |    2 +
 4 files changed, 240 insertions(+), 78 deletions(-)
---
diff --git a/extensions/exiv2_tools/exiv2-utils.cpp b/extensions/exiv2_tools/exiv2-utils.cpp
index 38d031c..0075fe8 100644
--- a/extensions/exiv2_tools/exiv2-utils.cpp
+++ b/extensions/exiv2_tools/exiv2-utils.cpp
@@ -196,14 +196,13 @@ attribute_is_date (const char *key)
 }
 
 
-static void
-set_file_info (GFileInfo  *info,
-	       const char *key,
-	       const char *description,
-	       const char *formatted_value,
-	       const char *raw_value,
-	       const char *category,
-	       const char *type_name)
+static GthMetadata *
+create_metadata (const char *key,
+		 const char *description,
+		 const char *formatted_value,
+		 const char *raw_value,
+		 const char *category,
+		 const char *type_name)
 {
 	char            *attribute;
 	GthMetadataInfo *metadata_info;
@@ -212,7 +211,7 @@ set_file_info (GFileInfo  *info,
 	char            *formatted_value_utf8;
 
 	if (_g_utf8_all_spaces (formatted_value))
-		return;
+		return NULL;
 
 	attribute = exiv2_key_to_attribute (key);
 	description_utf8 = g_locale_to_utf8 (description, -1, NULL, NULL, NULL);
@@ -261,12 +260,106 @@ set_file_info (GFileInfo  *info,
 		      "raw", raw_value,
 		      "value-type", type_name,
 		      NULL);
-	g_file_info_set_attribute_object (info, attribute, G_OBJECT (metadata));
 
-	g_object_unref (metadata);
 	g_free (formatted_value_utf8);
 	g_free (description_utf8);
 	g_free (attribute);
+
+	return metadata;
+}
+
+
+static void
+set_file_info (GFileInfo  *info,
+	       const char *key,
+	       const char *description,
+	       const char *formatted_value,
+	       const char *raw_value,
+	       const char *category,
+	       const char *type_name)
+{
+	char        *attribute;
+	GthMetadata *metadata;
+
+	attribute = exiv2_key_to_attribute (key);
+	metadata = create_metadata (key, description, formatted_value, raw_value, category, type_name);
+	if (metadata != NULL) {
+		g_file_info_set_attribute_object (info, attribute, G_OBJECT (metadata));
+		g_object_unref (metadata);
+	}
+
+	g_free (attribute);
+}
+
+
+GHashTable *
+create_metadata_hash (void)
+{
+	return g_hash_table_new_full (g_str_hash,
+				      g_str_equal,
+				      g_free,
+				      g_object_unref);
+}
+
+
+static void
+add_metadata_to_hash (GHashTable  *table,
+		      GthMetadata *metadata)
+{
+	char     *key;
+	gpointer  object;
+
+	if (metadata == NULL)
+		return;
+
+	key = exiv2_key_to_attribute (gth_metadata_get_id (metadata));
+	object = g_hash_table_lookup (table, key);
+	if (object != NULL) {
+		GthStringList *string_list;
+		GList         *list;
+
+		string_list = NULL;
+		if (GTH_IS_METADATA (object)) {
+			string_list = gth_string_list_new (NULL);
+			list = g_list_append (NULL, g_strdup (gth_metadata_get_raw (GTH_METADATA (object))));
+			gth_string_list_set_list (string_list, list);
+		}
+		else if (GTH_IS_STRING_LIST (object))
+			string_list = GTH_STRING_LIST (g_object_ref (object));
+
+		if (string_list == NULL)
+			return;
+
+		list = gth_string_list_get_list (string_list);
+		list = g_list_append (list, g_strdup (gth_metadata_get_raw (metadata)));
+		gth_string_list_set_list (string_list, list);
+
+		g_hash_table_replace (table,
+				      g_strdup (key),
+				      g_object_ref (string_list));
+
+		g_object_unref (string_list);
+	}
+	else
+		g_hash_table_insert (table,
+				     g_strdup (key),
+				     g_object_ref (metadata));
+
+	g_free (key);
+}
+
+
+static void
+set_file_info_from_hash (GFileInfo  *info,
+			 GHashTable *table)
+{
+	GHashTableIter iter;
+	gpointer       key;
+	gpointer       value;
+
+	g_hash_table_iter_init (&iter, table);
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		g_file_info_set_attribute_object (info, (char *)key, G_OBJECT (value));
 }
 
 
@@ -327,11 +420,8 @@ set_string_list_attribute_from_tagset (GFileInfo  *info,
 				       const char *attribute,
 				       const char *tagset[])
 {
-	GObject        *metadata;
-	int             i;
-	char           *raw;
-	char          **keywords;
-	GthStringList  *string_list;
+	GObject *metadata;
+	int      i;
 
 	metadata = NULL;
 	for (i = 0; tagset[i] != NULL; i++) {
@@ -343,13 +433,21 @@ set_string_list_attribute_from_tagset (GFileInfo  *info,
 	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));
+	if (GTH_IS_METADATA (metadata)) {
+		char           *raw;
+		char          **keywords;
+		GthStringList  *string_list;
 
-	g_strfreev (keywords);
-	g_free (raw);
+		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);
+	}
+	else if (GTH_IS_STRING_LIST (metadata))
+		g_file_info_set_attribute_object (info, attribute, metadata);
 }
 
 
@@ -445,6 +543,8 @@ exiv2_read_metadata (Exiv2::Image::AutoPtr  image,
 
 	Exiv2::IptcData &iptcData = image->iptcData();
 	if (! iptcData.empty()) {
+		GHashTable *table = create_metadata_hash ();
+
 		Exiv2::IptcData::iterator end = iptcData.end();
 		for (Exiv2::IptcData::iterator md = iptcData.begin(); md != end; ++md) {
 			stringstream raw_value;
@@ -456,18 +556,26 @@ exiv2_read_metadata (Exiv2::Image::AutoPtr  image,
 			else
 				description << md->tagName();
 
-			set_file_info (info,
-				       md->key().c_str(),
-				       description.str().c_str(),
-				       md->print().c_str(),
-				       raw_value.str().c_str(),
-				       "Iptc",
-				       md->typeName());
+			GthMetadata *metadata;
+			metadata = create_metadata (md->key().c_str(),
+						    description.str().c_str(),
+						    md->print().c_str(),
+						    raw_value.str().c_str(),
+						    "Iptc",
+						    md->typeName());
+
+			add_metadata_to_hash (table, metadata);
+			_g_object_unref (metadata);
 		}
+
+		set_file_info_from_hash (info, table);
+		g_hash_table_unref (table);
 	}
 
 	Exiv2::XmpData &xmpData = image->xmpData();
 	if (! xmpData.empty()) {
+		GHashTable *table = create_metadata_hash ();
+
 		Exiv2::XmpData::iterator end = xmpData.end();
 		for (Exiv2::XmpData::iterator md = xmpData.begin(); md != end; ++md) {
 			stringstream raw_value;
@@ -479,14 +587,19 @@ exiv2_read_metadata (Exiv2::Image::AutoPtr  image,
 			else
 				description << md->groupName() << "." << md->tagName();
 
-			set_file_info (info,
-				       md->key().c_str(),
-				       description.str().c_str(),
-				       md->print().c_str(),
-				       raw_value.str().c_str(),
-				       "Xmp::Embedded",
-				       md->typeName());
+			GthMetadata *metadata;
+			metadata = create_metadata (md->key().c_str(),
+						    description.str().c_str(),
+						    md->print().c_str(),
+						    raw_value.str().c_str(),
+						    "Xmp::Embedded",
+						    md->typeName());
+			add_metadata_to_hash (table, metadata);
+			_g_object_unref (metadata);
 		}
+
+		set_file_info_from_hash (info, table);
+		g_hash_table_unref (table);
 	}
 
 	set_attributes_from_tagsets (info);
@@ -587,6 +700,8 @@ exiv2_read_sidecar (GFile     *file,
 			return FALSE;
 
 		if (! xmpData.empty()) {
+			GHashTable *table = create_metadata_hash ();
+
 			Exiv2::XmpData::iterator end = xmpData.end();
 			for (Exiv2::XmpData::iterator md = xmpData.begin(); md != end; ++md) {
 				stringstream raw_value;
@@ -598,14 +713,19 @@ exiv2_read_sidecar (GFile     *file,
 				else
 					description << md->groupName() << "." << md->tagName();
 
-				set_file_info (info,
-					       md->key().c_str(),
-					       description.str().c_str(),
-					       md->print().c_str(),
-					       raw_value.str().c_str(),
-					       "Xmp::Sidecar",
-					       md->typeName());
+				GthMetadata *metadata;
+				metadata = create_metadata (md->key().c_str(),
+							    description.str().c_str(),
+							    md->print().c_str(),
+							    raw_value.str().c_str(),
+							    "Xmp::Sidecar",
+							    md->typeName());
+				add_metadata_to_hash (table, metadata);
+				_g_object_unref (metadata);
 			}
+
+			set_file_info_from_hash (info, table);
+			g_hash_table_unref (table);
 		}
 		Exiv2::XmpParser::terminate();
 
@@ -643,18 +763,20 @@ mandatory_string (Exiv2::ExifData &checkdata,
 
 
 const char *
-gth_main_get_metadata_type (GthMetadata *metadata,
-			    const char  *attribute)
+gth_main_get_metadata_type (gpointer    metadata,
+			    const char *attribute)
 {
 	const char      *value_type;
 	GthMetadataInfo *metadatum_info;
 
-	value_type = gth_metadata_get_value_type (metadata);
-	if (g_strcmp0 (value_type, "Undefined") == 0)
-		value_type = NULL;
+	if (GTH_IS_METADATA (metadata)) {
+		value_type = gth_metadata_get_value_type (GTH_METADATA (metadata));
+		if (g_strcmp0 (value_type, "Undefined") == 0)
+			value_type = NULL;
 
-	if (value_type != NULL)
-		return value_type;
+		if (value_type != NULL)
+			return value_type;
+	}
 
 	metadatum_info = gth_main_get_metadata_info (attribute);
 	if (metadatum_info != NULL)
@@ -788,19 +910,39 @@ exiv2_write_metadata_private (Exiv2::Image::AutoPtr  image,
 	Exiv2::IptcData id;
 	attributes = g_file_info_list_attributes (info, "Iptc");
 	for (i = 0; attributes[i] != NULL; i++) {
-		GthMetadata *metadatum = (GthMetadata *) g_file_info_get_attribute_object (info, attributes[i]);
-		char *key = exiv2_key_from_attribute (attributes[i]);
+		gpointer  metadatum = (GthMetadata *) g_file_info_get_attribute_object (info, attributes[i]);
+		char     *key = exiv2_key_from_attribute (attributes[i]);
 
 		try {
-			const char *raw_value = gth_metadata_get_raw (metadatum);
-			const char *value_type = gth_main_get_metadata_type (metadatum, attributes[i]);
+			const char *value_type;
 
-			if ((raw_value != NULL) && (strcmp (raw_value, "") != 0) &&  (value_type != NULL)) {
+			value_type = gth_main_get_metadata_type (metadatum, attributes[i]);
+			if (value_type != NULL) {
 				/* See the exif data code above for an explanation. */
 				Exiv2::Value::AutoPtr value = Exiv2::Value::create (Exiv2::TypeInfo::typeId (value_type));
-				value->read (raw_value);
 				Exiv2::IptcKey iptc_key(key);
-				id.add (iptc_key, value.get());
+
+				if (GTH_IS_STRING_LIST (metadatum)) {
+					GthStringList *string_list;
+					GList         *scan;
+
+					string_list = GTH_STRING_LIST (metadatum);
+					for (scan = gth_string_list_get_list (string_list); scan; scan = scan->next) {
+						char *single_value = (char *) scan->data;
+
+						value->read (single_value);
+						id.add (iptc_key, value.get());
+					}
+				}
+				else if (GTH_IS_METADATA (metadatum)) {
+					const char *raw_value;
+
+					raw_value = gth_metadata_get_raw (GTH_METADATA (metadatum));
+					if ((raw_value != NULL) && (strcmp (raw_value, "") != 0)) {
+						value->read (raw_value);
+						id.add (iptc_key, value.get());
+					}
+				}
 			}
 		}
 		catch (Exiv2::AnyError& e) {
@@ -817,26 +959,46 @@ exiv2_write_metadata_private (Exiv2::Image::AutoPtr  image,
 	Exiv2::XmpData xd;
 	attributes = g_file_info_list_attributes (info, "Xmp");
 	for (i = 0; attributes[i] != NULL; i++) {
-		GthMetadata *metadatum = (GthMetadata *) g_file_info_get_attribute_object (info, attributes[i]);
-		char *key = exiv2_key_from_attribute (attributes[i]);
+		gpointer  metadatum = (GthMetadata *) g_file_info_get_attribute_object (info, attributes[i]);
+		char     *key = exiv2_key_from_attribute (attributes[i]);
 
 		// Remove existing tags of the same type.
 		// Seems to be needed for storing category keywords.
 		// Not exactly sure why!
-		Exiv2::XmpData::iterator iter = xd.findKey (Exiv2::XmpKey (key));
+		/*Exiv2::XmpData::iterator iter = xd.findKey (Exiv2::XmpKey (key));
 		if (iter != xd.end ())
-			xd.erase (iter);
+			xd.erase (iter);*/
 
 		try {
-			const char *raw_value = gth_metadata_get_raw (metadatum);
-			const char *value_type = gth_main_get_metadata_type (metadatum, attributes[i]);
+			const char *value_type;
 
-			if ((raw_value != NULL) && (strcmp (raw_value, "") != 0) &&  (value_type != NULL)) {
+			value_type = gth_main_get_metadata_type (metadatum, attributes[i]);
+			if (value_type != NULL) {
 				/* See the exif data code above for an explanation. */
 				Exiv2::Value::AutoPtr value = Exiv2::Value::create (Exiv2::TypeInfo::typeId (value_type));
-				value->read (raw_value);
 				Exiv2::XmpKey xmp_key(key);
-				xd.add (xmp_key, value.get());
+
+				if (GTH_IS_STRING_LIST (metadatum)) {
+					GthStringList *string_list;
+					GList         *scan;
+
+					string_list = GTH_STRING_LIST (metadatum);
+					for (scan = gth_string_list_get_list (string_list); scan; scan = scan->next) {
+						char *single_value = (char *) scan->data;
+
+						value->read (single_value);
+						xd.add (xmp_key, value.get());
+					}
+				}
+				else if (GTH_IS_METADATA (metadatum)) {
+					const char *raw_value;
+
+					raw_value = gth_metadata_get_raw (GTH_METADATA (metadatum));
+					if ((raw_value != NULL) && (strcmp (raw_value, "") != 0)) {
+						value->read (raw_value);
+						xd.add (xmp_key, value.get());
+					}
+				}
 			}
 		}
 		catch (Exiv2::AnyError& e) {
diff --git a/extensions/exiv2_tools/gth-metadata-provider-exiv2.c b/extensions/exiv2_tools/gth-metadata-provider-exiv2.c
index fd9de33..1181c77 100644
--- a/extensions/exiv2_tools/gth-metadata-provider-exiv2.c
+++ b/extensions/exiv2_tools/gth-metadata-provider-exiv2.c
@@ -164,18 +164,8 @@ gth_metadata_provider_exiv2_write (GthMetadataProvider   *self,
 
 	metadata = g_file_info_get_attribute_object (file_data->info, "general::tags");
 	if (metadata != NULL) {
-		GthMetadata *meta;
-		char        *raw;
-
-		meta = gth_metadata_new ();
-		raw = gth_string_list_join (GTH_STRING_LIST (metadata), ", ");
-		g_object_set (meta, "id", "general::tags", "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);
+		g_file_info_set_attribute_object (file_data->info, "Xmp::iptc::Keywords", metadata);
+		g_file_info_set_attribute_object (file_data->info, "Iptc::Application2::Keywords", metadata);
 	}
 
 	metadata = g_file_info_get_attribute_object (file_data->info, "general::datetime");
diff --git a/gthumb/gth-string-list.c b/gthumb/gth-string-list.c
index ba403a1..18c7108 100644
--- a/gthumb/gth-string-list.c
+++ b/gthumb/gth-string-list.c
@@ -138,6 +138,14 @@ gth_string_list_get_list (GthStringList *list)
 }
 
 
+void
+gth_string_list_set_list (GthStringList *list,
+			  GList         *value)
+{
+	list->priv->list = value;
+}
+
+
 char *
 gth_string_list_join (GthStringList *list,
 		      const char    *separator)
diff --git a/gthumb/gth-string-list.h b/gthumb/gth-string-list.h
index 5f410c9..c8083fd 100644
--- a/gthumb/gth-string-list.h
+++ b/gthumb/gth-string-list.h
@@ -52,6 +52,8 @@ GthStringList *   gth_string_list_new                 (GList          *list);
 GthStringList *   gth_string_list_new_from_strv       (char          **strv);
 GthStringList *   gth_string_list_new_from_ptr_array  (GPtrArray      *array);
 GList *           gth_string_list_get_list            (GthStringList  *list);
+void              gth_string_list_set_list            (GthStringList  *list,
+						       GList          *value);
 char *            gth_string_list_join                (GthStringList  *list,
 						       const char     *separator);
 gboolean          gth_string_list_equal               (GthStringList  *list1,



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