[gthumb] edit metadata: allow to save the metadata without closing the dialog



commit bbded358eead173cb57db0db3d7d398bf984e27e
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Fri Nov 25 21:42:53 2011 +0100

    edit metadata: allow to save the metadata without closing the dialog
    
    [new feature]

 extensions/edit_metadata/actions.c                 |   13 +-
 extensions/edit_metadata/dlg-edit-metadata.c       |  233 +++++++++++++++----
 extensions/edit_metadata/dlg-edit-metadata.h       |    3 +-
 extensions/edit_metadata/gth-edit-comment-page.c   |    7 +-
 .../edit_metadata/gth-edit-metadata-dialog.c       |   13 +-
 gthumb/gth-file-data.c                             |   11 +-
 6 files changed, 210 insertions(+), 70 deletions(-)
---
diff --git a/extensions/edit_metadata/actions.c b/extensions/edit_metadata/actions.c
index 429c2de..d6e6631 100644
--- a/extensions/edit_metadata/actions.c
+++ b/extensions/edit_metadata/actions.c
@@ -32,18 +32,7 @@ void
 gth_browser_activate_action_edit_metadata (GtkAction  *action,
 				 	   GthBrowser *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);
+	dlg_edit_metadata (browser);
 }
 
 
diff --git a/extensions/edit_metadata/dlg-edit-metadata.c b/extensions/edit_metadata/dlg-edit-metadata.c
index 8f2224c..42d1039 100644
--- a/extensions/edit_metadata/dlg-edit-metadata.c
+++ b/extensions/edit_metadata/dlg-edit-metadata.c
@@ -26,30 +26,86 @@
 #include "gth-edit-metadata-dialog.h"
 
 
+#define UPDATE_SELECTION_DELAY    300
+#define EDIT_METADATA_DIALOG_NAME "dlg-edit-metadata"
+
+
 typedef struct {
+	int         ref;
 	GthBrowser *browser;
 	GtkWidget  *dialog;
-	GList      *files; /* GFile list */
 	GList      *file_list; /* GthFileData list */
 	GList      *parents;
+	gboolean    never_shown;
+	gboolean    close_dialog;
+	GthTask    *loader;
+	gulong      file_selection_changed_event;
+	guint       update_selectection_event;
 } DialogData;
 
 
+static DialogData *
+dialog_data_ref (DialogData *data)
+{
+	g_atomic_int_inc (&data->ref);
+	return data;
+}
+
+
+static void
+cancel_file_list_loading (DialogData *data)
+{
+	if (data->loader == NULL)
+		return;
+	gth_task_cancel (data->loader);
+	g_object_unref (data->loader);
+	data->loader = NULL;
+}
+
+
 static void
-destroy_cb (GtkWidget  *widget,
-	    DialogData *data)
+dialog_data_unref (DialogData *data)
 {
+	if (! g_atomic_int_dec_and_test (&data->ref))
+		return;
+
+	if (data->file_selection_changed_event != 0) {
+		g_signal_handler_disconnect (gth_browser_get_file_list_view (data->browser),
+					     data->file_selection_changed_event);
+		data->file_selection_changed_event = 0;
+	}
+	if (data->update_selectection_event != 0) {
+		g_source_remove (data->update_selectection_event);
+		data->update_selectection_event = 0;
+	}
+	cancel_file_list_loading (data);
+
+	gth_browser_set_dialog (data->browser, EDIT_METADATA_DIALOG_NAME, NULL);
+	gtk_widget_destroy (data->dialog);
+
 	_g_object_list_unref (data->file_list);
-	_g_object_list_unref (data->files);
 	_g_object_list_unref (data->parents);
 	g_free (data);
 }
 
 
 static void
-save_file_data_task_completed_cb (GthTask  *task,
-				  GError   *error,
-				  gpointer  user_data)
+close_dialog (DialogData *data)
+{
+	if (data->file_selection_changed_event != 0) {
+		g_signal_handler_disconnect (gth_browser_get_file_list_view (data->browser),
+					     data->file_selection_changed_event);
+		data->file_selection_changed_event = 0;
+	}
+	gtk_widget_hide (data->dialog);
+	dialog_data_unref (data);
+}
+
+
+static void
+saver_completed_cb (GthTask  *task,
+		    GError   *error,
+		    gpointer  user_data)
 {
 	DialogData *data = user_data;
 	GthMonitor *monitor;
@@ -60,28 +116,25 @@ save_file_data_task_completed_cb (GthTask  *task,
 		gth_monitor_resume (monitor, (GFile *) scan->data);
 
 	if (error != NULL) {
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not save the file metadata"), error);
-		return;
+		if (! g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+			_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not save the file metadata"), error);
 	}
+	else {
+		for (scan = data->file_list; scan; scan = scan->next) {
+			GthFileData *file_data = scan->data;
+			GList       *files;
 
-	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);
-		if (G_UNLIKELY (parent == NULL))
-			continue;
-
-		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);
+			files = g_list_prepend (NULL, g_object_ref (file_data->file));
+			gth_monitor_metadata_changed (monitor, file_data);
 
-		_g_object_list_unref (files);
-		g_object_unref (parent);
+			_g_object_list_unref (files);
+		}
 	}
 
-	gtk_widget_destroy (GTK_WIDGET (data->dialog));
+	if (data->close_dialog)
+		close_dialog (data);
+
+	dialog_data_unref (data);
 }
 
 
@@ -96,11 +149,17 @@ edit_metadata_dialog__response_cb (GtkDialog *dialog,
 	GList      *scan;
 	GthTask    *task;
 
-	if (response != GTK_RESPONSE_OK) {
-		gtk_widget_destroy (GTK_WIDGET (data->dialog));
+	if ((response != GTK_RESPONSE_OK) && (response != GTK_RESPONSE_APPLY)) {
+		cancel_file_list_loading (data);
+		close_dialog (data);
 		return;
 	}
 
+	if (data->file_list == NULL)
+		return;
+
+	data->close_dialog = (response == GTK_RESPONSE_OK);
+
 	/* get the parents list */
 
 	parents = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
@@ -115,6 +174,7 @@ edit_metadata_dialog__response_cb (GtkDialog *dialog,
 			g_object_unref (parent);
 		}
 	}
+	_g_object_list_unref (data->parents);
 	data->parents = g_hash_table_get_keys (parents);
 	g_list_foreach (data->parents, (GFunc) g_object_ref, NULL);
 	g_hash_table_unref (parents);
@@ -127,10 +187,11 @@ edit_metadata_dialog__response_cb (GtkDialog *dialog,
 
 	gth_edit_metadata_dialog_update_info (GTH_EDIT_METADATA_DIALOG (data->dialog), data->file_list);
 
+	dialog_data_ref (data);
 	task = gth_save_file_data_task_new (data->file_list, "*");
 	g_signal_connect (task,
 			  "completed",
-			  G_CALLBACK (save_file_data_task_completed_cb),
+			  G_CALLBACK (saver_completed_cb),
 			  data);
 	gth_browser_exec_task (data->browser, task, FALSE);
 
@@ -139,55 +200,129 @@ edit_metadata_dialog__response_cb (GtkDialog *dialog,
 }
 
 
+typedef struct {
+	DialogData *data;
+	GList      *files;
+} LoaderData;
+
+
+static void
+loader_data_free (LoaderData *loader_data)
+{
+	dialog_data_unref (loader_data->data);
+	_g_object_list_unref (loader_data->files);
+	g_free (loader_data);
+}
+
+
 static void
-load_file_data_task_completed_cb (GthTask  *task,
-				  GError   *error,
-				  gpointer  user_data)
+loader_completed_cb (GthTask  *task,
+		     GError   *error,
+		     gpointer  user_data)
 {
-	DialogData *data = user_data;
+	LoaderData *loader_data = user_data;
+	DialogData *data = loader_data->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));
+		if (! g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+			_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Cannot read file information"), error);
+		loader_data_free (loader_data);
+		if (data->never_shown)
+			close_dialog (data);
 		return;
 	}
 
+	_g_object_list_unref (data->file_list);
 	data->file_list = _g_object_list_ref (gth_load_file_data_task_get_result (GTH_LOAD_FILE_DATA_TASK (task)));
 	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_set_modal (GTK_WINDOW (data->dialog), FALSE);
 	gtk_window_present (GTK_WINDOW (data->dialog));
+
+	data->never_shown = FALSE;
+
+	loader_data_free (loader_data);
+}
+
+
+static gboolean
+update_file_list (gpointer user_data)
+{
+	DialogData *data = user_data;
+	LoaderData *loader_data;
+	GList      *items;
+	GList      *file_data_list;
+
+	if (data->update_selectection_event != 0) {
+		g_source_remove (data->update_selectection_event);
+		data->update_selectection_event = 0;
+	}
+
+	cancel_file_list_loading (data);
+
+	loader_data = g_new0 (LoaderData, 1);
+	loader_data->data = dialog_data_ref (data);
+
+	items = gth_file_selection_get_selected (GTH_FILE_SELECTION (gth_browser_get_file_list_view (data->browser)));
+	file_data_list = gth_file_list_get_files (GTH_FILE_LIST (gth_browser_get_file_list (data->browser)), items);
+	loader_data->files = gth_file_data_list_to_file_list (file_data_list);
+
+	data->loader = gth_load_file_data_task_new (loader_data->files, "*");
+	g_signal_connect (data->loader,
+			  "completed",
+			  G_CALLBACK (loader_completed_cb),
+			  loader_data);
+	gth_browser_exec_task (data->browser, data->loader, FALSE);
+
+	_g_object_list_unref (file_data_list);
+	_gtk_tree_path_list_free (items);
+
+	return FALSE;
+}
+
+
+static void
+file_selection_changed_cb (GthFileSelection *self,
+			   DialogData       *data)
+{
+	if (data->update_selectection_event != 0)
+		g_source_remove (data->update_selectection_event);
+	data->update_selectection_event = g_timeout_add (UPDATE_SELECTION_DELAY, update_file_list, data);
 }
 
 
 void
