Cleaned
This commit is contained in:
parent
b89d7ea00b
commit
3be13a914b
|
@ -10,6 +10,7 @@ use std::mem;
|
|||
use std::time::SystemTime;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use mime_guess::get_mime_extensions;
|
||||
use rayon::prelude::*;
|
||||
|
||||
|
@ -208,7 +209,7 @@ impl BadExtensions {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
if !self.check_files(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -283,7 +284,7 @@ impl BadExtensions {
|
|||
self.excluded_items.set_excluded_items(excluded_items, &mut self.text_messages);
|
||||
}
|
||||
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let result = DirTraversalBuilder::new()
|
||||
.root_dirs(self.directories.included_directories.clone())
|
||||
.group_by(|_fe| ())
|
||||
|
@ -317,14 +318,13 @@ impl BadExtensions {
|
|||
}
|
||||
}
|
||||
|
||||
fn look_for_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn look_for_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let system_time = SystemTime::now();
|
||||
|
||||
let check_was_stopped = AtomicBool::new(false); // Used for breaking from GUI and ending check thread
|
||||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
let progress_thread_handle = prepare_thread_handler_common(
|
||||
progress_sender,
|
||||
&progress_thread_run,
|
||||
|
|
|
@ -2,33 +2,28 @@ use std::collections::BTreeMap;
|
|||
use std::fs::{DirEntry, File, Metadata};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{sleep, JoinHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
use std::fs;
|
||||
use std::time::SystemTime;
|
||||
use std::{fs, thread};
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use humansize::format_size;
|
||||
use humansize::BINARY;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::common::{check_folder_children, send_info_and_wait_for_ending_all_threads, split_path};
|
||||
use crate::common::{Common, LOOP_DURATION};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time};
|
||||
use crate::common::Common;
|
||||
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_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
use crate::common_messages::Messages;
|
||||
use crate::common_traits::{DebugPrint, PrintResults, SaveResults};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProgressData {
|
||||
pub files_checked: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileEntry {
|
||||
pub path: PathBuf,
|
||||
|
@ -94,7 +89,7 @@ impl BigFile {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_big_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_big_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.optimize_directories();
|
||||
if !self.look_for_big_files(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -147,33 +142,7 @@ impl BigFile {
|
|||
self.allowed_extensions.set_allowed_extensions(allowed_extensions, &mut self.text_messages);
|
||||
}
|
||||
|
||||
pub fn prepare_thread_handler(
|
||||
&self,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_thread_run: &Arc<AtomicBool>,
|
||||
atomic_counter: &Arc<AtomicU64>,
|
||||
) -> JoinHandle<()> {
|
||||
if let Some(progress_sender) = progress_sender {
|
||||
let progress_send = progress_sender.clone();
|
||||
let progress_thread_run = progress_thread_run.clone();
|
||||
let atomic_counter = atomic_counter.clone();
|
||||
thread::spawn(move || loop {
|
||||
progress_send
|
||||
.unbounded_send(ProgressData {
|
||||
files_checked: atomic_counter.load(Ordering::Relaxed) as usize,
|
||||
})
|
||||
.unwrap();
|
||||
if !progress_thread_run.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(LOOP_DURATION as u64));
|
||||
})
|
||||
} else {
|
||||
thread::spawn(|| {})
|
||||
}
|
||||
}
|
||||
|
||||
fn look_for_big_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn look_for_big_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
let mut folders_to_check: Vec<PathBuf> = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector
|
||||
let mut old_map: BTreeMap<u64, Vec<FileEntry>> = Default::default();
|
||||
|
@ -184,8 +153,8 @@ impl BigFile {
|
|||
}
|
||||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicU64::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler(progress_sender, &progress_thread_run, &atomic_counter);
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = prepare_thread_handler_common(progress_sender, &progress_thread_run, &atomic_counter, 0, 0, 0, CheckingMethod::None);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -251,7 +220,7 @@ impl BigFile {
|
|||
|
||||
pub fn collect_file_entry(
|
||||
&self,
|
||||
atomic_counter: &Arc<AtomicU64>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
metadata: &Metadata,
|
||||
entry_data: &DirEntry,
|
||||
fe_result: &mut Vec<(u64, FileEntry)>,
|
||||
|
|
|
@ -5,11 +5,12 @@ use std::io::{BufReader, BufWriter};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{sleep, JoinHandle};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::{fs, mem, panic, thread};
|
||||
|
||||
use std::time::SystemTime;
|
||||
use std::{fs, mem, panic};
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use pdf::file::FileOptions;
|
||||
use pdf::object::ParseOptions;
|
||||
use pdf::PdfError;
|
||||
|
@ -17,23 +18,17 @@ use pdf::PdfError::Try;
|
|||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::common::{check_folder_children, create_crash_message, open_cache_folder, send_info_and_wait_for_ending_all_threads, Common, LOOP_DURATION, PDF_FILES_EXTENSIONS};
|
||||
use crate::common::{
|
||||
check_folder_children, create_crash_message, open_cache_folder, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, Common, 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};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
use crate::common_messages::Messages;
|
||||
use crate::common_traits::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProgressData {
|
||||
pub current_stage: u8,
|
||||
pub max_stage: u8,
|
||||
pub files_checked: usize,
|
||||
pub files_to_check: usize,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||
pub enum DeleteMethod {
|
||||
None,
|
||||
|
@ -121,7 +116,7 @@ impl BrokenFiles {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
if !self.check_files(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -197,39 +192,7 @@ impl BrokenFiles {
|
|||
self.excluded_items.set_excluded_items(excluded_items, &mut self.text_messages);
|
||||
}
|
||||
|
||||
pub fn prepare_thread_handler_broken_files(
|
||||
&self,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_thread_run: &Arc<AtomicBool>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
current_stage: u8,
|
||||
max_stage: u8,
|
||||
max_value: usize,
|
||||
) -> JoinHandle<()> {
|
||||
if let Some(progress_sender) = progress_sender {
|
||||
let progress_send = progress_sender.clone();
|
||||
let progress_thread_run = progress_thread_run.clone();
|
||||
let atomic_counter = atomic_counter.clone();
|
||||
thread::spawn(move || loop {
|
||||
progress_send
|
||||
.unbounded_send(ProgressData {
|
||||
current_stage,
|
||||
max_stage,
|
||||
files_checked: atomic_counter.load(Ordering::Relaxed),
|
||||
files_to_check: max_value,
|
||||
})
|
||||
.unwrap();
|
||||
if !progress_thread_run.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(LOOP_DURATION as u64));
|
||||
})
|
||||
} else {
|
||||
thread::spawn(|| {})
|
||||
}
|
||||
}
|
||||
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
let mut folders_to_check: Vec<PathBuf> = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector
|
||||
|
||||
|
@ -240,7 +203,7 @@ impl BrokenFiles {
|
|||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_broken_files(progress_sender, &progress_thread_run, &atomic_counter, 0, 1, 0);
|
||||
let progress_thread_handle = prepare_thread_handler_common(progress_sender, &progress_thread_run, &atomic_counter, 0, 1, 0, CheckingMethod::None);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -441,7 +404,7 @@ impl BrokenFiles {
|
|||
}
|
||||
}
|
||||
|
||||
fn look_for_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn look_for_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let system_time = SystemTime::now();
|
||||
|
||||
let loaded_hash_map;
|
||||
|
@ -481,7 +444,15 @@ impl BrokenFiles {
|
|||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_broken_files(progress_sender, &progress_thread_run, &atomic_counter, 1, 1, non_cached_files_to_check.len());
|
||||
let progress_thread_handle = prepare_thread_handler_common(
|
||||
progress_sender,
|
||||
&progress_thread_run,
|
||||
&atomic_counter,
|
||||
1,
|
||||
1,
|
||||
non_cached_files_to_check.len(),
|
||||
CheckingMethod::None,
|
||||
);
|
||||
|
||||
let mut vec_file_entry: Vec<FileEntry> = non_cached_files_to_check
|
||||
.into_par_iter()
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::{fs, thread};
|
|||
#[cfg(feature = "heif")]
|
||||
use anyhow::Result;
|
||||
use directories_next::ProjectDirs;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use image::{DynamicImage, ImageBuffer, Rgb};
|
||||
use imagepipe::{ImageSource, Pipeline};
|
||||
// #[cfg(feature = "heif")]
|
||||
|
@ -360,7 +361,7 @@ pub fn check_folder_children(
|
|||
}
|
||||
|
||||
pub fn prepare_thread_handler_common(
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_sender: Option<&UnboundedSender<ProgressData>>,
|
||||
progress_thread_run: &Arc<AtomicBool>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
current_stage: u8,
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::sync::Arc;
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::common::{prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
|
||||
|
@ -99,7 +100,7 @@ pub struct DirTraversalBuilder<'a, 'b, F> {
|
|||
group_by: Option<F>,
|
||||
root_dirs: Vec<PathBuf>,
|
||||
stop_receiver: Option<&'a Receiver<()>>,
|
||||
progress_sender: Option<&'b futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_sender: Option<&'b UnboundedSender<ProgressData>>,
|
||||
minimal_file_size: Option<u64>,
|
||||
maximal_file_size: Option<u64>,
|
||||
checking_method: CheckingMethod,
|
||||
|
@ -115,7 +116,7 @@ pub struct DirTraversal<'a, 'b, F> {
|
|||
group_by: F,
|
||||
root_dirs: Vec<PathBuf>,
|
||||
stop_receiver: Option<&'a Receiver<()>>,
|
||||
progress_sender: Option<&'b futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_sender: Option<&'b UnboundedSender<ProgressData>>,
|
||||
recursive_search: bool,
|
||||
directories: Directories,
|
||||
excluded_items: ExcludedItems,
|
||||
|
@ -168,7 +169,7 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn progress_sender(mut self, progress_sender: Option<&'b futures::channel::mpsc::UnboundedSender<ProgressData>>) -> Self {
|
||||
pub fn progress_sender(mut self, progress_sender: Option<&'b UnboundedSender<ProgressData>>) -> Self {
|
||||
self.progress_sender = progress_sender;
|
||||
self
|
||||
}
|
||||
|
@ -333,16 +334,8 @@ where
|
|||
folders_to_check.extend(self.root_dirs);
|
||||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_entry_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = prepare_thread_handler_common(
|
||||
self.progress_sender,
|
||||
&progress_thread_run,
|
||||
&atomic_entry_counter,
|
||||
0,
|
||||
self.max_stage,
|
||||
0,
|
||||
self.checking_method,
|
||||
);
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = prepare_thread_handler_common(self.progress_sender, &progress_thread_run, &atomic_counter, 0, self.max_stage, 0, self.checking_method);
|
||||
|
||||
let DirTraversal {
|
||||
collect,
|
||||
|
@ -386,7 +379,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_entry_counter.fetch_add(1, Ordering::Relaxed);
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
process_dir_in_dir_mode(
|
||||
&metadata,
|
||||
current_folder,
|
||||
|
@ -400,7 +393,7 @@ where
|
|||
);
|
||||
}
|
||||
(EntryType::File, Collect::Files) => {
|
||||
atomic_entry_counter.fetch_add(1, Ordering::Relaxed);
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
process_file_in_file_mode(
|
||||
&metadata,
|
||||
entry_data,
|
||||
|
@ -427,10 +420,10 @@ where
|
|||
set_as_not_empty_folder_list.push(current_folder.clone());
|
||||
}
|
||||
(EntryType::File, Collect::InvalidSymlinks) => {
|
||||
atomic_entry_counter.fetch_add(1, Ordering::Relaxed);
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
(EntryType::Symlink, Collect::InvalidSymlinks) => {
|
||||
atomic_entry_counter.fetch_add(1, Ordering::Relaxed);
|
||||
atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
process_symlink_in_symlink_mode(
|
||||
&metadata,
|
||||
entry_data,
|
||||
|
|
|
@ -15,9 +15,11 @@ use std::time::SystemTime;
|
|||
use std::{fs, mem};
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use humansize::format_size;
|
||||
use humansize::BINARY;
|
||||
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, Common};
|
||||
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData};
|
||||
|
@ -43,7 +45,7 @@ impl HashType {
|
|||
match self {
|
||||
HashType::Blake3 => Box::new(blake3::Hasher::new()),
|
||||
HashType::Crc32 => Box::new(crc32fast::Hasher::new()),
|
||||
HashType::Xxh3 => Box::new(xxhash_rust::xxh3::Xxh3::new()),
|
||||
HashType::Xxh3 => Box::new(Xxh3::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +149,7 @@ impl DuplicateFinder {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_duplicates(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_duplicates(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
self.use_reference_folders = !self.directories.reference_directories.is_empty();
|
||||
|
||||
|
@ -340,7 +342,7 @@ impl DuplicateFinder {
|
|||
&self.files_with_identical_size_names_referenced
|
||||
}
|
||||
|
||||
fn check_files_name(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files_name(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let group_by_func = if self.case_sensitive_name_comparison {
|
||||
|fe: &FileEntry| fe.path.file_name().unwrap().to_string_lossy().to_string()
|
||||
} else {
|
||||
|
@ -435,7 +437,7 @@ impl DuplicateFinder {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_files_size_name(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files_size_name(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let group_by_func = if self.case_sensitive_name_comparison {
|
||||
|fe: &FileEntry| (fe.size, fe.path.file_name().unwrap().to_string_lossy().to_string())
|
||||
} else {
|
||||
|
@ -535,7 +537,7 @@ impl DuplicateFinder {
|
|||
|
||||
/// Read file length and puts it to different boxes(each for different lengths)
|
||||
/// If in box is only 1 result, then it is removed
|
||||
fn check_files_size(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files_size(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let max_stage = match self.check_method {
|
||||
CheckingMethod::Size => 0,
|
||||
CheckingMethod::Hash => 2,
|
||||
|
@ -718,7 +720,7 @@ impl DuplicateFinder {
|
|||
fn prehashing(
|
||||
&mut self,
|
||||
stop_receiver: Option<&Receiver<()>>,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_sender: Option<&UnboundedSender<ProgressData>>,
|
||||
pre_checked_map: &mut BTreeMap<u64, Vec<FileEntry>>,
|
||||
) -> Option<()> {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
|
@ -886,7 +888,7 @@ impl DuplicateFinder {
|
|||
fn full_hashing(
|
||||
&mut self,
|
||||
stop_receiver: Option<&Receiver<()>>,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_sender: Option<&UnboundedSender<ProgressData>>,
|
||||
pre_checked_map: BTreeMap<u64, Vec<FileEntry>>,
|
||||
) -> Option<()> {
|
||||
let check_was_stopped = AtomicBool::new(false); // Used for breaking from GUI and ending check thread
|
||||
|
@ -1018,7 +1020,7 @@ impl DuplicateFinder {
|
|||
}
|
||||
|
||||
/// The slowest checking type, which must be applied after checking for size
|
||||
fn check_files_hash(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files_hash(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
assert_eq!(self.check_method, CheckingMethod::Hash);
|
||||
|
||||
let mut pre_checked_map: BTreeMap<u64, Vec<FileEntry>> = Default::default();
|
||||
|
@ -1617,7 +1619,7 @@ impl MyHasher for crc32fast::Hasher {
|
|||
}
|
||||
}
|
||||
|
||||
impl MyHasher for xxhash_rust::xxh3::Xxh3 {
|
||||
impl MyHasher for Xxh3 {
|
||||
fn update(&mut self, bytes: &[u8]) {
|
||||
self.write(bytes);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::path::PathBuf;
|
|||
use std::time::SystemTime;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::common::Common;
|
||||
use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData};
|
||||
|
@ -64,7 +65,7 @@ impl EmptyFiles {
|
|||
}
|
||||
|
||||
/// Finding empty files, save results to internal struct variables
|
||||
pub fn find_empty_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_empty_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
if !self.check_files(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -125,7 +126,7 @@ impl EmptyFiles {
|
|||
}
|
||||
|
||||
/// Check files for any with size == 0
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let result = DirTraversalBuilder::new()
|
||||
.root_dirs(self.directories.included_directories.clone())
|
||||
.group_by(|_fe| ())
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::path::PathBuf;
|
|||
use std::time::SystemTime;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::common::Common;
|
||||
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, FolderEmptiness, FolderEntry, ProgressData};
|
||||
|
@ -88,7 +89,7 @@ impl EmptyFolder {
|
|||
self.directories.set_excluded_directory(excluded_directory, &mut self.text_messages);
|
||||
}
|
||||
/// Public function used by CLI to search for empty folders
|
||||
pub fn find_empty_folders(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_empty_folders(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(true, &mut self.text_messages);
|
||||
if !self.check_for_empty_folders(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -128,7 +129,7 @@ impl EmptyFolder {
|
|||
|
||||
/// Function to check if folder are empty.
|
||||
/// Parameter `initial_checking` for second check before deleting to be sure that checked folder is still empty
|
||||
fn check_for_empty_folders(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_for_empty_folders(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let result = DirTraversalBuilder::new()
|
||||
.root_dirs(self.directories.included_directories.clone())
|
||||
.group_by(|_fe| ())
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::path::PathBuf;
|
|||
use std::time::SystemTime;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::common::Common;
|
||||
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, ErrorType, FileEntry, ProgressData};
|
||||
|
@ -63,7 +64,7 @@ impl InvalidSymlinks {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_invalid_links(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_invalid_links(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
if !self.check_files(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -124,7 +125,7 @@ impl InvalidSymlinks {
|
|||
}
|
||||
|
||||
/// Check files for any with size == 0
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let result = DirTraversalBuilder::new()
|
||||
.root_dirs(self.directories.included_directories.clone())
|
||||
.group_by(|_fe| ())
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::time::SystemTime;
|
|||
use std::{mem, panic};
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use lofty::TaggedFileExt;
|
||||
use lofty::{read_from, AudioFile, ItemKey};
|
||||
use rayon::prelude::*;
|
||||
|
@ -148,7 +149,7 @@ impl SameMusic {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_same_music(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_same_music(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
self.use_reference_folders = !self.directories.reference_directories.is_empty();
|
||||
if !self.check_files(stop_receiver, progress_sender) {
|
||||
|
@ -276,7 +277,7 @@ impl SameMusic {
|
|||
self.use_reference_folders
|
||||
}
|
||||
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
if !self.allowed_extensions.using_custom_extensions() {
|
||||
self.allowed_extensions.extend_allowed_extensions(AUDIO_FILES_EXTENSIONS);
|
||||
} else {
|
||||
|
@ -367,7 +368,7 @@ impl SameMusic {
|
|||
save_cache_to_file(&all_results, &mut self.text_messages, self.save_also_as_json);
|
||||
}
|
||||
|
||||
fn read_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn read_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
|
||||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.read_tags_load_cache();
|
||||
|
@ -515,7 +516,7 @@ impl SameMusic {
|
|||
Some(music_entry)
|
||||
}
|
||||
|
||||
fn check_for_duplicate_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_for_duplicate_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
assert_ne!(MusicSimilarity::NONE, self.music_similarity, "This can't be none");
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
|
||||
|
|
|
@ -6,12 +6,13 @@ use std::panic;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{sleep, JoinHandle};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::{mem, thread};
|
||||
|
||||
use std::mem;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use bk_tree::BKTree;
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use humansize::format_size;
|
||||
use humansize::BINARY;
|
||||
use image::GenericImageView;
|
||||
|
@ -22,10 +23,10 @@ use serde::{Deserialize, Serialize};
|
|||
#[cfg(feature = "heif")]
|
||||
use crate::common::get_dynamic_image_from_heic;
|
||||
use crate::common::{
|
||||
check_folder_children, create_crash_message, get_dynamic_image_from_raw_image, get_number_of_threads, open_cache_folder, send_info_and_wait_for_ending_all_threads, Common,
|
||||
HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, LOOP_DURATION, RAW_IMAGE_EXTENSIONS,
|
||||
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, Common, 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};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -42,14 +43,6 @@ pub const SIMILAR_VALUES: [[u32; 6]; 4] = [
|
|||
[6, 20, 40, 40, 40, 40], // 64
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProgressData {
|
||||
pub current_stage: u8,
|
||||
pub max_stage: u8,
|
||||
pub images_checked: usize,
|
||||
pub images_to_check: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct FileEntry {
|
||||
pub path: PathBuf,
|
||||
|
@ -254,7 +247,7 @@ impl SimilarImages {
|
|||
}
|
||||
|
||||
/// Public function used by CLI to search for empty folders
|
||||
pub fn find_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(true, &mut self.text_messages);
|
||||
self.use_reference_folders = !self.directories.reference_directories.is_empty();
|
||||
if !self.check_for_similar_images(stop_receiver, progress_sender) {
|
||||
|
@ -279,41 +272,9 @@ impl SimilarImages {
|
|||
// self.delete_folders = delete_folder;
|
||||
// }
|
||||
|
||||
pub fn prepare_thread_handler_similar_images(
|
||||
&self,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_thread_run: &Arc<AtomicBool>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
current_stage: u8,
|
||||
max_stage: u8,
|
||||
max_value: usize,
|
||||
) -> JoinHandle<()> {
|
||||
if let Some(progress_sender) = progress_sender {
|
||||
let progress_send = progress_sender.clone();
|
||||
let progress_thread_run = progress_thread_run.clone();
|
||||
let atomic_counter = atomic_counter.clone();
|
||||
thread::spawn(move || loop {
|
||||
progress_send
|
||||
.unbounded_send(ProgressData {
|
||||
current_stage,
|
||||
max_stage,
|
||||
images_checked: atomic_counter.load(Ordering::Relaxed),
|
||||
images_to_check: max_value,
|
||||
})
|
||||
.unwrap();
|
||||
if !progress_thread_run.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(LOOP_DURATION as u64));
|
||||
})
|
||||
} else {
|
||||
thread::spawn(|| {})
|
||||
}
|
||||
}
|
||||
|
||||
/// Function to check if folder are empty.
|
||||
/// Parameter `initial_checking` for second check before deleting to be sure that checked folder is still empty
|
||||
fn check_for_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_for_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
let mut folders_to_check: Vec<PathBuf> = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector
|
||||
|
||||
|
@ -337,7 +298,7 @@ impl SimilarImages {
|
|||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_similar_images(progress_sender, &progress_thread_run, &atomic_counter, 0, 3, 0);
|
||||
let progress_thread_handle = prepare_thread_handler_common(progress_sender, &progress_thread_run, &atomic_counter, 0, 2, 0, CheckingMethod::None);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -466,7 +427,7 @@ impl SimilarImages {
|
|||
// - Join already read hashes with hashes which were read from file
|
||||
// - Join all hashes and save it to file
|
||||
|
||||
fn hash_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn hash_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let hash_map_modification = SystemTime::now();
|
||||
|
||||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.hash_images_load_cache();
|
||||
|
@ -477,7 +438,15 @@ impl SimilarImages {
|
|||
let check_was_stopped = AtomicBool::new(false); // Used for breaking from GUI and ending check thread
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_similar_images(progress_sender, &progress_thread_run, &atomic_counter, 1, 3, non_cached_files_to_check.len());
|
||||
let progress_thread_handle = prepare_thread_handler_common(
|
||||
progress_sender,
|
||||
&progress_thread_run,
|
||||
&atomic_counter,
|
||||
1,
|
||||
2,
|
||||
non_cached_files_to_check.len(),
|
||||
CheckingMethod::None,
|
||||
);
|
||||
|
||||
let mut vec_file_entry: Vec<(FileEntry, ImHash)> = non_cached_files_to_check
|
||||
.into_par_iter()
|
||||
|
@ -610,7 +579,7 @@ impl SimilarImages {
|
|||
fn compare_hashes(
|
||||
&self,
|
||||
hashes_to_check: &[ImHash],
|
||||
atomic_mode_counter: &Arc<AtomicUsize>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
stop_receiver: Option<&Receiver<()>>,
|
||||
check_was_stopped: &AtomicBool,
|
||||
tolerance: u32,
|
||||
|
@ -632,7 +601,7 @@ impl SimilarImages {
|
|||
// Also don't add too often data to atomic variable
|
||||
const CYCLES_COUNTER: usize = 0b11_1111;
|
||||
if ((index & CYCLES_COUNTER) == CYCLES_COUNTER) && index != 0 {
|
||||
atomic_mode_counter.fetch_add(CYCLES_COUNTER, Ordering::Relaxed);
|
||||
atomic_counter.fetch_add(CYCLES_COUNTER, Ordering::Relaxed);
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
check_was_stopped.store(true, Ordering::Relaxed);
|
||||
return None;
|
||||
|
@ -839,7 +808,7 @@ impl SimilarImages {
|
|||
self.collect_hash_compare_result(hashes_parents, hashes_with_multiple_images, all_hashed_images, collected_similar_images, hashes_similarity);
|
||||
}
|
||||
|
||||
fn find_similar_hashes(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn find_similar_hashes(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
if self.image_hashes.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
@ -865,8 +834,8 @@ impl SimilarImages {
|
|||
} else {
|
||||
let check_was_stopped = AtomicBool::new(false); // Used for breaking from GUI and ending check thread
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_mode_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_similar_images(progress_sender, &progress_thread_run, &atomic_mode_counter, 2, 2, all_hashes.len());
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = prepare_thread_handler_common(progress_sender, &progress_thread_run, &atomic_counter, 2, 2, all_hashes.len(), CheckingMethod::None);
|
||||
|
||||
// Don't use hashes with multiple images in bktree, because they will always be master of group and cannot be find by other hashes
|
||||
|
||||
|
@ -877,7 +846,7 @@ impl SimilarImages {
|
|||
.map(|hashes_to_check| {
|
||||
self.compare_hashes(
|
||||
&hashes_to_check,
|
||||
&atomic_mode_counter,
|
||||
&atomic_counter,
|
||||
stop_receiver,
|
||||
&check_was_stopped,
|
||||
tolerance,
|
||||
|
|
|
@ -5,12 +5,13 @@ use std::io::*;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{sleep, JoinHandle};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::{mem, thread};
|
||||
|
||||
use std::mem;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use ffmpeg_cmdline_utils::FfmpegErrorKind::FfmpegNotFound;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use humansize::format_size;
|
||||
use humansize::BINARY;
|
||||
use rayon::prelude::*;
|
||||
|
@ -18,9 +19,9 @@ use serde::{Deserialize, Serialize};
|
|||
use vid_dup_finder_lib::HashCreationErrorKind::DetermineVideo;
|
||||
use vid_dup_finder_lib::{NormalizedTolerance, VideoHash};
|
||||
|
||||
use crate::common::{check_folder_children, send_info_and_wait_for_ending_all_threads, VIDEO_FILES_EXTENSIONS};
|
||||
use crate::common::{open_cache_folder, Common, LOOP_DURATION};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time};
|
||||
use crate::common::{check_folder_children, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, VIDEO_FILES_EXTENSIONS};
|
||||
use crate::common::{open_cache_folder, Common};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_extensions::Extensions;
|
||||
use crate::common_items::ExcludedItems;
|
||||
|
@ -31,14 +32,6 @@ use crate::localizer_core::generate_translation_hashmap;
|
|||
|
||||
pub const MAX_TOLERANCE: i32 = 20;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProgressData {
|
||||
pub current_stage: u8,
|
||||
pub max_stage: u8,
|
||||
pub videos_checked: usize,
|
||||
pub videos_to_check: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct FileEntry {
|
||||
pub path: PathBuf,
|
||||
|
@ -215,7 +208,7 @@ impl SimilarVideos {
|
|||
}
|
||||
|
||||
/// Public function used by CLI to search for empty folders
|
||||
pub fn find_similar_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_similar_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
if !check_if_ffmpeg_is_installed() {
|
||||
self.text_messages.errors.push(flc!("core_ffmpeg_not_found"));
|
||||
#[cfg(target_os = "windows")]
|
||||
|
@ -247,41 +240,9 @@ impl SimilarVideos {
|
|||
// self.delete_folders = delete_folder;
|
||||
// }
|
||||
|
||||
pub fn prepare_thread_handler_similar_video(
|
||||
&self,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_thread_run: &Arc<AtomicBool>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
current_stage: u8,
|
||||
max_stage: u8,
|
||||
max_value: usize,
|
||||
) -> JoinHandle<()> {
|
||||
if let Some(progress_sender) = progress_sender {
|
||||
let progress_send = progress_sender.clone();
|
||||
let progress_thread_run = progress_thread_run.clone();
|
||||
let atomic_counter = atomic_counter.clone();
|
||||
thread::spawn(move || loop {
|
||||
progress_send
|
||||
.unbounded_send(ProgressData {
|
||||
current_stage,
|
||||
max_stage,
|
||||
videos_checked: atomic_counter.load(Ordering::Relaxed),
|
||||
videos_to_check: max_value,
|
||||
})
|
||||
.unwrap();
|
||||
if !progress_thread_run.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(LOOP_DURATION as u64));
|
||||
})
|
||||
} else {
|
||||
thread::spawn(|| {})
|
||||
}
|
||||
}
|
||||
|
||||
/// Function to check if folder are empty.
|
||||
/// Parameter `initial_checking` for second check before deleting to be sure that checked folder is still empty
|
||||
fn check_for_similar_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_for_similar_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
let mut folders_to_check: Vec<PathBuf> = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector
|
||||
|
||||
|
@ -301,7 +262,7 @@ impl SimilarVideos {
|
|||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_similar_video(progress_sender, &progress_thread_run, &atomic_counter, 0, 1, 0);
|
||||
let progress_thread_handle = prepare_thread_handler_common(progress_sender, &progress_thread_run, &atomic_counter, 0, 1, 0, CheckingMethod::None);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
@ -424,7 +385,7 @@ impl SimilarVideos {
|
|||
(loaded_hash_map, records_already_cached, non_cached_files_to_check)
|
||||
}
|
||||
|
||||
fn sort_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn sort_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let hash_map_modification = SystemTime::now();
|
||||
|
||||
let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache_at_start();
|
||||
|
@ -436,7 +397,15 @@ impl SimilarVideos {
|
|||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_similar_video(progress_sender, &progress_thread_run, &atomic_counter, 1, 1, non_cached_files_to_check.len());
|
||||
let progress_thread_handle = prepare_thread_handler_common(
|
||||
progress_sender,
|
||||
&progress_thread_run,
|
||||
&atomic_counter,
|
||||
1,
|
||||
1,
|
||||
non_cached_files_to_check.len(),
|
||||
CheckingMethod::None,
|
||||
);
|
||||
|
||||
let mut vec_file_entry: Vec<FileEntry> = non_cached_files_to_check
|
||||
.par_iter()
|
||||
|
|
|
@ -4,15 +4,16 @@ use std::io::BufWriter;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{sleep, JoinHandle};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::{fs, thread};
|
||||
|
||||
use std::fs;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use futures::channel::mpsc::UnboundedSender;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::common::{check_folder_children, send_info_and_wait_for_ending_all_threads, Common, LOOP_DURATION};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time};
|
||||
use crate::common::{check_folder_children, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, Common};
|
||||
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData};
|
||||
use crate::common_directory::Directories;
|
||||
use crate::common_items::ExcludedItems;
|
||||
use crate::common_messages::Messages;
|
||||
|
@ -34,13 +35,6 @@ const TEMP_EXTENSIONS: &[&str] = &[
|
|||
".partial",
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProgressData {
|
||||
pub current_stage: u8,
|
||||
pub max_stage: u8,
|
||||
pub files_checked: usize,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||
pub enum DeleteMethod {
|
||||
None,
|
||||
|
@ -94,7 +88,7 @@ impl Temporary {
|
|||
}
|
||||
|
||||
/// Finding temporary files, save results to internal struct variables
|
||||
pub fn find_temporary_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
|
||||
pub fn find_temporary_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) {
|
||||
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
|
||||
if !self.check_files(stop_receiver, progress_sender) {
|
||||
self.stopped_search = true;
|
||||
|
@ -149,35 +143,7 @@ impl Temporary {
|
|||
self.excluded_items.set_excluded_items(excluded_items, &mut self.text_messages);
|
||||
}
|
||||
|
||||
fn prepare_thread_handler_temporary(
|
||||
&self,
|
||||
progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>,
|
||||
progress_thread_run: &Arc<AtomicBool>,
|
||||
atomic_counter: &Arc<AtomicUsize>,
|
||||
) -> JoinHandle<()> {
|
||||
if let Some(progress_sender) = progress_sender {
|
||||
let progress_send = progress_sender.clone();
|
||||
let progress_thread_run = progress_thread_run.clone();
|
||||
let atomic_counter = atomic_counter.clone();
|
||||
thread::spawn(move || loop {
|
||||
progress_send
|
||||
.unbounded_send(ProgressData {
|
||||
current_stage: 0,
|
||||
max_stage: 0,
|
||||
files_checked: atomic_counter.load(Ordering::Relaxed),
|
||||
})
|
||||
.unwrap();
|
||||
if !progress_thread_run.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(LOOP_DURATION as u64));
|
||||
})
|
||||
} else {
|
||||
thread::spawn(|| {})
|
||||
}
|
||||
}
|
||||
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&UnboundedSender<ProgressData>>) -> bool {
|
||||
let start_time: SystemTime = SystemTime::now();
|
||||
let mut folders_to_check: Vec<PathBuf> = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector
|
||||
|
||||
|
@ -188,7 +154,7 @@ impl Temporary {
|
|||
|
||||
let progress_thread_run = Arc::new(AtomicBool::new(true));
|
||||
let atomic_counter = Arc::new(AtomicUsize::new(0));
|
||||
let progress_thread_handle = self.prepare_thread_handler_temporary(progress_sender, &progress_thread_run, &atomic_counter);
|
||||
let progress_thread_handle = prepare_thread_handler_common(progress_sender, &progress_thread_run, &atomic_counter, 0, 0, 0, CheckingMethod::None);
|
||||
|
||||
while !folders_to_check.is_empty() {
|
||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use fs_extra::dir::CopyOptions;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use gtk4::prelude::*;
|
||||
|
@ -199,7 +200,7 @@ fn move_files_common(
|
|||
let thing = get_full_name_from_path_name(&path, &file_name);
|
||||
let destination_file = destination_folder.join(file_name);
|
||||
if Path::new(&thing).is_dir() {
|
||||
if let Err(e) = fs_extra::dir::move_dir(&thing, &destination_file, &fs_extra::dir::CopyOptions::new()) {
|
||||
if let Err(e) = fs_extra::dir::move_dir(&thing, &destination_file, &CopyOptions::new()) {
|
||||
messages += flg!("move_folder_failed", generate_translation_hashmap(vec![("name", thing), ("reason", e.to_string())])).as_str();
|
||||
messages += "\n";
|
||||
continue 'next_result;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use futures::channel::mpsc::UnboundedSender;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
@ -8,7 +9,8 @@ use gtk4::prelude::*;
|
|||
use czkawka_core::bad_extensions::BadExtensions;
|
||||
use czkawka_core::big_file::BigFile;
|
||||
use czkawka_core::broken_files::{BrokenFiles, CheckedTypes};
|
||||
use czkawka_core::common_dir_traversal;
|
||||
|
||||
use czkawka_core::common_dir_traversal::ProgressData;
|
||||
use czkawka_core::duplicate::DuplicateFinder;
|
||||
use czkawka_core::empty_files::EmptyFiles;
|
||||
use czkawka_core::empty_folder::EmptyFolder;
|
||||
|
@ -17,7 +19,6 @@ use czkawka_core::same_music::{MusicSimilarity, SameMusic};
|
|||
use czkawka_core::similar_images::SimilarImages;
|
||||
use czkawka_core::similar_videos::SimilarVideos;
|
||||
use czkawka_core::temporary::Temporary;
|
||||
use czkawka_core::*;
|
||||
|
||||
use crate::gui_structs::gui_data::GuiData;
|
||||
use crate::help_combo_box::{
|
||||
|
@ -33,17 +34,17 @@ use crate::{flg, DEFAULT_MAXIMAL_FILE_SIZE, DEFAULT_MINIMAL_CACHE_SIZE, DEFAULT_
|
|||
pub fn connect_button_search(
|
||||
gui_data: &GuiData,
|
||||
glib_stop_sender: Sender<Message>,
|
||||
futures_sender_duplicate_files: futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures_sender_empty_files: futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures_sender_empty_folder: futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures_sender_big_file: futures::channel::mpsc::UnboundedSender<big_file::ProgressData>,
|
||||
futures_sender_same_music: futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures_sender_similar_images: futures::channel::mpsc::UnboundedSender<similar_images::ProgressData>,
|
||||
futures_sender_similar_videos: futures::channel::mpsc::UnboundedSender<similar_videos::ProgressData>,
|
||||
futures_sender_temporary: futures::channel::mpsc::UnboundedSender<temporary::ProgressData>,
|
||||
futures_sender_invalid_symlinks: futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures_sender_broken_files: futures::channel::mpsc::UnboundedSender<broken_files::ProgressData>,
|
||||
futures_sender_bad_extensions: futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
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>,
|
||||
) {
|
||||
let check_button_settings_one_filesystem = gui_data.settings.check_button_settings_one_filesystem.clone();
|
||||
let combo_box_image_hash_size = gui_data.main_notebook.combo_box_image_hash_size.clone();
|
||||
|
|
|
@ -119,6 +119,7 @@ pub fn connect_popover_sort(gui_data: &GuiData) {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use glib::types::Type;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::{Popover, TreeView};
|
||||
|
||||
|
@ -126,7 +127,7 @@ mod test {
|
|||
|
||||
#[gtk4::test]
|
||||
fn test_sort_iters() {
|
||||
let columns_types: &[glib::types::Type] = &[glib::types::Type::U32, glib::types::Type::STRING];
|
||||
let columns_types: &[Type] = &[Type::U32, Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
|
||||
let values_to_add: &[&[(u32, &dyn ToValue)]] = &[&[(0, &2), (1, &"AAA")], &[(0, &3), (1, &"CCC")], &[(0, &1), (1, &"BBB")]];
|
||||
|
@ -156,7 +157,7 @@ mod test {
|
|||
|
||||
#[gtk4::test]
|
||||
pub fn test_popover_sort_general_simple() {
|
||||
let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL, glib::types::Type::STRING];
|
||||
let columns_types: &[Type] = &[Type::BOOL, Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
let tree_view = TreeView::builder().model(&list_store).build();
|
||||
let popover = Popover::new();
|
||||
|
@ -179,7 +180,7 @@ mod test {
|
|||
|
||||
#[gtk4::test]
|
||||
pub fn test_popover_sort_general() {
|
||||
let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL, glib::types::Type::STRING];
|
||||
let columns_types: &[Type] = &[Type::BOOL, Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
let tree_view = TreeView::builder().model(&list_store).build();
|
||||
let popover = Popover::new();
|
||||
|
|
|
@ -2,8 +2,8 @@ use futures::channel::mpsc::UnboundedReceiver;
|
|||
use futures::StreamExt;
|
||||
use gtk4::prelude::*;
|
||||
|
||||
use czkawka_core::common_dir_traversal;
|
||||
use czkawka_core::common_dir_traversal::ProgressData;
|
||||
use czkawka_core::{big_file, broken_files, common_dir_traversal, similar_images, similar_videos, temporary};
|
||||
|
||||
use crate::flg;
|
||||
use crate::gui_structs::gui_data::GuiData;
|
||||
|
@ -16,13 +16,13 @@ pub fn connect_progress_window(
|
|||
mut futures_receiver_duplicate_files: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_empty_files: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_empty_folder: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_big_files: UnboundedReceiver<big_file::ProgressData>,
|
||||
mut futures_receiver_big_files: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_same_music: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_similar_images: UnboundedReceiver<similar_images::ProgressData>,
|
||||
mut futures_receiver_similar_videos: UnboundedReceiver<similar_videos::ProgressData>,
|
||||
mut futures_receiver_temporary: UnboundedReceiver<temporary::ProgressData>,
|
||||
mut futures_receiver_similar_images: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_similar_videos: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_temporary: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_invalid_symlinks: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_broken_files: UnboundedReceiver<broken_files::ProgressData>,
|
||||
mut futures_receiver_broken_files: UnboundedReceiver<ProgressData>,
|
||||
mut futures_receiver_bad_extensions: UnboundedReceiver<ProgressData>,
|
||||
) {
|
||||
let main_context = glib::MainContext::default();
|
||||
|
@ -175,7 +175,7 @@ pub fn connect_progress_window(
|
|||
while let Some(item) = futures_receiver_big_files.next().await {
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_general_file",
|
||||
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
|
||||
generate_translation_hashmap(vec![("file_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
|
@ -257,18 +257,18 @@ pub fn connect_progress_window(
|
|||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_general_file",
|
||||
generate_translation_hashmap(vec![("file_number", item.images_checked.to_string())])
|
||||
generate_translation_hashmap(vec![("file_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
if item.images_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((1f64 + (item.images_checked) as f64 / item.images_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.images_checked) as f64 / item.images_to_check as f64);
|
||||
if item.entries_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((1f64 + (item.entries_checked) as f64 / item.entries_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.entries_checked) as f64 / item.entries_to_check as f64);
|
||||
taskbar_state.borrow().set_progress_value(
|
||||
(item.images_to_check + item.images_checked) as u64,
|
||||
item.images_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
(item.entries_to_check + item.entries_checked) as u64,
|
||||
item.entries_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
);
|
||||
} else {
|
||||
progress_bar_all_stages.set_fraction((item.current_stage as f64) / (item.max_stage + 1) as f64);
|
||||
|
@ -277,17 +277,17 @@ pub fn connect_progress_window(
|
|||
}
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_image",
|
||||
generate_translation_hashmap(vec![("file_checked", item.images_checked.to_string()), ("all_files", item.images_to_check.to_string())])
|
||||
generate_translation_hashmap(vec![("file_checked", item.entries_checked.to_string()), ("all_files", item.entries_to_check.to_string())])
|
||||
));
|
||||
}
|
||||
2 => {
|
||||
progress_bar_current_stage.show();
|
||||
if item.images_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((2f64 + (item.images_checked) as f64 / item.images_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.images_checked) as f64 / item.images_to_check as f64);
|
||||
if item.entries_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((2f64 + (item.entries_checked) as f64 / item.entries_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.entries_checked) as f64 / item.entries_to_check as f64);
|
||||
taskbar_state.borrow().set_progress_value(
|
||||
(item.images_to_check + item.images_checked) as u64,
|
||||
item.images_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
(item.entries_to_check + item.entries_checked) as u64,
|
||||
item.entries_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
);
|
||||
} else {
|
||||
progress_bar_all_stages.set_fraction((item.current_stage as f64) / (item.max_stage + 1) as f64);
|
||||
|
@ -296,7 +296,7 @@ pub fn connect_progress_window(
|
|||
}
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_comparing_image_hashes",
|
||||
generate_translation_hashmap(vec![("file_checked", item.images_checked.to_string()), ("all_files", item.images_to_check.to_string())])
|
||||
generate_translation_hashmap(vec![("file_checked", item.entries_checked.to_string()), ("all_files", item.entries_to_check.to_string())])
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
|
@ -320,18 +320,18 @@ pub fn connect_progress_window(
|
|||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_general_file",
|
||||
generate_translation_hashmap(vec![("file_number", item.videos_checked.to_string())])
|
||||
generate_translation_hashmap(vec![("file_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
if item.videos_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((1f64 + (item.videos_checked) as f64 / item.videos_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.videos_checked) as f64 / item.videos_to_check as f64);
|
||||
if item.entries_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((1f64 + (item.entries_checked) as f64 / item.entries_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.entries_checked) as f64 / item.entries_to_check as f64);
|
||||
taskbar_state.borrow().set_progress_value(
|
||||
(item.videos_to_check + item.videos_checked) as u64,
|
||||
item.videos_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
(item.entries_to_check + item.entries_checked) as u64,
|
||||
item.entries_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
);
|
||||
} else {
|
||||
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
|
||||
|
@ -340,7 +340,7 @@ pub fn connect_progress_window(
|
|||
}
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_video",
|
||||
generate_translation_hashmap(vec![("file_checked", item.videos_checked.to_string()), ("all_files", item.videos_to_check.to_string())])
|
||||
generate_translation_hashmap(vec![("file_checked", item.entries_checked.to_string()), ("all_files", item.entries_to_check.to_string())])
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
|
@ -359,7 +359,7 @@ pub fn connect_progress_window(
|
|||
while let Some(item) = futures_receiver_temporary.next().await {
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_general_file",
|
||||
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
|
||||
generate_translation_hashmap(vec![("file_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
|
@ -394,18 +394,19 @@ pub fn connect_progress_window(
|
|||
progress_bar_current_stage.hide();
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_general_file",
|
||||
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
|
||||
generate_translation_hashmap(vec![("file_number", item.entries_checked.to_string())])
|
||||
));
|
||||
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
|
||||
}
|
||||
1 => {
|
||||
progress_bar_current_stage.show();
|
||||
if item.files_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((1f64 + (item.files_checked) as f64 / item.files_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.files_checked) as f64 / item.files_to_check as f64);
|
||||
taskbar_state
|
||||
.borrow()
|
||||
.set_progress_value((item.files_to_check + item.files_checked) as u64, item.files_to_check as u64 * (item.max_stage + 1) as u64);
|
||||
if item.entries_to_check != 0 {
|
||||
progress_bar_all_stages.set_fraction((1f64 + (item.entries_checked) as f64 / item.entries_to_check as f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction((item.entries_checked) as f64 / item.entries_to_check as f64);
|
||||
taskbar_state.borrow().set_progress_value(
|
||||
(item.entries_to_check + item.entries_checked) as u64,
|
||||
item.entries_to_check as u64 * (item.max_stage + 1) as u64,
|
||||
);
|
||||
} else {
|
||||
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
|
||||
progress_bar_current_stage.set_fraction(0f64);
|
||||
|
@ -413,7 +414,7 @@ pub fn connect_progress_window(
|
|||
}
|
||||
label_stage.set_text(&flg!(
|
||||
"progress_scanning_broken_files",
|
||||
generate_translation_hashmap(vec![("file_checked", item.files_checked.to_string()), ("all_files", item.files_to_check.to_string())])
|
||||
generate_translation_hashmap(vec![("file_checked", item.entries_checked.to_string()), ("all_files", item.entries_to_check.to_string())])
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufReader;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crossbeam_channel::bounded;
|
||||
|
@ -122,7 +123,7 @@ impl GuiData {
|
|||
window_main.set_title(Some(&flg!("window_main_title")));
|
||||
window_main.show();
|
||||
|
||||
let pixbuf = Pixbuf::from_read(std::io::BufReader::new(ICON_ABOUT)).unwrap();
|
||||
let pixbuf = Pixbuf::from_read(BufReader::new(ICON_ABOUT)).unwrap();
|
||||
|
||||
window_main.set_application(Some(application));
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufReader;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use gdk4::gdk_pixbuf::{InterpType, Pixbuf};
|
||||
|
@ -714,7 +715,7 @@ const TYPE_OF_INTERPOLATION: InterpType = InterpType::Tiles;
|
|||
|
||||
pub fn set_icon_of_button<P: IsA<Widget>>(button: &P, data: &'static [u8]) {
|
||||
let image = get_custom_image_from_widget(&button.clone());
|
||||
let pixbuf = Pixbuf::from_read(std::io::BufReader::new(data)).unwrap();
|
||||
let pixbuf = Pixbuf::from_read(BufReader::new(data)).unwrap();
|
||||
let pixbuf = pixbuf.scale_simple(SIZE_OF_ICON, SIZE_OF_ICON, TYPE_OF_INTERPOLATION).unwrap();
|
||||
image.set_from_pixbuf(Some(&pixbuf));
|
||||
}
|
||||
|
@ -778,6 +779,7 @@ pub fn scale_step_function(scale: >k4::Scale, _scroll_type: ScrollType, value:
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use glib::types::Type;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::Orientation;
|
||||
use image::DynamicImage;
|
||||
|
@ -789,7 +791,7 @@ mod test {
|
|||
|
||||
#[gtk4::test]
|
||||
fn test_check_if_list_store_column_have_all_same_values() {
|
||||
let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL];
|
||||
let columns_types: &[Type] = &[Type::BOOL];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
|
||||
list_store.clear();
|
||||
|
@ -823,7 +825,7 @@ mod test {
|
|||
|
||||
#[gtk4::test]
|
||||
fn test_check_if_value_is_in_list_store() {
|
||||
let columns_types: &[glib::types::Type] = &[glib::types::Type::STRING];
|
||||
let columns_types: &[Type] = &[Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &"Koczkodan"), (0, &"Kachir")];
|
||||
for i in values_to_add {
|
||||
|
@ -833,7 +835,7 @@ mod test {
|
|||
assert!(check_if_value_is_in_list_store(&list_store, 0, "Kachir"));
|
||||
assert!(!check_if_value_is_in_list_store(&list_store, 0, "Koczkodan2"));
|
||||
|
||||
let columns_types: &[glib::types::Type] = &[glib::types::Type::STRING, glib::types::Type::STRING];
|
||||
let columns_types: &[Type] = &[Type::STRING, Type::STRING];
|
||||
let list_store = gtk4::ListStore::new(columns_types);
|
||||
let values_to_add: &[&[(u32, &dyn ToValue)]] = &[&[(0, &"Koczkodan"), (1, &"Krakus")], &[(0, &"Kachir"), (1, &"Wodnica")]];
|
||||
for i in values_to_add {
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::Path;
|
|||
use std::rc::Rc;
|
||||
|
||||
use gdk4::gdk_pixbuf::Pixbuf;
|
||||
use glib::types::Type;
|
||||
use gtk4::gdk_pixbuf::InterpType;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::{CheckButton, Image, SelectionMode, TextView, TreeView};
|
||||
|
@ -304,9 +305,9 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
let evk = gui_data.upper_notebook.evk_tree_view_included_directories.clone();
|
||||
let gc = gui_data.upper_notebook.gc_tree_view_included_directories.clone();
|
||||
|
||||
let col_types: [glib::types::Type; 2] = [
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::BOOL, // ReferenceButton
|
||||
let col_types: [Type; 2] = [
|
||||
Type::STRING, // Path
|
||||
Type::BOOL, // ReferenceButton
|
||||
];
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(&col_types);
|
||||
|
||||
|
@ -341,7 +342,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
let evk = gui_data.upper_notebook.evk_tree_view_excluded_directories.clone();
|
||||
let gc = gui_data.upper_notebook.gc_tree_view_excluded_directories.clone();
|
||||
|
||||
let col_types: [glib::types::Type; 1] = [glib::types::Type::STRING];
|
||||
let col_types: [Type; 1] = [Type::STRING];
|
||||
let list_store: gtk4::ListStore = gtk4::ListStore::new(&col_types);
|
||||
|
||||
tree_view.set_model(Some(&list_store));
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#![allow(clippy::type_complexity)]
|
||||
#![allow(clippy::needless_late_init)]
|
||||
|
||||
use futures::channel::mpsc;
|
||||
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
|
||||
|
@ -32,6 +34,7 @@ use connect_things::connect_settings::*;
|
|||
use connect_things::connect_show_hide_ui::*;
|
||||
use connect_things::connect_similar_image_size_change::*;
|
||||
use czkawka_core::common::{get_number_of_threads, set_number_of_threads};
|
||||
use czkawka_core::common_dir_traversal::ProgressData;
|
||||
use czkawka_core::*;
|
||||
use gui_structs::gui_data::*;
|
||||
|
||||
|
@ -80,50 +83,17 @@ 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): (
|
||||
futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<common_dir_traversal::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_empty_files, futures_receiver_empty_files): (
|
||||
futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<common_dir_traversal::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_empty_folder, futures_receiver_empty_folder): (
|
||||
futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<common_dir_traversal::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_big_file, futures_receiver_big_files): (
|
||||
futures::channel::mpsc::UnboundedSender<big_file::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<big_file::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_same_music, futures_receiver_same_music): (
|
||||
futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<common_dir_traversal::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_similar_images, futures_receiver_similar_images): (
|
||||
futures::channel::mpsc::UnboundedSender<similar_images::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<similar_images::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_similar_videos, futures_receiver_similar_videos): (
|
||||
futures::channel::mpsc::UnboundedSender<similar_videos::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<similar_videos::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_temporary, futures_receiver_temporary): (
|
||||
futures::channel::mpsc::UnboundedSender<temporary::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<temporary::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_invalid_symlinks, futures_receiver_invalid_symlinks): (
|
||||
futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<common_dir_traversal::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_broken_files, futures_receiver_broken_files): (
|
||||
futures::channel::mpsc::UnboundedSender<broken_files::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<broken_files::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
let (futures_sender_bad_extensions, futures_receiver_bad_extensions): (
|
||||
futures::channel::mpsc::UnboundedSender<common_dir_traversal::ProgressData>,
|
||||
futures::channel::mpsc::UnboundedReceiver<common_dir_traversal::ProgressData>,
|
||||
) = futures::channel::mpsc::unbounded();
|
||||
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();
|
||||
|
||||
initialize_gui(&mut gui_data);
|
||||
validate_notebook_data(&gui_data); // Must be run after initialization of gui, to check if everything was properly setup
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::help_functions::{
|
|||
ColumnsSameMusic, ColumnsSimilarImages, ColumnsSimilarVideos, ColumnsTemporaryFiles, PopoverTypes,
|
||||
};
|
||||
use crate::notebook_enums::{NotebookMainEnum, NUMBER_OF_NOTEBOOK_MAIN_TABS};
|
||||
use glib::types::Type;
|
||||
|
||||
pub struct NotebookObject {
|
||||
pub notebook_type: NotebookMainEnum,
|
||||
|
@ -16,7 +17,7 @@ pub struct NotebookObject {
|
|||
pub column_size: Option<i32>,
|
||||
pub column_size_as_bytes: Option<i32>,
|
||||
pub column_modification_as_secs: Option<i32>,
|
||||
pub columns_types: &'static [glib::types::Type],
|
||||
pub columns_types: &'static [Type],
|
||||
pub bottom_buttons: &'static [BottomButtonsEnum],
|
||||
}
|
||||
|
||||
|
@ -41,17 +42,17 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: Some(ColumnsDuplicates::SizeAsBytes as i32),
|
||||
column_modification_as_secs: Some(ColumnsDuplicates::ModificationAsSecs as i32),
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // ActivatableSelectButton
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Size
|
||||
glib::types::Type::U64, // SizeAsBytes
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
glib::types::Type::STRING, // Color
|
||||
glib::types::Type::BOOL, // IsHeader
|
||||
glib::types::Type::STRING, // TextColor
|
||||
Type::BOOL, // ActivatableSelectButton
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Size
|
||||
Type::U64, // SizeAsBytes
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
Type::STRING, // Color
|
||||
Type::BOOL, // IsHeader
|
||||
Type::STRING, // TextColor
|
||||
],
|
||||
bottom_buttons: &[
|
||||
BottomButtonsEnum::Save,
|
||||
|
@ -76,11 +77,11 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
@ -97,13 +98,13 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Size
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // SizeAsBytes
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Size
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // SizeAsBytes
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
@ -120,11 +121,11 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
@ -141,11 +142,11 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
@ -162,19 +163,19 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: Some(ColumnsSimilarImages::SizeAsBytes as i32),
|
||||
column_modification_as_secs: Some(ColumnsSimilarImages::ModificationAsSecs as i32),
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // ActivatableSelectButton
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Similarity
|
||||
glib::types::Type::STRING, // Size
|
||||
glib::types::Type::U64, // SizeAsBytes
|
||||
glib::types::Type::STRING, // Dimensions
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
glib::types::Type::STRING, // Color
|
||||
glib::types::Type::BOOL, // IsHeader
|
||||
glib::types::Type::STRING, // TextColor
|
||||
Type::BOOL, // ActivatableSelectButton
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Similarity
|
||||
Type::STRING, // Size
|
||||
Type::U64, // SizeAsBytes
|
||||
Type::STRING, // Dimensions
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
Type::STRING, // Color
|
||||
Type::BOOL, // IsHeader
|
||||
Type::STRING, // TextColor
|
||||
],
|
||||
bottom_buttons: &[
|
||||
BottomButtonsEnum::Save,
|
||||
|
@ -200,17 +201,17 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: Some(ColumnsSimilarVideos::SizeAsBytes as i32),
|
||||
column_modification_as_secs: Some(ColumnsSimilarVideos::ModificationAsSecs as i32),
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // ActivatableSelectButton
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Size
|
||||
glib::types::Type::U64, // SizeAsBytes
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
glib::types::Type::STRING, // Color
|
||||
glib::types::Type::BOOL, // IsHeader
|
||||
glib::types::Type::STRING, // TextColor
|
||||
Type::BOOL, // ActivatableSelectButton
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Size
|
||||
Type::U64, // SizeAsBytes
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
Type::STRING, // Color
|
||||
Type::BOOL, // IsHeader
|
||||
Type::STRING, // TextColor
|
||||
],
|
||||
bottom_buttons: &[
|
||||
BottomButtonsEnum::Save,
|
||||
|
@ -235,24 +236,24 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: Some(ColumnsSameMusic::SizeAsBytes as i32),
|
||||
column_modification_as_secs: Some(ColumnsSameMusic::ModificationAsSecs as i32),
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // ActivatableSelectButton
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Size
|
||||
glib::types::Type::U64, // SizeAsBytes
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // Title
|
||||
glib::types::Type::STRING, // Artist
|
||||
glib::types::Type::STRING, // Year
|
||||
glib::types::Type::STRING, // Bitrate
|
||||
glib::types::Type::U64, // BitrateAsNumber
|
||||
glib::types::Type::STRING, // Length
|
||||
glib::types::Type::STRING, // Genre
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
glib::types::Type::STRING, // Color
|
||||
glib::types::Type::BOOL, // IsHeader
|
||||
glib::types::Type::STRING, // TextColor
|
||||
Type::BOOL, // ActivatableSelectButton
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Size
|
||||
Type::U64, // SizeAsBytes
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // Title
|
||||
Type::STRING, // Artist
|
||||
Type::STRING, // Year
|
||||
Type::STRING, // Bitrate
|
||||
Type::U64, // BitrateAsNumber
|
||||
Type::STRING, // Length
|
||||
Type::STRING, // Genre
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
Type::STRING, // Color
|
||||
Type::BOOL, // IsHeader
|
||||
Type::STRING, // TextColor
|
||||
],
|
||||
bottom_buttons: &[
|
||||
BottomButtonsEnum::Save,
|
||||
|
@ -277,13 +278,13 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // DestinationPath
|
||||
glib::types::Type::STRING, // TypeOfError
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // DestinationPath
|
||||
Type::STRING, // TypeOfError
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
@ -300,12 +301,12 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // ErrorType
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // ErrorType
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
@ -322,13 +323,13 @@ pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
|
|||
column_size_as_bytes: None,
|
||||
column_modification_as_secs: None,
|
||||
columns_types: &[
|
||||
glib::types::Type::BOOL, // SelectionButton
|
||||
glib::types::Type::STRING, // Name
|
||||
glib::types::Type::STRING, // Path
|
||||
glib::types::Type::STRING, // CurrentExtension
|
||||
glib::types::Type::STRING, // ProperExtensions
|
||||
glib::types::Type::STRING, // Modification
|
||||
glib::types::Type::U64, // ModificationAsSecs
|
||||
Type::BOOL, // SelectionButton
|
||||
Type::STRING, // Name
|
||||
Type::STRING, // Path
|
||||
Type::STRING, // CurrentExtension
|
||||
Type::STRING, // ProperExtensions
|
||||
Type::STRING, // Modification
|
||||
Type::U64, // ModificationAsSecs
|
||||
],
|
||||
bottom_buttons: &[BottomButtonsEnum::Save, BottomButtonsEnum::Delete, BottomButtonsEnum::Select, BottomButtonsEnum::Move],
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue