[gthumb] allow to edit the metadata of many files at the same time
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] allow to edit the metadata of many files at the same time
- Date: Sun, 27 Jun 2010 21:27:44 +0000 (UTC)
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]