From 43d76888c6cc8078e03d91df083d6d68d7b44b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= <41945903+qarmin@users.noreply.github.com> Date: Sun, 7 Mar 2021 08:57:48 +0100 Subject: [PATCH] Add confirmation dialog when removing files with delete key (#282) --- czkawka_gui/czkawka.glade | 2 +- czkawka_gui/src/connect_button_delete.rs | 111 ++++++++++++++++------- czkawka_gui/src/connect_button_stop.rs | 13 ++- czkawka_gui/src/initialize_gui.rs | 35 ++++++- 4 files changed, 123 insertions(+), 38 deletions(-) diff --git a/czkawka_gui/czkawka.glade b/czkawka_gui/czkawka.glade index 243cc5c..d996d0c 100644 --- a/czkawka_gui/czkawka.glade +++ b/czkawka_gui/czkawka.glade @@ -2586,7 +2586,7 @@ This program is free to use and will always be. vertical - Hide hard links + Hide hard links(only Linux and MacOS) True True False diff --git a/czkawka_gui/src/connect_button_delete.rs b/czkawka_gui/src/connect_button_delete.rs index 23ef138..b7ab831 100644 --- a/czkawka_gui/src/connect_button_delete.rs +++ b/czkawka_gui/src/connect_button_delete.rs @@ -3,6 +3,7 @@ use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; use gtk::prelude::*; +use gtk::Align; use std::collections::BTreeMap; use std::fs; use std::fs::Metadata; @@ -29,30 +30,8 @@ pub fn connect_button_delete(gui_data: &GuiData) { let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone(); buttons_delete.connect_clicked(move |_| { - if check_button_settings_confirm_deletion.get_active() { - let confirmation_dialog_delete = gtk::Dialog::with_buttons(Some("Delete confirmation"), Some(&window_main), gtk::DialogFlags::MODAL, &[("Ok", gtk::ResponseType::Ok), ("Close", gtk::ResponseType::Cancel)]); - let label: gtk::Label = gtk::Label::new(Some("Are you sure that you want to delete files?")); - let check_button: gtk::CheckButton = gtk::CheckButton::with_label("Ask next time"); - check_button.set_active(true); - - for widgets in confirmation_dialog_delete.get_children() { - // By default GtkBox is child of dialog, so we can easily add other things to it - widgets.clone().downcast::().unwrap().add(&label); - widgets.downcast::().unwrap().add(&check_button); - } - - confirmation_dialog_delete.show_all(); - - let response_type = confirmation_dialog_delete.run(); - if response_type == gtk::ResponseType::Ok { - if !check_button.get_active() { - check_button_settings_confirm_deletion.set_active(false); - } - } else { - confirmation_dialog_delete.close(); - return; - } - confirmation_dialog_delete.close(); + if !check_if_can_delete_files(&check_button_settings_confirm_deletion, &window_main) { + return; } match to_notebook_main_enum(notebook_main.get_current_page().unwrap()) { @@ -107,6 +86,53 @@ pub fn connect_button_delete(gui_data: &GuiData) { }); } +pub fn check_if_can_delete_files(check_button_settings_confirm_deletion: >k::CheckButton, window_main: >k::Window) -> bool { + if check_button_settings_confirm_deletion.get_active() { + let confirmation_dialog_delete = gtk::Dialog::with_buttons( + Some("Delete confirmation"), + Some(window_main), + gtk::DialogFlags::DESTROY_WITH_PARENT, + &[("Ok", gtk::ResponseType::Ok), ("Close", gtk::ResponseType::Cancel)], + ); + let label: gtk::Label = gtk::Label::new(Some("Are you sure that you want to delete files?")); + let check_button: gtk::CheckButton = gtk::CheckButton::with_label("Ask next time"); + check_button.set_active(true); + check_button.set_halign(Align::Center); + + let button_box = confirmation_dialog_delete.get_children()[0].clone().downcast::().unwrap().get_children()[0] + .clone() + .downcast::() + .unwrap() + .get_children()[0] + .clone() + .downcast::() + .unwrap(); + + let button_ok = button_box.get_children()[0].clone(); + button_ok.grab_focus(); + + let internal_box = confirmation_dialog_delete.get_children()[0].clone().downcast::().unwrap(); + internal_box.add(&label); + internal_box.add(&check_button); + + confirmation_dialog_delete.show_all(); + + let response_type = confirmation_dialog_delete.run(); + if response_type == gtk::ResponseType::Ok { + if !check_button.get_active() { + check_button_settings_confirm_deletion.set_active(false); + } + confirmation_dialog_delete.hide(); + confirmation_dialog_delete.close(); + } else { + confirmation_dialog_delete.hide(); + confirmation_dialog_delete.close(); + return false; + }; + } + true +} + pub fn check_if_deleting_all_files_in_group(tree_view: >k::TreeView, column_color: i32, window_main: >k::Window, check_button_settings_confirm_group_deletion: >k::CheckButton) -> bool { let selection = tree_view.get_selection(); let (selection_rows, tree_model) = selection.get_selected_rows(); @@ -149,34 +175,49 @@ pub fn check_if_deleting_all_files_in_group(tree_view: >k::TreeView, column_co if !selected_all_records { return false; } else { - let confirmation_dialog_delete = gtk::Dialog::with_buttons( + let confirmation_dialog_group_delete = gtk::Dialog::with_buttons( Some("Confirmation of deleting all files in group"), Some(window_main), gtk::DialogFlags::MODAL, &[("Ok", gtk::ResponseType::Ok), ("Close", gtk::ResponseType::Cancel)], ); - let label: gtk::Label = gtk::Label::new(Some("In some groups there are selected all records, are you sure that you want to delete them?")); + let label: gtk::Label = gtk::Label::new(Some("In some groups there are selected all records.")); + let label2: gtk::Label = gtk::Label::new(Some("Are you sure that you want to delete them?")); let check_button: gtk::CheckButton = gtk::CheckButton::with_label("Ask next time"); check_button.set_active(true); + check_button.set_halign(Align::Center); - for widgets in confirmation_dialog_delete.get_children() { - // By default GtkBox is child of dialog, so we can easily add other things to it - widgets.clone().downcast::().unwrap().add(&label); - widgets.downcast::().unwrap().add(&check_button); - } + let button_box = confirmation_dialog_group_delete.get_children()[0].clone().downcast::().unwrap().get_children()[0] + .clone() + .downcast::() + .unwrap() + .get_children()[0] + .clone() + .downcast::() + .unwrap(); - confirmation_dialog_delete.show_all(); + let button_ok = button_box.get_children()[0].clone(); + button_ok.grab_focus(); - let response_type = confirmation_dialog_delete.run(); + let internal_box = confirmation_dialog_group_delete.get_children()[0].clone().downcast::().unwrap(); + internal_box.add(&label); + internal_box.add(&label2); + internal_box.add(&check_button); + + confirmation_dialog_group_delete.show_all(); + + let response_type = confirmation_dialog_group_delete.run(); if response_type == gtk::ResponseType::Ok { if !check_button.get_active() { check_button_settings_confirm_group_deletion.set_active(false); } } else { - confirmation_dialog_delete.close(); + confirmation_dialog_group_delete.hide(); + confirmation_dialog_group_delete.close(); return true; } - confirmation_dialog_delete.close(); + confirmation_dialog_group_delete.hide(); + confirmation_dialog_group_delete.close(); } false diff --git a/czkawka_gui/src/connect_button_stop.rs b/czkawka_gui/src/connect_button_stop.rs index e4f9ec6..c0fef4f 100644 --- a/czkawka_gui/src/connect_button_stop.rs +++ b/czkawka_gui/src/connect_button_stop.rs @@ -5,7 +5,18 @@ use gtk::prelude::*; pub fn connect_button_stop(gui_data: &GuiData) { let button_stop_in_dialog = gui_data.progress_window.button_stop_in_dialog.clone(); let stop_sender = gui_data.stop_sender.clone(); - button_stop_in_dialog.connect_clicked(move |_| { + button_stop_in_dialog.connect_key_release_event(move |_, e| { + if e.get_keycode() == Some(36) { + // Only accept enter key to stop search + stop_sender.send(()).unwrap(); + } + gtk::Inhibit(false) + }); + + let button_stop_in_dialog = gui_data.progress_window.button_stop_in_dialog.clone(); + let stop_sender = gui_data.stop_sender.clone(); + button_stop_in_dialog.connect_button_release_event(move |_, _e| { stop_sender.send(()).unwrap(); + gtk::Inhibit(false) }); } diff --git a/czkawka_gui/src/initialize_gui.rs b/czkawka_gui/src/initialize_gui.rs index ace7262..bc49e42 100644 --- a/czkawka_gui/src/initialize_gui.rs +++ b/czkawka_gui/src/initialize_gui.rs @@ -1,4 +1,4 @@ -use crate::connect_button_delete::{basic_remove, empty_folder_remover, tree_remove}; +use crate::connect_button_delete::{basic_remove, check_if_can_delete_files, check_if_deleting_all_files_in_group, empty_folder_remover, tree_remove}; use crate::create_tree_view::*; use crate::double_click_opening::*; use crate::gui_data::*; @@ -85,6 +85,17 @@ pub fn initialize_gui(gui_data: &mut GuiData) { if let Some(button_number) = e.get_keycode() { // Handle delete button if button_number == 119 { + if tree_view.get_selection().get_selected_rows().0.is_empty() { + return gtk::Inhibit(false); + } + if !check_if_can_delete_files(&gui_data.settings.check_button_settings_confirm_deletion, &gui_data.window_main) { + return gtk::Inhibit(false); + } + if gui_data.settings.check_button_settings_confirm_group_deletion.get_active() + && check_if_deleting_all_files_in_group(&tree_view.clone(), ColumnsDuplicates::Color as i32, &gui_data.window_main, &gui_data.settings.check_button_settings_confirm_group_deletion) + { + return gtk::Inhibit(false); + } tree_remove(&tree_view, ColumnsDuplicates::Name as i32, ColumnsDuplicates::Path as i32, ColumnsDuplicates::Color as i32, &gui_data); } } @@ -247,6 +258,17 @@ pub fn initialize_gui(gui_data: &mut GuiData) { if let Some(button_number) = e.get_keycode() { // Handle delete button if button_number == 119 { + if tree_view.get_selection().get_selected_rows().0.is_empty() { + return gtk::Inhibit(false); + } + if !check_if_can_delete_files(&gui_data.settings.check_button_settings_confirm_deletion, &gui_data.window_main) { + return gtk::Inhibit(false); + } + if gui_data.settings.check_button_settings_confirm_group_deletion.get_active() + && check_if_deleting_all_files_in_group(&tree_view.clone(), ColumnsSimilarImages::Color as i32, &gui_data.window_main, &gui_data.settings.check_button_settings_confirm_group_deletion) + { + return gtk::Inhibit(false); + } tree_remove(&tree_view, ColumnsSimilarImages::Name as i32, ColumnsSimilarImages::Path as i32, ColumnsSimilarImages::Color as i32, &gui_data); image_preview_similar_images_clone.hide(); } @@ -320,6 +342,17 @@ pub fn initialize_gui(gui_data: &mut GuiData) { if let Some(button_number) = e.get_keycode() { // Handle delete button if button_number == 119 { + if tree_view.get_selection().get_selected_rows().0.is_empty() { + return gtk::Inhibit(false); + } + if !check_if_can_delete_files(&gui_data.settings.check_button_settings_confirm_deletion, &gui_data.window_main) { + return gtk::Inhibit(false); + } + if gui_data.settings.check_button_settings_confirm_group_deletion.get_active() + && check_if_deleting_all_files_in_group(&tree_view.clone(), ColumnsSameMusic::Color as i32, &gui_data.window_main, &gui_data.settings.check_button_settings_confirm_group_deletion) + { + return gtk::Inhibit(false); + } tree_remove(&tree_view, ColumnsSameMusic::Name as i32, ColumnsSameMusic::Path as i32, ColumnsSameMusic::Color as i32, &gui_data); } }