[gthumb] allow to edit the metadata of many files at the same time



commit 1747fa977e9556963817390259ba256d35643c5d
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Jun 27 21:55:43 2010 +0200

    allow to edit the metadata of many files at the same time
    
    ...and renamed the "Metadata" as "Comment"

 extensions/edit_metadata/actions.c                 |   13 ++-
 extensions/edit_metadata/callbacks.c               |    6 +-
 extensions/edit_metadata/dlg-edit-metadata.c       |   80 +++++++----
 extensions/edit_metadata/dlg-edit-metadata.h       |    3 +-
 extensions/edit_metadata/gth-edit-comment-page.c   |  147 ++++++++++++--------
 .../edit_metadata/gth-edit-metadata-dialog.c       |   74 +++++++---
 .../edit_metadata/gth-edit-metadata-dialog.h       |   36 +++---
 extensions/exiv2_tools/gth-edit-exiv2-page.c       |  114 ++++++++++------
 gthumb/gth-file-data.c                             |   80 ++++++++++-
 gthumb/gth-file-data.h                             |   10 ++
 10 files changed, 386 insertions(+), 177 deletions(-)
---
diff --git a/extensions/edit_metadata/actions.c b/extensions/edit_metadata/actions.c
index 17ebe80..0219cfd 100644
--- a/extensions/edit_metadata/actions.c
+++ b/extensions/edit_metadata/actions.c
@@ -30,5 +30,16 @@ void
 gth_browser_activate_action_edit_metadata (GtkAction  *action,
 				 	   GthBrowser *browser)
 {
-	dlg_edit_metadata (browser);
+	GList *items;
+	GList *file_data_list;
+	GList *file_list;
+
+	items = gth_file_selection_get_selected (GTH_FILE_SELECTION (gth_browser_get_file_list_view (browser)));
+	file_data_list = gth_file_list_get_files (GTH_FILE_LIST (gth_browser_get_file_list (browser)), items);
+	file_list = gth_file_data_list_to_file_list (file_data_list);
+	dlg_edit_metadata (browser, file_list);
+
+	_g_object_list_unref (file_list);
+	_g_object_list_unref (file_data_list);
+	_gtk_tree_path_list_free (items);
 }
diff --git a/extensions/edit_metadata/callbacks.c b/extensions/edit_metadata/callbacks.c
index 9d4ef8f..8cd5b80 100644
--- a/extensions/edit_metadata/callbacks.c
+++ b/extensions/edit_metadata/callbacks.c
@@ -87,8 +87,8 @@ static const char *viewer_ui_info =
 
 static GtkActionEntry edit_metadata_action_entries[] = {
 	{ "Edit_Metadata", GTK_STOCK_EDIT,
-	  N_("Metadata"), "<control>M",
-	  N_("Edit file metadata"),
+	  N_("Comment"), "<control>M",
+	  N_("Edit the comment an other information of the selected files"),
 	  G_CALLBACK (gth_browser_activate_action_edit_metadata) }
 };
 
@@ -199,6 +199,6 @@ edit_metadata__gth_browser_update_sensitivity_cb (GthBrowser *browser)
 	n_selected = gth_file_selection_get_n_selected (GTH_FILE_SELECTION (gth_browser_get_file_list_view (browser)));
 
 	action = gtk_action_group_get_action (data->actions, "Edit_Metadata");
-	sensitive = (n_selected == 1);
+	sensitive = (n_selected > 0);
 	g_object_set (action, "sensitive", sensitive, NULL);
 }
diff --git a/extensions/edit_metadata/dlg-edit-metadata.c b/extensions/edit_metadata/dlg-edit-metadata.c
index faa5577..5164f4e 100644
--- a/extensions/edit_metadata/dlg-edit-metadata.c
+++ b/extensions/edit_metadata/dlg-edit-metadata.c
@@ -28,9 +28,10 @@
 
 
 typedef struct {
-	GthBrowser  *browser;
-	GtkWidget   *dialog;
-	GthFileData *file_data;
+	GthBrowser *browser;
+	GtkWidget  *dialog;
+	GList      *files; /* GFile list */
+	GList      *file_list; /* GthFileData list */
 } DialogData;
 
 
@@ -38,7 +39,8 @@ static void
 destroy_cb (GtkWidget  *widget,
 	    DialogData *data)
 {
-	g_object_unref (data->file_data);
+	_g_object_list_unref (data->file_list);
+	_g_object_list_unref (data->files);
 	g_free (data);
 }
 
