PATCH: use timeouts for progress dialogs



Hi all,

one of the main reasons I think Nautilus feels sluggish sometimes is
that it pops up a progress dialog for every copy/move/link I perform,
even if it's just a single file being moved. That's quite annoying since
the dialog appears only to disappear again right away.

The attached patch makes nautilus-file-operations-progress use a timeout
for displaying itself. If the operation isn't done within 1200
milliseconds a dialog will be displayed. This also makes sure we don't
actually do the work to build the dialog UI if it isn't going to be
displayed, the UI is only created when the dialog receives a 'realize'
event.

This patch makes simple file operations feel a whole lot snappier on my
machine. Ok to commit as is?

- Frank

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/nautilus/ChangeLog,v
retrieving revision 1.5464
diff -u -p -r1.5464 ChangeLog
--- ChangeLog	28 Jul 2002 03:06:22 -0000	1.5464
+++ ChangeLog	29 Jul 2002 05:32:55 -0000
@@ -1,3 +1,23 @@
+2002-07-28  Frank Worsley  <fworsley shaw ca>
+
+	* libnautilus-private/nautilus-file-operations-progress.h:
+	* libnautilus-private/nautilus-file-operations-progress.c:
+	(nautilus_file_operations_progress_update_icon),
+	(nautilus_file_operations_progress_update),
+	(nautilus_file_operations_progress_destroy), (create_ui),
+	(nautilus_file_operations_progress_init), (delayed_show_callback),
+	(nautilus_file_operations_progress_new),
+	(nautilus_file_operations_progress_set_operation_string),
+	(nautilus_file_operations_progress_new_file),
+	(nautilus_file_operations_progress_clear):
+	use a timeout to display the progress dialog, this makes it more
+	consistent as to when we show a dialog
+
+	* libnautilus-private/nautilus-file-operations.c:
+	(create_transfer_dialog), (nautilus_file_operations_copy_move),
+	(nautilus_file_operations_delete), (do_empty_trash):
+	use timeout instead of explicitly showing progress dialog
+
 2002-07-27  Dave Camp  <dave ximian com>
 
 	* libnautilus-private/nautilus-icon-factory.c
Index: libnautilus-private/nautilus-file-operations-progress.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-operations-progress.c,v
retrieving revision 1.36
diff -u -p -r1.36 nautilus-file-operations-progress.c
--- libnautilus-private/nautilus-file-operations-progress.c	17 Apr 2002 12:29:10 -0000	1.36
+++ libnautilus-private/nautilus-file-operations-progress.c	29 Jul 2002 05:32:55 -0000
@@ -87,8 +87,26 @@ struct NautilusFileOperationsProgressDet
 	gint64 start_time;
 
 	guint delayed_close_timeout_id;
+	guint delayed_show_timeout_id;
 
 	int progress_jar_position;
+	
+	/* this is set to true when the widget is first shown and
+	 * the ui is created. ideally the operation is fast and the
+	 * widget is never shown so we don't waste time building
+	 * its ui.
+	 */
+	gboolean ui_ready;
+	
+	/* stuff we might need at ui creation time */
+	char *operation_string;
+	char *progress_verb;
+	char *file_item_name;
+	char *from_path;
+	char *to_path;
+	gulong file_index;
+	gulong size;
+	gboolean new_file;	
 };
 
 /* Private functions. */
@@ -100,6 +118,10 @@ nautilus_file_operations_progress_update
 	GdkPixbuf *pixbuf;
 	int position;
 
