From 2cc8b970352bd862ce6ca57671c66588fb3b6216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= Date: Thu, 15 Feb 2024 16:47:58 +0100 Subject: [PATCH] Models --- czkawka_core/src/bad_extensions.rs | 14 ++- czkawka_core/src/common_dir_traversal.rs | 10 ++ krokiet/src/common.rs | 1 + krokiet/src/connect_scan.rs | 154 ++++++++++++++++++++++- 4 files changed, 176 insertions(+), 3 deletions(-) diff --git a/czkawka_core/src/bad_extensions.rs b/czkawka_core/src/bad_extensions.rs index 38d1021..6d62146 100644 --- a/czkawka_core/src/bad_extensions.rs +++ b/czkawka_core/src/bad_extensions.rs @@ -1,7 +1,7 @@ use std::collections::{BTreeSet, HashMap}; use std::io::prelude::*; use std::mem; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; @@ -169,6 +169,18 @@ pub struct BadFileEntry { pub proper_extensions: String, } +impl ResultEntry for BadFileEntry { + fn get_path(&self) -> &Path { + &self.path + } + fn get_modified_date(&self) -> u64 { + self.modified_date + } + fn get_size(&self) -> u64 { + self.size + } +} + #[derive(Default)] pub struct Info { pub number_of_files_with_bad_extension: usize, diff --git a/czkawka_core/src/common_dir_traversal.rs b/czkawka_core/src/common_dir_traversal.rs index 44cd95c..1f02457 100644 --- a/czkawka_core/src/common_dir_traversal.rs +++ b/czkawka_core/src/common_dir_traversal.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::fmt::Display; use std::fs; use std::fs::{DirEntry, FileType, Metadata}; #[cfg(target_family = "unix")] @@ -87,6 +88,15 @@ pub enum ErrorType { NonExistentFile, } +impl Display for ErrorType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ErrorType::InfiniteRecursion => write!(f, "Infinite recursion"), + ErrorType::NonExistentFile => write!(f, "Non existent file"), + } + } +} + #[derive(Copy, Clone, Eq, PartialEq)] pub enum Collect { InvalidSymlinks, diff --git a/krokiet/src/common.rs b/krokiet/src/common.rs index acc0f59..fc6b609 100644 --- a/krokiet/src/common.rs +++ b/krokiet/src/common.rs @@ -178,6 +178,7 @@ pub enum StrDataBrokenFiles { Size, ModificationDate, } +// Bad Extensions #[repr(u8)] pub enum IntDataBadExtensions { ModificationDatePart1, diff --git a/krokiet/src/connect_scan.rs b/krokiet/src/connect_scan.rs index 2060a4b..86eafb8 100644 --- a/krokiet/src/connect_scan.rs +++ b/krokiet/src/connect_scan.rs @@ -3,7 +3,9 @@ use std::thread; use chrono::NaiveDateTime; use crossbeam_channel::{Receiver, Sender}; +use czkawka_core::bad_extensions::{BadExtensions, BadFileEntry}; use czkawka_core::big_file::BigFile; +use czkawka_core::broken_files::{BrokenEntry, BrokenFiles}; use humansize::{format_size, BINARY}; use rayon::prelude::*; use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak}; @@ -15,6 +17,7 @@ use czkawka_core::common_traits::ResultEntry; use czkawka_core::duplicate::{DuplicateEntry, DuplicateFinder}; use czkawka_core::empty_files::EmptyFiles; use czkawka_core::empty_folder::{EmptyFolder, FolderEntry}; +use czkawka_core::invalid_symlinks::{InvalidSymlinks, SymlinksFileEntry}; use czkawka_core::same_music::{MusicEntry, SameMusic}; use czkawka_core::similar_images; use czkawka_core::similar_images::{ImagesEntry, SimilarImages}; @@ -56,6 +59,21 @@ pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender { scan_similar_images(a, progress_sender, stop_receiver, custom_settings); } + CurrentTab::SimilarVideos => { + scan_similar_videos(a, progress_sender, stop_receiver, custom_settings); + } + CurrentTab::SimilarMusic => { + scan_similar_music(a, progress_sender, stop_receiver, custom_settings); + } + CurrentTab::InvalidSymlinks => { + scan_invalid_symlinks(a, progress_sender, stop_receiver, custom_settings); + } + CurrentTab::BadExtensions => { + scan_bad_extensions(a, progress_sender, stop_receiver, custom_settings); + } + CurrentTab::BrokenFiles => { + scan_broken_files(a, progress_sender, stop_receiver, custom_settings); + } CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"), _ => unimplemented!(), } @@ -465,7 +483,7 @@ fn scan_similar_music(a: Weak, progress_sender: Sender set_common_settings(&mut finder, &custom_settings); // TODO set rest of settings - finder.find_similar_music(Some(&stop_receiver), Some(&progress_sender)); + finder.find_same_music(Some(&stop_receiver), Some(&progress_sender)); let messages = finder.get_text_messages().create_messages_text(); @@ -478,7 +496,7 @@ fn scan_similar_music(a: Weak, progress_sender: Sender .map(|(original, others)| (Some(original), others)) .collect::>(); } else { - vector = finder.get_similar_music().iter().cloned().map(|items| (None, items)).collect::>(); + vector = finder.get_duplicated_music_entries().iter().cloned().map(|items| (None, items)).collect::>(); } for (_first_entry, vec_fe) in &mut vector { vec_fe.par_sort_unstable_by(|a, b| split_path_compare(a.path.as_path(), b.path.as_path())); @@ -529,6 +547,138 @@ fn prepare_data_model_similar_music(fe: &MusicEntry) -> (ModelRc, 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) } +// Invalid Symlinks +fn scan_invalid_symlinks(a: Weak, progress_sender: Sender, stop_receiver: Receiver<()>, custom_settings: SettingsCustom) { + thread::Builder::new() + .stack_size(DEFAULT_THREAD_SIZE) + .spawn(move || { + let mut finder = InvalidSymlinks::new(); + set_common_settings(&mut finder, &custom_settings); + // TOOD set rest of settings + finder.find_invalid_links(Some(&stop_receiver), Some(&progress_sender)); + + let mut vector = finder.get_invalid_symlinks().clone(); + let messages = finder.get_text_messages().create_messages_text(); + + 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| { + write_invalid_symlinks_results(&app, vector, messages); + }) + }) + .unwrap(); +} +fn write_invalid_symlinks_results(app: &MainWindow, vector: Vec, messages: String) { + 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_invalid_symlinks(&fe); + insert_data_to_model(&items, data_model_str, data_model_int, false); + } + app.set_invalid_symlinks_model(items.into()); + app.invoke_scan_ended(format!("Found {items_found} invalid symlinks").into()); + app.global::().set_info_text(messages.into()); +} + +fn prepare_data_model_invalid_symlinks(fe: &SymlinksFileEntry) -> (ModelRc, ModelRc) { + let (directory, file) = split_path(fe.get_path()); + let data_model_str = VecModel::from_slice(&[ + file.into(), + directory.into(), + fe.symlink_info.destination_path.to_string_lossy().to_string().into(), + fe.symlink_info.type_of_error.to_string().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 data_model_int = VecModel::from_slice(&[modification_split.0, modification_split.1]); + (data_model_str, data_model_int) +} +////////////////////////////////////////// Broken Files +fn scan_broken_files(a: Weak, progress_sender: Sender, stop_receiver: Receiver<()>, custom_settings: SettingsCustom) { + thread::Builder::new() + .stack_size(DEFAULT_THREAD_SIZE) + .spawn(move || { + let mut finder = BrokenFiles::new(); + set_common_settings(&mut finder, &custom_settings); + finder.find_broken_files(Some(&stop_receiver), Some(&progress_sender)); + + let mut vector = finder.get_broken_files().clone(); + let messages = finder.get_text_messages().create_messages_text(); + + 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_broken_files_results(&app, vector, messages); + }) + }) + .unwrap(); +} +fn write_broken_files_results(app: &MainWindow, vector: Vec, messages: String) { + 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_broken_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} files").into()); + app.global::().set_info_text(messages.into()); +} + +fn prepare_data_model_broken_files(fe: &BrokenEntry) -> (ModelRc, ModelRc) { + let (directory, file) = split_path(&fe.path); + let data_model_str = VecModel::from_slice(&[ + file.into(), + directory.into(), + fe.error_string.clone().into(), + format_size(fe.size, BINARY).into(), + NaiveDateTime::from_timestamp_opt(fe.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) +} +////////////////////////////////////////// Bad Extensions +fn scan_bad_extensions(a: Weak, progress_sender: Sender, stop_receiver: Receiver<()>, custom_settings: SettingsCustom) { + thread::Builder::new() + .stack_size(DEFAULT_THREAD_SIZE) + .spawn(move || { + let mut finder = BadExtensions::new(); + set_common_settings(&mut finder, &custom_settings); + finder.find_bad_extensions_files(Some(&stop_receiver), Some(&progress_sender)); + + let mut vector = finder.get_bad_extensions_files().clone(); + let messages = finder.get_text_messages().create_messages_text(); + + 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_bad_extensions_results(&app, vector, messages); + }) + }) + .unwrap(); +} +fn write_bad_extensions_results(app: &MainWindow, vector: Vec, messages: String) { + let items_found = vector.len(); + let items = Rc::new(VecModel::default()); + for fe in vector { + let (data_model_str, data_model_int) = prepare_data_model_bad_extensions(&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} files with bad extensions").into()); + app.global::().set_info_text(messages.into()); +} + +fn prepare_data_model_bad_extensions(fe: &BadFileEntry) -> (ModelRc, ModelRc) { + let (directory, file) = split_path(&fe.path); + let data_model_str = VecModel::from_slice(&[file.into(), directory.into(), fe.current_extension.clone().into(), fe.proper_extensions.clone().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) +} ////////////////////////////////////////// Common fn insert_data_to_model(items: &Rc>, data_model_str: ModelRc, data_model_int: ModelRc, header_row: bool) { let main = MainListModel {