@@ -49,8 +51,7 @@ write_metadata_ready_cb (GError   *error,
 {
 	DialogData *data = user_data;
 	GthMonitor *monitor;
-	GFile      *parent;
-	GList      *files;
+	GList      *scan;
 
 	if (error != NULL) {
 		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not save the file metadata"), &error);
@@ -58,15 +59,21 @@ write_metadata_ready_cb (GError   *error,
 	}
 
 	monitor = gth_main_get_default_monitor ();
-	parent = g_file_get_parent (data->file_data->file);
-	files = g_list_prepend (NULL, g_object_ref (data->file_data->file));
-	gth_monitor_folder_changed (monitor, parent, files, GTH_MONITOR_EVENT_CHANGED);
-	gth_monitor_metadata_changed (monitor, data->file_data);
+	for (scan = data->file_list; scan; scan = scan->next) {
+		GthFileData *file_data = scan->data;
+		GFile       *parent;
+		GList       *files;
+
+		parent = g_file_get_parent (file_data->file);
+		files = g_list_prepend (NULL, g_object_ref (file_data->file));
+		gth_monitor_folder_changed (monitor, parent, files, GTH_MONITOR_EVENT_CHANGED);
+		gth_monitor_metadata_changed (monitor, file_data);
+
+		_g_object_list_unref (files);
+		g_object_unref (parent);
+	}
 
 	gtk_widget_destroy (GTK_WIDGET (data->dialog));
-
-	_g_object_list_unref (files);
-	g_object_unref (parent);
 }
 
 
@@ -76,33 +83,48 @@ edit_metadata_dialog__response_cb (GtkDialog *dialog,
 				   gpointer   user_data)
 {
 	DialogData *data = user_data;
-	GList      *files;
 
 	if (response != GTK_RESPONSE_OK) {
 		gtk_widget_destroy (GTK_WIDGET (data->dialog));
 		return;
 	}
 
-	gth_edit_metadata_dialog_update_info (GTH_EDIT_METADATA_DIALOG (data->dialog), data->file_data->info);
+	gth_edit_metadata_dialog_update_info (GTH_EDIT_METADATA_DIALOG (data->dialog), data->file_list);
+	_g_write_metadata_async (data->file_list, "*", NULL, write_metadata_ready_cb, data);
+}
 
-	files = g_list_prepend (NULL, g_object_ref (data->file_data));
-	_g_write_metadata_async (files, "*", NULL, write_metadata_ready_cb, data);
 
-	_g_object_list_unref (files);
+static void
+info_ready_cb (GList    *files,
+	       GError   *error,
+	       gpointer  user_data)
+{
+	DialogData *data = user_data;
+
+	if (error != NULL) {
+		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Cannot read file information"), &error);
+		gtk_widget_destroy (GTK_WIDGET (data->dialog));
+		return;
+	}
+
+	data->file_list = _g_object_list_ref (files);
+	gth_edit_metadata_dialog_set_file_list (GTH_EDIT_METADATA_DIALOG (data->dialog), data->file_list);
+
+	gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (data->browser));
+	gtk_window_set_modal (GTK_WINDOW (data->dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (data->dialog));
 }
 
 
 void
-dlg_edit_metadata (GthBrowser *browser)
+dlg_edit_metadata (GthBrowser *browser,
+		   GList      *files)
 {
 	DialogData *data;
 
-	if (gth_browser_get_current_file (browser) == NULL)
-		return;
-
 	data = g_new0 (DialogData, 1);
 	data->browser = browser;
-	data->file_data = g_object_ref (gth_browser_get_current_file (browser));
+	data->files = _g_object_list_ref (files);
 	data->dialog = gth_edit_metadata_dialog_new ();
 
 	g_signal_connect (G_OBJECT (data->dialog),
@@ -114,9 +136,13 @@ dlg_edit_metadata (GthBrowser *browser)
 			  G_CALLBACK (edit_metadata_dialog__response_cb),
 			  data);
 
-	gth_edit_metadata_dialog_set_file (GTH_EDIT_METADATA_DIALOG (data->dialog), data->file_data);
+	/* FIXME: progress dialog ? */
 
-	gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (browser));
-	gtk_window_set_modal (GTK_WINDOW (data->dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (data->dialog));
+	_g_query_all_metadata_async (data->files,
+				     FALSE,
+				     TRUE,
+				     "*",
+				     NULL,
+				     info_ready_cb,
+				     data);
 }
diff --git a/extensions/edit_metadata/dlg-edit-metadata.h b/extensions/edit_metadata/dlg-edit-metadata.h
index 5208078..a2e229e 100644
--- a/extensions/edit_metadata/dlg-edit-metadata.h
+++ b/extensions/edit_metadata/dlg-edit-metadata.h
@@ -25,6 +25,7 @@
 
 #include <gthumb.h>
 
-void dlg_edit_metadata (GthBrowser *browser);
+void dlg_edit_metadata (GthBrowser *browser,
+			GList      *files /* GFile list */);
 
 #endif /* DLG_EDIT_METADATA_H */
diff --git a/extensions/edit_metadata/gth-edit-comment-page.c b/extensions/edit_metadata/gth-edit-comment-page.c
index 2f75334..93ea38b 100644
--- a/extensions/edit_metadata/gth-edit-comment-page.c
+++ b/extensions/edit_metadata/gth-edit-comment-page.c
@@ -55,8 +55,8 @@ struct _GthEditCommentPagePrivate {
 
 
 void
-gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
-		 		     GthFileData         *file_data)
+gth_edit_comment_page_real_set_file_list (GthEditMetadataPage *base,
+		 			  GList               *file_list)
 {
 	GthEditCommentPage  *self;
 	GtkTextBuffer       *buffer;
@@ -64,15 +64,16 @@ gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
 	GthStringList       *tags;
 	GthMetadataProvider *provider;
 	gboolean             no_provider;
+	GthFileData         *file_data;
+	const char          *mime_type;
 
 	self = GTH_EDIT_COMMENT_PAGE (base);
 
 	_g_object_unref (self->priv->info);
-	self->priv->info = g_file_info_new ();
-	g_file_info_copy_into (file_data->info, self->priv->info);
+	self->priv->info = gth_file_data_list_get_common_info (file_list, "general::description,general::title,general::location,general::datetime,general::tags,general::rating");
 
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (GET_WIDGET ("note_text")));
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "general::description");
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (self->priv->info, "general::description");
 	if (metadata != NULL) {
 		GtkTextIter iter;
 
@@ -83,19 +84,19 @@ gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
 	else
 		gtk_text_buffer_set_text (buffer, "", -1);
 
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "general::title");
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (self->priv->info, "general::title");
 	if (metadata != NULL)
 		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("title_entry")), gth_metadata_get_formatted (metadata));
 	else
 		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("title_entry")), "");
 
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "general::location");
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (self->priv->info, "general::location");
 	if (metadata != NULL)
 		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("place_entry")), gth_metadata_get_formatted (metadata));
 	else
 		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("place_entry")), "");
 
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "general::datetime");
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (self->priv->info, "general::datetime");
 	if (metadata != NULL) {
 		gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->date_combobox), FOLLOWING_DATE);
 		gth_time_selector_set_exif_date (GTH_TIME_SELECTOR (self->priv->date_selector), gth_metadata_get_raw (metadata));