-dlg_edit_metadata (GthBrowser *browser,
-		   GList      *files)
+dlg_edit_metadata (GthBrowser *browser)
 {
 	DialogData *data;
-	GthTask    *task;
+
+	if (gth_browser_get_dialog (browser, EDIT_METADATA_DIALOG_NAME)) {
+		gtk_window_present (GTK_WINDOW (gth_browser_get_dialog (browser, EDIT_METADATA_DIALOG_NAME)));
+		return;
+	}
 
 	data = g_new0 (DialogData, 1);
+	data->ref = 1;
 	data->browser = browser;
-	data->files = _g_object_list_ref (files);
 	data->dialog = gth_edit_metadata_dialog_new ();
+	data->never_shown = TRUE;
+
+	gth_browser_set_dialog (browser, EDIT_METADATA_DIALOG_NAME, data->dialog);
 
 	g_signal_connect (G_OBJECT (data->dialog),
-			  "destroy",
-			  G_CALLBACK (destroy_cb),
-			  data);
+			  "delete-event",
+			  G_CALLBACK (gtk_true),
+			  NULL);
 	g_signal_connect (data->dialog,
 			  "response",
 			  G_CALLBACK (edit_metadata_dialog__response_cb),
 			  data);
+	data->file_selection_changed_event =
+			g_signal_connect (gth_browser_get_file_list_view (data->browser),
+					  "file-selection-changed",
+					  G_CALLBACK (file_selection_changed_cb),
+					  data);
 
-	task = gth_load_file_data_task_new (data->files, "*");
-	g_signal_connect (task,
-			  "completed",
-			  G_CALLBACK (load_file_data_task_completed_cb),
-			  data);
-	gth_browser_exec_task (browser, task, FALSE);
-
-	g_object_unref (task);
+	update_file_list (data);
 }
diff --git a/extensions/edit_metadata/dlg-edit-metadata.h b/extensions/edit_metadata/dlg-edit-metadata.h
index 13ab8a1..fc5424b 100644
--- a/extensions/edit_metadata/dlg-edit-metadata.h
+++ b/extensions/edit_metadata/dlg-edit-metadata.h
@@ -24,7 +24,6 @@
 
 #include <gthumb.h>
 
