1
0
Fork 0
mirror of synced 2024-05-03 03:52:58 +12:00
This commit is contained in:
Rafał Mikrut 2024-02-17 12:16:31 +01:00
parent 747a784977
commit cd1c6e953d
5 changed files with 138 additions and 57 deletions

View file

@ -4,8 +4,8 @@ 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 czkawka_core::big_file::{BigFile, SearchMode};
use czkawka_core::broken_files::{BrokenEntry, BrokenFiles, CheckedTypes};
use humansize::{format_size, BINARY};
use rayon::prelude::*;
use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak};
@ -18,14 +18,18 @@ 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::same_music::{MusicEntry, MusicSimilarity, SameMusic};
use czkawka_core::similar_images;
use czkawka_core::similar_images::{ImagesEntry, SimilarImages};
use czkawka_core::similar_videos::{SimilarVideos, VideosEntry};
use czkawka_core::temporary::{Temporary, TemporaryFileEntry};
use crate::common::split_u64_into_i32s;
use crate::settings::{collect_settings, SettingsCustom, ALLOWED_HASH_TYPE_VALUES, ALLOWED_RESIZE_ALGORITHM_VALUES};
use crate::settings::{
collect_settings, get_audio_check_type_idx, get_biggest_item_idx, get_duplicates_check_method_idx, get_duplicates_hash_type_idx, get_image_hash_alg_idx,
get_resize_algorithm_idx, SettingsCustom, ALLOWED_AUDIO_CHECK_TYPE_VALUES, ALLOWED_BIG_FILE_SIZE_VALUES, ALLOWED_DUPLICATES_CHECK_METHOD_VALUES,
ALLOWED_DUPLICATES_HASH_TYPE_VALUES, ALLOWED_IMAGE_HASH_ALG_VALUES, ALLOWED_RESIZE_ALGORITHM_VALUES,
};
use crate::{CurrentTab, GuiState, MainListModel, MainWindow, ProgressToSend};
pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender<ProgressData>, stop_receiver: Receiver<()>) {
@ -91,16 +95,17 @@ fn scan_duplicates(a: Weak<MainWindow>, progress_sender: Sender<ProgressData>, s
.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.set_minimal_cache_file_size(custom_settings.duplicate_minimal_hash_cache_size as u64);
finder.set_minimal_prehash_cache_file_size(custom_settings.duplicate_minimal_prehash_cache_size as u64);
let check_method = ALLOWED_DUPLICATES_CHECK_METHOD_VALUES[get_duplicates_check_method_idx(&custom_settings.duplicates_sub_check_method).unwrap()].2;
finder.set_check_method(check_method);
let hash_type = ALLOWED_DUPLICATES_HASH_TYPE_VALUES[get_duplicates_hash_type_idx(&custom_settings.duplicates_sub_available_hash_type).unwrap()].2;
finder.set_hash_type(hash_type);
// finder.set_ignore_hard_links(custom_settings.ignore); // TODO
finder.set_use_prehash_cache(custom_settings.duplicate_use_prehash);
finder.set_delete_outdated_cache(custom_settings.duplicate_delete_outdated_entries);
// finder.set_case_sensitive_name_comparison(custom_settings.); // TODO
finder.find_duplicates(Some(&stop_receiver), Some(&progress_sender));
let messages = finder.get_text_messages().create_messages_text();
@ -240,15 +245,15 @@ fn scan_big_files(a: Weak<MainWindow>, progress_sender: Sender<ProgressData>, st
.spawn(move || {
let mut finder = BigFile::new();
set_common_settings(&mut finder, &custom_settings);
// finder.set_number_of_files_to_check(numbers_of_files_to_check);
// finder.set_search_mode(sett);
finder.set_number_of_files_to_check(custom_settings.biggest_files_sub_number_of_files as usize);
let big_files_mode = ALLOWED_BIG_FILE_SIZE_VALUES[get_biggest_item_idx(&custom_settings.biggest_files_sub_method).unwrap()].2;
finder.set_search_mode(big_files_mode);
finder.find_big_files(Some(&stop_receiver), Some(&progress_sender));
let mut vector = finder.get_big_files().clone();
let messages = finder.get_text_messages().create_messages_text();
// TODO - if biggest files
if true {
if big_files_mode == SearchMode::BiggestFiles {
vector.par_sort_unstable_by_key(|fe| u64::MAX - fe.size);
} else {
vector.par_sort_unstable_by_key(|fe| fe.size);
@ -338,22 +343,16 @@ fn scan_similar_images(a: Weak<MainWindow>, progress_sender: Sender<ProgressData
.spawn(move || {
let mut finder = SimilarImages::new();
set_common_settings(&mut finder, &custom_settings);
finder.set_hash_size(custom_settings.similar_images_sub_hash_size);
let resize_algorithm = ALLOWED_RESIZE_ALGORITHM_VALUES
.iter()
.find(|(setting_name, _gui_name, _resize_alg)| setting_name == &custom_settings.similar_images_sub_resize_algorithm)
.expect("Resize algorithm not found")
.2;
finder.set_image_filter(resize_algorithm);
let hash_type = ALLOWED_HASH_TYPE_VALUES
.iter()
.find(|(setting_name, _gui_name, _resize_alg)| setting_name == &custom_settings.similar_images_sub_hash_type)
.expect("Hash type not found")
.2;
finder.set_hash_alg(hash_type);
finder.set_exclude_images_with_same_size(custom_settings.similar_images_sub_ignore_same_size);
finder.set_similarity(custom_settings.similar_images_sub_similarity as u32);
let hash_alg = ALLOWED_IMAGE_HASH_ALG_VALUES[get_image_hash_alg_idx(&custom_settings.similar_images_sub_hash_alg).unwrap()].2;
finder.set_hash_alg(hash_alg);
finder.set_hash_size(custom_settings.similar_images_sub_hash_size);
let resize_algorithm = ALLOWED_RESIZE_ALGORITHM_VALUES[get_resize_algorithm_idx(&custom_settings.similar_images_sub_resize_algorithm).unwrap()].2;
finder.set_image_filter(resize_algorithm);
finder.set_delete_outdated_cache(custom_settings.similar_images_delete_outdated_entries);
finder.set_exclude_images_with_same_size(custom_settings.similar_images_sub_ignore_same_size);
finder.find_similar_images(Some(&stop_receiver), Some(&progress_sender));
let messages = finder.get_text_messages().create_messages_text();
@ -425,7 +424,10 @@ fn scan_similar_videos(a: Weak<MainWindow>, progress_sender: Sender<ProgressData
let mut finder = SimilarVideos::new();
set_common_settings(&mut finder, &custom_settings);
// TODO set rest of settings
finder.set_tolerance(custom_settings.similar_videos_sub_similarity);
finder.set_delete_outdated_cache(custom_settings.similar_videos_delete_outdated_entries);
finder.set_exclude_videos_with_same_size(custom_settings.similar_videos_sub_ignore_same_size);
finder.find_similar_videos(Some(&stop_receiver), Some(&progress_sender));
let messages = finder.get_text_messages().create_messages_text();
@ -492,7 +494,41 @@ fn scan_similar_music(a: Weak<MainWindow>, progress_sender: Sender<ProgressData>
let mut finder = SameMusic::new();
set_common_settings(&mut finder, &custom_settings);
// TODO set rest of settings
let mut music_similarity: MusicSimilarity = MusicSimilarity::NONE;
if custom_settings.similar_music_sub_title {
music_similarity |= MusicSimilarity::TRACK_TITLE;
}
if custom_settings.similar_music_sub_artist {
music_similarity |= MusicSimilarity::TRACK_ARTIST;
}
if custom_settings.similar_music_sub_bitrate {
music_similarity |= MusicSimilarity::BITRATE;
}
if custom_settings.similar_music_sub_length {
music_similarity |= MusicSimilarity::LENGTH;
}
if custom_settings.similar_music_sub_year {
music_similarity |= MusicSimilarity::YEAR;
}
if custom_settings.similar_music_sub_genre {
music_similarity |= MusicSimilarity::GENRE;
}
if music_similarity == MusicSimilarity::NONE {
a.upgrade_in_event_loop(move |app| {
app.set_text_summary_text("Cannot find similar music files without any similarity method selected.".into());
})
.unwrap();
return Ok(());
}
finder.set_music_similarity(music_similarity);
// finder.set_maximum_difference(custom_settings.mus); // TODO
// finder.set_minimum_segment_duration(minimum_segment_duration); // TODO
let audio_check_type = ALLOWED_AUDIO_CHECK_TYPE_VALUES[get_audio_check_type_idx(&custom_settings.similar_music_sub_audio_check_type).unwrap()].2;
finder.set_check_type(audio_check_type);
finder.set_approximate_comparison(custom_settings.similar_music_sub_approximate_comparison);
finder.find_same_music(Some(&stop_receiver), Some(&progress_sender));
let messages = finder.get_text_messages().create_messages_text();
@ -564,7 +600,7 @@ fn scan_invalid_symlinks(a: Weak<MainWindow>, progress_sender: Sender<ProgressDa
.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();
@ -609,6 +645,7 @@ fn scan_temporary_files(a: Weak<MainWindow>, progress_sender: Sender<ProgressDat
.spawn(move || {
let mut finder = Temporary::new();
set_common_settings(&mut finder, &custom_settings);
finder.find_temporary_files(Some(&stop_receiver), Some(&progress_sender));
let mut vector = finder.get_temporary_files().clone();
@ -652,6 +689,30 @@ fn scan_broken_files(a: Weak<MainWindow>, progress_sender: Sender<ProgressData>,
.spawn(move || {
let mut finder = BrokenFiles::new();
set_common_settings(&mut finder, &custom_settings);
let mut checked_types: CheckedTypes = CheckedTypes::NONE;
if custom_settings.broken_files_sub_audio {
checked_types |= CheckedTypes::AUDIO;
}
if custom_settings.broken_files_sub_pdf {
checked_types |= CheckedTypes::PDF;
}
if custom_settings.broken_files_sub_image {
checked_types |= CheckedTypes::IMAGE;
}
if custom_settings.broken_files_sub_archive {
checked_types |= CheckedTypes::ARCHIVE;
}
if checked_types == CheckedTypes::NONE {
a.upgrade_in_event_loop(move |app| {
app.set_text_summary_text("Cannot find broken files without any file type selected.".into());
})
.unwrap();
return Ok(());
}
finder.set_checked_types(checked_types);
finder.find_broken_files(Some(&stop_receiver), Some(&progress_sender));
let mut vector = finder.get_broken_files().clone();

View file

@ -1,12 +1,17 @@
use czkawka_core::big_file::SearchMode;
use image::imageops::FilterType;
use image_hasher::HashAlg;
use slint::{ComponentHandle, SharedString, VecModel};
use czkawka_core::common::get_all_available_threads;
use crate::settings::{ALLOWED_HASH_SIZE_VALUES, ALLOWED_HASH_TYPE_VALUES, ALLOWED_RESIZE_ALGORITHM_VALUES};
use crate::settings::{
ALLOWED_BIG_FILE_SIZE_VALUES, ALLOWED_DUPLICATES_CHECK_METHOD_VALUES, ALLOWED_DUPLICATES_HASH_TYPE_VALUES, ALLOWED_HASH_SIZE_VALUES, ALLOWED_IMAGE_HASH_ALG_VALUES,
ALLOWED_RESIZE_ALGORITHM_VALUES,
};
use crate::{GuiState, MainWindow, Settings};
// Some info needs to be send to gui at the start like available thread number in OS.
//
pub fn set_initial_gui_infos(app: &MainWindow) {
let threads = get_all_available_threads();
let settings = app.global::<Settings>();
@ -20,7 +25,19 @@ pub fn set_initial_gui_infos(app: &MainWindow) {
.iter()
.map(|(_settings_key, gui_name, _filter_type)| (*gui_name).into())
.collect::<Vec<_>>();
let available_hash_type: Vec<SharedString> = ALLOWED_HASH_TYPE_VALUES
let available_hash_type: Vec<SharedString> = ALLOWED_IMAGE_HASH_ALG_VALUES
.iter()
.map(|(_settings_key, gui_name, _hash_type)| (*gui_name).into())
.collect::<Vec<_>>();
let available_big_file_search_mode: Vec<SharedString> = ALLOWED_BIG_FILE_SIZE_VALUES
.iter()
.map(|(_settings_key, gui_name, _search_mode)| (*gui_name).into())
.collect::<Vec<_>>();
let available_duplicates_check_method: Vec<SharedString> = ALLOWED_DUPLICATES_CHECK_METHOD_VALUES
.iter()
.map(|(_settings_key, gui_name, _checking_method)| (*gui_name).into())
.collect::<Vec<_>>();
let available_duplicates_hash_type: Vec<SharedString> = ALLOWED_DUPLICATES_HASH_TYPE_VALUES
.iter()
.map(|(_settings_key, gui_name, _hash_type)| (*gui_name).into())
.collect::<Vec<_>>();
@ -28,4 +45,7 @@ pub fn set_initial_gui_infos(app: &MainWindow) {
settings.set_similar_images_sub_available_hash_size(VecModel::from_slice(&available_hash_size));
settings.set_similar_images_sub_available_resize_algorithm(VecModel::from_slice(&available_resize_algorithm));
settings.set_similar_images_sub_available_hash_type(VecModel::from_slice(&available_hash_type));
settings.set_biggest_files_sub_method(VecModel::from_slice(&available_big_file_search_mode));
settings.set_duplicates_sub_check_method(VecModel::from_slice(&available_duplicates_check_method));
settings.set_duplicates_sub_available_hash_type(VecModel::from_slice(&available_duplicates_hash_type));
}

View file

@ -39,7 +39,7 @@ pub const ALLOWED_RESIZE_ALGORITHM_VALUES: &[(&str, &str, FilterType)] = &[
("nearest", "Nearest", FilterType::Nearest),
];
pub const ALLOWED_HASH_TYPE_VALUES: &[(&str, &str, HashAlg)] = &[
pub const ALLOWED_IMAGE_HASH_ALG_VALUES: &[(&str, &str, HashAlg)] = &[
("mean", "Mean", HashAlg::Mean),
("gradient", "Gradient", HashAlg::Gradient),
("blockhash", "BlockHash", HashAlg::Blockhash),
@ -118,7 +118,7 @@ pub struct SettingsCustom {
#[serde(default = "default_sub_hash_size")]
pub similar_images_sub_hash_size: u8,
#[serde(default = "default_hash_type")]
pub similar_images_sub_hash_type: String,
pub similar_images_sub_hash_alg: String,
#[serde(default = "default_resize_algorithm")]
pub similar_images_sub_resize_algorithm: String,
#[serde(default)]
@ -450,14 +450,14 @@ pub fn set_settings_to_gui(app: &MainWindow, custom_settings: &SettingsCustom) {
settings.set_similar_images_sub_hash_size_value(ALLOWED_HASH_SIZE_VALUES[similar_images_sub_hash_size_idx].1.to_string().into());
// TODO all items with _value are not necessary, but due bug in slint are required, because combobox is not updated properly
let similar_images_sub_hash_type_idx = get_hash_type_idx(&custom_settings.similar_images_sub_hash_type).unwrap_or_else(|| {
let similar_images_sub_hash_alg_idx = get_image_hash_alg_idx(&custom_settings.similar_images_sub_hash_alg).unwrap_or_else(|| {
warn!(
"Value of hash type \"{}\" is invalid, setting it to default value",
custom_settings.similar_images_sub_hash_type
custom_settings.similar_images_sub_hash_alg
);
0
});
settings.set_similar_images_sub_hash_type_index(similar_images_sub_hash_type_idx as i32);
settings.set_similar_images_sub_hash_alg_index(similar_images_sub_hash_alg_idx as i32);
let similar_images_sub_resize_algorithm_idx = get_resize_algorithm_idx(&custom_settings.similar_images_sub_resize_algorithm).unwrap_or_else(|| {
warn!(
@ -581,8 +581,8 @@ pub fn collect_settings(app: &MainWindow) -> SettingsCustom {
let similar_images_sub_hash_size_idx = settings.get_similar_images_sub_hash_size_index();
let similar_images_sub_hash_size = ALLOWED_HASH_SIZE_VALUES[similar_images_sub_hash_size_idx as usize].0;
let similar_images_sub_hash_type_idx = settings.get_similar_images_sub_hash_type_index();
let similar_images_sub_hash_type = ALLOWED_HASH_TYPE_VALUES[similar_images_sub_hash_type_idx as usize].0.to_string();
let similar_images_sub_hash_alg_idx = settings.get_similar_images_sub_hash_alg_index();
let similar_images_sub_hash_alg = ALLOWED_IMAGE_HASH_ALG_VALUES[similar_images_sub_hash_alg_idx as usize].0.to_string();
let similar_images_sub_resize_algorithm_idx = settings.get_similar_images_sub_resize_algorithm_index();
let similar_images_sub_resize_algorithm = ALLOWED_RESIZE_ALGORITHM_VALUES[similar_images_sub_resize_algorithm_idx as usize].0.to_string();
let similar_images_sub_ignore_same_size = settings.get_similar_images_sub_ignore_same_size();
@ -641,7 +641,7 @@ pub fn collect_settings(app: &MainWindow) -> SettingsCustom {
similar_videos_delete_outdated_entries,
similar_music_delete_outdated_entries,
similar_images_sub_hash_size,
similar_images_sub_hash_type,
similar_images_sub_hash_alg,
similar_images_sub_resize_algorithm,
similar_images_sub_ignore_same_size,
similar_images_sub_similarity,
@ -755,7 +755,7 @@ pub fn default_resize_algorithm() -> String {
ALLOWED_RESIZE_ALGORITHM_VALUES[0].0.to_string()
}
pub fn default_hash_type() -> String {
ALLOWED_HASH_TYPE_VALUES[0].0.to_string()
ALLOWED_IMAGE_HASH_ALG_VALUES[0].0.to_string()
}
pub fn default_sub_hash_size() -> u8 {
DEFAULT_HASH_SIZE
@ -765,33 +765,33 @@ fn get_allowed_hash_size_idx(h_size: u8) -> Option<usize> {
ALLOWED_HASH_SIZE_VALUES.iter().position(|(hash_size, _max_similarity)| *hash_size == h_size)
}
fn get_hash_type_idx(string_hash_type: &str) -> Option<usize> {
ALLOWED_HASH_TYPE_VALUES
pub fn get_image_hash_alg_idx(string_hash_type: &str) -> Option<usize> {
ALLOWED_IMAGE_HASH_ALG_VALUES
.iter()
.position(|(settings_key, gui_name, _hash_type)| *settings_key == string_hash_type || *gui_name == string_hash_type)
}
fn get_resize_algorithm_idx(string_resize_algorithm: &str) -> Option<usize> {
pub fn get_resize_algorithm_idx(string_resize_algorithm: &str) -> Option<usize> {
ALLOWED_RESIZE_ALGORITHM_VALUES
.iter()
.position(|(settings_key, gui_name, _resize_alg)| *settings_key == string_resize_algorithm || *gui_name == string_resize_algorithm)
}
fn get_biggest_item_idx(string_biggest_item: &str) -> Option<usize> {
pub fn get_biggest_item_idx(string_biggest_item: &str) -> Option<usize> {
ALLOWED_BIG_FILE_SIZE_VALUES
.iter()
.position(|(settings_key, gui_name, _search_mode)| *settings_key == string_biggest_item || *gui_name == string_biggest_item)
}
fn get_duplicates_check_method_idx(string_duplicates_check_method: &str) -> Option<usize> {
pub fn get_duplicates_check_method_idx(string_duplicates_check_method: &str) -> Option<usize> {
ALLOWED_DUPLICATES_CHECK_METHOD_VALUES
.iter()
.position(|(settings_key, gui_name, _check_method)| *settings_key == string_duplicates_check_method || *gui_name == string_duplicates_check_method)
}
fn get_duplicates_hash_type_idx(string_duplicates_hash_type: &str) -> Option<usize> {
pub fn get_duplicates_hash_type_idx(string_duplicates_hash_type: &str) -> Option<usize> {
ALLOWED_DUPLICATES_HASH_TYPE_VALUES
.iter()
.position(|(settings_key, gui_name, _hash_type)| *settings_key == string_duplicates_hash_type || *gui_name == string_duplicates_hash_type)
}
fn get_audio_check_type_idx(string_audio_check_type: &str) -> Option<usize> {
pub fn get_audio_check_type_idx(string_audio_check_type: &str) -> Option<usize> {
ALLOWED_AUDIO_CHECK_TYPE_VALUES
.iter()
.position(|(settings_key, gui_name, _audio_check_type)| *settings_key == string_audio_check_type || *gui_name == string_audio_check_type)

View file

@ -48,8 +48,8 @@ export global Settings {
in-out property <int> similar_images_sub_resize_algorithm_index: 0;
in-out property <string> similar_images_sub_resize_algorithm_value: "Lanczos3";
in-out property <[string]> similar_images_sub_available_hash_type: ["Gradient", "Mean", "VertGradient", "BlockHash", "DoubleGradient"];
in-out property <int> similar_images_sub_hash_type_index: 0;
in-out property <string> similar_images_sub_hash_type_value: "Gradient";
in-out property <int> similar_images_sub_hash_alg_index: 0;
in-out property <string> similar_images_sub_hash_alg_value: "Gradient";
in-out property <float> similar_images_sub_max_similarity: 40;
in-out property <float> similar_images_sub_current_similarity: 20;
in-out property <bool> similar_images_sub_ignore_same_size;

View file

@ -85,8 +85,8 @@ export component ToolSettings {
ComboBoxWrapper {
text: "Hash type";
model: Settings.similar_images_sub_available_hash_type;
current_index <=> Settings.similar_images_sub_hash_type_index;
current_value <=> Settings.similar_images_sub_hash_type_value;
current_index <=> Settings.similar_images_sub_hash_alg_index;
current_value <=> Settings.similar_images_sub_hash_alg_value;
}
CheckBoxWrapper {
text: "Ignore same size";