summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Soriano <csoriano@gnome.org>2015-07-14 10:13:48 +0200
committerCarlos Soriano <csoriano@gnome.org>2015-07-17 00:32:36 +0200
commit6c576b9266ee223075c08b2441b675ac7c1aef07 (patch)
tree6dfdd3b83809cd6fab4a9a550ca00651be004327
parent1e8ede102f115d66c52fe098f4e1ebc4ef2d790f (diff)
downloadnautilus-6c576b9266ee223075c08b2441b675ac7c1aef07.tar.gz
progress-info: allow finished infos to remain alive
We want to not hide the operations and the operations button in the toolbar if the popover is open. For that, we need to allow operations widgets to remain alive even when the operation is finished. For that we need to add a new status state to copying/moving/trashing, like copied/moved/trashed. On the way, improve the wording of file-operations to match the mockups, and also make the report operations code more consistent to each other.
-rw-r--r--libnautilus-private/nautilus-file-operations.c565
-rw-r--r--libnautilus-private/nautilus-progress-info-manager.c34
-rw-r--r--libnautilus-private/nautilus-progress-info-manager.h3
-rw-r--r--libnautilus-private/nautilus-progress-info.c271
-rw-r--r--libnautilus-private/nautilus-progress-info.h1
-rw-r--r--src/nautilus-progress-info-widget.c22
-rw-r--r--src/nautilus-toolbar-ui.xml1
-rw-r--r--src/nautilus-toolbar.c114
8 files changed, 703 insertions, 308 deletions
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index 7762916a4..38bdf3977 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -1453,29 +1453,50 @@ report_delete_progress (CommonJob *job,
double elapsed, transfer_rate;
int remaining_time;
gint64 now;
- char *files_left_s;
+ char *details;
+ char *status;
+ DeleteJob *delete_job;
+ delete_job = (DeleteJob *) job;
now = g_get_monotonic_time ();
- if (transfer_info->last_report_time != 0 &&
- ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC) {
- return;
- }
- transfer_info->last_report_time = now;
-
files_left = source_info->num_files - transfer_info->num_files;
/* Races and whatnot could cause this to be negative... */
if (files_left < 0) {
- files_left = 1;
+ files_left = 0;
}
- files_left_s = f (ngettext ("%'d file left to delete",
- "%'d files left to delete",
- files_left),
- files_left);
+ /* If the number of files left is 0, we want to update the status withouth
+ * considering this time, since we want to change the status to completed
+ * and probably we won't get more calls to this function */
+ if (transfer_info->last_report_time != 0 &&
+ ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC &&
+ files_left > 0) {
+ return;
+ }
- nautilus_progress_info_take_status (job->progress,
- f (_("Deleting files")));
+ transfer_info->last_report_time = now;
+
+ if (source_info->num_files == 1) {
+ if (files_left == 0) {
+ status = _("Deleted “%B”");
+ } else {
+ status = _("Deleting “%B”");
+ }
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ (GFile*) delete_job->files->data));
+
+ } else {
+ if (files_left == 0) {
+ status = _("Deleted %'d files");
+ } else {
+ status = _("Deleting %'d files");
+ }
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ source_info->num_files));
+ }
elapsed = g_timer_elapsed (job->time, NULL);
transfer_rate = 0;
@@ -1487,23 +1508,35 @@ report_delete_progress (CommonJob *job,
}
if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE) {
- nautilus_progress_info_set_details (job->progress, files_left_s);
+ if (files_left > 0) {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files + 1,
+ source_info->num_files);
+ } else {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files,
+ source_info->num_files);
+ }
} else {
- char *details, *time_left_s;
-
- /* To translators: %T will expand to a time like "2 minutes".
- * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
- */
- time_left_s = f (ngettext ("%T left",
- "%T left",
- seconds_count_format_time_units (remaining_time)),
- remaining_time);
-
- details = g_strconcat (files_left_s, " \xE2\x80\x94 ", time_left_s, NULL);
- nautilus_progress_info_take_details (job->progress, details);
-
- g_free (time_left_s);
+ if (files_left > 0) {
+ /* To translators: %T will expand to a time duration like "2 minutes".
+ * So the whole thing will be something like "1 of 5 -- 2 hours left (4 files/sec)"
+ *
+ * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
+ */
+ details = f (ngettext ("%'d / %'d \xE2\x80\x94 %T left (%d files/sec)",
+ "%'d / %'d \xE2\x80\x94 %T left (%d files/sec)",
+ seconds_count_format_time_units (remaining_time)),
+ transfer_info->num_files + 1, source_info->num_files,
+ remaining_time,
+ (int) transfer_rate + 0.5);
+ } else {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files,
+ source_info->num_files);
+ }
}
+ nautilus_progress_info_set_details (job->progress, details);
if (elapsed > SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE) {
nautilus_progress_info_set_remaining_time (job->progress,
@@ -1511,7 +1544,6 @@ report_delete_progress (CommonJob *job,
nautilus_progress_info_set_elapsed_time (job->progress,
elapsed);
}
- g_free (files_left_s);
if (source_info->num_files != 0) {
nautilus_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
@@ -1786,114 +1818,234 @@ delete_files (CommonJob *job, GList *files, int *files_skipped)
}
static void
-report_trash_progress (CommonJob *job,
- int files_trashed,
- int total_files)
+report_trash_progress (CommonJob *job,
+ SourceInfo *source_info,
+ TransferInfo *transfer_info)
{
int files_left;
- char *s;
+ double elapsed, transfer_rate;
+ int remaining_time;
+ gint64 now;
+ char *details;
+ char *status;
+ DeleteJob *delete_job;
- files_left = total_files - files_trashed;
+ delete_job = (DeleteJob *) job;
+ now = g_get_monotonic_time ();
+ files_left = source_info->num_files - transfer_info->num_files;
- nautilus_progress_info_take_status (job->progress,
- f (_("Moving files to trash")));
+ /* Races and whatnot could cause this to be negative... */
+ if (files_left < 0) {
+ files_left = 0;
+ }
+
+ /* If the number of files left is 0, we want to update the status withouth
+ * considering this time, since we want to change the status to completed
+ * and probably we won't get more calls to this function */
+ if (transfer_info->last_report_time != 0 &&
+ ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC &&
+ files_left > 0) {
+ return;
+ }
+
+ transfer_info->last_report_time = now;
+
+ if (source_info->num_files == 1) {
+ if (files_left > 0) {
+ status = _("Trashing “%B”");
+ } else {
+ status = _("Trashed “%B”");
+ }
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ (GFile*) delete_job->files->data));
+
+ } else {
+ if (files_left > 0) {
+ status = _("Trashing %'d files");
+ } else {
+ status = _("Trashed %'d files");
+ }
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ source_info->num_files));
+ }
- s = f (ngettext ("%'d file left to trash",
- "%'d files left to trash",
- files_left),
- files_left);
- nautilus_progress_info_take_details (job->progress, s);
- if (total_files != 0) {
- nautilus_progress_info_set_progress (job->progress, files_trashed, total_files);
+ elapsed = g_timer_elapsed (job->time, NULL);
+ transfer_rate = 0;
+ remaining_time = INT_MAX;
+ if (elapsed > 0) {
+ transfer_rate = transfer_info->num_files / elapsed;
+ if (transfer_rate > 0)
+ remaining_time = (source_info->num_files - transfer_info->num_files) / transfer_rate;
}
-}
+ if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE) {
+ if (files_left > 0) {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files + 1,
+ source_info->num_files);
+ } else {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files,
+ source_info->num_files);
+ }
+ } else {
+ if (files_left > 0) {
+ /* To translators: %T will expand to a time duration like "2 minutes".
+ * So the whole thing will be something like "1 of 5 -- 2 hours left (4 files/sec)"
+ *
+ * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
+ */
+ details = f (ngettext ("%'d / %'d \xE2\x80\x94 %T left (%d files/sec)",
+ "%'d / %'d \xE2\x80\x94 %T left (%d files/sec)",
+ seconds_count_format_time_units (remaining_time)),
+ transfer_info->num_files + 1, source_info->num_files,
+ remaining_time,
+ (int) transfer_rate + 0.5);
+ } else {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files,
+ source_info->num_files);
+ }
+ }
+ nautilus_progress_info_set_details (job->progress, details);
+
+ if (elapsed > SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE) {
+ nautilus_progress_info_set_remaining_time (job->progress,
+ remaining_time);
+ nautilus_progress_info_set_elapsed_time (job->progress,
+ elapsed);
+ }
+
+ if (source_info->num_files != 0) {
+ nautilus_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
+ }
+}
static void
-trash_files (CommonJob *job, GList *files, int *files_skipped)
+trash_file (CommonJob *job,
+ GFile *file,
+ gboolean *skipped_file,
+ SourceInfo *source_info,
+ TransferInfo *transfer_info,
+ gboolean toplevel,
+ GList *to_delete)
{
- GList *l;
- GFile *file;
- GList *to_delete;
GError *error;
- int total_files, files_trashed;
char *primary, *secondary, *details;
int response;
- if (job_aborted (job)) {
+ if (should_skip_file (job, file)) {
+ *skipped_file = TRUE;
return;
}
- total_files = g_list_length (files);
- files_trashed = 0;
+ error = NULL;
- report_trash_progress (job, files_trashed, total_files);
+ if (g_file_trash (file, job->cancellable, &error)) {
+ transfer_info->num_files ++;
+ nautilus_file_changes_queue_file_removed (file);
- to_delete = NULL;
- for (l = files;
- l != NULL && !job_aborted (job);
- l = l->next) {
- file = l->data;
+ if (job->undo_info != NULL) {
+ nautilus_file_undo_info_trash_add_file (NAUTILUS_FILE_UNDO_INFO_TRASH (job->undo_info), file);
+ }
- error = NULL;
+ report_trash_progress (job, source_info, transfer_info);
+ return;
+ }
- if (!g_file_trash (file, job->cancellable, &error)) {
- if (job->skip_all_error) {
- (*files_skipped)++;
- goto skip;
- }
+ if (job->skip_all_error) {
+ *skipped_file = TRUE;
+ goto skip;
+ }
- if (job->delete_all) {
- to_delete = g_list_prepend (to_delete, file);
- goto skip;
- }
+ if (job->delete_all) {
+ to_delete = g_list_prepend (to_delete, file);
+ goto skip;
+ }
- /* Translators: %B is a file name */
- primary = f (_("“%B” can't be put in the trash. Do you want to delete it immediately?"), file);
- details = NULL;
- secondary = NULL;
- if (!IS_IO_ERROR (error, NOT_SUPPORTED)) {
- details = error->message;
- } else if (!g_file_is_native (file)) {
- secondary = f (_("This remote location does not support sending items to the trash."));
- }
+ /* Translators: %B is a file name */
+ primary = f (_("“%B” can't be put in the trash. Do you want to delete it immediately?"), file);
+ details = NULL;
+ secondary = NULL;
+ if (!IS_IO_ERROR (error, NOT_SUPPORTED)) {
+ details = error->message;
+ } else if (!g_file_is_native (file)) {
+ secondary = f (_("This remote location does not support sending items to the trash."));
+ }
- response = run_question (job,
- primary,
- secondary,
- details,
- (total_files - files_trashed) > 1,
- CANCEL, SKIP_ALL, SKIP, DELETE_ALL, DELETE,
- NULL);
+ response = run_question (job,
+ primary,
+ secondary,
+ details,
+ (source_info->num_files - transfer_info->num_files) > 1,
+ CANCEL, SKIP_ALL, SKIP, DELETE_ALL, DELETE,
+ NULL);
- if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
- ((DeleteJob *) job)->user_cancel = TRUE;
- abort_job (job);
- } else if (response == 1) { /* skip all */
- (*files_skipped)++;
- job->skip_all_error = TRUE;
- } else if (response == 2) { /* skip */
- (*files_skipped)++;
- } else if (response == 3) { /* delete all */
- to_delete = g_list_prepend (to_delete, file);
- job->delete_all = TRUE;
- } else if (response == 4) { /* delete */
- to_delete = g_list_prepend (to_delete, file);
- }
+ if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
+ ((DeleteJob *) job)->user_cancel = TRUE;
+ abort_job (job);
+ } else if (response == 1) { /* skip all */
+ *skipped_file = TRUE;
+ job->skip_all_error = TRUE;
+ } else if (response == 2) { /* skip */
+ *skipped_file = TRUE;
+ job->skip_all_error = TRUE;
+ } else if (response == 3) { /* delete all */
+ to_delete = g_list_prepend (to_delete, file);
+ job->delete_all = TRUE;
+ } else if (response == 4) { /* delete */
+ to_delete = g_list_prepend (to_delete, file);
+ }
- skip:
- g_error_free (error);
- total_files--;
- } else {
- nautilus_file_changes_queue_file_removed (file);
+skip:
+ g_error_free (error);
+}
- if (job->undo_info != NULL) {
- nautilus_file_undo_info_trash_add_file (NAUTILUS_FILE_UNDO_INFO_TRASH (job->undo_info), file);
- }
+static void
+trash_files (CommonJob *job,
+ GList *files,
+ int *files_skipped)
+{
+ GList *l;
+ GFile *file;
+ GList *to_delete;
+ SourceInfo source_info;
+ TransferInfo transfer_info;
+ gboolean skipped_file;
+
+ if (job_aborted (job)) {
+ return;
+ }
- files_trashed++;
- report_trash_progress (job, files_trashed, total_files);
+ scan_sources (files,
+ &source_info,
+ job,
+ OP_KIND_TRASH);
+ if (job_aborted (job)) {
+ return;
+ }
+
+ g_timer_start (job->time);
+
+ memset (&transfer_info, 0, sizeof (transfer_info));
+ report_trash_progress (job, &source_info, &transfer_info);
+
+ to_delete = NULL;
+ for (l = files;
+ l != NULL && !job_aborted (job);
+ l = l->next) {
+ file = l->data;
+
+ skipped_file = FALSE;
+ trash_file (job, file,
+ &skipped_file,
+ &source_info, &transfer_info,
+ TRUE, to_delete);
+ if (skipped_file) {
+ (*files_skipped)++;
}
}
@@ -2968,6 +3120,8 @@ report_copy_progress (CopyMoveJob *copy_job,
guint64 now;
CommonJob *job;
gboolean is_move;
+ gchar *status;
+ char *details;
job = (CommonJob *)copy_job;
@@ -2975,73 +3129,103 @@ report_copy_progress (CopyMoveJob *copy_job,
now = g_get_monotonic_time ();
- if (transfer_info->last_report_time != 0 &&
- ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC) {
- return;
- }
- transfer_info->last_report_time = now;
-
files_left = source_info->num_files - transfer_info->num_files;
/* Races and whatnot could cause this to be negative... */
if (files_left < 0) {
- files_left = 1;
+ files_left = 0;
}
+ /* If the number of files left is 0, we want to update the status withouth
+ * considering this time, since we want to change the status to completed
+ * and probably we won't get more calls to this function */
+ if (transfer_info->last_report_time != 0 &&
+ ABS ((gint64)(transfer_info->last_report_time - now)) < 100 * NSEC_PER_MICROSEC &&
+ files_left > 0) {
+ return;
+ }
+ transfer_info->last_report_time = now;
+
if (files_left != transfer_info->last_reported_files_left ||
transfer_info->last_reported_files_left == 0) {
/* Avoid changing this unless files_left changed since last time */
transfer_info->last_reported_files_left = files_left;
-
+
if (source_info->num_files == 1) {
if (copy_job->destination != NULL) {
+ if (is_move) {
+ if (files_left > 0) {
+ status = _("Moving “%B” to “%B”");
+ } else {
+ status = _("Moved “%B” to “%B”");
+ }
+ } else {
+ if (files_left > 0) {
+ status = _("Copying “%B” to “%B”");
+ } else {
+ status = _("Copied “%B” to “%B”");
+ }
+ }
nautilus_progress_info_take_status (job->progress,
- f (is_move ?
- _("Moving “%B” to “%B”"):
- _("Copying “%B” to “%B”"),
+ f (status,
copy_job->fake_display_source != NULL ?
copy_job->fake_display_source :
(GFile *)copy_job->files->data,
copy_job->destination));
} else {
+ if (files_left > 0) {
+ status = _("Duplicating “%B”");
+ } else {
+ status = _("Duplicated “%B”");
+ }
nautilus_progress_info_take_status (job->progress,
- f (_("Duplicating “%B”"),
- (GFile *)copy_job->files->data));
- }
- } else if (copy_job->files != NULL &&
- copy_job->files->next == NULL) {
- if (copy_job->destination != NULL) {
- nautilus_progress_info_take_status (job->progress,
- f (is_move ?
- _("Moving file %'d of %'d (in “%B”) to “%B”")
- :
- _("Copying file %'d of %'d (in “%B”) to “%B”"),
- transfer_info->num_files + 1,
- source_info->num_files,
- (GFile *)copy_job->files->data,
- copy_job->destination));
- } else {
- nautilus_progress_info_take_status (job->progress,
- f (_("Duplicating file %'d of %'d (in “%B”)"),
- transfer_info->num_files + 1,
- source_info->num_files,
+ f (status,
(GFile *)copy_job->files->data));
}
- } else {
+ } else if (copy_job->files != NULL) {
if (copy_job->destination != NULL) {
- nautilus_progress_info_take_status (job->progress,
- f (is_move ?
- _("Moving file %'d of %'d to “%B”")
- :
- _ ("Copying file %'d of %'d to “%B”"),
- transfer_info->num_files + 1,
- source_info->num_files,
- copy_job->destination));
+ if (files_left > 0) {
+ if (is_move) {
+ status = _("Moving %'d files to “%B”");
+ } else {
+ status = _("Copying %'d files to “%B”");
+ }
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ source_info->num_files,
+ (GFile *)copy_job->destination,
+ copy_job->destination));
+ } else {
+ if (is_move) {
+ status = _("Moved %'d files to “%B”");
+ } else {
+ status = _("Copied %'d files to “%B”");
+ }
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ source_info->num_files,
+ (GFile *)copy_job->destination,
+ copy_job->destination));
+ }
} else {
- nautilus_progress_info_take_status (job->progress,
- f (_("Duplicating file %'d of %'d"),
- transfer_info->num_files + 1,
- source_info->num_files));
+ GFile *parent;
+
+ parent = g_file_get_parent (copy_job->files->data);
+ if (files_left > 0) {
+ status = _("Duplicating %'d files in “%B”");
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ transfer_info->num_files + 1,
+ source_info->num_files,
+ parent));
+ } else {
+ status = _("Duplicated %'d files in “%B”");
+ nautilus_progress_info_take_status (job->progress,
+ f (status,
+ source_info->num_files,
+ parent));
+ }
+ g_object_unref (parent);
}
}
}
@@ -3057,28 +3241,63 @@ report_copy_progress (CopyMoveJob *copy_job,
remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate;
}
- if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE &&
- transfer_rate > 0) {
- char *s;
- /* To translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */
- s = f (_("%S of %S"), transfer_info->num_bytes, total_size);
- nautilus_progress_info_take_details (job->progress, s);
+ if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE &&
+ transfer_rate > 0) {
+ if (source_info->num_files == 1) {
+ /* To translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */
+ details = f (_("%S / %S"), transfer_info->num_bytes, total_size);
+ } else {
+ if (files_left > 0) {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files + 1,
+ source_info->num_files);
+ } else {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files,
+ source_info->num_files);
+ }
+ }
} else {
- char *s;
-
- /* To translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
- * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)"
- *
- * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
- */
- s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)",
- "%S of %S \xE2\x80\x94 %T left (%S/sec)",
- seconds_count_format_time_units (remaining_time)),
- transfer_info->num_bytes, total_size,
- remaining_time,
- (goffset)transfer_rate);
- nautilus_progress_info_take_details (job->progress, s);
+ if (source_info->num_files == 1) {
+ if (files_left > 0) {
+ /* To translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
+ * "2 minutes". So the whole thing will be something like "2 kb / 4 MB -- 2 hours left (4kb/sec)"
+ *
+ * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
+ */
+ details = f (ngettext ("%S / %S \xE2\x80\x94 %T left (%S/sec)",
+ "%S / %S \xE2\x80\x94 %T left (%S/sec)",
+ seconds_count_format_time_units (remaining_time)),
+ transfer_info->num_bytes, total_size,
+ remaining_time,
+ (goffset)transfer_rate);
+ } else {
+ /* To translators: %S will expand to a size like "2 bytes" or "3 MB". */
+ details = f (_("%S / %S"),
+ transfer_info->num_bytes,
+ total_size);
+ }
+ } else {
+ if (files_left > 0) {
+ /* To translators: %T will expand to a time duration like "2 minutes".
+ * So the whole thing will be something like "1 / 5 -- 2 hours left (4kb/sec)"
+ *
+ * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
+ */
+ details = f (ngettext ("%'d / %'d \xE2\x80\x94 %T left (%S/sec)",
+ "%'d / %'d \xE2\x80\x94 %T left (%S/sec)",
+ seconds_count_format_time_units (remaining_time)),
+ transfer_info->num_files + 1, source_info->num_files,
+ remaining_time,
+ (goffset)transfer_rate);
+ } else {
+ details = f (_("%'d / %'d"),
+ transfer_info->num_files,
+ source_info->num_files);
+ }
+ }
}
+ nautilus_progress_info_take_details (job->progress, details);
if (elapsed > SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE) {
nautilus_progress_info_set_remaining_time (job->progress,
diff --git a/libnautilus-private/nautilus-progress-info-manager.c b/libnautilus-private/nautilus-progress-info-manager.c
index 401cd47fa..d2a7e8ae3 100644
--- a/libnautilus-private/nautilus-progress-info-manager.c
+++ b/libnautilus-private/nautilus-progress-info-manager.c
@@ -102,14 +102,6 @@ nautilus_progress_info_manager_class_init (NautilusProgressInfoManagerClass *kla
g_type_class_add_private (klass, sizeof (NautilusProgressInfoManagerPriv));
}
-static void
-progress_info_finished_cb (NautilusProgressInfo *info,
- NautilusProgressInfoManager *self)
-{
- self->priv->progress_infos =
- g_list_remove (self->priv->progress_infos, info);
-}
-
NautilusProgressInfoManager *
nautilus_progress_info_manager_dup_singleton (void)
{
@@ -128,12 +120,27 @@ nautilus_progress_info_manager_add_new_info (NautilusProgressInfoManager *self,
self->priv->progress_infos =
g_list_prepend (self->priv->progress_infos, g_object_ref (info));
- g_signal_connect (info, "finished",
- G_CALLBACK (progress_info_finished_cb), self);
-
g_signal_emit (self, signals[NEW_PROGRESS_INFO], 0, info);
}
+void
+nautilus_progress_info_manager_remove_finished_or_cancelled_infos (NautilusProgressInfoManager *self)
+{
+ GList *l;
+ GList *next;
+
+ l = self->priv->progress_infos;
+ while (l != NULL) {
+ next = l->next;
+ if (nautilus_progress_info_get_is_finished (l->data) ||
+ nautilus_progress_info_get_is_cancelled (l->data)) {
+ self->priv->progress_infos = g_list_remove (self->priv->progress_infos,
+ l->data);
+ }
+ l = next;
+ }
+}
+
GList *
nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self)
{
@@ -141,12 +148,13 @@ nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self)
}
gboolean
-nautilus_progress_manager_are_all_infos_finished (NautilusProgressInfoManager *self)
+nautilus_progress_manager_are_all_infos_finished_or_cancelled (NautilusProgressInfoManager *self)
{
GList *l;
for (l = self->priv->progress_infos; l != NULL; l = l->next) {
- if (!nautilus_progress_info_get_is_finished (l->data)) {
+ if (!(nautilus_progress_info_get_is_finished (l->data) ||
+ nautilus_progress_info_get_is_cancelled (l->data))) {
return FALSE;
}
}
diff --git a/libnautilus-private/nautilus-progress-info-manager.h b/libnautilus-private/nautilus-progress-info-manager.h
index da0eda751..73bae1679 100644
--- a/libnautilus-private/nautilus-progress-info-manager.h
+++ b/libnautilus-private/nautilus-progress-info-manager.h
@@ -62,7 +62,8 @@ NautilusProgressInfoManager* nautilus_progress_info_manager_dup_singleton (void)
void nautilus_progress_info_manager_add_new_info (NautilusProgressInfoManager *self,
NautilusProgressInfo *info);
GList *nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self);
-gboolean nautilus_progress_manager_are_all_infos_finished (NautilusProgressInfoManager *self);
+void nautilus_progress_info_manager_remove_finished_or_cancelled_infos (NautilusProgressInfoManager *self);
+gboolean nautilus_progress_manager_are_all_infos_finished_or_cancelled (NautilusProgressInfoManager *self);
G_END_DECLS
diff --git a/libnautilus-private/nautilus-progress-info.c b/libnautilus-private/nautilus-progress-info.c
index 389aaeb15..ddec24896 100644
--- a/libnautilus-private/nautilus-progress-info.c
+++ b/libnautilus-private/nautilus-progress-info.c
@@ -34,6 +34,7 @@ enum {
PROGRESS_CHANGED,
STARTED,
FINISHED,
+ CANCELLED,
LAST_SIGNAL
};
@@ -46,6 +47,8 @@ struct _NautilusProgressInfo
GObject parent_instance;
GCancellable *cancellable;
+ guint cancellable_id;
+ GCancellable *details_in_thread_cancellable;
char *status;
char *details;
@@ -62,6 +65,7 @@ struct _NautilusProgressInfo
gboolean start_at_idle;
gboolean finish_at_idle;
+ gboolean cancel_at_idle;
gboolean changed_at_idle;
gboolean progress_at_idle;
};
@@ -84,7 +88,10 @@ nautilus_progress_info_finalize (GObject *object)
g_free (info->status);
g_free (info->details);
+ g_cancellable_disconnect (info->cancellable, info->cancellable_id);
g_object_unref (info->cancellable);
+ g_cancellable_cancel (info->details_in_thread_cancellable);
+ g_clear_object (&info->details_in_thread_cancellable);
if (G_OBJECT_CLASS (nautilus_progress_info_parent_class)->finalize) {
(*G_OBJECT_CLASS (nautilus_progress_info_parent_class)->finalize) (object);
@@ -155,6 +162,155 @@ nautilus_progress_info_class_init (NautilusProgressInfoClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ signals[CANCELLED] =
+ g_signal_new ("cancelled",
+ NAUTILUS_TYPE_PROGRESS_INFO,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static gboolean
+idle_callback (gpointer data)
+{
+ NautilusProgressInfo *info = data;
+ gboolean start_at_idle;
+ gboolean finish_at_idle;
+ gboolean changed_at_idle;
+ gboolean progress_at_idle;
+ gboolean cancelled_at_idle;
+ GSource *source;
+
+ source = g_main_current_source ();
+
+ G_LOCK (progress_info);
+
+ /* Protect agains races where the source has
+ been destroyed on another thread while it
+ was being dispatched.
+ Similar to what gdk_threads_add_idle does.
+ */
+ if (g_source_is_destroyed (source)) {
+ G_UNLOCK (progress_info);
+ return FALSE;
+ }
+
+ /* We hadn't destroyed the source, so take a ref.
+ * This might ressurect the object from dispose, but
+ * that should be ok.
+ */
+ g_object_ref (info);
+
+ g_assert (source == info->idle_source);
+
+ g_source_unref (source);
+ info->idle_source = NULL;
+
+ start_at_idle = info->start_at_idle;
+ finish_at_idle = info->finish_at_idle;
+ changed_at_idle = info->changed_at_idle;
+ progress_at_idle = info->progress_at_idle;
+ cancelled_at_idle = info->cancel_at_idle;
+
+ info->start_at_idle = FALSE;
+ info->finish_at_idle = FALSE;
+ info->changed_at_idle = FALSE;
+ info->progress_at_idle = FALSE;
+ info->cancel_at_idle = FALSE;
+
+ G_UNLOCK (progress_info);
+
+ if (start_at_idle) {
+ g_signal_emit (info,
+ signals[STARTED],
+ 0);
+ }
+
+ if (changed_at_idle) {
+ g_signal_emit (info,
+ signals[CHANGED],
+ 0);
+ }
+
+ if (progress_at_idle) {
+ g_signal_emit (info,
+ signals[PROGRESS_CHANGED],
+ 0);
+ }
+
+ if (finish_at_idle) {
+ g_signal_emit (info,
+ signals[FINISHED],
+ 0);
+ }
+
+ if (cancelled_at_idle) {
+ g_signal_emit (info,
+ signals[CANCELLED],
+ 0);
+ }
+
+ g_object_unref (info);
+
+ return FALSE;
+}
+
+
+/* Called with lock held */
+static void
+queue_idle (NautilusProgressInfo *info, gboolean now)
+{
+ if (info->idle_source == NULL ||
+ (now && !info->source_is_now)) {
+ if (info->idle_source) {
+ g_source_destroy (info->idle_source);
+ g_source_unref (info->idle_source);
+ info->idle_source = NULL;
+ }
+
+ info->source_is_now = now;
+ if (now) {
+ info->idle_source = g_idle_source_new ();
+ } else {
+ info->idle_source = g_timeout_source_new (SIGNAL_DELAY_MSEC);
+ }
+ g_source_set_callback (info->idle_source, idle_callback, info, NULL);
+ g_source_attach (info->idle_source, NULL);
+ }
+}
+
+static void
+set_details_in_thread (GTask *task,
+ NautilusProgressInfo *info,
+ gpointer user_data,
+ GCancellable *cancellable)
+{
+ if (!g_cancellable_is_cancelled (cancellable)) {
+ nautilus_progress_info_set_details (info, _("Cancelled"));
+ G_LOCK (progress_info);
+ info->cancel_at_idle = TRUE;
+ queue_idle (info, TRUE);
+ G_UNLOCK (progress_info);
+ }
+}
+
+static void
+on_canceled (GCancellable *cancellable,
+ NautilusProgressInfo *info)
+{
+ GTask *task;
+
+ /* We can't do any lock operaton here, since this is probably the main
+ * thread, so modify the details in another thread. Also it can happens
+ * that we were finalizing the object, so create a new cancellable here
+ * so it can be cancelled in finalize */
+ info->details_in_thread_cancellable = g_cancellable_new ();
+ task = g_task_new (info, info->details_in_thread_cancellable, NULL, NULL);
+ g_task_run_in_thread (task, (GTaskThreadFunc) set_details_in_thread);
+
+ g_object_unref (task);
}
static void
@@ -163,6 +319,10 @@ nautilus_progress_info_init (NautilusProgressInfo *info)
NautilusProgressInfoManager *manager;
info->cancellable = g_cancellable_new ();
+ info->cancellable_id = g_cancellable_connect (info->cancellable,
+ G_CALLBACK (on_canceled),
+ info,
+ NULL);
manager = nautilus_progress_info_manager_dup_singleton ();
nautilus_progress_info_manager_add_new_info (manager, info);
@@ -258,6 +418,18 @@ nautilus_progress_info_get_cancellable (NautilusProgressInfo *info)
}
gboolean
+nautilus_progress_info_get_is_cancelled (NautilusProgressInfo *info)
+{
+ gboolean cancelled;
+
+ G_LOCK (progress_info);
+ cancelled = g_cancellable_is_cancelled (info->cancellable);
+ G_UNLOCK (progress_info);
+
+ return cancelled;
+}
+
+gboolean
nautilus_progress_info_get_is_started (NautilusProgressInfo *info)
{
gboolean res;
@@ -299,105 +471,6 @@ nautilus_progress_info_get_is_paused (NautilusProgressInfo *info)
return res;
}
-static gboolean
-idle_callback (gpointer data)
-{
- NautilusProgressInfo *info = data;
- gboolean start_at_idle;
- gboolean finish_at_idle;
- gboolean changed_at_idle;
- gboolean progress_at_idle;
- GSource *source;
-
- source = g_main_current_source ();
-
- G_LOCK (progress_info);
-
- /* Protect agains races where the source has
- been destroyed on another thread while it
- was being dispatched.
- Similar to what gdk_threads_add_idle does.
- */
- if (g_source_is_destroyed (source)) {
- G_UNLOCK (progress_info);
- return FALSE;
- }
-
- /* We hadn't destroyed the source, so take a ref.
- * This might ressurect the object from dispose, but
- * that should be ok.
- */
- g_object_ref (info);
-
- g_assert (source == info->idle_source);
-
- g_source_unref (source);
- info->idle_source = NULL;
-
- start_at_idle = info->start_at_idle;
- finish_at_idle = info->finish_at_idle;
- changed_at_idle = info->changed_at_idle;
- progress_at_idle = info->progress_at_idle;
-
- info->start_at_idle = FALSE;
- info->finish_at_idle = FALSE;
- info->changed_at_idle = FALSE;
- info->progress_at_idle = FALSE;
-
- G_UNLOCK (progress_info);
-
- if (start_at_idle) {
- g_signal_emit (info,
- signals[STARTED],
- 0);
- }
-
- if (changed_at_idle) {
- g_signal_emit (info,
- signals[CHANGED],
- 0);
- }
-
- if (progress_at_idle) {
- g_signal_emit (info,
- signals[PROGRESS_CHANGED],
- 0);
- }
-
- if (finish_at_idle) {
- g_signal_emit (info,
- signals[FINISHED],
- 0);
- }
-
- g_object_unref (info);
-
- return FALSE;
-}
-
-/* Called with lock held */
-static void
-queue_idle (NautilusProgressInfo *info, gboolean now)
-{
- if (info->idle_source == NULL ||
- (now && !info->source_is_now)) {
- if (info->idle_source) {
- g_source_destroy (info->idle_source);
- g_source_unref (info->idle_source);
- info->idle_source = NULL;
- }
-
- info->source_is_now = now;
- if (now) {
- info->idle_source = g_idle_source_new ();
- } else {
- info->idle_source = g_timeout_source_new (SIGNAL_DELAY_MSEC);
- }
- g_source_set_callback (info->idle_source, idle_callback, info, NULL);
- g_source_attach (info->idle_source, NULL);
- }
-}
-
void
nautilus_progress_info_pause (NautilusProgressInfo *info)
{
diff --git a/libnautilus-private/nautilus-progress-info.h b/libnautilus-private/nautilus-progress-info.h
index 0ce0ad19f..44b812c57 100644
--- a/libnautilus-private/nautilus-progress-info.h
+++ b/libnautilus-private/nautilus-progress-info.h
@@ -60,6 +60,7 @@ void nautilus_progress_info_cancel (NautilusProgressInfo *info
gboolean nautilus_progress_info_get_is_started (NautilusProgressInfo *info);
gboolean nautilus_progress_info_get_is_finished (NautilusProgressInfo *info);
gboolean nautilus_progress_info_get_is_paused (NautilusProgressInfo *info);
+gboolean nautilus_progress_info_get_is_cancelled (NautilusProgressInfo *info);
void nautilus_progress_info_start (NautilusProgressInfo *info);
void nautilus_progress_info_finish (NautilusProgressInfo *info);
diff --git a/src/nautilus-progress-info-widget.c b/src/nautilus-progress-info-widget.c
index 783467686..452284bc6 100644
--- a/src/nautilus-progress-info-widget.c
+++ b/src/nautilus-progress-info-widget.c
@@ -47,7 +47,13 @@ G_DEFINE_TYPE_WITH_PRIVATE (NautilusProgressInfoWidget, nautilus_progress_info_w
static void
info_finished (NautilusProgressInfoWidget *self)
{
- gtk_widget_destroy (GTK_WIDGET (self));
+ gtk_widget_set_sensitive (self->priv->cancel, FALSE);
+}
+
+static void
+info_cancelled (NautilusProgressInfoWidget *self)
+{
+ gtk_widget_set_sensitive (self->priv->cancel, FALSE);
}
static void
@@ -85,7 +91,6 @@ cancel_clicked (GtkWidget *button,
NautilusProgressInfoWidget *self)
{
nautilus_progress_info_cancel (self->priv->info);
- gtk_widget_set_sensitive (button, FALSE);
}
static void
@@ -117,6 +122,9 @@ nautilus_progress_info_widget_constructed (GObject *obj)
g_signal_connect_swapped (self->priv->info,
"finished",
G_CALLBACK (info_finished), self);
+ g_signal_connect_swapped (self->priv->info,
+ "cancelled",
+ G_CALLBACK (info_cancelled), self);
update_data (self);
update_progress (self);
@@ -186,7 +194,15 @@ nautilus_progress_info_widget_class_init (NautilusProgressInfoWidgetClass *klass
GtkWidget *
nautilus_progress_info_widget_new (NautilusProgressInfo *info)
{
- return g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_WIDGET,
+ NautilusProgressInfoWidget *self;
+
+ self = g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_WIDGET,
"info", info,
NULL);
+
+ gtk_widget_set_sensitive (self->priv->cancel,
+ !nautilus_progress_info_get_is_finished (self->priv->info) &&
+ !nautilus_progress_info_get_is_cancelled (self->priv->info));
+
+ return GTK_WIDGET (self);
}
diff --git a/src/nautilus-toolbar-ui.xml b/src/nautilus-toolbar-ui.xml
index 42051b258..a417667de 100644
--- a/src/nautilus-toolbar-ui.xml
+++ b/src/nautilus-toolbar-ui.xml
@@ -149,6 +149,7 @@
<object class="GtkMenuButton" id="operations_button">
<property name="visible">False</property>
<property name="popover">operations_popover</property>
+ <signal name="toggled" handler="on_operations_button_toggled" object="NautilusToolbar" swapped="yes"/>
<style>
<class name="button"/>
</style>
diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c
index c083e13d2..0b85ed0ed 100644
--- a/src/nautilus-toolbar.c
+++ b/src/nautilus-toolbar.c
@@ -40,6 +40,7 @@
#include <math.h>
#define OPERATION_MINIMUM_TIME 5 //s
+#define REMOVE_FINISHED_OPERATIONS_TIEMOUT 2 //s
typedef enum {
NAUTILUS_NAVIGATION_DIRECTION_NONE,
@@ -59,6 +60,7 @@ struct _NautilusToolbarPrivate {
guint popup_timeout_id;
guint start_operations_timeout_id;
+ guint remove_finished_operations_timeout_id;
GtkWidget *operations_button;
GtkWidget *view_button;
@@ -98,6 +100,7 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE(NautilusToolbar, nautilus_toolbar, GTK_TYPE_HEADER_BAR);
static void unschedule_menu_popup_timeout (NautilusToolbar *self);
+static void update_operations (NautilusToolbar *self);
static void
toolbar_update_appearance (NautilusToolbar *self)
@@ -443,7 +446,9 @@ should_hide_operations_button (NautilusToolbar *self)
for (l = progress_infos; l != NULL; l = l->next) {
if (nautilus_progress_info_get_elapsed_time (l->data) +
- nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME) {
+ nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME &&
+ !nautilus_progress_info_get_is_cancelled (l->data) &&
+ !nautilus_progress_info_get_is_finished (l->data)) {
return FALSE;
}
}
@@ -451,24 +456,67 @@ should_hide_operations_button (NautilusToolbar *self)
return TRUE;
}
+static gboolean
+remove_finished_operations (NautilusToolbar *self)
+{
+ nautilus_progress_info_manager_remove_finished_or_cancelled_infos (self->priv->progress_manager);
+ if (should_hide_operations_button (self)) {
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->priv->operations_revealer),
+ FALSE);
+ } else {
+ update_operations (self);
+ }
+
+ self->priv->remove_finished_operations_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+unschedule_remove_finished_operations (NautilusToolbar *self)
+{
+ if (self->priv->remove_finished_operations_timeout_id != 0) {
+ g_source_remove (self->priv->remove_finished_operations_timeout_id);
+ self->priv->remove_finished_operations_timeout_id = 0;
+ }
+}
+
+static void
+schedule_remove_finished_operations (NautilusToolbar *self)
+{
+ if (self->priv->remove_finished_operations_timeout_id == 0) {
+ self->priv->remove_finished_operations_timeout_id =
+ g_timeout_add_seconds (REMOVE_FINISHED_OPERATIONS_TIEMOUT,
+ (GSourceFunc) remove_finished_operations,
+ self);
+ }
+}
+
static void
-on_progress_info_progress_changed (NautilusProgressInfo *info,
- NautilusToolbar *self)
+on_progress_info_cancelled (NautilusToolbar *self)
{
/* Update the pie chart progress */
gtk_widget_queue_draw (self->priv->operations_icon);
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
+ schedule_remove_finished_operations (self);
+ }
}
static void
-on_progress_info_finished (NautilusProgressInfo *info,
- NautilusToolbar *self)
+on_progress_info_progress_changed (NautilusToolbar *self)
{
/* Update the pie chart progress */
gtk_widget_queue_draw (self->priv->operations_icon);
+}
- if (should_hide_operations_button (self)) {
- gtk_revealer_set_reveal_child (GTK_REVEALER (self->priv->operations_revealer),
- FALSE);
+static void
+on_progress_info_finished (NautilusToolbar *self)
+{
+ /* Update the pie chart progress */
+ gtk_widget_queue_draw (self->priv->operations_icon);
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
+ schedule_remove_finished_operations (self);
}
}
@@ -504,10 +552,12 @@ update_operations (NautilusToolbar *self)
nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME) {
total_remaining_time = nautilus_progress_info_get_remaining_time (l->data);
- g_signal_connect (l->data, "finished",
- G_CALLBACK (on_progress_info_finished), self);
- g_signal_connect (l->data, "progress-changed",
- G_CALLBACK (on_progress_info_progress_changed), self);
+ g_signal_connect_swapped (l->data, "finished",
+ G_CALLBACK (on_progress_info_finished), self);
+ g_signal_connect_swapped (l->data, "cancelled",
+ G_CALLBACK (on_progress_info_cancelled), self);
+ g_signal_connect_swapped (l->data, "progress-changed",
+ G_CALLBACK (on_progress_info_progress_changed), self);
progress = nautilus_progress_info_widget_new (l->data);
gtk_box_pack_start (GTK_BOX (self->priv->operations_container),
progress,
@@ -540,10 +590,13 @@ on_progress_info_started_timeout (NautilusToolbar *self)
/* In case we didn't show the operations button because the operation total
* time stimation is not good enough, update again to make sure we don't miss
* a long time operation because of that */
- if (!nautilus_progress_manager_are_all_infos_finished (self->priv->progress_manager)) {
+ if (!nautilus_progress_manager_are_all_infos_finished_or_cancelled (self->priv->progress_manager)) {
return G_SOURCE_CONTINUE;
} else {
self->priv->start_operations_timeout_id = 0;
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
+ schedule_remove_finished_operations (self);
+ }
return G_SOURCE_REMOVE;
}
}
@@ -600,21 +653,31 @@ on_operations_icon_draw (GtkWidget *widget,
GList *l;
guint width;
guint height;
+ gboolean all_cancelled;
GdkRGBA background = {.red = 0, .green = 0, .blue = 0, .alpha = 0.2 };
GdkRGBA foreground = {.red = 0, .green = 0, .blue = 0, .alpha = 0.7 };
+ all_cancelled = TRUE;
progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager);
for (l = progress_infos; l != NULL; l = l->next) {
- remaining_progress += nautilus_progress_info_get_remaining_time (l->data);
- elapsed_progress += nautilus_progress_info_get_elapsed_time (l->data);
+ if (!nautilus_progress_info_get_is_cancelled (l->data)) {
+ all_cancelled = FALSE;
+ remaining_progress += nautilus_progress_info_get_remaining_time (l->data);
+ elapsed_progress += nautilus_progress_info_get_elapsed_time (l->data);
+ }
}
total_progress = remaining_progress + elapsed_progress;
- if (total_progress > 0)
- ratio = MAX (0.05, elapsed_progress / total_progress);
- else
- ratio = 0.05;
+ if (all_cancelled) {
+ ratio = 1.0;
+ } else {
+ if (total_progress > 0) {
+ ratio = MAX (0.05, elapsed_progress / total_progress);
+ } else {
+ ratio = 0.05;
+ }
+ }
width = gtk_widget_get_allocated_width (widget);
@@ -637,6 +700,17 @@ on_operations_icon_draw (GtkWidget *widget,
}
static void
+on_operations_button_toggled (NautilusToolbar *self)
+{
+ unschedule_remove_finished_operations (self);
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
+ schedule_remove_finished_operations (self);
+ } else {
+ update_operations (self);
+ }
+}
+
+static void
nautilus_toolbar_init (NautilusToolbar *self)
{
GtkBuilder *builder;
@@ -750,6 +824,7 @@ nautilus_toolbar_dispose (GObject *obj)
toolbar_update_appearance, self);
disconnect_progress_infos (self);
unschedule_menu_popup_timeout (self);
+ unschedule_remove_finished_operations (self);
unschedule_operations_start (self);
g_signal_handlers_disconnect_by_data (self->priv->progress_manager, self);
@@ -801,6 +876,7 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, forward_button);
gtk_widget_class_bind_template_callback (widget_class, on_operations_icon_draw);
+ gtk_widget_class_bind_template_callback (widget_class, on_operations_button_toggled);
}
void