From 77cdf7e6a4f1097d4d7d29e90bdb709c42a9f59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= <41945903+qarmin@users.noreply.github.com> Date: Sat, 6 Mar 2021 15:56:39 +0100 Subject: [PATCH] Add confirmation dialog when trying to remove all files in group (#281) --- czkawka_gui/czkawka.glade | 17 +++- czkawka_gui/src/connect_button_delete.rs | 106 ++++++++++++++++++++--- czkawka_gui/src/gui_settings.rs | 3 + czkawka_gui/src/saving_loading.rs | 24 +++++ 4 files changed, 139 insertions(+), 11 deletions(-) diff --git a/czkawka_gui/czkawka.glade b/czkawka_gui/czkawka.glade index c17d994..243cc5c 100644 --- a/czkawka_gui/czkawka.glade +++ b/czkawka_gui/czkawka.glade @@ -2515,6 +2515,21 @@ This program is free to use and will always be. 2 + + + Show confirm dialog when deleting all files in group + True + True + False + True + True + + + False + True + 3 + + Show bottom text panel @@ -2527,7 +2542,7 @@ This program is free to use and will always be. False False - 3 + 4 diff --git a/czkawka_gui/src/connect_button_delete.rs b/czkawka_gui/src/connect_button_delete.rs index 9647b77..23ef138 100644 --- a/czkawka_gui/src/connect_button_delete.rs +++ b/czkawka_gui/src/connect_button_delete.rs @@ -25,6 +25,7 @@ pub fn connect_button_delete(gui_data: &GuiData) { let tree_view_invalid_symlinks = gui_data.main_notebook.tree_view_invalid_symlinks.clone(); let tree_view_broken_files = gui_data.main_notebook.tree_view_broken_files.clone(); let check_button_settings_confirm_deletion = gui_data.settings.check_button_settings_confirm_deletion.clone(); + let check_button_settings_confirm_group_deletion = gui_data.settings.check_button_settings_confirm_group_deletion.clone(); let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone(); buttons_delete.connect_clicked(move |_| { @@ -56,7 +57,10 @@ pub fn connect_button_delete(gui_data: &GuiData) { match to_notebook_main_enum(notebook_main.get_current_page().unwrap()) { NotebookMainEnum::Duplicate => { - tree_remove(&tree_view_duplicate_finder.clone(), ColumnsDuplicates::Name as i32, ColumnsDuplicates::Path as i32, ColumnsDuplicates::Color as i32, &gui_data); + if !check_button_settings_confirm_group_deletion.get_active() || !check_if_deleting_all_files_in_group(&tree_view_duplicate_finder.clone(), ColumnsDuplicates::Color as i32, &window_main, &check_button_settings_confirm_group_deletion) + { + tree_remove(&tree_view_duplicate_finder.clone(), ColumnsDuplicates::Name as i32, ColumnsDuplicates::Path as i32, ColumnsDuplicates::Color as i32, &gui_data); + } } NotebookMainEnum::EmptyDirectories => { empty_folder_remover(&tree_view_empty_folder_finder.clone(), ColumnsEmptyFolders::Name as i32, ColumnsEmptyFolders::Path as i32, &gui_data); @@ -71,20 +75,27 @@ pub fn connect_button_delete(gui_data: &GuiData) { basic_remove(&tree_view_big_files_finder.clone(), ColumnsBigFiles::Name as i32, ColumnsBigFiles::Path as i32, &gui_data); } NotebookMainEnum::SimilarImages => { - tree_remove( - &tree_view_similar_images_finder.clone(), - ColumnsSimilarImages::Name as i32, - ColumnsSimilarImages::Path as i32, - ColumnsSimilarImages::Color as i32, - &gui_data, - ); - image_preview_similar_images.hide(); + if !check_button_settings_confirm_group_deletion.get_active() + || !check_if_deleting_all_files_in_group(&tree_view_similar_images_finder.clone(), ColumnsSimilarImages::Color as i32, &window_main, &check_button_settings_confirm_group_deletion) + { + tree_remove( + &tree_view_similar_images_finder.clone(), + ColumnsSimilarImages::Name as i32, + ColumnsSimilarImages::Path as i32, + ColumnsSimilarImages::Color as i32, + &gui_data, + ); + image_preview_similar_images.hide(); + } } NotebookMainEnum::Zeroed => { basic_remove(&tree_view_zeroed_files_finder.clone(), ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, &gui_data); } NotebookMainEnum::SameMusic => { - tree_remove(&tree_view_same_music_finder.clone(), ColumnsSameMusic::Name as i32, ColumnsSameMusic::Path as i32, ColumnsSameMusic::Color as i32, &gui_data); + if !check_button_settings_confirm_group_deletion.get_active() || !check_if_deleting_all_files_in_group(&tree_view_same_music_finder.clone(), ColumnsSameMusic::Color as i32, &window_main, &check_button_settings_confirm_group_deletion) + { + tree_remove(&tree_view_same_music_finder.clone(), ColumnsSameMusic::Name as i32, ColumnsSameMusic::Path as i32, ColumnsSameMusic::Color as i32, &gui_data); + } } NotebookMainEnum::Symlinks => { basic_remove(&tree_view_invalid_symlinks.clone(), ColumnsInvalidSymlinks::Name as i32, ColumnsInvalidSymlinks::Path as i32, &gui_data); @@ -96,6 +107,81 @@ pub fn connect_button_delete(gui_data: &GuiData) { }); } +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(); + if selection_rows.is_empty() { + return false; + } + + let mut current_selected_row = 0; + + let mut selected_all_records: bool = true; + + if let Some(first_iter) = tree_model.get_iter_first() { + let current_iter = first_iter; + if tree_model.get_value(¤t_iter, column_color).get::().unwrap().unwrap() != HEADER_ROW_COLOR { + panic!("First element, should be a header"); // First element should be header + }; + + loop { + if !tree_model.iter_next(¤t_iter) { + if selected_all_records { + break; + } + break; + } + + if tree_model.get_value(¤t_iter, column_color).get::().unwrap().unwrap() == HEADER_ROW_COLOR { + if selected_all_records { + break; + } + } else if current_selected_row != selection_rows.len() && selection_rows[current_selected_row] == tree_model.get_path(¤t_iter).unwrap() { + current_selected_row += 1; + } else { + selected_all_records = false; + } + } + } else { + return false; + } + + if !selected_all_records { + return false; + } else { + let confirmation_dialog_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 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_group_deletion.set_active(false); + } + } else { + confirmation_dialog_delete.close(); + return true; + } + confirmation_dialog_delete.close(); + } + + false +} + pub fn empty_folder_remover(tree_view: >k::TreeView, column_file_name: i32, column_path: i32, gui_data: &GuiData) { let text_view_errors = gui_data.text_view_errors.clone(); diff --git a/czkawka_gui/src/gui_settings.rs b/czkawka_gui/src/gui_settings.rs index 72d0101..5801ba1 100644 --- a/czkawka_gui/src/gui_settings.rs +++ b/czkawka_gui/src/gui_settings.rs @@ -8,6 +8,7 @@ pub struct GUISettings { pub check_button_settings_save_at_exit: gtk::CheckButton, pub check_button_settings_load_at_start: gtk::CheckButton, pub check_button_settings_confirm_deletion: gtk::CheckButton, + pub check_button_settings_confirm_group_deletion: gtk::CheckButton, pub check_button_settings_show_text_view: gtk::CheckButton, pub check_button_settings_use_cache: gtk::CheckButton, @@ -31,6 +32,7 @@ impl GUISettings { let check_button_settings_save_at_exit: gtk::CheckButton = builder.get_object("check_button_settings_save_at_exit").unwrap(); let check_button_settings_load_at_start: gtk::CheckButton = builder.get_object("check_button_settings_load_at_start").unwrap(); let check_button_settings_confirm_deletion: gtk::CheckButton = builder.get_object("check_button_settings_confirm_deletion").unwrap(); + let check_button_settings_confirm_group_deletion: gtk::CheckButton = builder.get_object("check_button_settings_confirm_group_deletion").unwrap(); let check_button_settings_show_text_view: gtk::CheckButton = builder.get_object("check_button_settings_show_text_view").unwrap(); let check_button_settings_use_cache: gtk::CheckButton = builder.get_object("check_button_settings_use_cache").unwrap(); @@ -50,6 +52,7 @@ impl GUISettings { check_button_settings_save_at_exit, check_button_settings_load_at_start, check_button_settings_confirm_deletion, + check_button_settings_confirm_group_deletion, check_button_settings_show_text_view, button_settings_save_configuration, button_settings_load_configuration, diff --git a/czkawka_gui/src/saving_loading.rs b/czkawka_gui/src/saving_loading.rs index 7620df7..01b6832 100644 --- a/czkawka_gui/src/saving_loading.rs +++ b/czkawka_gui/src/saving_loading.rs @@ -102,6 +102,11 @@ pub fn save_configuration(gui_data: &GuiData, manual_execution: bool) { let check_button_settings_confirm_deletion = gui_data.settings.check_button_settings_confirm_deletion.clone(); data_to_save.push(check_button_settings_confirm_deletion.get_active().to_string()); + //// Confirm deletion of all files in group + data_to_save.push("--confirm_group_deletion:".to_string()); + let check_button_settings_confirm_group_deletion = gui_data.settings.check_button_settings_confirm_group_deletion.clone(); + data_to_save.push(check_button_settings_confirm_group_deletion.get_active().to_string()); + //// Show image previews in similar images data_to_save.push("--show_previews:".to_string()); let check_button_settings_show_preview_similar_images = gui_data.settings.check_button_settings_show_preview_similar_images.clone(); @@ -166,6 +171,7 @@ enum TypeOfLoadedData { LoadingAtStart, SavingAtExit, ConfirmDeletion, + ConfirmGroupDeletion, ShowPreviews, BottomTextPanel, HideHardLinks, @@ -210,6 +216,7 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) { let mut loading_at_start: bool = true; let mut saving_at_exit: bool = true; let mut confirm_deletion: bool = true; + let mut confirm_group_deletion: bool = true; let mut show_previews: bool = true; let mut bottom_text_panel: bool = true; let mut hide_hard_links: bool = true; @@ -235,6 +242,8 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) { current_type = TypeOfLoadedData::SavingAtExit; } else if line.starts_with("--confirm_deletion") { current_type = TypeOfLoadedData::ConfirmDeletion; + } else if line.starts_with("--confirm_group_deletion") { + current_type = TypeOfLoadedData::ConfirmGroupDeletion; } else if line.starts_with("--show_previews") { current_type = TypeOfLoadedData::ShowPreviews; } else if line.starts_with("--bottom_text_panel") { @@ -308,6 +317,19 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) { ); } } + TypeOfLoadedData::ConfirmGroupDeletion => { + let line = line.to_lowercase(); + if line == "1" || line == "true" { + confirm_group_deletion = true; + } else if line == "0" || line == "false" { + confirm_group_deletion = false; + } else { + add_text_to_text_view( + &text_view_errors, + format!("Found invalid data in line {} \"{}\" isn't proper value(0/1/true/false) when loading file {:?}", line_number, line, config_file).as_str(), + ); + } + } TypeOfLoadedData::ShowPreviews => { let line = line.to_lowercase(); if line == "1" || line == "true" { @@ -402,6 +424,7 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) { gui_data.settings.check_button_settings_load_at_start.set_active(loading_at_start); gui_data.settings.check_button_settings_save_at_exit.set_active(saving_at_exit); gui_data.settings.check_button_settings_confirm_deletion.set_active(confirm_deletion); + gui_data.settings.check_button_settings_confirm_group_deletion.set_active(confirm_group_deletion); gui_data.settings.check_button_settings_show_preview_similar_images.set_active(show_previews); gui_data.settings.check_button_settings_show_text_view.set_active(bottom_text_panel); @@ -489,6 +512,7 @@ pub fn reset_configuration(gui_data: &GuiData, manual_clearing: bool) { gui_data.settings.check_button_settings_save_at_exit.set_active(true); gui_data.settings.check_button_settings_load_at_start.set_active(true); gui_data.settings.check_button_settings_confirm_deletion.set_active(true); + gui_data.settings.check_button_settings_confirm_group_deletion.set_active(true); gui_data.settings.check_button_settings_show_preview_similar_images.set_active(true); gui_data.settings.check_button_settings_show_text_view.set_active(true); gui_data.settings.check_button_settings_hide_hard_links.set_active(true);