Re: [PATCH] bug 75212: empty trash dialog is modal



I've posted a new patch for this bug on Bugzilla (and attached it to
this e-mail) which fixes a problem in the original: closing the
confirmation dialog's parent window before the dialog itself would cause
a crash, as the parent_view pointer would be invald.

The new patch does two things over the old one:

1.) Marks the confirmation dialog to be deleted along with its parent, and

2.) Catches the "delete" signal from the confirmation dialog, to make
sure the dialog pointer is set to NULL when the dialog (or its parent)
is closed.

This seems to work fine now, but I wonder if a better strategy would be
simply to always create the "Empty Trash?" dialog as a child of the root
window.  I think that would mean the progress dialog would also have to
be a child of the root, though... I'm sure there's a reason why it was
written the way it was.

--
Simon South
ssouth hamlet dyndns org
Index: nautilus-file-operations.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-operations.c,v
retrieving revision 1.152
diff -u -r1.152 nautilus-file-operations.c
--- nautilus-file-operations.c	2002/05/13 17:44:14	1.152
+++ nautilus-file-operations.c	2002/05/18 23:25:09
@@ -80,6 +80,9 @@
 	gboolean cancelled;	
 } TransferInfo;
 
+/* dialog to confirm emptying the Trash (there should be at most one) */
+static GtkDialog *confirm_empty_trash_dialog = NULL;
+
 static TransferInfo *
 transfer_info_new (GtkWidget *parent_view)
 {
@@ -2202,56 +2205,79 @@
 	gnome_vfs_uri_list_free (trash_dir_list);
 }
 
-static gboolean
-confirm_empty_trash (GtkWidget *parent_view)
+static void
+confirm_empty_trash_dialog_response_callback (GtkDialog *dialog,
+					      int response,
+					      GtkWidget *parent_view)
 {
-	GtkDialog *dialog;
-	GtkWindow *parent_window;
-	int response;
+	g_assert (dialog == confirm_empty_trash_dialog);
+	g_assert (confirm_empty_trash_dialog != NULL);
 
-	/* Just Say Yes if the preference says not to confirm. */
-	if (!eel_preferences_get_boolean (NAUTILUS_PREFERENCES_CONFIRM_TRASH)) {
-		return TRUE;
+	if (response == GTK_RESPONSE_YES) {
+		do_empty_trash(parent_view);
 	}
-	
-	parent_window = GTK_WINDOW (gtk_widget_get_toplevel (parent_view));
 
-	dialog = eel_show_yes_no_dialog (
-		_("Are you sure you want to permanently delete "
-		  "all of the items in the Trash?"),
-		_("Empty Trash?"),
-		_("Empty"),
-		GTK_STOCK_CANCEL,
-		parent_window);
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
 
-	gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
+static void
+confirm_empty_trash_dialog_destroy_callback (GtkDialog *dialog,
+					     gpointer data)
+{
+	g_assert (dialog == confirm_empty_trash_dialog);
+	g_assert (confirm_empty_trash_dialog != NULL);
 
-	response = gtk_dialog_run (dialog);
+	confirm_empty_trash_dialog = NULL;
+}
 
-	gtk_object_destroy (GTK_OBJECT (dialog));
+static void
+confirm_empty_trash (GtkWidget *parent_view)
+{
+	GtkWindow *parent_window;
 
-	return response == GTK_RESPONSE_YES;
-}
+	parent_window = GTK_WINDOW (gtk_widget_get_toplevel (parent_view));
 
+	/* if a (non-modal) "Empty Trash?" confirmation dialog is already open,
+	 * do not create another */
+	if (confirm_empty_trash_dialog != NULL) {
+		gtk_window_set_transient_for (GTK_WINDOW (confirm_empty_trash_dialog),
+					      parent_window);
+		gtk_window_present (GTK_WINDOW (confirm_empty_trash_dialog));
+	} else {
+		confirm_empty_trash_dialog = eel_show_yes_no_dialog (
+			_("Are you sure you want to permanently delete "
+			  "all of the items in the Trash?"),
+			_("Empty Trash?"),
+			_("Empty"),
+			GTK_STOCK_CANCEL,
+			parent_window);
+
+		gtk_window_set_destroy_with_parent (GTK_WINDOW (confirm_empty_trash_dialog), TRUE);
+		gtk_window_set_resizable (GTK_WINDOW (confirm_empty_trash_dialog), FALSE);
+		gtk_dialog_set_default_response (confirm_empty_trash_dialog, GTK_RESPONSE_CANCEL);
+
+		g_signal_connect (confirm_empty_trash_dialog, 
+				  "response",
+				  G_CALLBACK (confirm_empty_trash_dialog_response_callback),
+				  parent_view);
+
+		g_signal_connect (confirm_empty_trash_dialog, 
+				  "destroy",
+				  G_CALLBACK (confirm_empty_trash_dialog_destroy_callback),
+				  NULL);
+	}
+}
+				
 void 
 nautilus_file_operations_empty_trash (GtkWidget *parent_view)
 {
 	g_return_if_fail (parent_view != NULL);
 
-	/* 
-	 * I chose to use a modal confirmation dialog here. 
-	 * If we used a modeless dialog, we'd have to do work to
-	 * make sure that no more than one appears on screen at
-	 * a time. That one probably couldn't be parented, because
-	 * otherwise you'd get into weird layer-shifting problems
-	 * selecting "Empty Trash" from one window when there was
-	 * already a modeless "Empty Trash" dialog parented on a 
-	 * different window. And if the dialog were not parented, it
-	 * might show up in some weird place since window manager
-	 * placement is unreliable (i.e., sucks). So modal it is.
-	 */
-	if (confirm_empty_trash (parent_view)) {
+	/* just empty the Trash if the preference says not to confirm */
+	if (!eel_preferences_get_boolean (NAUTILUS_PREFERENCES_CONFIRM_TRASH)) {
 		do_empty_trash (parent_view);
+	} else {
+		confirm_empty_trash (parent_view);
 	}
 }
 



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