@@ -105,7 +106,7 @@ gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
 		gth_time_selector_set_exif_date (GTH_TIME_SELECTOR (self->priv->date_selector), "");
 	}
 
-	tags = (GthStringList *) g_file_info_get_attribute_object (file_data->info, "general::tags");
+	tags = (GthStringList *) g_file_info_get_attribute_object (self->priv->info, "general::tags");
 	if (tags != NULL) {
 		char *value;
 
@@ -117,7 +118,7 @@ gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
 	else
 		gth_tags_entry_set_text (GTH_TAGS_ENTRY (self->priv->tags_entry), "");
 
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "general::rating");
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (self->priv->info, "general::rating");
 	if (metadata != NULL) {
 		int v;
 
@@ -131,32 +132,41 @@ gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
 
 	no_provider = TRUE;
 
-  	provider = gth_main_get_metadata_writer ("general::description", gth_file_data_get_mime_type (file_data));
+	if (file_list->next == NULL) {
+		GthFileData *first = file_list->data;
+		file_data = gth_file_data_new (first->file, first->info);
+	}
+	else
+		file_data = gth_file_data_new (NULL, ((GthFileData *) file_list->data)->info);
+
+	mime_type = gth_file_data_get_mime_type (file_data);
+
+  	provider = gth_main_get_metadata_writer ("general::description", mime_type);
 	gtk_widget_set_sensitive (GET_WIDGET ("note_text"), provider != NULL);
 	if (no_provider && (provider != NULL))
 		no_provider = FALSE;
 	_g_object_unref (provider);
 
-	provider = gth_main_get_metadata_writer ("general::location", gth_file_data_get_mime_type (file_data));
+	provider = gth_main_get_metadata_writer ("general::location", mime_type);
 	gtk_widget_set_sensitive (GET_WIDGET ("place_entry"), provider != NULL);
 	if (no_provider && (provider != NULL))
 		no_provider = FALSE;
 	_g_object_unref (provider);
 
-	provider = gth_main_get_metadata_writer ("general::datetime", gth_file_data_get_mime_type (file_data));
+	provider = gth_main_get_metadata_writer ("general::datetime", mime_type);
 	gtk_widget_set_sensitive (self->priv->date_combobox, provider != NULL);
 	gtk_widget_set_sensitive (self->priv->date_selector, provider != NULL);
 	if (no_provider && (provider != NULL))
 		no_provider = FALSE;
 	_g_object_unref (provider);
 
-	provider = gth_main_get_metadata_writer ("general::tags", gth_file_data_get_mime_type (file_data));
+	provider = gth_main_get_metadata_writer ("general::tags", mime_type);
 	gtk_widget_set_sensitive (self->priv->tags_entry, provider != NULL);
 	if (no_provider && (provider != NULL))
 		no_provider = FALSE;
 	_g_object_unref (provider);
 
-	provider = gth_main_get_metadata_writer ("general::rating", gth_file_data_get_mime_type (file_data));
+	provider = gth_main_get_metadata_writer ("general::rating", mime_type);
 	gtk_widget_set_sensitive (GET_WIDGET ("rating_spinbutton"), provider != NULL);
 	if (no_provider && (provider != NULL))
 		no_provider = FALSE;
@@ -166,14 +176,18 @@ gth_edit_comment_page_real_set_file (GthEditMetadataPage *base,
 		gtk_widget_hide (GTK_WIDGET (self));
 	else
 		gtk_widget_show (GTK_WIDGET (self));
+
+	g_object_unref (file_data);
 }
 
 
 void
 gth_edit_comment_page_real_update_info (GthEditMetadataPage *base,
-					GFileInfo           *info)
+					GFileInfo           *info,
+					gboolean             only_modified_fields)
 {
 	GthEditCommentPage  *self;
+	GthFileData         *file_data;
 	GtkTextBuffer       *buffer;
 	GtkTextIter          start;
 	GtkTextIter          end;
@@ -185,55 +199,66 @@ gth_edit_comment_page_real_update_info (GthEditMetadataPage *base,
 	GthStringList       *string_list;
 	GthDateTime         *date_time;
 	char                *exif_date;
+	char                *s;
 
 	self = GTH_EDIT_COMMENT_PAGE (base);
 
+	file_data = gth_file_data_new (NULL, self->priv->info);
+
 	/* caption */
 
-	metadata = g_object_new (GTH_TYPE_METADATA,
-				 "id", "general::title",
-				 "raw", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("title_entry"))),
-				 "formatted", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("title_entry"))),
-				 NULL);
-	g_file_info_set_attribute_object (info, "general::title", G_OBJECT (metadata));
-	g_object_unref (metadata);
+	if (! only_modified_fields || ! gth_file_data_attribute_equal (file_data, "general::title", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("title_entry"))))) {
+		metadata = g_object_new (GTH_TYPE_METADATA,
+					 "id", "general::title",
+					 "raw", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("title_entry"))),
+					 "formatted", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("title_entry"))),
+					 NULL);
+		g_file_info_set_attribute_object (info, "general::title", G_OBJECT (metadata));
+		g_object_unref (metadata);
+	}
 
 	/* 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);
-	metadata = g_object_new (GTH_TYPE_METADATA,
-				 "id", "general::description",
-				 "raw", text,
-				 "formatted", text,
-				 NULL);
-	g_file_info_set_attribute_object (info, "general::description", G_OBJECT (metadata));
-	g_object_unref (metadata);
+	if (! only_modified_fields || ! gth_file_data_attribute_equal (file_data, "general::description", text)) {
+		metadata = g_object_new (GTH_TYPE_METADATA,
+					 "id", "general::description",
+					 "raw", text,
+					 "formatted", text,
+					 NULL);
+		g_file_info_set_attribute_object (info, "general::description", G_OBJECT (metadata));
+		g_object_unref (metadata);
+	}
 	g_free (text);
 
 	/* location */
 
