From 2310b7a6e9d44f909ba9bd696831f850d419aa44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= Date: Thu, 15 Feb 2024 13:49:23 +0100 Subject: [PATCH] Heh --- krokiet/icons/settings.svg | 6 +- krokiet/icons/subsettings.svg | 17 +++ krokiet/src/common.rs | 1 + krokiet/src/connect_scan.rs | 198 ++++++++++++++++------------ krokiet/src/connect_show_preview.rs | 5 +- krokiet/ui/left_side_panel.slint | 28 ++-- 6 files changed, 153 insertions(+), 102 deletions(-) create mode 100644 krokiet/icons/subsettings.svg diff --git a/krokiet/icons/settings.svg b/krokiet/icons/settings.svg index ac19230..64597bb 100644 --- a/krokiet/icons/settings.svg +++ b/krokiet/icons/settings.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + diff --git a/krokiet/icons/subsettings.svg b/krokiet/icons/subsettings.svg new file mode 100644 index 0000000..62007e6 --- /dev/null +++ b/krokiet/icons/subsettings.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/krokiet/src/common.rs b/krokiet/src/common.rs index f594f9f..d00ebcb 100644 --- a/krokiet/src/common.rs +++ b/krokiet/src/common.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] // TODO later remove use std::path::PathBuf; use crate::{CurrentTab, ExcludedDirectoriesModel, IncludedDirectoriesModel, MainListModel, MainWindow}; diff --git a/krokiet/src/connect_scan.rs b/krokiet/src/connect_scan.rs index c56ef8c..b337c13 100644 --- a/krokiet/src/connect_scan.rs +++ b/krokiet/src/connect_scan.rs @@ -9,10 +9,10 @@ use rayon::prelude::*; use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak}; use czkawka_core::common::{split_path, split_path_compare, DEFAULT_THREAD_SIZE}; -use czkawka_core::common_dir_traversal::{FileEntry, ProgressData}; +use czkawka_core::common_dir_traversal::{CheckingMethod, FileEntry, ProgressData}; use czkawka_core::common_tool::CommonData; use czkawka_core::common_traits::ResultEntry; -use czkawka_core::duplicate::DuplicateFinder; +use czkawka_core::duplicate::{DuplicateEntry, DuplicateFinder}; use czkawka_core::empty_files::EmptyFiles; use czkawka_core::empty_folder::{EmptyFolder, FolderEntry}; use czkawka_core::similar_images; @@ -20,7 +20,6 @@ use czkawka_core::similar_images::{ImagesEntry, SimilarImages}; use crate::common::split_u64_into_i32s; use crate::settings::{collect_settings, SettingsCustom, ALLOWED_HASH_TYPE_VALUES, ALLOWED_RESIZE_ALGORITHM_VALUES}; -use crate::CurrentTab::DuplicateFiles; use crate::{CurrentTab, GuiState, MainListModel, MainWindow, ProgressToSend}; pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender, stop_receiver: Receiver<()>) { @@ -49,6 +48,12 @@ pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender { scan_similar_images(a, progress_sender, stop_receiver, custom_settings); } + CurrentTab::BigFiles => { + scan_big_files(a, progress_sender, stop_receiver, custom_settings); + } + CurrentTab::DuplicateFiles => { + scan_duplicates(a, progress_sender, stop_receiver, custom_settings); + } CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"), _ => unimplemented!(), } @@ -57,84 +62,109 @@ pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender, progress_sender: Sender, stop_receiver: Receiver<()>, custom_settings: SettingsCustom) { -// thread::Builder::new() -// .stack_size(DEFAULT_THREAD_SIZE) -// .spawn(move || { -// let mut finder = DuplicateFinder::new(); -// set_common_settings(&mut finder, &custom_settings); -// // TODO Fill rest of settings -// finder.find_duplicates(Some(&stop_receiver), Some(&progress_sender)); -// -// if finder.get_use_reference() { -// let mut vector = finder.get_ref().clone(); -// let messages = finder.get_text_messages().create_messages_text(); -// -// for (_first_entry, vec_fe) in &mut vector { -// vec_fe.par_sort_unstable_by_key(|e| e.similarity); -// } -// -// a.upgrade_in_event_loop(move |app| { -// write_duplicates_results_referenced(&app, vector, messages); -// }) -// } else { -// let mut vector = finder.get_similar_images().clone(); -// let messages = finder.get_text_messages().create_messages_text(); -// -// for vec_fe in &mut vector { -// vec_fe.par_sort_unstable_by_key(|e| e.similarity); -// } -// -// a.upgrade_in_event_loop(move |app| { -// write_duplicates_results(&app, vector, messages); -// }) -// } -// }) -// .unwrap(); -// } -// fn write_duplicates_results_referenced(app: &MainWindow, vector: Vec<(ImagesEntry, Vec)>, messages: String) { -// let items_found = vector.len(); -// let items = Rc::new(VecModel::default()); -// for (ref_fe, vec_fe) in vector { -// let (data_model_str, data_model_int) = prepare_data_model_duplicates(&ref_fe); -// insert_data_to_model(&items, data_model_str, data_model_int, true); -// -// for fe in vec_fe { -// let (data_model_str, data_model_int) = prepare_data_model_duplicates(&fe); -// insert_data_to_model(&items, data_model_str, data_model_int, false); -// } -// } -// app.set_duplicate_files_model(items.into()); -// app.invoke_scan_ended(format!("Found {items_found} duplicate files").into()); -// app.global::().set_info_text(messages.into()); -// } -// fn write_duplicates_results(app: &MainWindow, vector: Vec>, messages: String) { -// let items_found = vector.len(); -// let items = Rc::new(VecModel::default()); -// for vec_fe in vector { -// insert_data_to_model(&items, ModelRc::new(VecModel::default()), ModelRc::new(VecModel::default()), true); -// for fe in vec_fe { -// let (data_model_str, data_model_int) = prepare_data_model_duplicates(&fe); -// insert_data_to_model(&items, data_model_str, data_model_int, false); -// } -// } -// app.set_duplicate_files_model(items.into()); -// app.invoke_scan_ended(format!("Found {items_found} duplicate files").into()); -// app.global::().set_info_text(messages.into()); -// } -// fn prepare_data_model_duplicates(fe: &ImagesEntry) -> (ModelRc, ModelRc) { -// let (directory, file) = split_path(fe.get_path()); -// let data_model_str = VecModel::from_slice(&[ -// format_size(fe.size, BINARY).into(), -// file.into(), -// directory.into(), -// NaiveDateTime::from_timestamp_opt(fe.get_modified_date() as i64, 0).unwrap().to_string().into(), -// ]); -// let modification_split = split_u64_into_i32s(fe.get_modified_date()); -// let size_split = split_u64_into_i32s(fe.size); -// let data_model_int = VecModel::from_slice(&[modification_split.0, modification_split.1, size_split.0, size_split.1]); -// (data_model_str, data_model_int) -// } +fn scan_duplicates(a: Weak, progress_sender: Sender, stop_receiver: Receiver<()>, custom_settings: SettingsCustom) { + thread::Builder::new() + .stack_size(DEFAULT_THREAD_SIZE) + .spawn(move || { + let mut finder = DuplicateFinder::new(); + set_common_settings(&mut finder, &custom_settings); + // TODO Fill rest of settings + finder.set_check_method(CheckingMethod::Hash); + // finder.set_minimal_cache_file_size(loaded_commons.minimal_cache_file_size); + // finder.set_minimal_prehash_cache_file_size(minimal_prehash_cache_file_size); + // finder.set_check_method(check_method); + // finder.set_hash_type(hash_type); + // finder.set_ignore_hard_links(loaded_commons.hide_hard_links); + // finder.set_use_prehash_cache(use_prehash_cache); + // finder.set_delete_outdated_cache(delete_outdated_cache); + // finder.set_case_sensitive_name_comparison(case_sensitive_name_comparison); + finder.find_duplicates(Some(&stop_receiver), Some(&progress_sender)); + let messages = finder.get_text_messages().create_messages_text(); + + let mut vector; + if finder.get_use_reference() { + match finder.get_check_method() { + CheckingMethod::Hash => { + vector = finder + .get_files_with_identical_hashes_referenced() + .values() + .cloned() + .flatten() + .map(|(original, other)| (Some(original), other)) + .collect::>(); + } + CheckingMethod::Name | CheckingMethod::Size | CheckingMethod::SizeName => { + let values: Vec<_> = match finder.get_check_method() { + CheckingMethod::Name => finder.get_files_with_identical_name_referenced().values().cloned().collect(), + CheckingMethod::Size => finder.get_files_with_identical_size_referenced().values().cloned().collect(), + CheckingMethod::SizeName => finder.get_files_with_identical_size_names_referenced().values().cloned().collect(), + _ => unreachable!("Invalid check method."), + }; + vector = values.into_iter().map(|(original, other)| (Some(original), other)).collect::>(); + } + _ => unreachable!("Invalid check method."), + } + } else { + match finder.get_check_method() { + CheckingMethod::Hash => { + vector = finder.get_files_sorted_by_hash().values().cloned().flatten().map(|items| (None, items)).collect::>(); + } + CheckingMethod::Name | CheckingMethod::Size | CheckingMethod::SizeName => { + let values: Vec<_> = match finder.get_check_method() { + CheckingMethod::Name => finder.get_files_sorted_by_names().values().cloned().collect(), + CheckingMethod::Size => finder.get_files_sorted_by_size().values().cloned().collect(), + CheckingMethod::SizeName => finder.get_files_sorted_by_size_name().values().cloned().collect(), + _ => unreachable!("Invalid check method."), + }; + vector = values.into_iter().map(|items| (None, items)).collect::>(); + } + _ => unreachable!("Invalid check method."), + } + } + + for (_first, vec) in &mut vector { + vec.par_sort_unstable_by(|a, b| split_path_compare(a.path.as_path(), b.path.as_path())); + } + + a.upgrade_in_event_loop(move |app| { + write_duplicate_results(&app, vector, messages); + }) + }) + .unwrap(); +} +fn write_duplicate_results(app: &MainWindow, vector: Vec<(Option, Vec)>, messages: String) { + let items_found = vector.len(); + let items = Rc::new(VecModel::default()); + for (ref_fe, vec_fe) in vector { + if let Some(ref_fe) = ref_fe { + let (data_model_str, data_model_int) = prepare_data_model_duplicates(&ref_fe); + insert_data_to_model(&items, data_model_str, data_model_int, true); + } else { + insert_data_to_model(&items, ModelRc::new(VecModel::default()), ModelRc::new(VecModel::default()), true); + } + + for fe in vec_fe { + let (data_model_str, data_model_int) = prepare_data_model_duplicates(&fe); + insert_data_to_model(&items, data_model_str, data_model_int, false); + } + } + app.set_similar_images_model(items.into()); + app.invoke_scan_ended(format!("Found {items_found} similar duplicates files").into()); + app.global::().set_info_text(messages.into()); +} +fn prepare_data_model_duplicates(fe: &DuplicateEntry) -> (ModelRc, ModelRc) { + let (directory, file) = split_path(fe.get_path()); + let data_model_str = VecModel::from_slice(&[ + format_size(fe.size, BINARY).into(), + file.into(), + directory.into(), + NaiveDateTime::from_timestamp_opt(fe.get_modified_date() as i64, 0).unwrap().to_string().into(), + ]); + let modification_split = split_u64_into_i32s(fe.get_modified_date()); + let size_split = split_u64_into_i32s(fe.size); + let data_model_int = VecModel::from_slice(&[modification_split.0, modification_split.1, size_split.0, size_split.1]); + (data_model_str, data_model_int) +} ////////////////////////////////////////// Empty Folders fn scan_empty_folders(a: Weak, progress_sender: Sender, stop_receiver: Receiver<()>, custom_settings: SettingsCustom) { @@ -195,7 +225,7 @@ fn scan_big_files(a: Weak, progress_sender: Sender, st vector.par_sort_unstable_by(|a, b| split_path_compare(a.path.as_path(), b.path.as_path())); a.upgrade_in_event_loop(move |app| { - crate::connect_scan::write_big_files_results(&app, vector, messages); + write_big_files_results(&app, vector, messages); }) }) .unwrap(); @@ -204,11 +234,11 @@ fn write_big_files_results(app: &MainWindow, vector: Vec, messages: S let items_found = vector.len(); let items = Rc::new(VecModel::default()); for fe in vector { - let (data_model_str, data_model_int) = crate::connect_scan::prepare_data_model_big_files(&fe); + let (data_model_str, data_model_int) = prepare_data_model_big_files(&fe); insert_data_to_model(&items, data_model_str, data_model_int, false); } app.set_empty_folder_model(items.into()); - app.invoke_scan_ended(format!("Found {items_found} empty folders").into()); + app.invoke_scan_ended(format!("Found {items_found} files").into()); app.global::().set_info_text(messages.into()); } diff --git a/krokiet/src/connect_show_preview.rs b/krokiet/src/connect_show_preview.rs index 9220c86..de8636f 100644 --- a/krokiet/src/connect_show_preview.rs +++ b/krokiet/src/connect_show_preview.rs @@ -2,12 +2,11 @@ use std::panic; use std::path::Path; use std::time::{Duration, Instant}; -use czkawka_core::broken_files::BrokenEntry; use image::DynamicImage; use log::{debug, error}; use slint::ComponentHandle; -use czkawka_core::common::{create_crash_message, get_dynamic_image_from_raw_image, IMAGE_RS_EXTENSIONS, RAW_IMAGE_EXTENSIONS}; +use czkawka_core::common::{get_dynamic_image_from_raw_image, IMAGE_RS_EXTENSIONS, RAW_IMAGE_EXTENSIONS}; use crate::{Callabler, CurrentTab, GuiState, MainWindow, Settings}; @@ -72,7 +71,7 @@ fn convert_into_slint_image(img: DynamicImage) -> slint::Image { slint::Image::from_rgba8(buffer) } -fn load_image(image_path: &Path) -> Option<(Duration, image::DynamicImage)> { +fn load_image(image_path: &Path) -> Option<(Duration, DynamicImage)> { if !image_path.is_file() { return None; } diff --git a/krokiet/ui/left_side_panel.slint b/krokiet/ui/left_side_panel.slint index 6ab414e..f6408d2 100644 --- a/krokiet/ui/left_side_panel.slint +++ b/krokiet/ui/left_side_panel.slint @@ -116,20 +116,6 @@ export component LeftSidePanel { Rectangle { HorizontalLayout { alignment: start; - Button { - visible: GuiState.available_subsettings; - min-width: 20px; - min-height: 20px; - max-height: self.width; - preferred-height: self.width; - icon: @image-url("../icons/settings.svg"); - clicked => { - GuiState.visible_tool_settings = !GuiState.visible-tool-settings; - } - } - } - HorizontalLayout { - alignment: end; Button { visible: GuiState.active_tab != CurrentTab.Settings; min-width: 20px; @@ -144,6 +130,20 @@ export component LeftSidePanel { } } } + HorizontalLayout { + alignment: end; + Button { + visible: GuiState.available_subsettings; + min-width: 20px; + min-height: 20px; + max-height: self.width; + preferred-height: self.width; + icon: @image-url("../icons/subsettings.svg"); + clicked => { + GuiState.visible_tool_settings = !GuiState.visible-tool-settings; + } + } + } } } }