Unify progress data (#972)
* Unify progress data code * Do not increment in threads values every time when finding file/folder(works quite good, may works bad with folders with ~several thousands of files) * Partial changes * Simplify creating tree_view * Allow setting thread number in CLI * Simplified code and add tests with help of copilot
This commit is contained in:
parent
78d00eeb99
commit
582e5417ac
|
@ -85,6 +85,8 @@ pub enum Commands {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct DuplicatesArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -163,6 +165,8 @@ pub struct DuplicatesArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct EmptyFoldersArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -180,6 +184,8 @@ pub struct EmptyFoldersArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct BiggestFilesArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -205,6 +211,8 @@ pub struct BiggestFilesArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct EmptyFilesArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -226,6 +234,8 @@ pub struct EmptyFilesArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct TemporaryArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -245,6 +255,8 @@ pub struct TemporaryArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct SimilarImagesArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -313,6 +325,8 @@ pub struct SimilarImagesArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct SameMusicArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -359,6 +373,8 @@ pub struct SameMusicArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct InvalidSymlinksArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -380,6 +396,8 @@ pub struct InvalidSymlinksArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct BrokenFilesArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -401,6 +419,8 @@ pub struct BrokenFilesArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct SimilarVideosArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -449,6 +469,8 @@ pub struct SimilarVideosArgs {
|
|||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct BadExtensionsArgs {
|
||||
#[clap(flatten)]
|
||||
pub thread_number: ThreadNumber,
|
||||
#[clap(flatten)]
|
||||
pub directories: Directories,
|
||||
#[clap(flatten)]
|
||||
|
@ -517,6 +539,12 @@ pub struct NotRecursive {
|
|||
pub not_recursive: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct ThreadNumber {
|
||||
#[clap(short = 'T', long, default_value = "0", help = "Limits thread number, 0(default) will use all available threads")]
|
||||
pub thread_number: usize,
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct ExcludeOtherFilesystems {
|
||||
|
|
|
@ -6,7 +6,7 @@ use clap::Parser;
|
|||
|
||||
use commands::Commands;
|
||||
use czkawka_core::big_file::SearchMode;
|
||||
use czkawka_core::common::{get_number_of_threads, set_default_number_of_threads};
|
||||
use czkawka_core::common::set_number_of_threads;
|
||||
#[allow(unused_imports)] // It is used in release for print_results().
|
||||
use czkawka_core::common_traits::*;
|
||||
use czkawka_core::similar_images::test_image_conversion_speed;
|
||||
|
@ -34,8 +34,6 @@ mod commands;
|
|||
fn main() {
|
||||
let command = Args::parse().command;
|
||||
|
||||
set_default_number_of_threads();
|
||||
println!("Set thread number to {}", get_number_of_threads());
|
||||
#[cfg(debug_assertions)]
|
||||
println!("{command:?}");
|
||||
|
||||
|
@ -59,6 +57,7 @@ fn main() {
|
|||
|
||||
fn duplicates(duplicates: DuplicatesArgs) {
|
||||
let DuplicatesArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -78,6 +77,8 @@ fn duplicates(duplicates: DuplicatesArgs) {
|
|||
case_sensitive_name_comparison,
|
||||
} = duplicates;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut df = DuplicateFinder::new();
|
||||
|
||||
df.set_included_directory(directories.directories);
|
||||
|
@ -113,6 +114,7 @@ fn duplicates(duplicates: DuplicatesArgs) {
|
|||
|
||||
fn empty_folders(empty_folders: EmptyFoldersArgs) {
|
||||
let EmptyFoldersArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
delete_folders,
|
||||
file_to_save,
|
||||
|
@ -122,6 +124,8 @@ fn empty_folders(empty_folders: EmptyFoldersArgs) {
|
|||
exclude_other_filesystems,
|
||||
} = empty_folders;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut ef = EmptyFolder::new();
|
||||
|
||||
ef.set_included_directory(directories.directories);
|
||||
|
@ -147,6 +151,7 @@ fn empty_folders(empty_folders: EmptyFoldersArgs) {
|
|||
|
||||
fn biggest_files(biggest_files: BiggestFilesArgs) {
|
||||
let BiggestFilesArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -160,6 +165,8 @@ fn biggest_files(biggest_files: BiggestFilesArgs) {
|
|||
smallest_mode,
|
||||
} = biggest_files;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut bf = BigFile::new();
|
||||
|
||||
bf.set_included_directory(directories.directories);
|
||||
|
@ -193,6 +200,7 @@ fn biggest_files(biggest_files: BiggestFilesArgs) {
|
|||
|
||||
fn empty_files(empty_files: EmptyFilesArgs) {
|
||||
let EmptyFilesArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -204,6 +212,8 @@ fn empty_files(empty_files: EmptyFilesArgs) {
|
|||
exclude_other_filesystems,
|
||||
} = empty_files;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut ef = EmptyFiles::new();
|
||||
|
||||
ef.set_included_directory(directories.directories);
|
||||
|
@ -234,6 +244,7 @@ fn empty_files(empty_files: EmptyFilesArgs) {
|
|||
|
||||
fn temporary(temporary: TemporaryArgs) {
|
||||
let TemporaryArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -244,6 +255,8 @@ fn temporary(temporary: TemporaryArgs) {
|
|||
not_recursive,
|
||||
} = temporary;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut tf = Temporary::new();
|
||||
|
||||
tf.set_included_directory(directories.directories);
|
||||
|
@ -273,6 +286,7 @@ fn temporary(temporary: TemporaryArgs) {
|
|||
|
||||
fn similar_images(similar_images: SimilarImagesArgs) {
|
||||
let SimilarImagesArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -288,6 +302,8 @@ fn similar_images(similar_images: SimilarImagesArgs) {
|
|||
hash_size,
|
||||
} = similar_images;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut sf = SimilarImages::new();
|
||||
|
||||
sf.set_included_directory(directories.directories);
|
||||
|
@ -320,6 +336,7 @@ fn similar_images(similar_images: SimilarImagesArgs) {
|
|||
|
||||
fn same_music(same_music: SameMusicArgs) {
|
||||
let SameMusicArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -333,6 +350,8 @@ fn same_music(same_music: SameMusicArgs) {
|
|||
music_similarity,
|
||||
} = same_music;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut mf = SameMusic::new();
|
||||
|
||||
mf.set_included_directory(directories.directories);
|
||||
|
@ -365,6 +384,7 @@ fn same_music(same_music: SameMusicArgs) {
|
|||
|
||||
fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs) {
|
||||
let InvalidSymlinksArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -376,6 +396,8 @@ fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs) {
|
|||
delete_files,
|
||||
} = invalid_symlinks;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut ifs = InvalidSymlinks::new();
|
||||
|
||||
ifs.set_included_directory(directories.directories);
|
||||
|
@ -405,6 +427,7 @@ fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs) {
|
|||
|
||||
fn broken_files(broken_files: BrokenFilesArgs) {
|
||||
let BrokenFilesArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -416,6 +439,8 @@ fn broken_files(broken_files: BrokenFilesArgs) {
|
|||
exclude_other_filesystems,
|
||||
} = broken_files;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut br = BrokenFiles::new();
|
||||
|
||||
br.set_included_directory(directories.directories);
|
||||
|
@ -446,6 +471,7 @@ fn broken_files(broken_files: BrokenFilesArgs) {
|
|||
|
||||
fn similar_videos(similar_videos: SimilarVideosArgs) {
|
||||
let SimilarVideosArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -459,6 +485,8 @@ fn similar_videos(similar_videos: SimilarVideosArgs) {
|
|||
allowed_extensions,
|
||||
} = similar_videos;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut vr = SimilarVideos::new();
|
||||
|
||||
vr.set_included_directory(directories.directories);
|
||||
|
@ -488,6 +516,7 @@ fn similar_videos(similar_videos: SimilarVideosArgs) {
|
|||
|
||||
fn bad_extensions(bad_extensions: BadExtensionsArgs) {
|
||||
let BadExtensionsArgs {
|
||||
thread_number,
|
||||
directories,
|
||||
excluded_directories,
|
||||
excluded_items,
|
||||
|
@ -498,6 +527,8 @@ fn bad_extensions(bad_extensions: BadExtensionsArgs) {
|
|||
allowed_extensions,
|
||||
} = bad_extensions;
|
||||
|
||||
set_number_of_threads(thread_number.thread_number);
|
||||
|
||||
let mut be = BadExtensions::new();
|
||||
|
||||
be.set_included_directory(directories.directories);
|
||||
|
|
|
@ -13,7 +13,7 @@ use mime_guess::get_mime_extensions;
|
|||
use rayon::prelude::*;
|
||||
|
||||
use crate::common::{prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -124,6 +124,7 @@ const WORKAROUNDS: &[(&str, &str)] = &[
|
|||
("xml", "vbox"), // VirtualBox
|
||||
("xml", "vbox-prev"), // VirtualBox
|
||||
("xml", "vcproj"), // VisualStudio
|
||||
("xml", "vcxproj"), // VisualStudio
|
||||
("xml", "xba"), // Libreoffice
|
||||
("xml", "xcd"), // Libreoffice files
|
||||
("zip", "apk"), // Android apk
|
||||
|
@ -172,6 +173,7 @@ impl Info {
|
|||
}
|
||||
|
||||
pub struct BadExtensions {
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
files_to_check: Vec<FileEntry>,
|
||||
|
@ -191,6 +193,7 @@ impl BadExtensions {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::BadExtensions,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
@ -314,7 +317,7 @@ impl BadExtensions {
|
|||
|
||||
fn look_for_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 1, self.files_to_check.len(), CheckingMethod::None);
|
||||
prepare_thread_handler_common(progress_sender, 1, 1, self.files_to_check.len(), CheckingMethod::None, self.tool_type);
|
||||
|
||||
let files_to_check = mem::take(&mut self.files_to_check);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use humansize::BINARY;
|
|||
use rayon::prelude::*;
|
||||
|
||||
use crate::common::{check_folder_children, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, split_path};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -55,6 +55,7 @@ impl Info {
|
|||
|
||||
/// Struct with required information's to work
|
||||
pub struct BigFile {
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
big_files: Vec<(u64, FileEntry)>,
|
||||
|
@ -72,6 +73,7 @@ impl BigFile {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::BigFile,
|
||||
text_messages: Default::default(),
|
||||
information: Info::new(),
|
||||
big_files: Default::default(),
|
||||
|
@ -148,7 +150,8 @@ impl BigFile {
|
|||
folders_to_check.push(id.clone());
|
||||
}
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = prepare_thread_handler_common(progress_sender, 0, 0, 0, CheckingMethod::None);
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 0, 0, 0, CheckingMethod::None, self.tool_type);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::common::{
|
|||
check_folder_children, create_crash_message, open_cache_folder, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, PDF_FILES_EXTENSIONS,
|
||||
};
|
||||
use crate::common::{AUDIO_FILES_EXTENSIONS, IMAGE_RS_BROKEN_FILES_EXTENSIONS, ZIP_FILES_EXTENSIONS};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -78,6 +78,7 @@ impl Info {
|
|||
}
|
||||
|
||||
pub struct BrokenFiles {
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
files_to_check: BTreeMap<String, FileEntry>,
|
||||
|
@ -99,6 +100,7 @@ impl BrokenFiles {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::BrokenFiles,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
@ -200,7 +202,8 @@ impl BrokenFiles {
|
|||
folders_to_check.push(id.clone());
|
||||
}
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = prepare_thread_handler_common(progress_sender, 0, 1, 0, CheckingMethod::None);
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 0, 1, 0, CheckingMethod::None, self.tool_type);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -436,7 +439,7 @@ impl BrokenFiles {
|
|||
}
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 1, non_cached_files_to_check.len(), CheckingMethod::None);
|
||||
prepare_thread_handler_common(progress_sender, 1, 1, non_cached_files_to_check.len(), CheckingMethod::None, self.tool_type);
|
||||
|
||||
let mut vec_file_entry: Vec<FileEntry> = non_cached_files_to_check
|
||||
.into_par_iter()
|
||||
|
|
|
@ -19,7 +19,7 @@ use libheif_rs::{ColorSpace, HeifContext, RgbChroma};
|
|||
|
||||
// #[cfg(feature = "heif")]
|
||||
// use libheif_rs::LibHeif;
|
||||
use crate::common_dir_traversal::{CheckingMethod, ProgressData};
|
||||
use crate::common_dir_traversal::{CheckingMethod, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_items::ExcludedItems;
|
||||
use crate::common_traits::ResultEntry;
|
||||
|
@ -392,6 +392,7 @@ pub fn prepare_thread_handler_common(
|
|||
max_stage: u8,
|
||||
max_value: usize,
|
||||
checking_method: CheckingMethod,
|
||||
tool_type: ToolType,
|
||||
) -> (JoinHandle<()>, Arc<AtomicBool>, Arc<AtomicUsize>, AtomicBool) {
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
|
@ -408,6 +409,7 @@ pub fn prepare_thread_handler_common(
|
|||
max_stage,
|
||||
entries_checked: atomic_counter.load(Ordering::Relaxed),
|
||||
entries_to_check: max_value,
|
||||
tool_type,
|
||||
})
|
||||
.unwrap();
|
||||
if !progress_thread_run.load(Ordering::Relaxed) {
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::fs;
|
|||
use std::fs::{DirEntry, Metadata, ReadDir};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
|
@ -25,6 +24,23 @@ pub struct ProgressData {
|
|||
pub max_stage: u8,
|
||||
pub entries_checked: usize,
|
||||
pub entries_to_check: usize,
|
||||
pub tool_type: ToolType,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Copy)]
|
||||
pub enum ToolType {
|
||||
Duplicate,
|
||||
EmptyFolders,
|
||||
EmptyFiles,
|
||||
InvalidSymlinks,
|
||||
BrokenFiles,
|
||||
BadExtensions,
|
||||
BigFile,
|
||||
SameMusic,
|
||||
SimilarImages,
|
||||
SimilarVideos,
|
||||
TemporaryFiles,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Copy)]
|
||||
|
@ -118,6 +134,7 @@ pub struct DirTraversalBuilder<'a, 'b, F> {
|
|||
directories: Option<Directories>,
|
||||
excluded_items: Option<ExcludedItems>,
|
||||
allowed_extensions: Option<Extensions>,
|
||||
tool_type: ToolType,
|
||||
}
|
||||
|
||||
pub struct DirTraversal<'a, 'b, F> {
|
||||
|
@ -133,6 +150,7 @@ pub struct DirTraversal<'a, 'b, F> {
|
|||
maximal_file_size: u64,
|
||||
checking_method: CheckingMethod,
|
||||
max_stage: u8,
|
||||
tool_type: ToolType,
|
||||
collect: Collect,
|
||||
}
|
||||
|
||||
|
@ -159,6 +177,7 @@ impl<'a, 'b> DirTraversalBuilder<'a, 'b, ()> {
|
|||
directories: None,
|
||||
allowed_extensions: None,
|
||||
excluded_items: None,
|
||||
tool_type: ToolType::BadExtensions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +255,12 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> {
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn tool_type(mut self, tool_type: ToolType) -> Self {
|
||||
self.tool_type = tool_type;
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[must_use]
|
||||
pub fn exclude_other_filesystems(mut self, exclude_other_filesystems: bool) -> Self {
|
||||
|
@ -264,6 +289,7 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> {
|
|||
collect: self.collect,
|
||||
checking_method: self.checking_method,
|
||||
max_stage: self.max_stage,
|
||||
tool_type: self.tool_type,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,6 +308,7 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> {
|
|||
excluded_items: self.excluded_items.expect("could not build"),
|
||||
allowed_extensions: self.allowed_extensions.unwrap_or_default(),
|
||||
recursive_search: self.recursive_search,
|
||||
tool_type: self.tool_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +366,7 @@ where
|
|||
folders_to_check.extend(self.root_dirs);
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(self.progress_sender, 0, self.max_stage, 0, self.checking_method);
|
||||
prepare_thread_handler_common(self.progress_sender, 0, self.max_stage, 0, self.checking_method, self.tool_type);
|
||||
|
||||
let DirTraversal {
|
||||
collect,
|
||||
|
@ -372,6 +399,7 @@ where
|
|||
return (dir_result, warnings, fe_result, set_as_not_empty_folder_list, folder_entries_list);
|
||||
};
|
||||
|
||||
let mut counter = 0;
|
||||
// Check every sub folder/file/link etc.
|
||||
'dir: for entry in read_dir {
|
||||
let Some((entry_data, metadata)) = common_get_entry_data_metadata(&entry, &mut warnings, current_folder) else {
|
||||
|
@ -383,7 +411,7 @@ where
|
|||
process_dir_in_file_symlink_mode(recursive_search, current_folder, entry_data, &directories, &mut dir_result, &mut warnings, &excluded_items);
|
||||
}
|
||||
(EntryType::Dir, Collect::EmptyFolders) => {
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
counter += 1;
|
||||
process_dir_in_dir_mode(
|
||||
&metadata,
|
||||
current_folder,
|
||||
|
@ -397,7 +425,7 @@ where
|
|||
);
|
||||
}
|
||||
(EntryType::File, Collect::Files) => {
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
counter += 1;
|
||||
process_file_in_file_mode(
|
||||
&metadata,
|
||||
entry_data,
|
||||
|
@ -424,10 +452,10 @@ where
|
|||
set_as_not_empty_folder_list.push(current_folder.clone());
|
||||
}
|
||||
(EntryType::File, Collect::InvalidSymlinks) => {
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
counter += 1;
|
||||
}
|
||||
(EntryType::Symlink, Collect::InvalidSymlinks) => {
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
counter += 1;
|
||||
process_symlink_in_symlink_mode(
|
||||
&metadata,
|
||||
entry_data,
|
||||
|
@ -444,6 +472,10 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
if counter > 0 {
|
||||
// Do not increase counter one by one in threads, because usually it
|
||||
atomic_counter.fetch_add(counter, Ordering::Relaxed);
|
||||
}
|
||||
(dir_result, warnings, fe_result, set_as_not_empty_folder_list, folder_entries_list)
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -21,7 +21,7 @@ use rayon::prelude::*;
|
|||
use xxhash_rust::xxh3::Xxh3;
|
||||
|
||||
use crate::common::{open_cache_folder, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -81,6 +81,7 @@ impl Info {
|
|||
}
|
||||
|
||||
pub struct DuplicateFinder {
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
files_with_identical_names: BTreeMap<String, Vec<FileEntry>>, // File Size, File Entry
|
||||
|
@ -116,6 +117,7 @@ impl DuplicateFinder {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::Duplicate,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
files_with_identical_names: Default::default(),
|
||||
|
@ -675,8 +677,14 @@ impl DuplicateFinder {
|
|||
pre_checked_map: &mut BTreeMap<u64, Vec<FileEntry>>,
|
||||
) -> Option<()> {
|
||||
let check_type = self.hash_type;
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 2, self.files_with_identical_size.values().map(Vec::len).sum(), self.check_method);
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common(
|
||||
progress_sender,
|
||||
1,
|
||||
2,
|
||||
self.files_with_identical_size.values().map(Vec::len).sum(),
|
||||
self.check_method,
|
||||
self.tool_type,
|
||||
);
|
||||
|
||||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.prehash_load_cache_at_start();
|
||||
|
||||
|
@ -831,7 +839,7 @@ impl DuplicateFinder {
|
|||
let check_type = self.hash_type;
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 2, 2, pre_checked_map.values().map(Vec::len).sum(), self.check_method);
|
||||
prepare_thread_handler_common(progress_sender, 2, 2, pre_checked_map.values().map(Vec::len).sum(), self.check_method, self.tool_type);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////// HASHING START
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::path::PathBuf;
|
|||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData};
|
||||
use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -35,6 +35,8 @@ impl Info {
|
|||
|
||||
/// Struct with required information's to work
|
||||
pub struct EmptyFiles {
|
||||
#[allow(dead_code)]
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
empty_files: Vec<FileEntry>,
|
||||
|
@ -50,6 +52,7 @@ impl EmptyFiles {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::EmptyFiles,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::path::PathBuf;
|
|||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, FolderEmptiness, FolderEntry, ProgressData};
|
||||
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, FolderEmptiness, FolderEntry, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_items::ExcludedItems;
|
||||
use crate::common_messages::Messages;
|
||||
|
@ -15,6 +15,8 @@ use crate::common_traits::{DebugPrint, PrintResults, SaveResults};
|
|||
|
||||
/// Struct to store most basics info about all folder
|
||||
pub struct EmptyFolder {
|
||||
#[allow(dead_code)]
|
||||
tool_type: ToolType,
|
||||
information: Info,
|
||||
delete_folders: bool,
|
||||
text_messages: Messages,
|
||||
|
@ -43,6 +45,7 @@ impl EmptyFolder {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::EmptyFolders,
|
||||
information: Default::default(),
|
||||
delete_folders: false,
|
||||
text_messages: Messages::new(),
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::path::PathBuf;
|
|||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, ErrorType, FileEntry, ProgressData};
|
||||
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, ErrorType, FileEntry, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -35,6 +35,8 @@ impl Info {
|
|||
|
||||
/// Struct with required information's to work
|
||||
pub struct InvalidSymlinks {
|
||||
#[allow(dead_code)]
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
invalid_symlinks: Vec<FileEntry>,
|
||||
|
@ -50,6 +52,7 @@ impl InvalidSymlinks {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::InvalidSymlinks,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
|
|
@ -25,7 +25,7 @@ use symphonia::core::probe::Hint;
|
|||
|
||||
use crate::common::{create_crash_message, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS};
|
||||
use crate::common::{filter_reference_folders_generic, open_cache_folder};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -108,6 +108,7 @@ impl Info {
|
|||
|
||||
/// Struct with required information's to work
|
||||
pub struct SameMusic {
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
music_to_check: HashMap<String, MusicEntry>,
|
||||
|
@ -138,6 +139,7 @@ impl SameMusic {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::SameMusic,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
@ -415,7 +417,7 @@ impl SameMusic {
|
|||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache(false);
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 3, non_cached_files_to_check.len(), self.check_type);
|
||||
prepare_thread_handler_common(progress_sender, 1, 3, non_cached_files_to_check.len(), self.check_type, self.tool_type);
|
||||
let configuration = &self.hash_preset_config;
|
||||
|
||||
// Clean for duplicate files
|
||||
|
@ -461,7 +463,7 @@ impl SameMusic {
|
|||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache(true);
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 2, non_cached_files_to_check.len(), self.check_type);
|
||||
prepare_thread_handler_common(progress_sender, 1, 2, non_cached_files_to_check.len(), self.check_type, self.tool_type);
|
||||
|
||||
// Clean for duplicate files
|
||||
let mut vec_file_entry = non_cached_files_to_check
|
||||
|
@ -502,7 +504,7 @@ impl SameMusic {
|
|||
|
||||
fn check_for_duplicate_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 2, 2, self.music_to_check.len(), self.check_type);
|
||||
prepare_thread_handler_common(progress_sender, 2, 2, self.music_to_check.len(), self.check_type, self.tool_type);
|
||||
|
||||
let mut old_duplicates: Vec<Vec<MusicEntry>> = vec![self.music_entries.clone()];
|
||||
let mut new_duplicates: Vec<Vec<MusicEntry>> = Vec::new();
|
||||
|
@ -601,7 +603,7 @@ impl SameMusic {
|
|||
fn read_tags_to_files_similar_by_content(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let groups_to_check = max(self.duplicated_music_entries.len(), self.duplicated_music_entries_referenced.len());
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 3, 3, groups_to_check, self.check_type);
|
||||
prepare_thread_handler_common(progress_sender, 3, 3, groups_to_check, self.check_type, self.tool_type);
|
||||
|
||||
// TODO is ther a way to just run iterator and not collect any info?
|
||||
if !self.duplicated_music_entries.is_empty() {
|
||||
|
@ -726,7 +728,7 @@ impl SameMusic {
|
|||
fn check_for_duplicate_fingerprints(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let (base_files, files_to_compare) = self.split_fingerprints_to_check();
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 2, 3, base_files.len(), self.check_type);
|
||||
prepare_thread_handler_common(progress_sender, 2, 3, base_files.len(), self.check_type, self.tool_type);
|
||||
|
||||
let Some(duplicated_music_entries) = self.compare_fingerprints(stop_receiver, &atomic_counter, base_files, &files_to_compare) else {
|
||||
send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle);
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::common::{
|
|||
check_folder_children, create_crash_message, get_dynamic_image_from_raw_image, get_number_of_threads, open_cache_folder, prepare_thread_handler_common,
|
||||
send_info_and_wait_for_ending_all_threads, HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS,
|
||||
};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -85,6 +85,7 @@ impl bk_tree::Metric<ImHash> for Hamming {
|
|||
|
||||
/// Struct to store most basics info about all folder
|
||||
pub struct SimilarImages {
|
||||
tool_type: ToolType,
|
||||
information: Info,
|
||||
text_messages: Messages,
|
||||
directories: Directories,
|
||||
|
@ -131,6 +132,7 @@ impl SimilarImages {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::SimilarImages,
|
||||
information: Default::default(),
|
||||
text_messages: Messages::new(),
|
||||
directories: Directories::new(),
|
||||
|
@ -300,7 +302,8 @@ impl SimilarImages {
|
|||
folders_to_check.push(id.clone());
|
||||
}
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = prepare_thread_handler_common(progress_sender, 0, 2, 0, CheckingMethod::None);
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 0, 2, 0, CheckingMethod::None, self.tool_type);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -435,7 +438,7 @@ impl SimilarImages {
|
|||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.hash_images_load_cache();
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 2, non_cached_files_to_check.len(), CheckingMethod::None);
|
||||
prepare_thread_handler_common(progress_sender, 1, 2, non_cached_files_to_check.len(), CheckingMethod::None, self.tool_type);
|
||||
|
||||
let mut vec_file_entry: Vec<(FileEntry, ImHash)> = non_cached_files_to_check
|
||||
.into_par_iter()
|
||||
|
@ -816,7 +819,7 @@ impl SimilarImages {
|
|||
}
|
||||
} else {
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 2, 2, all_hashes.len(), CheckingMethod::None);
|
||||
prepare_thread_handler_common(progress_sender, 2, 2, all_hashes.len(), CheckingMethod::None, self.tool_type);
|
||||
|
||||
// Don't use hashes with multiple images in bktree, because they will always be master of group and cannot be find by other hashes
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use vid_dup_finder_lib::{NormalizedTolerance, VideoHash};
|
|||
|
||||
use crate::common::open_cache_folder;
|
||||
use crate::common::{check_folder_children, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, VIDEO_FILES_EXTENSIONS};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -60,6 +60,7 @@ impl bk_tree::Metric<Vec<u8>> for Hamming {
|
|||
|
||||
/// Struct to store most basics info about all folder
|
||||
pub struct SimilarVideos {
|
||||
tool_type: ToolType,
|
||||
information: Info,
|
||||
text_messages: Messages,
|
||||
directories: Directories,
|
||||
|
@ -101,6 +102,7 @@ impl SimilarVideos {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::SimilarVideos,
|
||||
information: Default::default(),
|
||||
text_messages: Messages::new(),
|
||||
directories: Directories::new(),
|
||||
|
@ -261,7 +263,8 @@ impl SimilarVideos {
|
|||
folders_to_check.push(id.clone());
|
||||
}
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = prepare_thread_handler_common(progress_sender, 0, 1, 0, CheckingMethod::None);
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 0, 1, 0, CheckingMethod::None, self.tool_type);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -390,7 +393,7 @@ impl SimilarVideos {
|
|||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache_at_start();
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 1, 1, non_cached_files_to_check.len(), CheckingMethod::None);
|
||||
prepare_thread_handler_common(progress_sender, 1, 1, non_cached_files_to_check.len(), CheckingMethod::None, self.tool_type);
|
||||
|
||||
let mut vec_file_entry: Vec<FileEntry> = non_cached_files_to_check
|
||||
.par_iter()
|
||||
|
|
|
@ -11,7 +11,7 @@ use futures::channel::mpsc::UnboundedSender;
|
|||
use rayon::prelude::*;
|
||||
|
||||
use crate::common::{check_folder_children, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_items::ExcludedItems;
|
||||
use crate::common_messages::Messages;
|
||||
|
@ -60,6 +60,7 @@ impl Info {
|
|||
|
||||
/// Struct with required information's to work
|
||||
pub struct Temporary {
|
||||
tool_type: ToolType,
|
||||
text_messages: Messages,
|
||||
information: Info,
|
||||
temporary_files: Vec<FileEntry>,
|
||||
|
@ -74,6 +75,7 @@ impl Temporary {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tool_type: ToolType::TemporaryFiles,
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
@ -149,7 +151,8 @@ impl Temporary {
|
|||
folders_to_check.push(id.clone());
|
||||
}
|
||||
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = prepare_thread_handler_common(progress_sender, 0, 0, 0, CheckingMethod::None);
|
||||
let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
|
||||
prepare_thread_handler_common(progress_sender, 0, 0, 0, CheckingMethod::None, self.tool_type);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
|
|
@ -33,21 +33,7 @@ use crate::taskbar_progress::tbp_flags::TBPF_NOPROGRESS;
|
|||
use crate::{flg, DEFAULT_MAXIMAL_FILE_SIZE, DEFAULT_MINIMAL_CACHE_SIZE, DEFAULT_MINIMAL_FILE_SIZE};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn connect_button_search(
|
||||
gui_data: &GuiData,
|
||||
glib_stop_sender: Sender<Message>,
|
||||
futures_sender_duplicate_files: UnboundedSender<ProgressData>,
|
||||
futures_sender_empty_files: UnboundedSender<ProgressData>,
|
||||
futures_sender_empty_folder: UnboundedSender<ProgressData>,
|
||||
futures_sender_big_file: UnboundedSender<ProgressData>,
|
||||
futures_sender_same_music: UnboundedSender<ProgressData>,
|
||||
futures_sender_similar_images: UnboundedSender<ProgressData>,
|
||||
futures_sender_similar_videos: UnboundedSender<ProgressData>,
|
||||
futures_sender_temporary: UnboundedSender<ProgressData>,
|
||||
futures_sender_invalid_symlinks: UnboundedSender<ProgressData>,
|
||||
futures_sender_broken_files: UnboundedSender<ProgressData>,
|
||||
futures_sender_bad_extensions: UnboundedSender<ProgressData>,
|
||||
) {
|
||||
pub fn connect_button_search(gui_data: &GuiData, glib_stop_sender: Sender<Message>, progress_sender: UnboundedSender<ProgressData>) {
|
||||
let buttons_array = gui_data.bottom_buttons.buttons_array.clone();
|
||||
let buttons_search_clone = gui_data.bottom_buttons.buttons_search.clone();
|
||||
let grid_progress_stages = gui_data.progress_window.grid_progress_stages.clone();
|
||||
|
@ -109,7 +95,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_duplicate_files.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::EmptyFiles => empty_files_search(
|
||||
&gui_data,
|
||||
|
@ -117,7 +103,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_empty_files.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::EmptyDirectories => empty_directories_search(
|
||||
&gui_data,
|
||||
|
@ -125,7 +111,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_empty_folder.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::BigFiles => big_files_search(
|
||||
&gui_data,
|
||||
|
@ -133,7 +119,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_big_file.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::Temporary => temporary_files_search(
|
||||
&gui_data,
|
||||
|
@ -141,7 +127,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_temporary.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::SimilarImages => similar_image_search(
|
||||
&gui_data,
|
||||
|
@ -149,7 +135,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_similar_images.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::SimilarVideos => similar_video_search(
|
||||
&gui_data,
|
||||
|
@ -157,7 +143,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_similar_videos.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::SameMusic => same_music_search(
|
||||
&gui_data,
|
||||
|
@ -165,7 +151,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_same_music.clone(),
|
||||
progress_sender.clone(),
|
||||
&show_dialog,
|
||||
),
|
||||
NotebookMainEnum::Symlinks => bad_symlinks_search(
|
||||
|
@ -174,7 +160,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_invalid_symlinks.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
NotebookMainEnum::BrokenFiles => broken_files_search(
|
||||
&gui_data,
|
||||
|
@ -182,7 +168,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_broken_files.clone(),
|
||||
progress_sender.clone(),
|
||||
&show_dialog,
|
||||
),
|
||||
NotebookMainEnum::BadExtensions => bad_extensions_search(
|
||||
|
@ -191,7 +177,7 @@ pub fn connect_button_search(
|
|||
stop_receiver,
|
||||
glib_stop_sender,
|
||||
&grid_progress_stages,
|
||||
futures_sender_bad_extensions.clone(),
|
||||
progress_sender.clone(),
|
||||
),
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use gtk4::ProgressBar;
|
|||
|
||||
use common_dir_traversal::CheckingMethod;
|
||||
use czkawka_core::common_dir_traversal;
|
||||
use czkawka_core::common_dir_traversal::ProgressData;
|
||||
use czkawka_core::common_dir_traversal::{ProgressData, ToolType};
|
||||
|
||||
use crate::flg;
|
||||
use crate::gui_structs::gui_data::GuiData;
|
||||
|
@ -19,304 +19,256 @@ use crate::taskbar_progress::tbp_flags::TBPF_INDETERMINATE;
|
|||
use crate::taskbar_progress::TaskbarProgress;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn connect_progress_window(
|
||||
gui_data: &GuiData,
|
||||
futures_receiver_duplicate_files: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_empty_files: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_empty_folder: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_big_files: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_same_music: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_similar_images: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_similar_videos: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_temporary: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_invalid_symlinks: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_broken_files: UnboundedReceiver<ProgressData>,
|
||||
futures_receiver_bad_extensions: UnboundedReceiver<ProgressData>,
|
||||
) {
|
||||
pub fn connect_progress_window(gui_data: &GuiData, mut progress_receiver: UnboundedReceiver<ProgressData>) {
|
||||
let main_context = MainContext::default();
|
||||
let _guard = main_context.acquire().unwrap();
|
||||
|
||||
process_bar_duplicates(gui_data, &main_context, futures_receiver_duplicate_files);
|
||||
process_bar_empty_files(gui_data, &main_context, futures_receiver_empty_files);
|
||||
process_bar_empty_folder(gui_data, &main_context, futures_receiver_empty_folder);
|
||||
process_bar_big_files(gui_data, &main_context, futures_receiver_big_files);
|
||||
process_bar_same_music(gui_data, &main_context, futures_receiver_same_music);
|
||||
process_bar_similar_images(gui_data, &main_context, futures_receiver_similar_images);
|
||||
process_bar_similar_videos(gui_data, &main_context, futures_receiver_similar_videos);
|
||||
process_bar_temporary(gui_data, &main_context, futures_receiver_temporary);
|
||||
process_bar_invalid_symlinks(gui_data, &main_context, futures_receiver_invalid_symlinks);
|
||||
process_bar_broken_files(gui_data, &main_context, futures_receiver_broken_files);
|
||||
process_bar_bad_extensions(gui_data, &main_context, futures_receiver_bad_extensions);
|
||||
}
|
||||
fn process_bar_empty_files(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_empty_files: UnboundedReceiver<ProgressData>) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let gui_data = gui_data.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_empty_files.next().await {
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
while let Some(item) = progress_receiver.next().await {
|
||||
match item.tool_type {
|
||||
ToolType::Duplicate => process_bar_duplicates(&gui_data, &item),
|
||||
ToolType::EmptyFiles => process_bar_empty_files(&gui_data, &item),
|
||||
ToolType::EmptyFolders => process_bar_empty_folder(&gui_data, &item),
|
||||
ToolType::BigFile => process_bar_big_files(&gui_data, &item),
|
||||
ToolType::SameMusic => process_bar_same_music(&gui_data, &item),
|
||||
ToolType::SimilarImages => process_bar_similar_images(&gui_data, &item),
|
||||
ToolType::SimilarVideos => process_bar_similar_videos(&gui_data, &item),
|
||||
ToolType::TemporaryFiles => process_bar_temporary(&gui_data, &item),
|
||||
ToolType::InvalidSymlinks => process_bar_invalid_symlinks(&gui_data, &item),
|
||||
ToolType::BrokenFiles => process_bar_broken_files(&gui_data, &item),
|
||||
ToolType::BadExtensions => process_bar_bad_extensions(&gui_data, &item),
|
||||
ToolType::None => panic!(),
|
||||
}
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
}
|
||||
fn process_bar_empty_folder(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_empty_folder: UnboundedReceiver<ProgressData>) {
|
||||
fn process_bar_empty_files(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_empty_folder.next().await {
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_empty_folders",
|
||||
generate_translation_hashmap(vec![("folder_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
}
|
||||
fn process_bar_big_files(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_big_files: UnboundedReceiver<ProgressData>) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_big_files.next().await {
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
}
|
||||
fn process_bar_same_music(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_same_music: UnboundedReceiver<ProgressData>) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_same_music.next().await {
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
match item.checking_method {
|
||||
CheckingMethod::AudioTags => label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(&item))),
|
||||
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_content", progress_ratio_tm(&item))),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
match item.checking_method {
|
||||
CheckingMethod::AudioTags => label_stage.set_text(&flg!("progress_scanning_music_tags_end", progress_ratio_tm(&item))),
|
||||
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_content_end", progress_ratio_tm(&item))),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
match item.checking_method {
|
||||
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(&item))),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
fn process_bar_similar_images(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_similar_images: UnboundedReceiver<ProgressData>) {
|
||||
fn process_bar_empty_folder(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_empty_folders",
|
||||
generate_translation_hashmap(vec![("folder_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
fn process_bar_big_files(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
fn process_bar_same_music(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_similar_images.next().await {
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_image", progress_ratio_tm(&item)));
|
||||
}
|
||||
2 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_comparing_image_hashes", progress_ratio_tm(&item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
}
|
||||
fn process_bar_similar_videos(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_similar_videos: UnboundedReceiver<ProgressData>) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_similar_videos.next().await {
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_video", progress_ratio_tm(&item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
}
|
||||
fn process_bar_temporary(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_temporary: UnboundedReceiver<ProgressData>) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_temporary.next().await {
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
match item.checking_method {
|
||||
CheckingMethod::AudioTags => label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(item))),
|
||||
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_content", progress_ratio_tm(item))),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
match item.checking_method {
|
||||
CheckingMethod::AudioTags => label_stage.set_text(&flg!("progress_scanning_music_tags_end", progress_ratio_tm(item))),
|
||||
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_content_end", progress_ratio_tm(item))),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
match item.checking_method {
|
||||
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(item))),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
fn process_bar_invalid_symlinks(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_invalid_symlinks: UnboundedReceiver<ProgressData>) {
|
||||
fn process_bar_similar_images(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_invalid_symlinks.next().await {
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_image", progress_ratio_tm(item)));
|
||||
}
|
||||
2 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_comparing_image_hashes", progress_ratio_tm(item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
fn process_bar_broken_files(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_broken_files: UnboundedReceiver<ProgressData>) {
|
||||
fn process_bar_similar_videos(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_broken_files.next().await {
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_broken_files", progress_ratio_tm(&item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_video", progress_ratio_tm(item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
fn process_bar_bad_extensions(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_bad_extensions: UnboundedReceiver<ProgressData>) {
|
||||
fn process_bar_temporary(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
fn process_bar_invalid_symlinks(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
fn process_bar_broken_files(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_bad_extensions.next().await {
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_extension_of_files", progress_ratio_tm(&item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_broken_files", progress_ratio_tm(item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
fn process_bar_duplicates(gui_data: &GuiData, main_context: &MainContext, mut futures_receiver_duplicate_files: UnboundedReceiver<ProgressData>) {
|
||||
fn process_bar_bad_extensions(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
|
||||
match item.current_stage {
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_scanning_extension_of_files", progress_ratio_tm(item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
fn process_bar_duplicates(gui_data: &GuiData, item: &ProgressData) {
|
||||
let label_stage = gui_data.progress_window.label_stage.clone();
|
||||
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
|
||||
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
|
||||
let grid_progress_stages = gui_data.progress_window.grid_progress_stages.clone();
|
||||
let taskbar_state = gui_data.taskbar_state.clone();
|
||||
let future = async move {
|
||||
while let Some(item) = futures_receiver_duplicate_files.next().await {
|
||||
match item.checking_method {
|
||||
CheckingMethod::Hash => {
|
||||
label_stage.show();
|
||||
match item.current_stage {
|
||||
// Checking Size
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
// progress_bar_all_stages.hide();
|
||||
progress_bar_all_stages.set_fraction(0 as f64);
|
||||
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
// Hash - first 1KB file
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
// progress_bar_all_stages.show();
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
label_stage.set_text(&flg!("progress_analyzed_partial_hash", progress_ratio_tm(&item)));
|
||||
}
|
||||
// Hash - normal hash
|
||||
2 => {
|
||||
common_set_data(&item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_analyzed_full_hash", progress_ratio_tm(&item)));
|
||||
}
|
||||
_ => {
|
||||
panic!("Not available current_stage");
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckingMethod::Name => {
|
||||
label_stage.show();
|
||||
grid_progress_stages.hide();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_name", file_number_tm(&item)));
|
||||
match item.checking_method {
|
||||
CheckingMethod::Hash => {
|
||||
label_stage.show();
|
||||
match item.current_stage {
|
||||
// Checking Size
|
||||
0 => {
|
||||
progress_bar_current_stage.hide();
|
||||
// progress_bar_all_stages.hide();
|
||||
progress_bar_all_stages.set_fraction(0 as f64);
|
||||
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
CheckingMethod::SizeName => {
|
||||
label_stage.show();
|
||||
grid_progress_stages.hide();
|
||||
// Hash - first 1KB file
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
// progress_bar_all_stages.show();
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_size_name", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
label_stage.set_text(&flg!("progress_analyzed_partial_hash", progress_ratio_tm(item)));
|
||||
}
|
||||
CheckingMethod::Size => {
|
||||
label_stage.show();
|
||||
grid_progress_stages.hide();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(&item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
// Hash - normal hash
|
||||
2 => {
|
||||
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
|
||||
label_stage.set_text(&flg!("progress_analyzed_full_hash", progress_ratio_tm(item)));
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
_ => {
|
||||
panic!("Not available current_stage");
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckingMethod::Name => {
|
||||
label_stage.show();
|
||||
grid_progress_stages.hide();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_name", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
CheckingMethod::SizeName => {
|
||||
label_stage.show();
|
||||
grid_progress_stages.hide();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_size_name", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
CheckingMethod::Size => {
|
||||
label_stage.show();
|
||||
grid_progress_stages.hide();
|
||||
|
||||
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(item)));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
main_context.spawn_local(future);
|
||||
}
|
||||
|
||||
fn common_set_data(item: &ProgressData, progress_bar_all_stages: &ProgressBar, progress_bar_current_stage: &ProgressBar, taskbar_state: &Rc<RefCell<TaskbarProgress>>) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use gtk4::prelude::*;
|
||||
use gtk4::{CellRendererText, CellRendererToggle, TreeView, TreeViewColumn};
|
||||
use gtk4::{CellRendererText, CellRendererToggle, ListStore, TreeView, TreeViewColumn};
|
||||
|
||||
use crate::help_functions::*;
|
||||
|
||||
|
@ -8,726 +8,234 @@ use crate::help_functions::*;
|
|||
pub fn create_tree_view_included_directories(tree_view: &TreeView) {
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.set_title("Folders to check");
|
||||
column.pack_start(&renderer, true);
|
||||
column.add_attribute(&renderer, "text", ColumnsIncludedDirectory::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsIncludedDirectory::ReferenceButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsIncludedDirectory::ReferenceButton as u32, &fixed.to_value());
|
||||
});
|
||||
renderer.set_activatable(true);
|
||||
let column = TreeViewColumn::new();
|
||||
column.set_title("Reference folder");
|
||||
column.pack_start(&renderer, true);
|
||||
column.add_attribute(&renderer, "active", ColumnsIncludedDirectory::ReferenceButton as i32);
|
||||
tree_view.append_column(&column);
|
||||
create_default_column(tree_view, ColumnsIncludedDirectory::Path as i32, None, None);
|
||||
create_default_selection_button_column(tree_view, ColumnsIncludedDirectory::ReferenceButton as i32, model, None);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_excluded_directories(tree_view: &TreeView) {
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.add_attribute(&renderer, "text", ColumnsExcludedDirectory::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_headers_visible(false);
|
||||
create_default_column(tree_view, ColumnsExcludedDirectory::Path as i32, None, None);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_duplicates(tree_view: &TreeView) {
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsDuplicates::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsDuplicates::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "activatable", ColumnsDuplicates::ActivatableSelectButton as i32);
|
||||
column.add_attribute(&renderer, "active", ColumnsDuplicates::SelectionButton as i32);
|
||||
column.add_attribute(&renderer, "cell-background", ColumnsDuplicates::Color as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Size");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsDuplicates::Size as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsDuplicates::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsDuplicates::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsDuplicates::Name as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsDuplicates::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsDuplicates::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsDuplicates::Path as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsDuplicates::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsDuplicates::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsDuplicates::Modification as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsDuplicates::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsDuplicates::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
let columns_colors = (ColumnsDuplicates::Color as i32, ColumnsDuplicates::TextColor as i32);
|
||||
let activatable_colors = (ColumnsDuplicates::ActivatableSelectButton as i32, ColumnsDuplicates::Color as i32);
|
||||
|
||||
create_default_selection_button_column(tree_view, ColumnsDuplicates::SelectionButton as i32, model, Some(activatable_colors));
|
||||
|
||||
create_default_column(tree_view, ColumnsDuplicates::Size as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsDuplicates::Name as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsDuplicates::Path as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsDuplicates::Modification as i32, None, Some(columns_colors));
|
||||
}
|
||||
|
||||
pub fn create_tree_view_empty_folders(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsEmptyFolders::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsEmptyFolders::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "active", ColumnsEmptyFolders::SelectionButton as i32);
|
||||
tree_view.append_column(&column);
|
||||
create_default_selection_button_column(tree_view, ColumnsEmptyFolders::SelectionButton as i32, model, None);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Folder Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsEmptyFolders::Name as i32);
|
||||
column.set_sort_column_id(ColumnsEmptyFolders::Name as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsEmptyFolders::Path as i32);
|
||||
column.set_sort_column_id(ColumnsEmptyFolders::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsEmptyFolders::Modification as i32);
|
||||
column.set_sort_column_id(ColumnsEmptyFolders::ModificationAsSecs as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
create_default_column(tree_view, ColumnsEmptyFolders::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsEmptyFolders::Path as i32, None, None);
|
||||
create_default_column(
|
||||
tree_view,
|
||||
ColumnsEmptyFolders::Modification as i32,
|
||||
Some(ColumnsEmptyFolders::ModificationAsSecs as i32),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_big_files(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsBigFiles::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsBigFiles::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "active", ColumnsBigFiles::SelectionButton as i32);
|
||||
tree_view.append_column(&column);
|
||||
create_default_selection_button_column(tree_view, ColumnsBigFiles::SelectionButton as i32, model, None);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Size");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBigFiles::Size as i32);
|
||||
column.set_sort_column_id(ColumnsBigFiles::SizeAsBytes as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBigFiles::Name as i32);
|
||||
column.set_sort_column_id(ColumnsBigFiles::Name as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBigFiles::Path as i32);
|
||||
column.set_sort_column_id(ColumnsBigFiles::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBigFiles::Modification as i32);
|
||||
column.set_sort_column_id(ColumnsBigFiles::ModificationAsSecs as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
create_default_column(tree_view, ColumnsBigFiles::Size as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBigFiles::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBigFiles::Path as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBigFiles::Modification as i32, Some(ColumnsBigFiles::ModificationAsSecs as i32), None);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_temporary_files(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsTemporaryFiles::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsTemporaryFiles::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "active", ColumnsTemporaryFiles::SelectionButton as i32);
|
||||
tree_view.append_column(&column);
|
||||
create_default_selection_button_column(tree_view, ColumnsTemporaryFiles::SelectionButton as i32, model, None);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsTemporaryFiles::Name as i32);
|
||||
column.set_sort_column_id(ColumnsTemporaryFiles::Name as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsTemporaryFiles::Path as i32);
|
||||
column.set_sort_column_id(ColumnsTemporaryFiles::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsTemporaryFiles::Modification as i32);
|
||||
column.set_sort_column_id(ColumnsTemporaryFiles::ModificationAsSecs as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
create_default_column(tree_view, ColumnsTemporaryFiles::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsTemporaryFiles::Path as i32, None, None);
|
||||
create_default_column(
|
||||
tree_view,
|
||||
ColumnsTemporaryFiles::Modification as i32,
|
||||
Some(ColumnsTemporaryFiles::ModificationAsSecs as i32),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_empty_files(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsEmptyFiles::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsEmptyFiles::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "active", ColumnsEmptyFiles::SelectionButton as i32);
|
||||
tree_view.append_column(&column);
|
||||
create_default_selection_button_column(tree_view, ColumnsEmptyFiles::SelectionButton as i32, model, None);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsEmptyFiles::Name as i32);
|
||||
column.set_sort_column_id(ColumnsEmptyFiles::Name as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsEmptyFiles::Path as i32);
|
||||
column.set_sort_column_id(ColumnsEmptyFiles::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsEmptyFiles::Modification as i32);
|
||||
column.set_sort_column_id(ColumnsEmptyFiles::ModificationAsSecs as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
create_default_column(tree_view, ColumnsEmptyFiles::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsEmptyFiles::Path as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsEmptyFiles::Modification as i32, Some(ColumnsEmptyFiles::ModificationAsSecs as i32), None);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_similar_images(tree_view: &TreeView) {
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsSimilarImages::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsSimilarImages::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "activatable", ColumnsSimilarImages::ActivatableSelectButton as i32);
|
||||
column.add_attribute(&renderer, "active", ColumnsSimilarImages::SelectionButton as i32);
|
||||
column.add_attribute(&renderer, "cell-background", ColumnsSimilarImages::Color as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Similarity");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarImages::Similarity as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarImages::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarImages::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Size");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarImages::Size as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarImages::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarImages::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Dimensions");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarImages::Dimensions as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarImages::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarImages::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarImages::Name as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarImages::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarImages::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarImages::Path as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarImages::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarImages::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarImages::Modification as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarImages::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarImages::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
let columns_colors = (ColumnsSimilarImages::Color as i32, ColumnsSimilarImages::TextColor as i32);
|
||||
let activatable_colors = (ColumnsSimilarImages::ActivatableSelectButton as i32, ColumnsSimilarImages::Color as i32);
|
||||
|
||||
create_default_selection_button_column(tree_view, ColumnsSimilarImages::SelectionButton as i32, model, Some(activatable_colors));
|
||||
|
||||
create_default_column(tree_view, ColumnsSimilarImages::Similarity as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarImages::Size as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarImages::Dimensions as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarImages::Name as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarImages::Path as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarImages::Modification as i32, None, Some(columns_colors));
|
||||
}
|
||||
|
||||
pub fn create_tree_view_similar_videos(tree_view: &TreeView) {
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsSimilarVideos::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsSimilarVideos::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "activatable", ColumnsSimilarVideos::ActivatableSelectButton as i32);
|
||||
column.add_attribute(&renderer, "active", ColumnsSimilarVideos::SelectionButton as i32);
|
||||
column.add_attribute(&renderer, "cell-background", ColumnsSimilarVideos::Color as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Size");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarVideos::Size as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarVideos::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarVideos::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarVideos::Name as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarVideos::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarVideos::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarVideos::Path as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarVideos::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarVideos::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSimilarVideos::Modification as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSimilarVideos::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSimilarVideos::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
let columns_colors = (ColumnsSimilarVideos::Color as i32, ColumnsSimilarVideos::TextColor as i32);
|
||||
let activatable_colors = (ColumnsSimilarVideos::ActivatableSelectButton as i32, ColumnsSimilarVideos::Color as i32);
|
||||
|
||||
create_default_selection_button_column(tree_view, ColumnsSimilarVideos::SelectionButton as i32, model, Some(activatable_colors));
|
||||
|
||||
create_default_column(tree_view, ColumnsSimilarVideos::Size as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarVideos::Name as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarVideos::Path as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSimilarVideos::Modification as i32, None, Some(columns_colors));
|
||||
}
|
||||
|
||||
pub fn create_tree_view_same_music(tree_view: &TreeView) {
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsSameMusic::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsSameMusic::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "activatable", ColumnsSameMusic::ActivatableSelectButton as i32);
|
||||
column.add_attribute(&renderer, "active", ColumnsSameMusic::SelectionButton as i32);
|
||||
column.add_attribute(&renderer, "cell-background", ColumnsSameMusic::Color as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Size");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Size as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Name as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Title");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Title as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Artist");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Artist as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Year");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Year as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Bitrate");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Bitrate as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Length");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Length as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Genre");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Genre as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Path as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsSameMusic::Modification as i32);
|
||||
column.add_attribute(&renderer, "background", ColumnsSameMusic::Color as i32);
|
||||
column.add_attribute(&renderer, "foreground", ColumnsSameMusic::TextColor as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
let columns_colors = (ColumnsSameMusic::Color as i32, ColumnsSameMusic::TextColor as i32);
|
||||
let activatable_colors = (ColumnsSameMusic::ActivatableSelectButton as i32, ColumnsSameMusic::Color as i32);
|
||||
|
||||
create_default_selection_button_column(tree_view, ColumnsSameMusic::SelectionButton as i32, model, Some(activatable_colors));
|
||||
|
||||
create_default_column(tree_view, ColumnsSameMusic::Size as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Name as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Title as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Artist as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Year as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Bitrate as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Length as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Genre as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Path as i32, None, Some(columns_colors));
|
||||
create_default_column(tree_view, ColumnsSameMusic::Modification as i32, None, Some(columns_colors));
|
||||
}
|
||||
|
||||
pub fn create_tree_view_invalid_symlinks(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsInvalidSymlinks::SelectionButton as i32);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsInvalidSymlinks::SelectionButton as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "active", ColumnsInvalidSymlinks::SelectionButton as i32);
|
||||
tree_view.append_column(&column);
|
||||
create_default_selection_button_column(tree_view, ColumnsInvalidSymlinks::SelectionButton as i32, model, None);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Symlink File Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsInvalidSymlinks::Name as i32);
|
||||
column.set_sort_column_id(ColumnsInvalidSymlinks::Name as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Symlink Folder");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsInvalidSymlinks::Path as i32);
|
||||
column.set_sort_column_id(ColumnsInvalidSymlinks::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Destination Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsInvalidSymlinks::DestinationPath as i32);
|
||||
column.set_sort_column_id(ColumnsInvalidSymlinks::DestinationPath as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Type of Error");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsInvalidSymlinks::TypeOfError as i32);
|
||||
column.set_sort_column_id(ColumnsInvalidSymlinks::TypeOfError as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsInvalidSymlinks::Modification as i32);
|
||||
column.set_sort_column_id(ColumnsInvalidSymlinks::ModificationAsSecs as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
create_default_column(tree_view, ColumnsInvalidSymlinks::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsInvalidSymlinks::Path as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsInvalidSymlinks::DestinationPath as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsInvalidSymlinks::TypeOfError as i32, None, None);
|
||||
create_default_column(
|
||||
tree_view,
|
||||
ColumnsInvalidSymlinks::Modification as i32,
|
||||
Some(ColumnsInvalidSymlinks::ModificationAsSecs as i32),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_broken_files(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
create_default_selection_button_column(tree_view, ColumnsBrokenFiles::SelectionButton as i32, model, None);
|
||||
|
||||
create_default_column(tree_view, ColumnsBrokenFiles::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBrokenFiles::Path as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBrokenFiles::ErrorType as i32, None, None);
|
||||
create_default_column(
|
||||
tree_view,
|
||||
ColumnsBrokenFiles::Modification as i32,
|
||||
Some(ColumnsBrokenFiles::ModificationAsSecs as i32),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn create_tree_view_bad_extensions(tree_view: &TreeView) {
|
||||
tree_view.set_vexpand(true);
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
create_default_selection_button_column(tree_view, ColumnsBadExtensions::SelectionButton as i32, model, None);
|
||||
|
||||
create_default_column(tree_view, ColumnsBadExtensions::Name as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBadExtensions::Path as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBadExtensions::CurrentExtension as i32, None, None);
|
||||
create_default_column(tree_view, ColumnsBadExtensions::ValidExtensions as i32, None, None);
|
||||
}
|
||||
|
||||
fn create_default_selection_button_column(
|
||||
tree_view: &TreeView,
|
||||
column_id: i32,
|
||||
model: ListStore,
|
||||
activatable_color_columns: Option<(i32, i32)>,
|
||||
) -> (CellRendererToggle, TreeViewColumn) {
|
||||
let renderer = CellRendererToggle::new();
|
||||
renderer.connect_toggled(move |_r, path| {
|
||||
let iter = model.iter(&path).unwrap();
|
||||
let mut fixed = model.get::<bool>(&iter, ColumnsBrokenFiles::SelectionButton as i32);
|
||||
let mut fixed = model.get::<bool>(&iter, column_id);
|
||||
fixed = !fixed;
|
||||
model.set_value(&iter, ColumnsBrokenFiles::SelectionButton as u32, &fixed.to_value());
|
||||
model.set_value(&iter, column_id as u32, &fixed.to_value());
|
||||
});
|
||||
let column = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(false);
|
||||
column.set_fixed_width(30);
|
||||
column.add_attribute(&renderer, "active", ColumnsBrokenFiles::SelectionButton as i32);
|
||||
column.add_attribute(&renderer, "active", column_id);
|
||||
if let Some(activatable_color_columns) = activatable_color_columns {
|
||||
column.add_attribute(&renderer, "activatable", activatable_color_columns.0);
|
||||
column.add_attribute(&renderer, "cell-background", activatable_color_columns.1);
|
||||
}
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Name");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBrokenFiles::Name as i32);
|
||||
column.set_sort_column_id(ColumnsBrokenFiles::Name as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Path");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBrokenFiles::Path as i32);
|
||||
column.set_sort_column_id(ColumnsBrokenFiles::Path as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("ErrorType");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBrokenFiles::ErrorType as i32);
|
||||
column.set_sort_column_id(ColumnsBrokenFiles::ErrorType as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_title("Modification Date");
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", ColumnsBrokenFiles::Modification as i32);
|
||||
column.set_sort_column_id(ColumnsBrokenFiles::ModificationAsSecs as i32);
|
||||
tree_view.append_column(&column);
|
||||
|
||||
tree_view.set_vexpand(true);
|
||||
(renderer, column)
|
||||
}
|
||||
|
||||
fn create_default_column(tree_view: &TreeView, column_id: i32, sort_column_id: Option<i32>, colors_columns_id: Option<(i32, i32)>) -> (CellRendererText, TreeViewColumn) {
|
||||
let renderer = CellRendererText::new();
|
||||
let column: TreeViewColumn = TreeViewColumn::new();
|
||||
column.pack_start(&renderer, true);
|
||||
column.set_resizable(true);
|
||||
column.set_min_width(50);
|
||||
column.add_attribute(&renderer, "text", column_id);
|
||||
if let Some(sort_column_id) = sort_column_id {
|
||||
column.set_sort_column_id(sort_column_id);
|
||||
} else {
|
||||
column.set_sort_column_id(column_id);
|
||||
}
|
||||
if let Some(colors_columns_id) = colors_columns_id {
|
||||
column.add_attribute(&renderer, "background", colors_columns_id.0);
|
||||
column.add_attribute(&renderer, "foreground", colors_columns_id.1);
|
||||
}
|
||||
tree_view.append_column(&column);
|
||||
(renderer, column)
|
||||
}
|
||||
|
|
|
@ -378,14 +378,34 @@ pub fn get_notebook_enum_from_tree_view(tree_view: &TreeView) -> NotebookMainEnu
|
|||
}
|
||||
}
|
||||
}
|
||||
pub fn get_tree_view_name_from_notebook_enum(notebook_enum: NotebookMainEnum) -> &'static str {
|
||||
match notebook_enum {
|
||||
NotebookMainEnum::Duplicate => "tree_view_duplicate_finder",
|
||||
NotebookMainEnum::EmptyDirectories => "tree_view_empty_folder_finder",
|
||||
NotebookMainEnum::EmptyFiles => "tree_view_empty_files_finder",
|
||||
NotebookMainEnum::Temporary => "tree_view_temporary_files_finder",
|
||||
NotebookMainEnum::BigFiles => "tree_view_big_files_finder",
|
||||
NotebookMainEnum::SimilarImages => "tree_view_similar_images_finder",
|
||||
NotebookMainEnum::SimilarVideos => "tree_view_similar_videos_finder",
|
||||
NotebookMainEnum::SameMusic => "tree_view_same_music_finder",
|
||||
NotebookMainEnum::Symlinks => "tree_view_invalid_symlinks",
|
||||
NotebookMainEnum::BrokenFiles => "tree_view_broken_files",
|
||||
NotebookMainEnum::BadExtensions => "tree_view_bad_extensions",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_notebook_upper_enum_from_tree_view(tree_view: &TreeView) -> NotebookUpperEnum {
|
||||
match (*tree_view).widget_name().to_string().as_str() {
|
||||
"tree_view_upper_included_directories" => NotebookUpperEnum::IncludedDirectories,
|
||||
"tree_view_upper_excluded_directories" => NotebookUpperEnum::ExcludedDirectories,
|
||||
e => {
|
||||
panic!("{}", e)
|
||||
}
|
||||
e => panic!("{}", e),
|
||||
}
|
||||
}
|
||||
pub fn get_tree_view_name_from_notebook_upper_enum(notebook_upper_enum: NotebookUpperEnum) -> &'static str {
|
||||
match notebook_upper_enum {
|
||||
NotebookUpperEnum::IncludedDirectories => "tree_view_upper_included_directories",
|
||||
NotebookUpperEnum::ExcludedDirectories => "tree_view_upper_excluded_directories",
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,15 +809,46 @@ pub fn scale_step_function(scale: &Scale, _scroll_type: ScrollType, value: f64)
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use glib::types::Type;
|
||||
use glib::Value;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::Orientation;
|
||||
use gtk4::{Orientation, TreeView};
|
||||
use image::DynamicImage;
|
||||
|
||||
use crate::help_functions::{
|
||||
change_dimension_to_krotka, check_if_list_store_column_have_all_same_values, check_if_value_is_in_list_store, get_all_boxes_from_widget, get_all_direct_children,
|
||||
get_max_file_name, get_pixbuf_from_dynamic_image,
|
||||
get_max_file_name, get_pixbuf_from_dynamic_image, get_string_from_list_store,
|
||||
};
|
||||
|
||||
#[gtk4::test]
|
||||
fn test_get_string_from_list_store() {
|
||||
let columns_types: &[Type] = &[Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
let tree_view = TreeView::with_model(&list_store);
|
||||
|
||||
let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &"test"), (0, &"test2"), (0, &"test3")];
|
||||
for i in values_to_add {
|
||||
list_store.set(&list_store.append(), &[*i]);
|
||||
}
|
||||
assert_eq!(
|
||||
get_string_from_list_store(&tree_view, 0, None),
|
||||
vec!["test".to_string(), "test2".to_string(), "test3".to_string()]
|
||||
);
|
||||
|
||||
let columns_types: &[Type] = &[Type::BOOL, Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
let tree_view = TreeView::with_model(&list_store);
|
||||
|
||||
let values_to_add: &[&[(u32, &dyn ToValue)]] = &[
|
||||
&[(0, &Into::<Value>::into(true)), (1, &Into::<Value>::into("test"))],
|
||||
&[(0, &Into::<Value>::into(true)), (1, &Into::<Value>::into("test2"))],
|
||||
&[(0, &Into::<Value>::into(false)), (1, &Into::<Value>::into("test3"))],
|
||||
];
|
||||
for i in values_to_add {
|
||||
list_store.set(&list_store.append(), i);
|
||||
}
|
||||
assert_eq!(get_string_from_list_store(&tree_view, 1, Some(0)), vec!["test".to_string(), "test2".to_string()]);
|
||||
}
|
||||
|
||||
#[gtk4::test]
|
||||
fn test_check_if_list_store_column_have_all_same_values() {
|
||||
let columns_types: &[Type] = &[Type::BOOL];
|
||||
|
|
|
@ -6,7 +6,7 @@ use gdk4::gdk_pixbuf::Pixbuf;
|
|||
use glib::types::Type;
|
||||
use gtk4::gdk_pixbuf::InterpType;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::{CheckButton, Image, SelectionMode, TextView, TreeView};
|
||||
use gtk4::{CheckButton, Image, ScrolledWindow, SelectionMode, TextView, TreeModel, TreePath, TreeSelection, TreeView};
|
||||
|
||||
#[cfg(feature = "heif")]
|
||||
use czkawka_core::common::get_dynamic_image_from_heic;
|
||||
|
@ -24,7 +24,7 @@ use crate::help_combo_box::{
|
|||
use crate::help_functions::*;
|
||||
use crate::language_functions::LANGUAGES_ALL;
|
||||
use crate::localizer_core::generate_translation_hashmap;
|
||||
use crate::notebook_enums::NotebookMainEnum;
|
||||
use crate::notebook_enums::{NotebookMainEnum, NotebookUpperEnum};
|
||||
use crate::notebook_info::NOTEBOOKS_INFO;
|
||||
use crate::opening_selecting_records::*;
|
||||
|
||||
|
@ -91,208 +91,104 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
// Set step increment
|
||||
{
|
||||
let scale_similarity_similar_images = gui_data.main_notebook.scale_similarity_similar_images.clone();
|
||||
scale_similarity_similar_images.set_range(0_f64, SIMILAR_VALUES[0][5] as f64); // This defaults to value of minimal size of hash 8
|
||||
scale_similarity_similar_images.set_fill_level(SIMILAR_VALUES[0][5] as f64);
|
||||
scale_similarity_similar_images.adjustment().set_step_increment(1_f64);
|
||||
scale_set_min_max_values(&scale_similarity_similar_images, 0_f64, SIMILAR_VALUES[0][5] as f64, 15_f64, Some(1_f64));
|
||||
}
|
||||
// Set step increment
|
||||
{
|
||||
let scale_similarity_similar_videos = gui_data.main_notebook.scale_similarity_similar_videos.clone();
|
||||
scale_similarity_similar_videos.set_range(0_f64, MAX_TOLERANCE as f64); // This defaults to value of minimal size of hash 8
|
||||
scale_similarity_similar_videos.set_value(15_f64);
|
||||
scale_similarity_similar_videos.set_fill_level(MAX_TOLERANCE as f64);
|
||||
scale_similarity_similar_videos.adjustment().set_step_increment(1_f64);
|
||||
scale_set_min_max_values(&scale_similarity_similar_videos, 0_f64, MAX_TOLERANCE as f64, 15_f64, Some(1_f64));
|
||||
}
|
||||
|
||||
// Set Main Scrolled Window Treeviews
|
||||
{
|
||||
// Duplicate Files
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_duplicate_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_duplicate_finder.clone();
|
||||
|
||||
let image_preview = gui_data.main_notebook.image_preview_duplicates.clone();
|
||||
image_preview.hide();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::Duplicate as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
tree_view.selection().set_select_function(select_function_duplicates);
|
||||
|
||||
create_tree_view_duplicates(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_duplicate_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Empty Folders
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_empty_folder_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_empty_folder_finder.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::EmptyDirectories as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_empty_folders(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_empty_folder_finder");
|
||||
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Empty Files
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_empty_files_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_empty_files_finder.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::EmptyFiles as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_empty_files(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_empty_files_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Temporary Files
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_temporary_files_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_temporary_files_finder.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::Temporary as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_temporary_files(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_temporary_files_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Big Files
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_big_files_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_big_files_finder.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::BigFiles as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_big_files(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_big_files_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Similar Images
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_similar_images_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_similar_images_finder.clone();
|
||||
|
||||
let image_preview = gui_data.main_notebook.image_preview_similar_images.clone();
|
||||
image_preview.hide();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::SimilarImages as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
tree_view.selection().set_select_function(select_function_similar_images);
|
||||
|
||||
create_tree_view_similar_images(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_similar_images_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Similar Videos
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_similar_videos_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_similar_videos_finder.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::SimilarVideos as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
tree_view.selection().set_select_function(select_function_similar_videos);
|
||||
|
||||
create_tree_view_similar_videos(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_similar_videos_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Same Music
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_same_music_finder.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_same_music_finder.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::SameMusic as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
tree_view.selection().set_select_function(select_function_same_music);
|
||||
|
||||
create_tree_view_same_music(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_same_music_finder");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Invalid Symlinks
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_invalid_symlinks.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_invalid_symlinks.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::Symlinks as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_invalid_symlinks(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_invalid_symlinks");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Broken Files
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_broken_files.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_broken_files.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::BrokenFiles as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_broken_files(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_broken_files");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
// Bad Extensions
|
||||
{
|
||||
let scrolled_window = gui_data.main_notebook.scrolled_window_bad_extensions.clone();
|
||||
let tree_view = gui_data.main_notebook.tree_view_bad_extensions.clone();
|
||||
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[NotebookMainEnum::BadExtensions as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
|
||||
create_tree_view_broken_files(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_bad_extensions");
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_duplicate_finder,
|
||||
&gui_data.main_notebook.tree_view_duplicate_finder,
|
||||
NotebookMainEnum::Duplicate,
|
||||
Some(select_function_duplicates),
|
||||
create_tree_view_duplicates,
|
||||
Some(&gui_data.main_notebook.image_preview_duplicates),
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_similar_images_finder,
|
||||
&gui_data.main_notebook.tree_view_similar_images_finder,
|
||||
NotebookMainEnum::SimilarImages,
|
||||
Some(select_function_similar_images),
|
||||
create_tree_view_similar_images,
|
||||
Some(&gui_data.main_notebook.image_preview_similar_images),
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_similar_videos_finder,
|
||||
&gui_data.main_notebook.tree_view_similar_videos_finder,
|
||||
NotebookMainEnum::SimilarVideos,
|
||||
Some(select_function_similar_videos),
|
||||
create_tree_view_similar_videos,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_same_music_finder,
|
||||
&gui_data.main_notebook.tree_view_same_music_finder,
|
||||
NotebookMainEnum::SameMusic,
|
||||
Some(select_function_same_music),
|
||||
create_tree_view_same_music,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_empty_folder_finder,
|
||||
&gui_data.main_notebook.tree_view_empty_folder_finder,
|
||||
NotebookMainEnum::EmptyDirectories,
|
||||
None,
|
||||
create_tree_view_empty_folders,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_empty_files_finder,
|
||||
&gui_data.main_notebook.tree_view_empty_files_finder,
|
||||
NotebookMainEnum::EmptyFiles,
|
||||
None,
|
||||
create_tree_view_empty_files,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_temporary_files_finder,
|
||||
&gui_data.main_notebook.tree_view_temporary_files_finder,
|
||||
NotebookMainEnum::Temporary,
|
||||
None,
|
||||
create_tree_view_temporary_files,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_big_files_finder,
|
||||
&gui_data.main_notebook.tree_view_big_files_finder,
|
||||
NotebookMainEnum::BigFiles,
|
||||
None,
|
||||
create_tree_view_big_files,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_invalid_symlinks,
|
||||
&gui_data.main_notebook.tree_view_invalid_symlinks,
|
||||
NotebookMainEnum::Symlinks,
|
||||
None,
|
||||
create_tree_view_invalid_symlinks,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_broken_files,
|
||||
&gui_data.main_notebook.tree_view_broken_files,
|
||||
NotebookMainEnum::BrokenFiles,
|
||||
None,
|
||||
create_tree_view_broken_files,
|
||||
None,
|
||||
);
|
||||
create_column_types(
|
||||
&gui_data.main_notebook.scrolled_window_bad_extensions,
|
||||
&gui_data.main_notebook.tree_view_bad_extensions,
|
||||
NotebookMainEnum::BadExtensions,
|
||||
None,
|
||||
create_tree_view_bad_extensions,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +212,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
|
||||
create_tree_view_included_directories(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_upper_included_directories");
|
||||
tree_view.set_widget_name(get_tree_view_name_from_notebook_upper_enum(NotebookUpperEnum::IncludedDirectories));
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
|
||||
|
@ -350,7 +246,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
|
||||
create_tree_view_excluded_directories(&tree_view);
|
||||
|
||||
tree_view.set_widget_name("tree_view_upper_excluded_directories");
|
||||
tree_view.set_widget_name(get_tree_view_name_from_notebook_upper_enum(NotebookUpperEnum::ExcludedDirectories));
|
||||
scrolled_window.set_child(Some(&tree_view));
|
||||
scrolled_window.show();
|
||||
|
||||
|
@ -387,6 +283,32 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
connect_event_mouse(gui_data);
|
||||
}
|
||||
|
||||
fn create_column_types(
|
||||
scrolled_window: &ScrolledWindow,
|
||||
tree_view: &TreeView,
|
||||
notebook_enum: NotebookMainEnum,
|
||||
select_function: Option<fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool>,
|
||||
create_tree_view_func: fn(&TreeView),
|
||||
image_preview: Option<&Image>,
|
||||
) {
|
||||
if let Some(image_preview) = image_preview {
|
||||
image_preview.hide();
|
||||
}
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(NOTEBOOKS_INFO[notebook_enum as usize].columns_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
tree_view.selection().set_mode(SelectionMode::Multiple);
|
||||
if let Some(select_function) = select_function {
|
||||
tree_view.selection().set_select_function(select_function);
|
||||
}
|
||||
|
||||
create_tree_view_func(tree_view);
|
||||
|
||||
tree_view.set_widget_name(get_tree_view_name_from_notebook_enum(notebook_enum));
|
||||
scrolled_window.set_child(Some(tree_view));
|
||||
scrolled_window.show();
|
||||
}
|
||||
|
||||
fn connect_event_mouse(gui_data: &GuiData) {
|
||||
// GTK 4
|
||||
for gc in [
|
||||
|
|
|
@ -84,17 +84,7 @@ fn build_ui(application: &Application, arguments: &[OsString]) {
|
|||
let (glib_stop_sender, glib_stop_receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
|
||||
// Futures progress report
|
||||
let (futures_sender_duplicate_files, futures_receiver_duplicate_files): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_empty_files, futures_receiver_empty_files): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_empty_folder, futures_receiver_empty_folder): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_big_file, futures_receiver_big_files): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_same_music, futures_receiver_same_music): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_similar_images, futures_receiver_similar_images): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_similar_videos, futures_receiver_similar_videos): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_temporary, futures_receiver_temporary): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_invalid_symlinks, futures_receiver_invalid_symlinks): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_broken_files, futures_receiver_broken_files): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (futures_sender_bad_extensions, futures_receiver_bad_extensions): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
let (progress_sender, progress_receiver): (UnboundedSender<ProgressData>, UnboundedReceiver<ProgressData>) = mpsc::unbounded();
|
||||
|
||||
initialize_gui(&mut gui_data);
|
||||
validate_notebook_data(&gui_data); // Must be run after initialization of gui, to check if everything was properly setup
|
||||
|
@ -117,21 +107,7 @@ fn build_ui(application: &Application, arguments: &[OsString]) {
|
|||
|
||||
connect_button_delete(&gui_data);
|
||||
connect_button_save(&gui_data);
|
||||
connect_button_search(
|
||||
&gui_data,
|
||||
glib_stop_sender,
|
||||
futures_sender_duplicate_files,
|
||||
futures_sender_empty_files,
|
||||
futures_sender_empty_folder,
|
||||
futures_sender_big_file,
|
||||
futures_sender_same_music,
|
||||
futures_sender_similar_images,
|
||||
futures_sender_similar_videos,
|
||||
futures_sender_temporary,
|
||||
futures_sender_invalid_symlinks,
|
||||
futures_sender_broken_files,
|
||||
futures_sender_bad_extensions,
|
||||
);
|
||||
connect_button_search(&gui_data, glib_stop_sender, progress_sender);
|
||||
connect_button_select(&gui_data);
|
||||
connect_button_sort(&gui_data);
|
||||
connect_button_stop(&gui_data);
|
||||
|
@ -145,20 +121,7 @@ fn build_ui(application: &Application, arguments: &[OsString]) {
|
|||
connect_popover_select(&gui_data);
|
||||
connect_popover_sort(&gui_data);
|
||||
connect_compute_results(&gui_data, glib_stop_receiver);
|
||||
connect_progress_window(
|
||||
&gui_data,
|
||||
futures_receiver_duplicate_files,
|
||||
futures_receiver_empty_files,
|
||||
futures_receiver_empty_folder,
|
||||
futures_receiver_big_files,
|
||||
futures_receiver_same_music,
|
||||
futures_receiver_similar_images,
|
||||
futures_receiver_similar_videos,
|
||||
futures_receiver_temporary,
|
||||
futures_receiver_invalid_symlinks,
|
||||
futures_receiver_broken_files,
|
||||
futures_receiver_bad_extensions,
|
||||
);
|
||||
connect_progress_window(&gui_data, progress_receiver);
|
||||
connect_show_hide_ui(&gui_data);
|
||||
connect_settings(&gui_data);
|
||||
connect_button_about(&gui_data);
|
||||
|
|
Loading…
Reference in a new issue