-	metadata = g_object_new (GTH_TYPE_METADATA,
-				 "id", "general::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 (info, "general::location", G_OBJECT (metadata));
-	g_object_unref (metadata);
+	if (! only_modified_fields || ! gth_file_data_attribute_equal (file_data, "general::location", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("place_entry"))))) {
+		metadata = g_object_new (GTH_TYPE_METADATA,
+					 "id", "general::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 (info, "general::location", G_OBJECT (metadata));
+		g_object_unref (metadata);
+	}
 
 	/* date */
 
 	date_time = gth_datetime_new ();
 	gth_time_selector_get_value (GTH_TIME_SELECTOR (self->priv->date_selector), date_time);
 	exif_date = gth_datetime_to_exif_date (date_time);
-	metadata = g_object_new (GTH_TYPE_METADATA,
-				 "id", "general::datetime",
-				 "raw", exif_date,
-				 "formatted", exif_date,
-				 NULL);
-	g_file_info_set_attribute_object (info, "general::datetime", G_OBJECT (metadata));
-	g_object_unref (metadata);
+	if (! only_modified_fields || ! gth_file_data_attribute_equal (file_data, "general::datetime", exif_date)) {
+		metadata = g_object_new (GTH_TYPE_METADATA,
+					 "id", "general::datetime",
+					 "raw", exif_date,
+					 "formatted", exif_date,
+					 NULL);
+		g_file_info_set_attribute_object (info, "general::datetime", G_OBJECT (metadata));
+		g_object_unref (metadata);
+	}
 	gth_datetime_free (date_time);
 
 	/* tags */
@@ -244,30 +269,32 @@ 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 (info, "general::tags", G_OBJECT (string_list));
+	if (! only_modified_fields || ! gth_file_data_attribute_equal_string_list (file_data, "general::tags", string_list))
+		g_file_info_set_attribute_object (info, "general::tags", G_OBJECT (string_list));
 
 	/* rating */
 
-	if (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("rating_spinbutton"))) > 0) {
-		char *s;
-
-		s = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("rating_spinbutton"))));
-		metadata = g_object_new (GTH_TYPE_METADATA,
-					 "id", "general::rating",
-					 "raw", s,
-					 "formatted", s,
-					 NULL);
-		g_file_info_set_attribute_object (info, "general::rating", G_OBJECT (metadata));
-		g_object_unref (metadata);
-		g_free (s);
+	s = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("rating_spinbutton"))));
+	if (! only_modified_fields || ! gth_file_data_attribute_equal (file_data, "general::rating", s)) {
+		if (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("rating_spinbutton"))) > 0) {
+			metadata = g_object_new (GTH_TYPE_METADATA,
+						 "id", "general::rating",
+						 "raw", s,
+						 "formatted", s,
+						 NULL);
+			g_file_info_set_attribute_object (info, "general::rating", G_OBJECT (metadata));
+			g_object_unref (metadata);
+		}
+		else
+			g_file_info_remove_attribute (info, "general::rating");
 	}
-	else
-		g_file_info_remove_attribute (info, "general::rating");
 
+	g_free (s);
 	g_free (exif_date);
 	g_object_unref (string_list);
 	g_strfreev (tagv);
 	g_list_free (tags);
+	g_object_unref (file_data);
 }
 
 
@@ -419,7 +446,7 @@ gth_edit_comment_page_init (GthEditCommentPage *self)
 static void
 gth_edit_comment_page_gth_edit_comment_page_interface_init (GthEditMetadataPageIface *iface)
 {
-	iface->set_file = gth_edit_comment_page_real_set_file;
+	iface->set_file_list = gth_edit_comment_page_real_set_file_list;
 	iface->update_info = gth_edit_comment_page_real_update_info;
 	iface->get_name = gth_edit_comment_page_real_get_name;
 }
diff --git a/extensions/edit_metadata/gth-edit-metadata-dialog.c b/extensions/edit_metadata/gth-edit-metadata-dialog.c
index 152bf39..d99ed5b 100644
--- a/extensions/edit_metadata/gth-edit-metadata-dialog.c
+++ b/extensions/edit_metadata/gth-edit-metadata-dialog.c
@@ -33,6 +33,7 @@ static gpointer gth_edit_metadata_dialog_parent_class = NULL;
 
 struct _GthEditMetadataDialogPrivate {
 	GtkWidget *notebook;
+	GtkWidget *save_changed_checkbutton;
 };
 
 