+	if (!progress->details->ui_ready) {
+		return;
+	}
+
 	position = gdk_pixbuf_get_height (empty_jar_pixbuf) * (1 - fraction);
 
 	if (position == progress->details->progress_jar_position) {
@@ -124,6 +146,10 @@ static void
 nautilus_file_operations_progress_update (NautilusFileOperationsProgress *progress)
 {
 	double fraction;
+
+	if (!progress->details->ui_ready) {
+		return;
+	}
 	
 	if (progress->details->bytes_total == 0) {
 		/* We haven't set up the file count yet, do not update
@@ -191,6 +217,11 @@ nautilus_file_operations_progress_destro
 		progress->details->delayed_close_timeout_id = 0;
 	}
 	
+	if (progress->details->delayed_show_timeout_id != 0) {
+		g_source_remove (progress->details->delayed_show_timeout_id);
+		progress->details->delayed_show_timeout_id = 0;
+	}
+	
 	EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
 }
 
@@ -242,13 +273,20 @@ delete_event_callback (GtkWidget *widget
 }
 
 static void
-nautilus_file_operations_progress_init (NautilusFileOperationsProgress *progress)
+create_ui (NautilusFileOperationsProgress *progress, gpointer callback_data)
 {
 	GtkWidget *hbox, *vbox;
 	GtkTable *titled_label_table;
 
-	progress->details = g_new0 (NautilusFileOperationsProgressDetails, 1);
-
+	if (progress->details->ui_ready) {
+		return;
+	}
+	
+	if (progress->details->delayed_show_timeout_id != 0) {
+		g_source_remove (progress->details->delayed_show_timeout_id);
+		progress->details->delayed_show_timeout_id = 0;
+	}
+	
 	vbox = gtk_vbox_new (FALSE, VERTICAL_SPACING);
 	gtk_container_set_border_width (GTK_CONTAINER (vbox), OUTER_BORDER);
 	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (progress)->vbox), vbox, TRUE, TRUE, VERTICAL_SPACING);
@@ -298,7 +336,44 @@ nautilus_file_operations_progress_init (
 	/* Set progress jar position */
 	progress->details->progress_jar_position = gdk_pixbuf_get_height (empty_jar_pixbuf);
 
+	progress->details->ui_ready = TRUE;
+	
+	if (progress->details->operation_string != NULL) {
+		nautilus_file_operations_progress_set_operation_string
+				(progress, progress->details->operation_string);
+		g_free (progress->details->operation_string);
+	}
+	
+	if (progress->details->new_file) {
+		nautilus_file_operations_progress_new_file
+				(progress,
+				 progress->details->progress_verb,
+				 progress->details->file_item_name,
+				 progress->details->from_path,
+				 progress->details->to_path,
+				 progress->details->from_prefix,
+				 progress->details->to_prefix,
+				 progress->details->file_index,
+				 progress->details->size);
+
+		g_free (progress->details->progress_verb);
+		g_free (progress->details->file_item_name);
+		g_free (progress->details->from_path);
+		g_free (progress->details->to_path);
+	}		 
+
 	gtk_widget_show_all (vbox);
+}	
+
+
+static void
+nautilus_file_operations_progress_init (NautilusFileOperationsProgress *progress)
+{
+	progress->details = g_new0 (NautilusFileOperationsProgressDetails, 1);
+
+	progress->details->ui_ready = FALSE;
+	
+	g_signal_connect (progress, "realize", G_CALLBACK (create_ui), NULL);
 }
 
 static void
@@ -335,13 +410,29 @@ nautilus_file_operations_progress_class_
 	
 }
 
+static gboolean
+delayed_show_callback (gpointer callback_data)
+{
+	NautilusFileOperationsProgress *progress;
+	
+	progress = NAUTILUS_FILE_OPERATIONS_PROGRESS (callback_data);
+	
+	progress->details->delayed_show_timeout_id = 0;
+	
+	create_ui (progress, NULL);
+	gtk_widget_show (GTK_WIDGET (progress));
+	
+	return FALSE;
+}
+
 NautilusFileOperationsProgress *
 nautilus_file_operations_progress_new (const char *title,
 				       const char *operation_string,
 				       const char *from_prefix,
 				       const char *to_prefix,
 				       gulong total_files,
-				       gulong total_bytes)
+				       gulong total_bytes,
+				       gboolean use_timeout)
 {
 	GtkWidget *widget;
 	NautilusFileOperationsProgress *progress;
@@ -359,6 +450,11 @@ nautilus_file_operations_progress_new (c
 
 	progress->details->from_prefix = from_prefix;
 	progress->details->to_prefix = to_prefix;
+
+	if (use_timeout) {
+		progress->details->delayed_show_timeout_id =
+			g_timeout_add (1200, delayed_show_callback, progress);
+	}
 	
 	return progress;
 }
@@ -382,6 +478,12 @@ nautilus_file_operations_progress_set_op
 {
 	g_return_if_fail (NAUTILUS_IS_FILE_OPERATIONS_PROGRESS (progress));
 
+	if (!progress->details->ui_ready) {
+		g_free (progress->details->operation_string);	
+		progress->details->operation_string = g_strdup (operation_string);
+		return;
+	}
+
 	gtk_label_set_text (GTK_LABEL (progress->details->progress_title_label),
 			    operation_string);
 }
@@ -400,11 +502,25 @@ nautilus_file_operations_progress_new_fi
 	char *progress_count;
 
 	g_return_if_fail (NAUTILUS_IS_FILE_OPERATIONS_PROGRESS (progress));
-	g_return_if_fail (GTK_WIDGET_REALIZED (progress));
 
 	progress->details->from_prefix = from_prefix;
 	progress->details->to_prefix = to_prefix;
 
+	if (!progress->details->ui_ready) {
+		g_free (progress->details->progress_verb);
+		g_free (progress->details->file_item_name);
+		g_free (progress->details->from_path);
+		g_free (progress->details->to_path);
+		progress->details->progress_verb = g_strdup (progress_verb);
+		progress->details->file_item_name = g_strdup (item_name);
+		progress->details->from_path = g_strdup (from_path);
+		progress->details->to_path = g_strdup (to_path);
+		progress->details->file_index = file_index;
+		progress->details->size = size;
+		progress->details->new_file = TRUE;
+		return;
+	}
+
 	if (progress->details->bytes_total > 0) {
 		/* we haven't set up the file count yet, do not update the progress
 		 * count until we do
@@ -438,6 +554,10 @@ nautilus_file_operations_progress_new_fi
 void
 nautilus_file_operations_progress_clear (NautilusFileOperationsProgress *progress)
 {
+	if (!progress->details->ui_ready) {
+		return;
+	}
+
 	gtk_label_set_text (GTK_LABEL (progress->details->from_label), "");
 	gtk_label_set_text (GTK_LABEL (progress->details->from_path_label), "");
 	gtk_label_set_text (GTK_LABEL (progress->details->to_label), "");
Index: libnautilus-private/nautilus-file-operations-progress.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-operations-progress.h,v
retrieving revision 1.10
diff -u -p -r1.10 nautilus-file-operations-progress.h
--- libnautilus-private/nautilus-file-operations-progress.h	27 Nov 2001 01:46:16 -0000	1.10
+++ libnautilus-private/nautilus-file-operations-progress.h	29 Jul 2002 05:32:55 -0000
@@ -55,7 +55,8 @@ NautilusFileOperationsProgress *nautilus
 											const char                     *from_prefix,
 											const char                     *to_prefix,
 											gulong                          files_total,
-											gulong                          bytes_total);
+											gulong                          bytes_total,
+											gboolean			use_timeout);
 void                            nautilus_file_operations_progress_done                 (NautilusFileOperationsProgress *dialog);
 void                            nautilus_file_operations_progress_set_progress_title   (NautilusFileOperationsProgress *dialog,
 											const char                     *progress_title);
Index: libnautilus-private/nautilus-file-operations.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-operations.c,v
retrieving revision 1.153
diff -u -p -r1.153 nautilus-file-operations.c
--- libnautilus-private/nautilus-file-operations.c	12 Jul 2002 18:36:13 -0000	1.153
+++ libnautilus-private/nautilus-file-operations.c	29 Jul 2002 05:32:56 -0000
@@ -73,7 +73,6 @@ typedef struct {
 	GnomeVFSXferOverwriteMode overwrite_mode;
 	GtkWidget *parent_view;
 	TransferKind kind;
-	gboolean show_progress_dialog;
 	void (* done_callback) (GHashTable *debuting_uris, gpointer data);
 	gpointer done_callback_data;
 	GHashTable *debuting_uris;
@@ -280,14 +279,10 @@ static void
 create_transfer_dialog (const GnomeVFSXferProgressInfo *progress_info,
 			TransferInfo *transfer_info)
 {
-	if (!transfer_info->show_progress_dialog) {
-		return;
-	}
-
 	g_return_if_fail (transfer_info->progress_dialog == NULL);
 
 	transfer_info->progress_dialog = nautilus_file_operations_progress_new 
-		(transfer_info->operation_title, "", "", "", 0, 0);
+		(transfer_info->operation_title, "", "", "", 0, 0, TRUE);
 
 	/* Treat clicking on the close box or use of the escape key
 	 * the same as clicking cancel.
@@ -307,8 +302,6 @@ create_transfer_dialog (const GnomeVFSXf
 			GTK_WINDOW (transfer_info->progress_dialog), 
 			GTK_WINDOW (gtk_widget_get_toplevel (transfer_info->parent_view)));
 	}
-
-	gtk_widget_show (GTK_WIDGET (transfer_info->progress_dialog));
 }
 
 static void
@@ -800,6 +793,12 @@ handle_transfer_vfs_error (const GnomeVF
 
 		/* transfer error, prompt the user to continue or stop */
 
+		/* make sure the progress dialog is shown at this point,
+		 * otherwise it might show up behind the error window 
+		 * which looks stupid.
+		 */
+		gtk_widget_show (GTK_WIDGET (transfer_info->progress_dialog));
+
 		formatted_source_name = NULL;
 		formatted_target_name = NULL;
 
@@ -1688,7 +1687,6 @@ nautilus_file_operations_copy_move (cons
 	gboolean target_is_trash;
 	gboolean is_desktop_trash_link;
 	gboolean duplicate;
-	gboolean all_local;
 	
 	IconPositionIterator *icon_position_iterator;
 
@@ -1712,7 +1710,6 @@ nautilus_file_operations_copy_move (cons
 	 */
 	source_uri_list = NULL;
 	target_uri_list = NULL;
-	all_local = TRUE;
 	duplicate = copy_action != GDK_ACTION_MOVE;
 	for (p = item_uris; p != NULL; p = p->next) {
 		/* Filter out special Nautilus link files */
@@ -1750,11 +1747,6 @@ nautilus_file_operations_copy_move (cons
 			target_uri_list = g_list_prepend (target_uri_list, target_uri);
 			source_uri_list = g_list_prepend (source_uri_list, source_uri);
 
-			if (all_local && (!gnome_vfs_uri_is_local (source_uri)
-					  || !gnome_vfs_uri_is_local (target_uri))) {
-				all_local = FALSE;
-			}
-
 			if (duplicate
 			    && !gnome_vfs_uri_equal (source_dir_uri, target_dir_uri)) {
 				duplicate = FALSE;
@@ -1823,11 +1815,6 @@ nautilus_file_operations_copy_move (cons
 
 		transfer_info->kind = TRANSFER_MOVE_TO_TRASH;
 
-		/* Do an arbitrary guess that an operation will take very little
-		 * time and the progress shouldn't be shown.
-		 */
-		transfer_info->show_progress_dialog = 
-			!all_local || g_list_length ((GList *) item_uris) > 20;
 	} else if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) {
 		/* localizers: progress dialog title */
 		transfer_info->operation_title = _("Moving files");
@@ -1840,11 +1827,6 @@ nautilus_file_operations_copy_move (cons
 
 		transfer_info->kind = TRANSFER_MOVE;
 
-		/* Do an arbitrary guess that an operation will take very little
-		 * time and the progress shouldn't be shown.
-		 */
-		transfer_info->show_progress_dialog = 
-			!all_local || g_list_length ((GList *) item_uris) > 20;
 	} else if ((move_options & GNOME_VFS_XFER_LINK_ITEMS) != 0) {
 		/* when creating links, handle name conflicts automatically */
 		move_options |= GNOME_VFS_XFER_USE_UNIQUE_NAMES;
@@ -1858,8 +1840,7 @@ nautilus_file_operations_copy_move (cons
 		transfer_info->cleanup_name = _("Finishing Creating Links...");
 
 		transfer_info->kind = TRANSFER_LINK;
-		transfer_info->show_progress_dialog =
-			g_list_length ((GList *)item_uris) > 20;
+
 	} else {
 		/* localizers: progress dialog title */
 		transfer_info->operation_title = _("Copying files");
@@ -1871,8 +1852,6 @@ nautilus_file_operations_copy_move (cons
 		transfer_info->cleanup_name = "";
 
 		transfer_info->kind = TRANSFER_COPY;
-		/* always show progress during copy */
-		transfer_info->show_progress_dialog = TRUE;
 	}
 
 	/* we'll need to check for copy into Trash and for moving/copying the Trash itself */
@@ -2140,7 +2119,6 @@ nautilus_file_operations_delete (const G
 	uri_list = g_list_reverse (uri_list);
 
 	transfer_info = transfer_info_new (parent_view);
-	transfer_info->show_progress_dialog = TRUE;
 
 	/* localizers: progress dialog title */
 	transfer_info->operation_title = _("Deleting files");
@@ -2176,7 +2154,6 @@ do_empty_trash (GtkWidget *parent_view)
 	if (trash_dir_list != NULL) {
 		/* set up the move parameters */
 		transfer_info = transfer_info_new (parent_view);
-		transfer_info->show_progress_dialog = TRUE;
 
 		/* localizers: progress dialog title */
 		transfer_info->operation_title = _("Emptying the Trash");
		


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