diff --git a/czkawka_core/src/big_file.rs b/czkawka_core/src/big_file.rs index b4a8412..a4b61dc 100644 --- a/czkawka_core/src/big_file.rs +++ b/czkawka_core/src/big_file.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; -use std::fs::{File, Metadata}; +use std::fs::{DirEntry, File, Metadata}; use std::io::{BufWriter, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::atomic::Ordering; use std::sync::atomic::{AtomicBool, AtomicU64}; use std::sync::Arc; @@ -232,82 +232,9 @@ impl BigFile { } }; if metadata.is_dir() { - if !self.recursive_search { - continue 'dir; - } - - let next_folder = current_folder.join(entry_data.file_name()); - if self.directories.is_excluded(&next_folder) { - continue 'dir; - } - - if self.excluded_items.is_excluded(&next_folder) { - continue 'dir; - } - - #[cfg(target_family = "unix")] - if self.directories.exclude_other_filesystems() { - match self.directories.is_on_other_filesystems(&next_folder) { - Ok(true) => continue 'dir, - Err(e) => warnings.push(e.to_string()), - _ => (), - } - } - - dir_result.push(next_folder); + self.check_folder_children(&mut dir_result, &mut warnings, current_folder, &entry_data); } else if metadata.is_file() { - atomic_file_counter.fetch_add(1, Ordering::Relaxed); - - if metadata.len() == 0 { - continue 'dir; - } - - let file_name_lowercase: String = match entry_data.file_name().into_string() { - Ok(t) => t, - Err(_inspected) => { - warnings.push(flc!( - "core_file_not_utf8_name", - generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())]) - )); - continue 'dir; - } - } - .to_lowercase(); - - if !self.allowed_extensions.matches_filename(&file_name_lowercase) { - continue 'dir; - } - - let current_file_name = current_folder.join(entry_data.file_name()); - if self.excluded_items.is_excluded(¤t_file_name) { - continue 'dir; - } - - let fe: FileEntry = FileEntry { - path: current_file_name.clone(), - size: metadata.len(), - modified_date: match metadata.modified() { - Ok(t) => match t.duration_since(UNIX_EPOCH) { - Ok(d) => d.as_secs(), - Err(_inspected) => { - warnings.push(flc!( - "core_file_modified_before_epoch", - generate_translation_hashmap(vec![("name", current_file_name.display().to_string())]) - )); - 0 - } - }, - Err(e) => { - warnings.push(flc!( - "core_file_no_modification_date", - generate_translation_hashmap(vec![("name", current_file_name.display().to_string()), ("reason", e.to_string())]) - )); - 0 - } - }, - }; - - fe_result.push((fe.size, fe)); + self.collect_file_entry(&atomic_file_counter, &metadata, &entry_data, &mut fe_result, &mut warnings, current_folder); } } (dir_result, warnings, fe_result) @@ -331,8 +258,102 @@ impl BigFile { progress_thread_run.store(false, Ordering::Relaxed); progress_thread_handle.join().unwrap(); - // Extract n biggest files to new TreeMap + self.extract_n_biggest_files(old_map); + Common::print_time(start_time, SystemTime::now(), "look_for_big_files"); + true + } + + pub fn check_folder_children(&self, dir_result: &mut Vec, warnings: &mut Vec, current_folder: &Path, entry_data: &DirEntry) { + if !self.recursive_search { + return; + } + + let next_folder = current_folder.join(entry_data.file_name()); + if self.directories.is_excluded(&next_folder) { + return; + } + + if self.excluded_items.is_excluded(&next_folder) { + return; + } + + #[cfg(target_family = "unix")] + if self.directories.exclude_other_filesystems() { + match self.directories.is_on_other_filesystems(&next_folder) { + Ok(true) => return, + Err(e) => warnings.push(e), + _ => (), + } + } + + dir_result.push(next_folder); + } + + pub fn collect_file_entry( + &self, + atomic_file_counter: &Arc, + metadata: &Metadata, + entry_data: &DirEntry, + fe_result: &mut Vec<(u64, FileEntry)>, + warnings: &mut Vec, + current_folder: &Path, + ) { + atomic_file_counter.fetch_add(1, Ordering::Relaxed); + + if metadata.len() == 0 { + return; + } + + let file_name_lowercase: String = match entry_data.file_name().into_string() { + Ok(t) => t, + Err(_inspected) => { + warnings.push(flc!( + "core_file_not_utf8_name", + generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())]) + )); + return; + } + } + .to_lowercase(); + + if !self.allowed_extensions.matches_filename(&file_name_lowercase) { + return; + } + + let current_file_name = current_folder.join(entry_data.file_name()); + if self.excluded_items.is_excluded(¤t_file_name) { + return; + } + + let fe: FileEntry = FileEntry { + path: current_file_name.clone(), + size: metadata.len(), + modified_date: match metadata.modified() { + Ok(t) => match t.duration_since(UNIX_EPOCH) { + Ok(d) => d.as_secs(), + Err(_inspected) => { + warnings.push(flc!( + "core_file_modified_before_epoch", + generate_translation_hashmap(vec![("name", current_file_name.display().to_string())]) + )); + 0 + } + }, + Err(e) => { + warnings.push(flc!( + "core_file_no_modification_date", + generate_translation_hashmap(vec![("name", current_file_name.display().to_string()), ("reason", e.to_string())]) + )); + 0 + } + }, + }; + + fe_result.push((fe.size, fe)); + } + + pub fn extract_n_biggest_files(&mut self, old_map: BTreeMap>) { let iter: Box>; if self.search_mode == SearchMode::SmallestFiles { iter = Box::new(old_map.into_iter()); @@ -360,9 +381,6 @@ impl BigFile { break; } } - - Common::print_time(start_time, SystemTime::now(), "look_for_big_files"); - true } pub fn set_number_of_files_to_check(&mut self, number_of_files_to_check: usize) { diff --git a/czkawka_core/src/same_music.rs b/czkawka_core/src/same_music.rs index 83ccf5d..f7ad8f2 100644 --- a/czkawka_core/src/same_music.rs +++ b/czkawka_core/src/same_music.rs @@ -30,6 +30,12 @@ pub enum DeleteMethod { Delete, } +#[derive(Eq, PartialEq, Clone, Debug, Copy)] +pub enum AudioCheckMethod { + Tags, + Content, +} + bitflags! { #[derive(PartialEq, Copy, Clone, Debug)] pub struct MusicSimilarity : u32 { @@ -112,6 +118,7 @@ pub struct SameMusic { delete_outdated_cache: bool, // TODO add this to GUI use_reference_folders: bool, save_also_as_json: bool, + check_type: AudioCheckMethod, } impl SameMusic { @@ -138,6 +145,7 @@ impl SameMusic { use_reference_folders: false, duplicated_music_entries_referenced: vec![], save_also_as_json: false, + check_type: AudioCheckMethod::Content, } } @@ -148,13 +156,20 @@ impl SameMusic { self.stopped_search = true; return; } - if !self.check_records_multithreaded(stop_receiver, progress_sender) { - self.stopped_search = true; - return; - } - if !self.check_for_duplicates(stop_receiver, progress_sender) { - self.stopped_search = true; - return; + match self.check_type { + AudioCheckMethod::Tags => { + if !self.read_tags(stop_receiver, progress_sender) { + self.stopped_search = true; + return; + } + if !self.check_for_duplicate_tags(stop_receiver, progress_sender) { + self.stopped_search = true; + return; + } + } + AudioCheckMethod::Content => { + unimplemented!(); + } } self.delete_files(); self.debug_print(); @@ -308,7 +323,7 @@ impl SameMusic { } } - fn check_records_multithreaded(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender>) -> bool { + fn read_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender>) -> bool { let start_time: SystemTime = SystemTime::now(); let loaded_hash_map; @@ -504,11 +519,11 @@ impl SameMusic { return false; } - Common::print_time(start_time, SystemTime::now(), "check_records_multithreaded"); + Common::print_time(start_time, SystemTime::now(), "read_tags"); true } - fn check_for_duplicates(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender>) -> bool { + fn check_for_duplicate_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender>) -> bool { assert!(MusicSimilarity::NONE != self.music_similarity, "This can't be none"); let start_time: SystemTime = SystemTime::now(); @@ -748,7 +763,7 @@ impl SameMusic { } } - Common::print_time(start_time, SystemTime::now(), "check_for_duplicates"); + Common::print_time(start_time, SystemTime::now(), "check_for_duplicate_tags"); // Clear unused data self.music_entries.clear(); diff --git a/czkawka_gui/ui/czkawka.cmb b/czkawka_gui/ui/czkawka.cmb index c8bebf5..a162491 100755 --- a/czkawka_gui/ui/czkawka.cmb +++ b/czkawka_gui/ui/czkawka.cmb @@ -160,7 +160,7 @@ (5,122,"GtkCheckButton","check_button_music_genre",117,None,None,None,4), (5,123,"GtkCheckButton","check_button_music_length",117,None,None,None,5), (5,124,"GtkBox",None,116,None,None,None,1), - (5,125,"GtkCheckButton","check_button_music_approximate_comparison",124,None,None,None,None), + (5,125,"GtkCheckButton","check_button_music_approximate_comparison",124,None,None,None,2), (5,126,"GtkScrolledWindow","scrolled_window_same_music_finder",116,None,None,None,2), (5,127,"GtkLabel",None,115,None,None,None,None), (5,128,"GtkNotebookPage",None,56,None,None,None,8), @@ -235,6 +235,8 @@ (5,230,"GtkBox",None,229,None,None,None,None), (5,231,"GtkImage",None,230,None,None,None,None), (5,232,"GtkLabel","label_buttons_sort",230,None,None,None,1), + (5,234,"GtkLabel","label_audio_check_type",124,None,None,None,None), + (5,235,"GtkComboBoxText","combo_box_audio_check_type",124,None,None,None,1), (6,1,"GtkPopover","popover_right_click",None,None,None,None,None), (6,2,"GtkBox",None,1,None,None,None,None), (6,3,"GtkButton","buttons_popover_right_click_open_file",2,None,None,None,None), @@ -765,6 +767,8 @@ (5,230,"GtkWidget","halign","center",None,None,None,None,None), (5,231,"GtkImage","icon-name","image-missing",None,None,None,None,None), (5,232,"GtkLabel","label","SortMenu",None,None,None,None,None), + (5,234,"GtkLabel","label","Audio check type",None,None,None,None,None), + (5,234,"GtkWidget","margin-end","2",None,None,None,None,None), (6,1,"GtkPopover","child",None,None,None,None,None,2), (6,1,"GtkPopover","position","left",None,None,None,None,None), (6,2,"GtkOrientable","orientation","vertical",None,None,None,None,None), diff --git a/czkawka_gui/ui/main_window.ui b/czkawka_gui/ui/main_window.ui index 298f88a..3f9aec6 100644 --- a/czkawka_gui/ui/main_window.ui +++ b/czkawka_gui/ui/main_window.ui @@ -728,6 +728,15 @@ 2 5 5 + + + Audio check type + 2 + + + + + 1