@@ -82,8 +83,9 @@ gth_edit_metadata_dialog_get_type (void)
 static void
 gth_edit_metadata_dialog_construct (GthEditMetadataDialog *self)
 {
-	GArray *pages;
-	int     i;
+	GtkWidget *vbox;
+	GArray    *pages;
+	int        i;
 
 	gtk_window_set_resizable (GTK_WINDOW (self), TRUE);
 	gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
@@ -93,10 +95,18 @@ gth_edit_metadata_dialog_construct (GthEditMetadataDialog *self)
 	gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
 	gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_SAVE, GTK_RESPONSE_OK);
 
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+	gtk_widget_show (vbox);
+	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), vbox, TRUE, TRUE, 0);
+
 	self->priv->notebook = gtk_notebook_new ();
 	gtk_widget_show (self->priv->notebook);
-	gtk_container_set_border_width (GTK_CONTAINER (self->priv->notebook), 5);
-	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), self->priv->notebook, TRUE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), self->priv->notebook, TRUE, TRUE, 0);
+
+	self->priv->save_changed_checkbutton = gtk_check_button_new_with_mnemonic (_("Save only cha_nged fields"));
+	gtk_widget_show (self->priv->save_changed_checkbutton);
+	gtk_box_pack_start (GTK_BOX (vbox), self->priv->save_changed_checkbutton, FALSE, FALSE, 0);
 
 	pages = gth_main_get_type_set ("edit-metadata-dialog-page");
 	if (pages == NULL)
@@ -134,23 +144,36 @@ gth_edit_metadata_dialog_new (void)
 
 
 void
-gth_edit_metadata_dialog_set_file (GthEditMetadataDialog *dialog,
-				   GthFileData           *file)
+gth_edit_metadata_dialog_set_file_list (GthEditMetadataDialog *dialog,
+				        GList                 *file_list)
 {
+	int    n_files;
 	char  *title;
 	GList *pages;
 	GList *scan;
 
-	if (file == NULL)
+	if (file_list == NULL)
 		return;
 
-	/* Translators: the %s in the string is the file name */
-	title = g_strdup_printf (_("%s Metadata"), g_file_info_get_display_name (file->info));
-	gtk_window_set_title (GTK_WINDOW (dialog), title);
+	n_files = g_list_length (file_list);
+	if (n_files == 1) {
+		GthFileData *file_data = file_list->data;
+
+		/* Translators: the %s symbol in the string is a file name */
+		title = g_strdup_printf (_("%s Metadata"), g_file_info_get_display_name (file_data->info));
+		gtk_window_set_title (GTK_WINDOW (dialog), title);
+	}
+	else {
+		title = g_strdup_printf (g_dngettext (NULL, "%d file", "%d files", n_files), n_files);
+		gtk_window_set_title (GTK_WINDOW (dialog), title);
+	}
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->save_changed_checkbutton), n_files > 1);
+	gtk_widget_set_sensitive (dialog->priv->save_changed_checkbutton, n_files > 1);
 
 	pages = gtk_container_get_children (GTK_CONTAINER (dialog->priv->notebook));
 	for (scan = pages; scan; scan = scan->next)
-		gth_edit_metadata_page_set_file (GTH_EDIT_METADATA_PAGE (scan->data), file);
+		gth_edit_metadata_page_set_file_list (GTH_EDIT_METADATA_PAGE (scan->data), file_list);
 
 	g_list_free (pages);
 	g_free (title);
@@ -159,14 +182,22 @@ gth_edit_metadata_dialog_set_file (GthEditMetadataDialog *dialog,
 
 void
 gth_edit_metadata_dialog_update_info (GthEditMetadataDialog *dialog,
-				      GFileInfo             *info)
+				      GList                 *file_list /* GthFileData list */)
 {
-	GList *pages;
-	GList *scan;
+	gboolean  only_modified_fields;
+	GList    *pages;
+	GList    *scan;
 
+	only_modified_fields = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->save_changed_checkbutton));
 	pages = gtk_container_get_children (GTK_CONTAINER (dialog->priv->notebook));
-	for (scan = pages; scan; scan = scan->next)
-		gth_edit_metadata_page_update_info (GTH_EDIT_METADATA_PAGE (scan->data), info);
+	for (scan = pages; scan; scan = scan->next) {
+		GList *scan_file;
+
+		for (scan_file = file_list; scan_file; scan_file = scan_file->next) {
+			GthFileData *file_data = scan_file->data;
+			gth_edit_metadata_page_update_info (GTH_EDIT_METADATA_PAGE (scan->data), file_data->info, only_modified_fields);
+		}
+	}
 
 	g_list_free (pages);
 }
@@ -198,18 +229,19 @@ gth_edit_metadata_page_get_type (void) {
 
 
 void
-gth_edit_metadata_page_set_file (GthEditMetadataPage *self,
-				 GthFileData         *file_data)
+gth_edit_metadata_page_set_file_list (GthEditMetadataPage *self,
+				      GList               *file_list)
 {
-	GTH_EDIT_METADATA_PAGE_GET_INTERFACE (self)->set_file (self, file_data);
+	GTH_EDIT_METADATA_PAGE_GET_INTERFACE (self)->set_file_list (self, file_list);
 }
 
 
 void
 gth_edit_metadata_page_update_info (GthEditMetadataPage *self,
-				    GFileInfo           *info)
+				    GFileInfo           *info,
+				    gboolean             only_modified_fields)
 {
-	GTH_EDIT_METADATA_PAGE_GET_INTERFACE (self)->update_info (self, info);
+	GTH_EDIT_METADATA_PAGE_GET_INTERFACE (self)->update_info (self, info, only_modified_fields);
 }
 
 