-void dlg_edit_metadata (GthBrowser *browser,
-			GList      *files /* GFile list */);
+void dlg_edit_metadata (GthBrowser *browser);
 
 #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 176167c..eaee343 100644
--- a/extensions/edit_metadata/gth-edit-comment-page.c
+++ b/extensions/edit_metadata/gth-edit-comment-page.c
@@ -110,7 +110,7 @@ gth_edit_comment_page_real_set_file_list (GthEditMetadataPage *base,
 		gth_time_selector_set_exif_date (GTH_TIME_SELECTOR (self->priv->date_selector), gth_metadata_get_raw (metadata));
 	}
 	else {
-		if (file_list->next == NULL)
+		if ((file_list != NULL) && (file_list->next == NULL))
 			gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->date_combobox), NO_DATE);
 		else
 			gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->date_combobox), NO_CHANGE);
@@ -144,7 +144,10 @@ gth_edit_comment_page_real_set_file_list (GthEditMetadataPage *base,
 
 	no_provider = TRUE;
 
-	if (file_list->next == NULL) {
+	if (file_list == NULL) {
+		file_data = gth_file_data_new (NULL, NULL);
+	}
+	else if (file_list->next == NULL) {
 		GthFileData *first = file_list->data;
 		file_data = gth_file_data_new (first->file, first->info);
 	}
diff --git a/extensions/edit_metadata/gth-edit-metadata-dialog.c b/extensions/edit_metadata/gth-edit-metadata-dialog.c
index c391cc3..fcc5912 100644
--- a/extensions/edit_metadata/gth-edit-metadata-dialog.c
+++ b/extensions/edit_metadata/gth-edit-metadata-dialog.c
@@ -54,7 +54,8 @@ gth_edit_metadata_dialog_init (GthEditMetadataDialog *self)
 	gtk_container_set_border_width (GTK_CONTAINER (self), 5);
 
 	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);
+	gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_SAVE, GTK_RESPONSE_APPLY);
+	gtk_dialog_add_button (GTK_DIALOG (self), _("Sa_ve and Close"), GTK_RESPONSE_OK);
 
 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
@@ -108,9 +109,6 @@ gth_edit_metadata_dialog_set_file_list (GthEditMetadataDialog *dialog,
 	GList *pages;
 	GList *scan;
 
-	if (file_list == NULL)
-		return;
-
 	n_files = g_list_length (file_list);
 	if (n_files == 1) {
 		GthFileData *file_data = file_list->data;
@@ -131,6 +129,13 @@ gth_edit_metadata_dialog_set_file_list (GthEditMetadataDialog *dialog,
 	for (scan = pages; scan; scan = scan->next)
 		gth_edit_metadata_page_set_file_list (GTH_EDIT_METADATA_PAGE (scan->data), file_list);
 
+	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+					   GTK_RESPONSE_APPLY,
+					   n_files > 0);
+	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+					   GTK_RESPONSE_OK,
+					   n_files > 0);
+
 	g_list_free (pages);
 	g_free (title);
 }
diff --git a/gthumb/gth-file-data.c b/gthumb/gth-file-data.c
index 6da5551..c79223c 100644
--- a/gthumb/gth-file-data.c
+++ b/gthumb/gth-file-data.c
@@ -212,9 +212,14 @@ gth_file_data_get_mime_type (GthFileData *self)
 	content_type = g_file_info_get_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
 	if (content_type == NULL)
 		content_type = g_file_info_get_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
+
 	if (content_type == NULL) {
-		char *filename = g_file_get_basename (self->file);
+		char *filename;
+
+		if (self->file == NULL)
+			return NULL;
 
+		filename = g_file_get_basename (self->file);
 		if (filename != NULL) {
 			content_type = g_content_type_guess (filename, NULL, 0, NULL);
 			g_free (filename);
@@ -515,6 +520,10 @@ gth_file_data_list_get_common_info (GList      *file_data_list,
 	int         i;
 
 	info = g_file_info_new ();
+
+	if (file_data_list == NULL)
+		return info;
+
 	g_file_info_copy_into (((GthFileData *) file_data_list->data)->info, info);
 
 	attributes_v = g_strsplit (attribtues, ",", -1);



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