diff --git a/Changelog.md b/Changelog.md index 02f9a1f..7cb2866 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,13 @@ +## Version 7.0.0 - ? +### GTK GUI + +### CLI + +### Slawka GUI + +### Core(all modes) + + ## Version 6.1.0 - 15.10.2023r - BREAKING CHANGE - Changed cache saving method, deduplicated, optimized and simplified procedure(all files needs to be hashed again) - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1086](https://github.com/qarmin/czkawka/pull/1086) - Remove up to 340ms of delay when waiting for results - [#1070](https://github.com/qarmin/czkawka/pull/1070) diff --git a/czkawka_slint_gui/src/connect_delete.rs b/czkawka_slint_gui/src/connect_delete.rs index 1689741..0559339 100644 --- a/czkawka_slint_gui/src/connect_delete.rs +++ b/czkawka_slint_gui/src/connect_delete.rs @@ -10,22 +10,32 @@ pub fn connect_delete_button(app: &MainWindow) { let r = app.get_empty_folder_model(); let m = r.borrow(); - let (entries_to_delete, mut entries_left): (Vec, Vec) = m.iter().partition(|(checked, _header_row, _selected_row, _data)| *checked); + + let (entries_to_delete, mut entries_left) = filter_out_checked_items(m, true); if !entries_to_delete.is_empty() { dbg!(format!("Items to remove {}", entries_to_delete.len())); - entries_to_delete.into_iter().for_each(|(_checked, _header_row, _selected_row, _data)| { - // TODO delete in parallel items, consider to add progress bar - }); - entries_left.iter_mut().for_each(|(_checked, _header_row, selected_row, _data)| { - *selected_row = false; - }); + + remove_all_items(entries_to_delete); + deselect_all_items(&mut entries_left); + let r = ModelRc::new(VecModel::from(entries_left)); app.set_empty_folder_model(r); } }); } +// TODO delete in parallel items, consider to add progress bar +fn remove_all_items(items: Vec) { + items.into_iter().for_each(|(_checked, _header_row, _selected_row, _data)| {}); +} + +fn deselect_all_items(items: &mut [ModelType]) { + items.iter_mut().for_each(|(_checked, _header_row, selected_row, _data)| { + *selected_row = false; + }); +} + fn filter_out_checked_items(items: &ModelRc, have_header: bool) -> (Vec, Vec) { if cfg!(debug_assertions) { check_if_header_is_checked(items); @@ -91,47 +101,122 @@ fn check_if_header_is_selected_but_should_not_be(items: &ModelRc, can } } -#[test] -fn test_filter_out_checked_items_empty() { - let vec_items = Vec::new(); - let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); - let (to_delete, left) = filter_out_checked_items(&items, false); - assert!(to_delete.is_empty()); - assert!(left.is_empty()); - let (to_delete, left) = filter_out_checked_items(&items, true); - assert!(to_delete.is_empty()); - assert!(left.is_empty()); -} +#[cfg(test)] +mod tests { + use crate::common::ModelType; + use crate::connect_delete::filter_out_checked_items; + use slint::{Model, ModelRc, SharedString, VecModel}; -#[test] -fn test_filter_out_checked_items_one_element_valid_normal() { - let vec_items = vec![(false, false, false, ModelRc::new(VecModel::default()))]; - let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); - let (to_delete, left) = filter_out_checked_items(&items, false); - assert!(to_delete.is_empty()); - assert_eq!(left.len(), items.iter().count()); -} + #[test] + fn test_filter_out_checked_items_empty() { + let vec_items = Vec::new(); + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + let (to_delete, left) = filter_out_checked_items(&items, false); + assert!(to_delete.is_empty()); + assert!(left.is_empty()); + let (to_delete, left) = filter_out_checked_items(&items, true); + assert!(to_delete.is_empty()); + assert!(left.is_empty()); + } + #[test] + fn test_filter_out_checked_items_one_element_valid_normal() { + let vec_items = vec![(false, false, false, ModelRc::new(VecModel::default()))]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + let (to_delete, left) = filter_out_checked_items(&items, false); + assert!(to_delete.is_empty()); + assert_eq!(left.len(), items.iter().count()); + } -#[test] -fn test_filter_out_checked_items_one_element_valid_header() { - let vec_items = vec![(false, true, false, ModelRc::new(VecModel::default()))]; - let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); - let (to_delete, left) = filter_out_checked_items(&items, true); - assert!(to_delete.is_empty()); - assert_eq!(left.len(), items.iter().count()); -} + #[test] + fn test_filter_out_checked_items_one_element_valid_header() { + let vec_items = vec![(false, true, false, ModelRc::new(VecModel::default()))]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + let (to_delete, left) = filter_out_checked_items(&items, true); + assert!(to_delete.is_empty()); + assert!(left.is_empty()); + } -#[test] -#[should_panic] -fn test_filter_out_checked_items_one_element_invalid_normal() { - let vec_items = vec![(false, true, false, ModelRc::new(VecModel::default()))]; - let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); - filter_out_checked_items(&items, false); -} -#[test] -#[should_panic] -fn test_filter_out_checked_items_one_element_invalid_header() { - let vec_items = vec![(false, false, false, ModelRc::new(VecModel::default()))]; - let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); - filter_out_checked_items(&items, true); + #[test] + #[should_panic] + fn test_filter_out_checked_items_one_element_invalid_normal() { + let vec_items = vec![(false, true, false, ModelRc::new(VecModel::default()))]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + filter_out_checked_items(&items, false); + } + #[test] + #[should_panic] + fn test_filter_out_checked_items_one_element_invalid_header() { + let vec_items = vec![(false, false, false, ModelRc::new(VecModel::default()))]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + filter_out_checked_items(&items, true); + } + + #[test] + fn test_filter_out_checked_items_multiple_element_valid_normal() { + let vec_items = vec![ + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("1")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("2")]))), + (true, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("3")]))), + (true, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("4")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("5")]))), + ]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + let (to_delete, left) = filter_out_checked_items(&items, false); + let to_delete_data = get_single_data_from_model(&to_delete); + let left_data = get_single_data_from_model(&left); + + assert_eq!(to_delete_data, vec!["3", "4"]); + assert_eq!(left_data, vec!["1", "2", "5"]); + } + + #[test] + fn test_filter_out_checked_items_multiple_element_valid_header() { + let vec_items = vec![ + (false, true, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("1")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("2")]))), + (true, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("3")]))), + (false, true, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("4")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("5")]))), + (false, true, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("6")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("7")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("8")]))), + ]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + let (to_delete, left) = filter_out_checked_items(&items, true); + let to_delete_data = get_single_data_from_model(&to_delete); + let left_data = get_single_data_from_model(&left); + + assert_eq!(to_delete_data, vec!["3"]); + assert_eq!(left_data, vec!["6", "7", "8"]); + } + + #[test] + fn test_filter_out_checked_items_multiple2_element_valid_header() { + let vec_items = vec![ + (false, true, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("1")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("2")]))), + (true, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("3")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("4")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("5")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("6")]))), + (false, true, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("7")]))), + (false, false, false, ModelRc::new(VecModel::from_slice(&[SharedString::from("8")]))), + ]; + let items: ModelRc = ModelRc::new(VecModel::from(vec_items)); + let (to_delete, left) = filter_out_checked_items(&items, true); + let to_delete_data = get_single_data_from_model(&to_delete); + let left_data = get_single_data_from_model(&left); + + assert_eq!(to_delete_data, vec!["3"]); + assert_eq!(left_data, vec!["1", "2", "4", "5", "6"]); + } + + fn get_single_data_from_model(model: &[ModelType]) -> Vec { + let mut d = model + .iter() + .map(|(_checked, _header_row, _selected_row, data)| data.iter().next().unwrap().to_string()) + .collect::>(); + d.sort(); + d + } } diff --git a/czkawka_slint_gui/src/main.rs b/czkawka_slint_gui/src/main.rs index a1b59f7..bdc8d56 100644 --- a/czkawka_slint_gui/src/main.rs +++ b/czkawka_slint_gui/src/main.rs @@ -1,3 +1,5 @@ +#![allow(clippy::comparison_chain)] + mod common; mod connect_delete; mod connect_open; diff --git a/czkawka_slint_gui/ui/main_window.slint b/czkawka_slint_gui/ui/main_window.slint index 690e2ea..a3baf61 100644 --- a/czkawka_slint_gui/ui/main_window.slint +++ b/czkawka_slint_gui/ui/main_window.slint @@ -97,16 +97,22 @@ export component MainWindow inherits Window { active-tab <=> root.active-tab; stop_requested <=> root.stop-requested; deleted => {root.deleted();} - scan_stopping => {root.scan_stopping();} - scan_starting(item) => {root.scan_starting(item);} + scan_stopping => { + text_summary.text = "Stopping scan, please wait..."; + root.scan_stopping(); + } + scan_starting(item) => { + text-summary.text = "Searching..."; + root.scan_starting(item); + } } - LineEdit { - text: root.stop-requested ? "Stopping scan, please wait..." : "Search stopped"; + text_summary := LineEdit { read-only: true; } } scan_ended() => { + text-summary.text = ""; // TODO this should be filled with results root.scanning = false; root.stop_requested = false; }