diff --git a/extensions/edit_metadata/gth-edit-metadata-dialog.h b/extensions/edit_metadata/gth-edit-metadata-dialog.h
index f96f8cd..d314bdf 100644
--- a/extensions/edit_metadata/gth-edit-metadata-dialog.h
+++ b/extensions/edit_metadata/gth-edit-metadata-dialog.h
@@ -58,30 +58,32 @@ typedef struct _GthEditMetadataPageIface GthEditMetadataPageIface;
 
 struct _GthEditMetadataPageIface {
 	GTypeInterface parent_iface;
-	void         (*set_file)    (GthEditMetadataPage *self,
-				     GthFileData         *file_data);
-	void         (*update_info) (GthEditMetadataPage *self,
-				     GFileInfo           *info);
-	const char * (*get_name)    (GthEditMetadataPage *self);
+	void         (*set_file_list) (GthEditMetadataPage *self,
+				       GList               *file_list /* GthFileData list */);
+	void         (*update_info)   (GthEditMetadataPage *self,
+				       GFileInfo           *info,
+				       gboolean             only_modified_fields);
+	const char * (*get_name)      (GthEditMetadataPage *self);
 };
 
 /* GthEditMetadataDialog */
 
-GType          gth_edit_metadata_dialog_get_type    (void);
-GtkWidget *    gth_edit_metadata_dialog_new         (void);
-void           gth_edit_metadata_dialog_set_file    (GthEditMetadataDialog *dialog,
-						     GthFileData           *file);
-void           gth_edit_metadata_dialog_update_info (GthEditMetadataDialog *dialog,
-						     GFileInfo             *info);
+GType          gth_edit_metadata_dialog_get_type       (void);
+GtkWidget *    gth_edit_metadata_dialog_new            (void);
+void           gth_edit_metadata_dialog_set_file_list  (GthEditMetadataDialog *dialog,
+						        GList                 *file_list /* GthFileData list */);
+void           gth_edit_metadata_dialog_update_info    (GthEditMetadataDialog *dialog,
+							GList                 *file_list /* GthFileData list */);
 
 /* GthEditMetadataPage */
 
-GType          gth_edit_metadata_page_get_type      (void);
-void           gth_edit_metadata_page_set_file      (GthEditMetadataPage   *self,
-		 			             GthFileData           *file_data);
-void           gth_edit_metadata_page_update_info   (GthEditMetadataPage   *self,
-						     GFileInfo             *info);
-const char *   gth_edit_metadata_page_get_name      (GthEditMetadataPage   *self);
+GType          gth_edit_metadata_page_get_type         (void);
+void           gth_edit_metadata_page_set_file_list    (GthEditMetadataPage   *self,
+							GList                 *file_list /* GthFileData list */);
+void           gth_edit_metadata_page_update_info      (GthEditMetadataPage   *self,
+						        GFileInfo             *info,
+							gboolean               only_modified_fields);
+const char *   gth_edit_metadata_page_get_name         (GthEditMetadataPage   *self);
 
 G_END_DECLS
 
diff --git a/extensions/exiv2_tools/gth-edit-exiv2-page.c b/extensions/exiv2_tools/gth-edit-exiv2-page.c
index 50bd967..d1bfc51 100644
--- a/extensions/exiv2_tools/gth-edit-exiv2-page.c
+++ b/extensions/exiv2_tools/gth-edit-exiv2-page.c
@@ -36,20 +36,21 @@ static gpointer gth_edit_exiv2_page_parent_class = NULL;
 
 
 struct _GthEditExiv2PagePrivate {
-	GtkBuilder  *builder;
-	gboolean     supported;
+	GtkBuilder *builder;
+	gboolean    supported;
+	GFileInfo  *info;
 };
 
 
 static void
 set_entry_value (GthEditExiv2Page *self,
-		 GthFileData      *file_data,
+		 GFileInfo        *info,
 		 const char       *attribute,
 		 const char       *widget_id)
 {
 	GthMetadata *metadata;
 
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, attribute);
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (info, attribute);
 	if (metadata != NULL)
 		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET (widget_id)), gth_metadata_get_formatted (metadata));
 	else
