From eee44838ba7ec3c4f4c1da5ab5abfbd41c03481d Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sun, 16 Oct 2016 16:33:44 +0200 Subject: Operations window fixes and control improvements --- libcaja-private/caja-file-operations.c | 82 ++++++++++++++++++++++++++-------- libcaja-private/caja-progress-info.c | 60 ++++++++++++++++++++----- libcaja-private/caja-progress-info.h | 4 +- 3 files changed, 114 insertions(+), 32 deletions(-) diff --git a/libcaja-private/caja-file-operations.c b/libcaja-private/caja-file-operations.c index e2d5ba05..97b387cd 100644 --- a/libcaja-private/caja-file-operations.c +++ b/libcaja-private/caja-file-operations.c @@ -913,11 +913,12 @@ f (const char *format, ...) { return res; } -#define op_job_new(__type, parent_window, should_start) ((__type *)(init_common (sizeof(__type), parent_window, should_start))) +#define op_job_new(__type, parent_window, should_start, can_pause) ((__type *)(init_common (sizeof(__type), parent_window, should_start, can_pause))) static gpointer init_common (gsize job_size, - GtkWindow *parent_window, gboolean should_start) + GtkWindow *parent_window, + gboolean should_start, gboolean can_pause) { CommonJob *common; GdkScreen *screen; @@ -928,7 +929,7 @@ init_common (gsize job_size, common->parent_window = parent_window; eel_add_weak_pointer (&common->parent_window); } - common->progress = caja_progress_info_new (should_start); + common->progress = caja_progress_info_new (should_start, can_pause); common->cancellable = caja_progress_info_get_cancellable (common->progress); common->time = g_timer_new (); common->inhibit_cookie = -1; @@ -1968,7 +1969,7 @@ trash_or_delete_internal (GList *files, /* TODO: special case desktop icon link files ... */ - job = op_job_new (DeleteJob, parent_window, TRUE); + job = op_job_new (DeleteJob, parent_window, TRUE, TRUE); job->files = eel_g_object_list_copy (files); job->try_trash = try_trash; job->user_cancel = FALSE; @@ -2269,7 +2270,7 @@ caja_file_operations_unmount_mount_full (GtkWindow *parent_ if (response == GTK_RESPONSE_ACCEPT) { EmptyTrashJob *job; - job = op_job_new (EmptyTrashJob, parent_window, TRUE); + job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE); job->should_confirm = FALSE; job->trash_dirs = get_trash_dirs_for_mount (mount); job->done_callback = (CajaOpCallback)do_unmount; @@ -3412,7 +3413,7 @@ copy_move_directory (CopyMoveJob *copy_job, gboolean *skipped_file, gboolean readonly_source_fs) { - GFileInfo *info; + GFileInfo *info, *nextinfo; GError *error; GFile *src_file; GFileEnumerator *enumerator; @@ -3464,16 +3465,28 @@ copy_move_directory (CopyMoveJob *copy_job, if (enumerator) { error = NULL; + nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error); while (!job_aborted (job) && - (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error)) != NULL) { + (info = nextinfo) != NULL) { + caja_progress_info_get_ready (job->progress); + + nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error); src_file = g_file_get_child (src, g_file_info_get_name (info)); + + if ((!nextinfo) && (!is_dir(src_file))) + /* this is the last file, cannot pause anymore */ + caja_progress_info_disable_pause (job->progress); + copy_move_file (copy_job, src_file, *dest, same_fs, FALSE, &dest_fs_type, source_info, transfer_info, NULL, NULL, FALSE, &local_skipped_file, readonly_source_fs); g_object_unref (src_file); g_object_unref (info); } + if (nextinfo) + g_object_unref (nextinfo); + g_file_enumerator_close (enumerator, job->cancellable, NULL); g_object_unref (enumerator); @@ -4084,8 +4097,6 @@ copy_move_file (CopyMoveJob *copy_job, retry: - caja_progress_info_get_ready (job->progress); - error = NULL; flags = G_FILE_COPY_NOFOLLOW_SYMLINKS; if (overwrite) { @@ -4414,8 +4425,14 @@ copy_files (CopyMoveJob *job, for (l = job->files; l != NULL && !job_aborted (common); l = l->next) { + caja_progress_info_get_ready (common->progress); + src = l->data; + if ((!l->next) && (!is_dir(src))) + /* this is the last file, cannot pause anymore */ + caja_progress_info_disable_pause (common->progress); + if (i < job->n_icon_positions) { point = &job->icon_positions[i]; } else { @@ -4542,6 +4559,24 @@ copy_job (GIOSchedulerJob *io_job, return FALSE; } +static gboolean +contains_multiple_items (GList *files) +{ + GFile *first; + + if (g_list_length (files) > 1) { + return TRUE; + } else { + if (files) { + first = files->data; + if (is_dir (first)) + return TRUE; + } + } + + return FALSE; +} + void caja_file_operations_copy (GList *files, GArray *relative_item_points, @@ -4552,7 +4587,7 @@ caja_file_operations_copy (GList *files, { CopyMoveJob *job; - job = op_job_new (CopyMoveJob, parent_window, FALSE); + job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files)); job->desktop_location = caja_get_desktop_location (); job->done_callback = done_callback; job->done_callback_data = done_callback_data; @@ -4885,6 +4920,7 @@ move_files_prepare (CopyMoveJob *job, total = left = g_list_length (job->files); + caja_progress_info_get_ready (common->progress); report_move_progress (job, total, left); i = 0; @@ -4893,6 +4929,10 @@ move_files_prepare (CopyMoveJob *job, l = l->next) { src = l->data; + if ((!l->next) && (!(*fallbacks)) && (!is_dir(src))) + /* this is the last file and there are no fallbacks to process, cannot pause anymore */ + caja_progress_info_disable_pause (common->progress); + if (i < job->n_icon_positions) { point = &job->icon_positions[i]; } else { @@ -4949,6 +4989,10 @@ common = &job->common; fallback = l->data; src = fallback->file; + if ((!l->next) && (!is_dir(src))) + /* this is the last file, cannot pause anymore */ + caja_progress_info_disable_pause (common->progress); + if (fallback->has_position) { point = &fallback->position; } else { @@ -5086,7 +5130,7 @@ caja_file_operations_move (GList *files, { CopyMoveJob *job; - job = op_job_new (CopyMoveJob, parent_window, FALSE); + job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files)); job->is_move = TRUE; job->done_callback = done_callback; job->done_callback_data = done_callback_data; @@ -5406,7 +5450,7 @@ caja_file_operations_link (GList *files, { CopyMoveJob *job; - job = op_job_new (CopyMoveJob, parent_window, TRUE); + job = op_job_new (CopyMoveJob, parent_window, TRUE, FALSE); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = eel_g_object_list_copy (files); @@ -5447,7 +5491,7 @@ caja_file_operations_duplicate (GList *files, { CopyMoveJob *job; - job = op_job_new (CopyMoveJob, parent_window, FALSE); + job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files)); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = eel_g_object_list_copy (files); @@ -5619,7 +5663,7 @@ caja_file_set_permissions_recursive (const char *directory, { SetPermissionsJob *job; - job = op_job_new (SetPermissionsJob, NULL, TRUE); + job = op_job_new (SetPermissionsJob, NULL, TRUE, TRUE); job->file = g_file_new_for_uri (directory); job->file_permissions = file_permissions; job->file_mask = file_mask; @@ -6087,7 +6131,7 @@ caja_file_operations_new_folder (GtkWidget *parent_view, parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } - job = op_job_new (CreateJob, parent_window, TRUE); + job = op_job_new (CreateJob, parent_window, TRUE, FALSE); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->dest_dir = g_file_new_for_uri (parent_dir); @@ -6127,7 +6171,7 @@ caja_file_operations_new_file_from_template (GtkWidget *parent_view, parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } - job = op_job_new (CreateJob, parent_window, TRUE); + job = op_job_new (CreateJob, parent_window, TRUE, FALSE); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->dest_dir = g_file_new_for_uri (parent_dir); @@ -6172,7 +6216,7 @@ caja_file_operations_new_file (GtkWidget *parent_view, parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } - job = op_job_new (CreateJob, parent_window, TRUE); + job = op_job_new (CreateJob, parent_window, TRUE, FALSE); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->dest_dir = g_file_new_for_uri (parent_dir); @@ -6308,7 +6352,7 @@ caja_file_operations_empty_trash (GtkWidget *parent_view) parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } - job = op_job_new (EmptyTrashJob, parent_window, TRUE); + job = op_job_new (EmptyTrashJob, parent_window, TRUE, TRUE); job->trash_dirs = g_list_prepend (job->trash_dirs, g_file_new_for_uri ("trash:")); job->should_confirm = TRUE; @@ -6534,7 +6578,7 @@ caja_file_mark_desktop_file_trusted (GFile *file, { MarkTrustedJob *job; - job = op_job_new (MarkTrustedJob, parent_window, TRUE); + job = op_job_new (MarkTrustedJob, parent_window, TRUE, FALSE); job->file = g_object_ref (file); job->interactive = interactive; job->done_callback = done_callback; diff --git a/libcaja-private/caja-progress-info.c b/libcaja-private/caja-progress-info.c index 2e65bc6d..1a48e131 100644 --- a/libcaja-private/caja-progress-info.c +++ b/libcaja-private/caja-progress-info.c @@ -75,6 +75,7 @@ struct _CajaProgressInfo gboolean finished; gboolean paused; + gboolean can_pause; gboolean waiting; GCond waiting_c; @@ -399,16 +400,22 @@ get_first_queued_widget () } static void -start_button_update_view (GtkWidget *button, ProgressWidgetState state) +start_button_update_view (ProgressWidgetData *data) { GtkWidget *toapply, *curimage; + GtkWidget *button = data->btstart; + ProgressWidgetState state = data->state; + gboolean as_pause; - if (state == STATE_RUNNING || state == STATE_QUEUING) + if (state == STATE_RUNNING || state == STATE_QUEUING) { toapply = g_object_get_data (G_OBJECT(button), STARTBT_DATA_IMAGE_PAUSE); - else + as_pause = TRUE; + } else { toapply = g_object_get_data (G_OBJECT(button), STARTBT_DATA_IMAGE_RESUME); + as_pause = FALSE; + } curimage = g_object_get_data (G_OBJECT(button), STARTBT_DATA_CURIMAGE); if (curimage != toapply) { @@ -419,12 +426,19 @@ start_button_update_view (GtkWidget *button, ProgressWidgetState state) gtk_widget_show (toapply); g_object_set_data (G_OBJECT(button), STARTBT_DATA_CURIMAGE, toapply); } + + if (as_pause && !data->info->can_pause) + gtk_widget_set_sensitive (button, FALSE); } static void -queue_button_update_view (GtkWidget *button, ProgressWidgetState state) +queue_button_update_view (ProgressWidgetData *data) { - if (state == STATE_QUEUING || state == STATE_QUEUED) + GtkWidget *button = data->btqueue; + ProgressWidgetState state = data->state; + + if ( (!data->info->can_pause) || + (state == STATE_QUEUING || state == STATE_QUEUED) ) gtk_widget_set_sensitive (button, FALSE); else gtk_widget_set_sensitive (button, TRUE); @@ -543,8 +557,8 @@ widget_state_transit_to (ProgressWidgetData *data, widget_reposition_as_running (data->widget); } - start_button_update_view (data->btstart, data->state); - queue_button_update_view (data->btqueue, data->state); + start_button_update_view (data); + queue_button_update_view (data); update_data (data); } @@ -585,6 +599,7 @@ static void update_status_icon_and_window (void) { char *tooltip; + gboolean toshow, window_shown; tooltip = g_strdup_printf (ngettext ("%'d file operation active", "%'d file operations active", @@ -593,12 +608,15 @@ update_status_icon_and_window (void) gtk_status_icon_set_tooltip_text (status_icon, tooltip); g_free (tooltip); - if (n_progress_ops == 0) + toshow = (n_progress_ops > 0); + window_shown = gtk_status_icon_get_visible (status_icon); + + if (!toshow && window_shown) { gtk_status_icon_set_visible (status_icon, FALSE); gtk_widget_hide (get_progress_window ()); } - else + else if (toshow && !window_shown) { gtk_widget_show_all (get_progress_window ()); gtk_status_icon_set_visible (status_icon, TRUE); @@ -617,12 +635,31 @@ op_finished (ProgressWidgetData *data) update_status_icon_and_window (); } +static int +do_disable_pause (CajaProgressInfo *info) +{ + info->can_pause = FALSE; + + start_button_update_view (info->widget); + queue_button_update_view (info->widget); + return G_SOURCE_REMOVE; +} + +void +caja_progress_info_disable_pause (CajaProgressInfo *info) +{ + GSource *source = g_idle_source_new (); + g_source_set_callback (source, (GSourceFunc)do_disable_pause, info, NULL); + g_source_attach (source, NULL); +} + static void cancel_clicked (GtkWidget *button, ProgressWidgetData *data) { caja_progress_info_cancel (data->info); gtk_widget_set_sensitive (button, FALSE); + do_disable_pause(data->info); } static void @@ -731,7 +768,7 @@ start_button_init (ProgressWidgetData *data) resumeImage, unref_callback); g_object_set_data (G_OBJECT(button), STARTBT_DATA_CURIMAGE, NULL); - start_button_update_view (button, data->state); + start_button_update_view (data); g_signal_connect (button, "clicked", (GCallback)start_clicked, data); data->btstart = button; @@ -941,12 +978,13 @@ caja_progress_info_init (CajaProgressInfo *info) } CajaProgressInfo * -caja_progress_info_new (gboolean should_start) +caja_progress_info_new (gboolean should_start, gboolean can_pause) { CajaProgressInfo *info; info = g_object_new (CAJA_TYPE_PROGRESS_INFO, NULL); info->waiting = !should_start; + info->can_pause = can_pause; return info; } diff --git a/libcaja-private/caja-progress-info.h b/libcaja-private/caja-progress-info.h index 2640b77e..61cdb02a 100644 --- a/libcaja-private/caja-progress-info.h +++ b/libcaja-private/caja-progress-info.h @@ -50,8 +50,9 @@ GType caja_progress_info_get_type (void) G_GNUC_CONST; All methods are threadsafe. */ -CajaProgressInfo *caja_progress_info_new (gboolean should_start); +CajaProgressInfo *caja_progress_info_new (gboolean should_start, gboolean can_pause); void caja_progress_info_get_ready (CajaProgressInfo *info); +void caja_progress_info_disable_pause (CajaProgressInfo *info); GList * caja_get_all_progress_info (void); @@ -82,5 +83,4 @@ void caja_progress_info_set_progress (CajaProgressInfo *info, void caja_progress_info_pulse_progress (CajaProgressInfo *info); - #endif /* CAJA_PROGRESS_INFO_H */ -- cgit v1.2.1