@@ -58,33 +59,42 @@ set_entry_value (GthEditExiv2Page *self,
 
 
 void
-gth_edit_exiv2_page_real_set_file (GthEditMetadataPage *base,
-		 		   GthFileData         *file_data)
+gth_edit_exiv2_page_real_set_file_list (GthEditMetadataPage *base,
+		 		        GList               *file_data_list)
 {
 	GthEditExiv2Page *self;
+	GList            *scan;
 	GthMetadata      *metadata;
 
 	self = GTH_EDIT_EXIV2_PAGE (base);
 
-	self->priv->supported = exiv2_supports_writes (gth_file_data_get_mime_type (file_data));
+	self->priv->supported = TRUE;
+	for (scan = file_data_list; self->priv->supported && scan; scan = scan->next) {
+		GthFileData *file_data = scan->data;
+		self->priv->supported = exiv2_supports_writes (gth_file_data_get_mime_type (file_data));
+	}
+
 	if (! self->priv->supported) {
 		gtk_widget_hide (GTK_WIDGET (base));
 		return;
 	}
 
-	set_entry_value (self, file_data, "Iptc::Application2::Copyright", "copyright_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::Credit", "credit_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::Byline", "byline_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::BylineTitle", "byline_title_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::CountryName", "country_name_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::CountryCode", "country_code_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::City", "city_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::Language", "language_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::ObjectName", "object_name_entry");
-	set_entry_value (self, file_data, "Iptc::Application2::Source", "source_entry");
-	set_entry_value (self, file_data, "Iptc::Envelope::Destination", "destination_entry");
-
-	metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "Iptc::Application2::Urgency");
+	_g_object_unref (self->priv->info);
+	self->priv->info = gth_file_data_list_get_common_info (file_data_list, "Iptc::Application2::Copyright,Iptc::Application2::Credit,Iptc::Application2::Byline,Iptc::Application2::BylineTitle,Iptc::Application2::CountryName,Iptc::Application2::CountryCode,Iptc::Application2::City,Iptc::Application2::Language,Iptc::Application2::ObjectName,Iptc::Application2::Source,Iptc::Envelope::Destination,Iptc::Application2::Urgency");
+
+	set_entry_value (self, self->priv->info, "Iptc::Application2::Copyright", "copyright_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::Credit", "credit_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::Byline", "byline_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::BylineTitle", "byline_title_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::CountryName", "country_name_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::CountryCode", "country_code_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::City", "city_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::Language", "language_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::ObjectName", "object_name_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Application2::Source", "source_entry");
+	set_entry_value (self, self->priv->info, "Iptc::Envelope::Destination", "destination_entry");
+
+	metadata = (GthMetadata *) g_file_info_get_attribute_object (self->priv->info, "Iptc::Application2::Urgency");
 	if (metadata != NULL) {
 		float v;
 
@@ -103,15 +113,22 @@ gth_edit_exiv2_page_real_set_file (GthEditMetadataPage *base,
 static void
 set_attribute_from_entry (GthEditExiv2Page *self,
 			  GFileInfo        *info,
+			  GthFileData      *file_data,
+			  gboolean          only_modified_fields,
 			  const char       *attribute,
 			  const char       *widget_id)
 {
 	GthMetadata *metadata;
+	const char  *value;
+
+	value = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET (widget_id)));
+	if (only_modified_fields && gth_file_data_attribute_equal (file_data, attribute, value))
+		return;
 
 	metadata = g_object_new (GTH_TYPE_METADATA,
 				 "id", attribute,
-				 "raw", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET (widget_id))),
-				 "formatted", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET (widget_id))),
+				 "raw", value,
+				 "formatted", value,
 				 NULL);
 	g_file_info_set_attribute_object (info, attribute, G_OBJECT (metadata));
 	g_object_unref (metadata);
@@ -120,42 +137,51 @@ set_attribute_from_entry (GthEditExiv2Page *self,
 
 void
 gth_edit_exiv2_page_real_update_info (GthEditMetadataPage *base,
-				      GFileInfo           *info)
+				      GFileInfo           *info,
+				      gboolean             only_modified_fields)
 {
 	GthEditExiv2Page *self;
+	GthFileData      *file_data;
 	double            v;
 	char             *s;
-	GthMetadata      *metadata;
 
 	self = GTH_EDIT_EXIV2_PAGE (base);
 
 	if (! self->priv->supported)
 		return;
 
-	set_attribute_from_entry (self, info, "Iptc::Application2::Copyright", "copyright_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::Credit", "credit_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::Byline", "byline_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::BylineTitle", "byline_title_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::CountryName", "country_name_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::CountryCode", "country_code_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::City", "city_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::Language", "language_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::ObjectName", "object_name_entry");
-	set_attribute_from_entry (self, info, "Iptc::Application2::Source", "source_entry");
-	set_attribute_from_entry (self, info, "Iptc::Envelope::Destination", "destination_entry");
+	file_data = gth_file_data_new (NULL, self->priv->info);
+
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::Copyright", "copyright_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::Credit", "credit_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::Byline", "byline_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::BylineTitle", "byline_title_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::CountryName", "country_name_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::CountryCode", "country_code_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::City", "city_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::Language", "language_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::ObjectName", "object_name_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Application2::Source", "source_entry");
+	set_attribute_from_entry (self, info, file_data, only_modified_fields, "Iptc::Envelope::Destination", "destination_entry");
 
 	/* urgency */
 
 	v = gtk_adjustment_get_value (GTK_ADJUSTMENT (GET_WIDGET ("urgency_adjustment")));
 	s = g_strdup_printf ("%1.g", v);
-	metadata = g_object_new (GTH_TYPE_METADATA,
-				 "id", "Iptc::Application2::Urgency",
-				 "raw", s,
-				 "formatted", s,
-				 NULL);
-	g_file_info_set_attribute_object (info, "Iptc::Application2::Urgency", G_OBJECT (metadata));
-	g_object_unref (metadata);
+	if (! only_modified_fields || ! gth_file_data_attribute_equal (file_data, "Iptc::Application2::Urgency", s)) {
+		GthMetadata *metadata;
+
+		metadata = g_object_new (GTH_TYPE_METADATA,
+					 "id", "Iptc::Application2::Urgency",
+					 "raw", s,
+					 "formatted", s,
+					 NULL);
+		g_file_info_set_attribute_object (info, "Iptc::Application2::Urgency", G_OBJECT (metadata));
+		g_object_unref (metadata);
+	}
 	g_free (s);
+
+	g_object_unref (file_data);
 }
 
 
@@ -173,6 +199,7 @@ gth_edit_exiv2_page_finalize (GObject *object)
 
 	self = GTH_EDIT_EXIV2_PAGE (object);
 
+	_g_object_unref (self->priv->info);
 	g_object_unref (self->priv->builder);
 
 	G_OBJECT_CLASS (gth_edit_exiv2_page_parent_class)->finalize (object);
@@ -193,6 +220,7 @@ static void
 gth_edit_exiv2_page_init (GthEditExiv2Page *self)
 {
 	self->priv = GTH_EDIT_EXIV2_PAGE_GET_PRIVATE (self);
+	self->priv->info = NULL;
 
 	gtk_container_set_border_width (GTK_CONTAINER (self), 12);
 
@@ -204,7 +232,7 @@ gth_edit_exiv2_page_init (GthEditExiv2Page *self)
 static void
 gth_edit_exiv2_page_gth_edit_exiv2_page_interface_init (GthEditMetadataPageIface *iface)
 {
-	iface->set_file = gth_edit_exiv2_page_real_set_file;
+	iface->set_file_list = gth_edit_exiv2_page_real_set_file_list;
 	iface->update_info = gth_edit_exiv2_page_real_update_info;
 	iface->get_name = gth_edit_exiv2_page_real_get_name;
 }
diff --git a/gthumb/gth-file-data.c b/gthumb/gth-file-data.c
index 00002f8..c3d1683 100644
--- a/gthumb/gth-file-data.c
+++ b/gthumb/gth-file-data.c
@@ -225,8 +225,10 @@ gth_file_data_get_mime_type (GthFileData *self)
 	if (content_type == NULL) {
 		char *filename = g_file_get_basename (self->file);
 
-		content_type = g_content_type_guess (filename, NULL, 0, NULL);
-		g_free (filename);
+		if (filename != NULL) {
+			content_type = g_content_type_guess (filename, NULL, 0, NULL);
+			g_free (filename);
+		}
 	}
 
 	return get_static_string (content_type);
@@ -505,8 +507,8 @@ char *
 gth_file_data_get_attribute_as_string (GthFileData *file_data,
 				       const char  *id)
 {
-	char     *value = NULL;
-	GObject  *obj;
+	char    *value = NULL;
+	GObject *obj;
 
 	switch (g_file_info_get_attribute_type (file_data->info, id)) {
 	case G_FILE_ATTRIBUTE_TYPE_OBJECT:
@@ -525,3 +527,73 @@ gth_file_data_get_attribute_as_string (GthFileData *file_data,
 
 	return value;
 }
+
+
+GFileInfo *
+gth_file_data_list_get_common_info (GList      *file_data_list,
+				    const char *attribtues)
+{
+	GFileInfo  *info;
+	char      **attributes_v;
+	int         i;
+
+	info = g_file_info_new ();
+	g_file_info_copy_into (((GthFileData *) file_data_list->data)->info, info);
+
+	attributes_v = g_strsplit (attribtues, ",", -1);
+	for (i = 0; attributes_v[i] != NULL; i++) {
+		char  *attribute = attributes_v[i];
+		char  *first_value;
+		GList *scan;
+
+		first_value = gth_file_data_get_attribute_as_string ((GthFileData *) file_data_list->data, attribute);
+		for (scan = file_data_list->next; (first_value != NULL) && scan; scan = scan->next) {
+			GthFileData *file_data = scan->data;
+			char        *value;
+
+			value = gth_file_data_get_attribute_as_string (file_data, attribute);
+			if (g_strcmp0 (first_value, value) != 0) {
+				g_free (first_value);
+				first_value = NULL;
+			}
+
+			g_free (value);
+		}
+
+		if (first_value == NULL)
+			g_file_info_remove_attribute (info, attribute);
+	}
+
+	g_strfreev (attributes_v);
+
+	return info;
+}
+
+
+gboolean
+gth_file_data_attribute_equal (GthFileData *file_data,
+			       const char  *attribute,
+			       const char  *value)
+{
+	char     *v;
+	gboolean  result;
+
+	v = gth_file_data_get_attribute_as_string (file_data, attribute);
+	result = g_strcmp0 (v, value) == 0;
+
+	g_free (v);
+
+	return result;
+}
+
+
+gboolean
+gth_file_data_attribute_equal_string_list (GthFileData    *file_data,
+					   const char     *attribute,
+					   GthStringList  *value)
+{
+	GObject *obj;
+
+	obj = g_file_info_get_attribute_object (file_data->info, attribute);
+	return gth_string_list_equal (GTH_STRING_LIST (obj), value);
+}
diff --git a/gthumb/gth-file-data.h b/gthumb/gth-file-data.h
index 30b23fd..81f0207 100644
--- a/gthumb/gth-file-data.h
+++ b/gthumb/gth-file-data.h
@@ -26,6 +26,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <gio/gio.h>
+#include "gth-string-list.h"
 
 G_BEGIN_DECLS
 
@@ -103,6 +104,15 @@ void          gth_file_data_ready_with_error        (GthFileData    *file_data,
 						     GError         *error);
 char *        gth_file_data_get_attribute_as_string (GthFileData    *file_data,
 				                     const char     *id);
+GFileInfo *   gth_file_data_list_get_common_info    (GList          *file_data_list,
+						     const char     *attribtues);
+gboolean      gth_file_data_attribute_equal         (GthFileData    *file_data,
+						     const char     *attribute,
+						     const char     *value);
+gboolean      gth_file_data_attribute_equal_string_list
+						    (GthFileData    *file_data,
+						     const char     *attribute,
+						     GthStringList  *value);
 
 G_END_DECLS
 



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