Use max line length 180 instead 250 (#515)

This was a little too big value.
I don't like too much too small values, because code looks ugly.
pull/524/head
Rafał Mikrut 2 years ago committed by GitHub
parent 878550446d
commit 5db5d17afb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,3 +1,3 @@
newline_style = "Unix"
max_width = 250
max_width = 180
remove_nested_parens = true

@ -217,19 +217,37 @@ pub enum Commands {
#[derive(Debug, StructOpt)]
pub struct Directories {
#[structopt(short, long, parse(from_os_str), required = true, help = "Directorie(s) to search", long_help = "List of directorie(s) which will be searched(absolute path)")]
#[structopt(
short,
long,
parse(from_os_str),
required = true,
help = "Directorie(s) to search",
long_help = "List of directorie(s) which will be searched(absolute path)"
)]
pub directories: Vec<PathBuf>,
}
#[derive(Debug, StructOpt)]
pub struct ExcludedDirectories {
#[structopt(short, long, parse(from_os_str), help = "Excluded directorie(s)", long_help = "List of directorie(s) which will be excluded from search(absolute path)")]
#[structopt(
short,
long,
parse(from_os_str),
help = "Excluded directorie(s)",
long_help = "List of directorie(s) which will be excluded from search(absolute path)"
)]
pub excluded_directories: Vec<PathBuf>,
}
#[derive(Debug, StructOpt)]
pub struct ExcludedItems {
#[structopt(short = "E", long, help = "Excluded item(s)", long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)")]
#[structopt(
short = "E",
long,
help = "Excluded item(s)",
long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)"
)]
pub excluded_items: Vec<String>,
}

@ -175,7 +175,10 @@ impl BigFile {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -185,14 +188,20 @@ impl BigFile {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -217,7 +226,10 @@ impl BigFile {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -239,7 +251,10 @@ impl BigFile {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},
@ -430,7 +445,11 @@ impl SaveResults for BigFile {
impl PrintResults for BigFile {
fn print_results(&self) {
let start_time: SystemTime = SystemTime::now();
println!("Found {} files which take {}:", self.information.number_of_real_files, self.information.taken_space.file_size(options::BINARY).unwrap());
println!(
"Found {} files which take {}:",
self.information.number_of_real_files,
self.information.taken_space.file_size(options::BINARY).unwrap()
);
for (size, vector) in self.big_files.iter().rev() {
// TODO Align all to same width
for entry in vector {

@ -215,7 +215,10 @@ impl BrokenFiles {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -225,14 +228,20 @@ impl BrokenFiles {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -257,7 +266,10 @@ impl BrokenFiles {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -283,7 +295,10 @@ impl BrokenFiles {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},
@ -466,7 +481,10 @@ impl BrokenFiles {
vec_file_entry.push(file_entry.clone());
}
self.broken_files = vec_file_entry.iter().filter_map(|f| if f.error_string.is_empty() { None } else { Some(f.clone()) }).collect();
self.broken_files = vec_file_entry
.iter()
.filter_map(|f| if f.error_string.is_empty() { None } else { Some(f.clone()) })
.collect();
if self.use_cache {
// Must save all results to file, old loaded from file with all currently counted results
@ -619,7 +637,9 @@ fn save_cache_to_file(hashmap_file_entry: &BTreeMap<String, FileEntry>, text_mes
let file_handler = match OpenOptions::new().truncate(true).write(true).create(true).open(&cache_file) {
Ok(t) => t,
Err(e) => {
text_messages.messages.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
return;
}
};
@ -628,10 +648,18 @@ fn save_cache_to_file(hashmap_file_entry: &BTreeMap<String, FileEntry>, text_mes
for file_entry in hashmap_file_entry.values() {
// Only save to cache files which have more than 1KB
if file_entry.size > 1024 {
let string: String = format!("{}//{}//{}//{}", file_entry.path.display(), file_entry.size, file_entry.modified_date, file_entry.error_string);
let string: String = format!(
"{}//{}//{}//{}",
file_entry.path.display(),
file_entry.size,
file_entry.modified_date,
file_entry.error_string
);
if let Err(e) = writeln!(writer, "{}", string) {
text_messages.messages.push(format!("Failed to save some data to cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Failed to save some data to cache file {}, reason {}", cache_file.display(), e));
return;
};
}
@ -661,13 +689,17 @@ fn load_cache_from_file(text_messages: &mut Messages) -> Option<BTreeMap<String,
let line = match line {
Ok(t) => t,
Err(e) => {
text_messages.warnings.push(format!("Failed to load line number {} from cache file {}, reason {}", index + 1, cache_file.display(), e));
text_messages
.warnings
.push(format!("Failed to load line number {} from cache file {}, reason {}", index + 1, cache_file.display(), e));
return None;
}
};
let uuu = line.split("//").collect::<Vec<&str>>();
if uuu.len() != 4 {
text_messages.warnings.push(format!("Found invalid data in line {} - ({}) in cache file {}", index + 1, line, cache_file.display()));
text_messages
.warnings
.push(format!("Found invalid data in line {} - ({}) in cache file {}", index + 1, line, cache_file.display()));
continue;
}
// Don't load cache data if destination file not exists
@ -679,18 +711,26 @@ fn load_cache_from_file(text_messages: &mut Messages) -> Option<BTreeMap<String,
size: match uuu[1].parse::<u64>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid size value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid size value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
},
modified_date: match uuu[2].parse::<u64>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid modified date value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid modified date value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
},

@ -12,7 +12,11 @@ impl Common {
#[allow(unused_variables)]
pub fn print_time(start_time: SystemTime, end_time: SystemTime, function_name: String) {
#[cfg(debug_assertions)]
println!("Execution of function \"{}\" took {:?}", function_name, end_time.duration_since(start_time).expect("Time cannot go reverse."));
println!(
"Execution of function \"{}\" took {:?}",
function_name,
end_time.duration_since(start_time).expect("Time cannot go reverse.")
);
}
pub fn delete_multiple_entries(entries: &[String]) -> Vec<String> {

@ -29,34 +29,47 @@ impl Directories {
let mut checked_directories: Vec<PathBuf> = Vec::new();
for directory in directories {
if directory.to_string_lossy().contains('*') {
text_messages.warnings.push(format!("Included Directory Warning: Wildcards in path are not supported, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Included Directory Warning: Wildcards in path are not supported, ignoring {}", directory.display()));
continue;
}
#[cfg(not(target_family = "windows"))]
if directory.is_relative() {
text_messages.warnings.push(format!("Included Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Included Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
continue;
}
#[cfg(target_family = "windows")]
if directory.is_relative() && !directory.starts_with("\\") {
text_messages.warnings.push(format!("Included Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Included Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
continue;
}
if !directory.exists() {
text_messages.warnings.push(format!("Included Directory Warning: Provided folder path must exits, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Included Directory Warning: Provided folder path must exits, ignoring {}", directory.display()));
continue;
}
if !directory.is_dir() {
text_messages.warnings.push(format!("Included Directory Warning: Provided path must point at the directory, ignoring {}", directory.display()));
text_messages.warnings.push(format!(
"Included Directory Warning: Provided path must point at the directory, ignoring {}",
directory.display()
));
continue;
}
checked_directories.push(directory);
}
if checked_directories.is_empty() {
text_messages.errors.push("Included Directory ERROR: Not found even one correct path to included which is required.".to_string());
text_messages
.errors
.push("Included Directory ERROR: Not found even one correct path to included which is required.".to_string());
return false;
}
@ -79,21 +92,29 @@ impl Directories {
for directory in directories {
let directory_as_string = directory.to_string_lossy();
if directory_as_string == "/" {
text_messages.errors.push("Excluded Directory ERROR: Excluding / is pointless, because it means that no files will be scanned.".to_string());
text_messages
.errors
.push("Excluded Directory ERROR: Excluding / is pointless, because it means that no files will be scanned.".to_string());
break;
}
if directory_as_string.contains('*') {
text_messages.warnings.push(format!("Excluded Directory Warning: Wildcards in path are not supported, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Excluded Directory Warning: Wildcards in path are not supported, ignoring {}", directory.display()));
continue;
}
#[cfg(not(target_family = "windows"))]
if directory.is_relative() {
text_messages.warnings.push(format!("Excluded Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Excluded Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
continue;
}
#[cfg(target_family = "windows")]
if directory.is_relative() && !directory.starts_with("\\") {
text_messages.warnings.push(format!("Excluded Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
text_messages
.warnings
.push(format!("Excluded Directory Warning: Relative path are not supported, ignoring {}", directory.display()));
continue;
}
@ -102,7 +123,10 @@ impl Directories {
continue;
}
if !directory.is_dir() {
text_messages.warnings.push(format!("Excluded Directory Warning: Provided path must point at the directory, ignoring {}", directory.display()));
text_messages.warnings.push(format!(
"Excluded Directory Warning: Provided path must point at the directory, ignoring {}",
directory.display()
));
continue;
}
checked_directories.push(directory);
@ -228,7 +252,9 @@ impl Directories {
self.excluded_directories = optimized_excluded;
if self.included_directories.is_empty() {
text_messages.errors.push("Optimize Directories ERROR: Excluded directories overlaps all included directories.".to_string());
text_messages
.errors
.push("Optimize Directories ERROR: Excluded directories overlaps all included directories.".to_string());
return false;
}

@ -40,7 +40,9 @@ impl Extensions {
}
if extension[1..].contains(' ') {
text_messages.warnings.push(format!("{} is not valid extension because contains empty space inside", extension));
text_messages
.warnings
.push(format!("{} is not valid extension because contains empty space inside", extension));
continue;
}
@ -50,7 +52,9 @@ impl Extensions {
}
if self.file_extensions.is_empty() {
text_messages.messages.push("No valid extensions were provided, so allowing all extensions by default.".to_string());
text_messages
.messages
.push("No valid extensions were provided, so allowing all extensions by default.".to_string());
}
Common::print_time(start_time, SystemTime::now(), "set_allowed_extensions".to_string());
}

@ -44,7 +44,9 @@ impl ExcludedItems {
continue;
}
if !expression.contains('*') {
text_messages.warnings.push("Excluded Items Warning: Wildcard * is required in expression, ignoring ".to_string() + expression.as_str());
text_messages
.warnings
.push("Excluded Items Warning: Wildcard * is required in expression, ignoring ".to_string() + expression.as_str());
continue;
}

@ -347,7 +347,10 @@ impl DuplicateFinder {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -357,14 +360,20 @@ impl DuplicateFinder {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -389,7 +398,10 @@ impl DuplicateFinder {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -412,7 +424,10 @@ impl DuplicateFinder {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},
@ -535,7 +550,10 @@ impl DuplicateFinder {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -545,14 +563,20 @@ impl DuplicateFinder {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -577,7 +601,10 @@ impl DuplicateFinder {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -601,7 +628,10 @@ impl DuplicateFinder {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},
@ -1100,8 +1130,16 @@ impl DebugPrint for DuplicateFinder {
"Number of duplicated files by name(in groups) - {} ({})",
self.information.number_of_duplicated_files_by_name, self.information.number_of_groups_by_name
);
println!("Lost space by size - {} ({} bytes)", self.information.lost_space_by_size.file_size(options::BINARY).unwrap(), self.information.lost_space_by_size);
println!("Lost space by hash - {} ({} bytes)", self.information.lost_space_by_hash.file_size(options::BINARY).unwrap(), self.information.lost_space_by_hash);
println!(
"Lost space by size - {} ({} bytes)",
self.information.lost_space_by_size.file_size(options::BINARY).unwrap(),
self.information.lost_space_by_size
);
println!(
"Lost space by hash - {} ({} bytes)",
self.information.lost_space_by_hash.file_size(options::BINARY).unwrap(),
self.information.lost_space_by_hash
);
println!(
"Gained space by removing duplicated entries - {} ({} bytes)",
self.information.gained_space.file_size(options::BINARY).unwrap(),
@ -1151,7 +1189,11 @@ impl SaveResults for DuplicateFinder {
match self.check_method {
CheckingMethod::Name => {
if !self.files_with_identical_names.is_empty() {
writeln!(writer, "-------------------------------------------------Files with same names-------------------------------------------------").unwrap();
writeln!(
writer,
"-------------------------------------------------Files with same names-------------------------------------------------"
)
.unwrap();
writeln!(
writer,
"Found {} files in {} groups with same name(may have different content)",
@ -1171,7 +1213,11 @@ impl SaveResults for DuplicateFinder {
}
CheckingMethod::Size => {
if !self.files_with_identical_size.is_empty() {
writeln!(writer, "-------------------------------------------------Files with same size-------------------------------------------------").unwrap();
writeln!(
writer,
"-------------------------------------------------Files with same size-------------------------------------------------"
)
.unwrap();
writeln!(
writer,
"Found {} duplicated files which in {} groups which takes {}.",
@ -1192,7 +1238,11 @@ impl SaveResults for DuplicateFinder {
}
CheckingMethod::Hash => {
if !self.files_with_identical_hashes.is_empty() {
writeln!(writer, "-------------------------------------------------Files with same hashes-------------------------------------------------").unwrap();
writeln!(
writer,
"-------------------------------------------------Files with same hashes-------------------------------------------------"
)
.unwrap();
writeln!(
writer,
"Found {} duplicated files which in {} groups which takes {}.",
@ -1406,7 +1456,9 @@ pub fn save_hashes_to_file(hashmap: &BTreeMap<String, FileEntry>, text_messages:
let file_handler = match OpenOptions::new().truncate(true).write(true).create(true).open(&cache_file) {
Ok(t) => t,
Err(e) => {
text_messages.messages.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
return;
}
};
@ -1418,7 +1470,9 @@ pub fn save_hashes_to_file(hashmap: &BTreeMap<String, FileEntry>, text_messages:
let string: String = format!("{}//{}//{}//{}", file_entry.path.display(), file_entry.size, file_entry.modified_date, file_entry.hash);
if let Err(e) = writeln!(writer, "{}", string) {
text_messages.messages.push(format!("Failed to save some data to cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Failed to save some data to cache file {}, reason {}", cache_file.display(), e));
return;
};
}
@ -1480,15 +1534,20 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
let line = match line {
Ok(t) => t,
Err(e) => {
text_messages.warnings.push(format!("Failed to load line number {} from cache file {}, reason {}", index + 1, cache_file.display(), e));
text_messages
.warnings
.push(format!("Failed to load line number {} from cache file {}, reason {}", index + 1, cache_file.display(), e));
return None;
}
};
let uuu = line.split("//").collect::<Vec<&str>>();
if uuu.len() != 4 {
text_messages
.warnings
.push(format!("Found invalid data(too much or too low amount of data) in line {} - ({}) in cache file {}", index + 1, line, cache_file.display()));
text_messages.warnings.push(format!(
"Found invalid data(too much or too low amount of data) in line {} - ({}) in cache file {}",
index + 1,
line,
cache_file.display()
));
continue;
}
// Don't load cache data if destination file not exists
@ -1498,18 +1557,26 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
size: match uuu[1].parse::<u64>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid size value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid size value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
},
modified_date: match uuu[2].parse::<u64>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid modified date value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid modified date value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
},

@ -186,7 +186,10 @@ impl EmptyFiles {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -196,14 +199,20 @@ impl EmptyFiles {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -228,7 +237,10 @@ impl EmptyFiles {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -250,7 +262,10 @@ impl EmptyFiles {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},

@ -201,9 +201,10 @@ impl EmptyFolder {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
self.text_messages
.warnings
.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
self.text_messages.warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue;
}
};
@ -213,18 +214,20 @@ impl EmptyFolder {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
self.text_messages
.warnings
.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
self.text_messages.warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
self.text_messages
.warnings
.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
self.text_messages.warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -245,16 +248,18 @@ impl EmptyFolder {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
self.text_messages
.warnings
.push(fl!("core_folder_modified_before_epoch", generate_translation_hashmap(vec![("name", current_folder.display().to_string())])));
self.text_messages.warnings.push(fl!(
"core_folder_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_folder.display().to_string())])
));
0
}
},
Err(e) => {
self.text_messages
.warnings
.push(fl!("core_folder_no_modification_date", generate_translation_hashmap(vec![("name", current_folder.display().to_string()), ("reason", e.to_string())])));
self.text_messages.warnings.push(fl!(
"core_folder_no_modification_date",
generate_translation_hashmap(vec![("name", current_folder.display().to_string()), ("reason", e.to_string())])
));
0
}
},
@ -356,13 +361,21 @@ impl SaveResults for EmptyFolder {
};
let mut writer = BufWriter::new(file_handler);
if let Err(e) = writeln!(writer, "Results of searching {:?} with excluded directories {:?}", self.directories.included_directories, self.directories.excluded_directories) {
if let Err(e) = writeln!(
writer,
"Results of searching {:?} with excluded directories {:?}",
self.directories.included_directories, self.directories.excluded_directories
) {
self.text_messages.errors.push(format!("Failed to save results to file {}, reason {}", file_name, e));
return false;
}
if !self.empty_folder_list.is_empty() {
writeln!(writer, "-------------------------------------------------Empty folder list-------------------------------------------------").unwrap();
writeln!(
writer,
"-------------------------------------------------Empty folder list-------------------------------------------------"
)
.unwrap();
writeln!(writer, "Found {} empty folders", self.information.number_of_empty_folders).unwrap();
for name in self.empty_folder_list.keys() {
writeln!(writer, "{}", name.display()).unwrap();

@ -196,7 +196,10 @@ impl InvalidSymlinks {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -206,14 +209,20 @@ impl InvalidSymlinks {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -240,7 +249,10 @@ impl InvalidSymlinks {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -299,7 +311,10 @@ impl InvalidSymlinks {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},

@ -257,7 +257,10 @@ impl SameMusic {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -267,14 +270,20 @@ impl SameMusic {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -299,7 +308,10 @@ impl SameMusic {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -323,7 +335,10 @@ impl SameMusic {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},

@ -245,8 +245,11 @@ impl SimilarImages {
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
self.allowed_extensions
.extend_allowed_extensions(&[".jpg", ".jpeg", ".png" /*, ".bmp"*/, ".tiff", ".tif", ".tga", ".ff" /*, ".gif"*/, ".jif", ".jfi" /*, ".webp"*/]); // webp cannot be seen in preview, gif needs to be enabled after releasing image crate 0.24.0, bmp needs to be fixed in image crate
self.allowed_extensions.extend_allowed_extensions(&[
".jpg", ".jpeg", ".png", /*, ".bmp"*/
".tiff", ".tif", ".tga", ".ff", /*, ".gif"*/
".jif", ".jfi", /*, ".webp"*/
]); // webp cannot be seen in preview, gif needs to be enabled after releasing image crate 0.24.0, bmp needs to be fixed in image crate
// Add root folders for finding
for id in &self.directories.included_directories {
@ -300,7 +303,10 @@ impl SimilarImages {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -310,14 +316,20 @@ impl SimilarImages {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -342,7 +354,10 @@ impl SimilarImages {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -367,7 +382,10 @@ impl SimilarImages {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},
@ -451,7 +469,11 @@ impl SimilarImages {
mem::swap(&mut self.images_to_check, &mut non_cached_files_to_check);
}
Common::print_time(hash_map_modification, SystemTime::now(), "sort_images - reading data from cache and preparing them".to_string());
Common::print_time(
hash_map_modification,
SystemTime::now(),
"sort_images - reading data from cache and preparing them".to_string(),
);
let hash_map_modification = SystemTime::now();
//// PROGRESS THREAD START
@ -511,7 +533,10 @@ impl SimilarImages {
file_entry.dimensions = format!("{}x{}", dimensions.0, dimensions.1);
let hasher_config = HasherConfig::new().hash_size(self.hash_size as u32, self.hash_size as u32).hash_alg(self.hash_alg).resize_filter(self.image_filter);
let hasher_config = HasherConfig::new()
.hash_size(self.hash_size as u32, self.hash_size as u32)
.hash_alg(self.hash_alg)
.resize_filter(self.image_filter);
let hasher = hasher_config.to_hasher();
let hash = hasher.hash_image(&image);
@ -805,14 +830,22 @@ pub fn save_hashes_to_file(hashmap: &BTreeMap<String, FileEntry>, text_messages:
let file_handler = match OpenOptions::new().truncate(true).write(true).create(true).open(&cache_file) {
Ok(t) => t,
Err(e) => {
text_messages.messages.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
return;
}
};
let mut writer = BufWriter::new(file_handler);
for file_entry in hashmap.values() {
let mut string: String = format!("{}//{}//{}//{}", file_entry.path.display(), file_entry.size, file_entry.dimensions, file_entry.modified_date);
let mut string: String = format!(
"{}//{}//{}//{}",
file_entry.path.display(),
file_entry.size,
file_entry.dimensions,
file_entry.modified_date
);
for hash in &file_entry.hash {
string.push_str("//");
@ -820,14 +853,22 @@ pub fn save_hashes_to_file(hashmap: &BTreeMap<String, FileEntry>, text_messages:
}
if let Err(e) = writeln!(writer, "{}", string) {
text_messages.messages.push(format!("Failed to save some data to cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Failed to save some data to cache file {}, reason {}", cache_file.display(), e));
return;
};
}
}
}
pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache: bool, hash_size: u8, hash_alg: HashAlg, image_filter: FilterType) -> Option<BTreeMap<String, FileEntry>> {
pub fn load_hashes_from_file(
text_messages: &mut Messages,
delete_outdated_cache: bool,
hash_size: u8,
hash_alg: HashAlg,
image_filter: FilterType,
) -> Option<BTreeMap<String, FileEntry>> {
if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
let cache_dir = PathBuf::from(proj_dirs.cache_dir());
let cache_file = cache_dir.join(get_cache_file(&hash_size, &hash_alg, &image_filter));
@ -850,7 +891,9 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
let line = match line {
Ok(t) => t,
Err(e) => {
text_messages.warnings.push(format!("Failed to load line number {} from cache file {}, reason {}", index + 1, cache_file.display(), e));
text_messages
.warnings
.push(format!("Failed to load line number {} from cache file {}, reason {}", index + 1, cache_file.display(), e));
return None;
}
};
@ -873,9 +916,13 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
hash.push(match uuu[4 + i as usize].parse::<u8>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid hash value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid hash value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
});
@ -888,9 +935,13 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
size: match uuu[1].parse::<u64>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid size value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid size value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
},
@ -898,9 +949,13 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
modified_date: match uuu[3].parse::<u64>() {
Ok(t) => t,
Err(e) => {
text_messages
.warnings
.push(format!("Found invalid modified date value in line {} - ({}) in cache file {}, reason {}", index + 1, line, cache_file.display(), e));
text_messages.warnings.push(format!(
"Found invalid modified date value in line {} - ({}) in cache file {}, reason {}",
index + 1,
line,
cache_file.display(),
e
));
continue;
}
},
@ -919,7 +974,12 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
}
fn get_cache_file(hash_size: &u8, hash_alg: &HashAlg, image_filter: &FilterType) -> String {
format!("cache_similar_images_{}_{}_{}.txt", hash_size, convert_algorithm_to_string(hash_alg), convert_filters_to_string(image_filter))
format!(
"cache_similar_images_{}_{}_{}.txt",
hash_size,
convert_algorithm_to_string(hash_alg),
convert_filters_to_string(image_filter)
)
}
pub fn get_string_from_similarity(similarity: &Similarity, hash_size: u8) -> String {
@ -1024,7 +1084,13 @@ pub fn test_image_conversion_speed() {
match image::open(file_path) {
Ok(img_open) => {
for alg in [HashAlg::Blockhash, HashAlg::Gradient, HashAlg::DoubleGradient, HashAlg::VertGradient, HashAlg::Mean] {
for filter in [FilterType::Lanczos3, FilterType::CatmullRom, FilterType::Gaussian, FilterType::Nearest, FilterType::Triangle] {
for filter in [
FilterType::Lanczos3,
FilterType::CatmullRom,
FilterType::Gaussian,
FilterType::Nearest,
FilterType::Triangle,
] {
for size in [8, 16, 32, 64] {
let hasher_config = HasherConfig::new().hash_alg(alg).resize_filter(filter).hash_size(size, size);

@ -203,8 +203,9 @@ impl SimilarVideos {
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
self.allowed_extensions
.extend_allowed_extensions(&[".mp4", ".mpv", ".flv", ".mp4a", ".webm", ".mpg", ".mp2", ".mpeg", ".m4p", ".m4v", ".avi", ".wmv", ".qt", ".mov", ".swf", ".mkv"]);
self.allowed_extensions.extend_allowed_extensions(&[
".mp4", ".mpv", ".flv", ".mp4a", ".webm", ".mpg", ".mp2", ".mpeg", ".m4p", ".m4v", ".avi", ".wmv", ".qt", ".mov", ".swf", ".mkv",
]);
// Add root folders for finding
for id in &self.directories.included_directories {
@ -258,7 +259,10 @@ impl SimilarVideos {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -268,14 +272,20 @@ impl SimilarVideos {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -300,7 +310,10 @@ impl SimilarVideos {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
@ -324,7 +337,10 @@ impl SimilarVideos {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},
@ -400,7 +416,11 @@ impl SimilarVideos {
mem::swap(&mut self.videos_to_check, &mut non_cached_files_to_check);
}
Common::print_time(hash_map_modification, SystemTime::now(), "sort_videos - reading data from cache and preparing them".to_string());
Common::print_time(
hash_map_modification,
SystemTime::now(),
"sort_videos - reading data from cache and preparing them".to_string(),
);
let hash_map_modification = SystemTime::now();
//// PROGRESS THREAD START
@ -640,7 +660,9 @@ pub fn save_hashes_to_file(hashmap: &BTreeMap<String, FileEntry>, text_messages:
let file_handler = match OpenOptions::new().truncate(true).write(true).create(true).open(&cache_file) {
Ok(t) => t,
Err(e) => {
text_messages.messages.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Cannot create or open cache file {}, reason {}", cache_file.display(), e));
return;
}
};
@ -648,12 +670,16 @@ pub fn save_hashes_to_file(hashmap: &BTreeMap<String, FileEntry>, text_messages:
let writer = BufWriter::new(file_handler);
#[cfg(not(debug_assertions))]
if let Err(e) = bincode::serialize_into(writer, hashmap) {
text_messages.messages.push(format!("Cannot write data to cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Cannot write data to cache file {}, reason {}", cache_file.display(), e));
return;
}
#[cfg(debug_assertions)]
if let Err(e) = serde_json::to_writer(writer, hashmap) {
text_messages.messages.push(format!("Cannot write data to cache file {}, reason {}", cache_file.display(), e));
text_messages
.messages
.push(format!("Cannot write data to cache file {}, reason {}", cache_file.display(), e));
return;
}
@ -678,7 +704,9 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
let mut hashmap_loaded_entries: BTreeMap<String, FileEntry> = match serde_json::from_reader(reader) {
Ok(t) => t,
Err(e) => {
text_messages.warnings.push(format!("Failed to load data from cache file {}, reason {}", cache_file.display(), e));
text_messages
.warnings
.push(format!("Failed to load data from cache file {}, reason {}", cache_file.display(), e));
return None;
}
};
@ -686,7 +714,9 @@ pub fn load_hashes_from_file(text_messages: &mut Messages, delete_outdated_cache
let mut hashmap_loaded_entries: BTreeMap<String, FileEntry> = match bincode::deserialize_from(reader) {
Ok(t) => t,
Err(e) => {
text_messages.warnings.push(format!("Failed to load data from cache file {}, reason {}", cache_file.display(), e));
text_messages
.warnings
.push(format!("Failed to load data from cache file {}, reason {}", cache_file.display(), e));
return None;
}
};
@ -721,7 +751,11 @@ fn get_cache_file() -> String {
pub fn check_if_ffmpeg_is_installed() -> bool {
let vid = "999999999999999999.txt";
if let Err(DetermineVideo { src_path: _a, error: FfmpegNotFound }) = VideoHash::from_path(&vid) {
if let Err(DetermineVideo {
src_path: _a,
error: FfmpegNotFound,
}) = VideoHash::from_path(&vid)
{
return false;
}
true

@ -178,7 +178,10 @@ impl Temporary {
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_open_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_open_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
return (dir_result, warnings, fe_result);
}
};
@ -188,14 +191,20 @@ impl Temporary {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_entry_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_entry_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
warnings.push(fl!("core_cannot_read_metadata_dir", generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])));
warnings.push(fl!(
"core_cannot_read_metadata_dir",
generate_translation_hashmap(vec![("dir", current_folder.display().to_string()), ("reason", e.to_string())])
));
continue 'dir;
}
};
@ -220,15 +229,32 @@ impl Temporary {
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
warnings.push(fl!("core_file_not_utf8_name", generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])));
warnings.push(fl!(
"core_file_not_utf8_name",
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
));
continue 'dir;
}
}
.to_lowercase();
if !["#", "thumbs.db", ".bak", "~", ".tmp", ".temp", ".ds_store", ".crdownload", ".part", ".cache", ".dmp", ".download", ".partial"]
.iter()
.any(|f| file_name_lowercase.ends_with(f))
if ![
"#",
"thumbs.db",
".bak",
"~",
".tmp",
".temp",
".ds_store",
".crdownload",
".part",
".cache",
".dmp",
".download",
".partial",
]
.iter()
.any(|f| file_name_lowercase.ends_with(f))
{
continue 'dir;
}
@ -244,7 +270,10 @@ impl Temporary {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
warnings.push(fl!("core_file_modified_before_epoch", generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])));
warnings.push(fl!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
));
0
}
},

@ -176,7 +176,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsDuplicates::Path as u32, &directory),
(
ColumnsDuplicates::Modification as u32,
&(format!("{} - ({})", NaiveDateTime::from_timestamp(entry.modified_date as i64, 0), entry.size.file_size(options::BINARY).unwrap())),
&(format!(
"{} - ({})",
NaiveDateTime::from_timestamp(entry.modified_date as i64, 0),
entry.size.file_size(options::BINARY).unwrap()
)),
),
(ColumnsDuplicates::ModificationAsSecs as u32, &(entry.modified_date)),
(ColumnsDuplicates::Color as u32, &(MAIN_ROW_COLOR.to_string())),
@ -206,7 +210,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let values: [(u32, &dyn ToValue); 8] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Name as u32, &(format!("{} x {} ({} {})", vector.len(), size.file_size(options::BINARY).unwrap(), size, fl!("general_bytes")))),
(
ColumnsDuplicates::Name as u32,
&(format!("{} x {} ({} {})", vector.len(), size.file_size(options::BINARY).unwrap(), size, fl!("general_bytes"))),
),
(
ColumnsDuplicates::Path as u32,
&(format!(
@ -232,7 +239,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(ColumnsDuplicates::Modification as u32, &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())),
(
ColumnsDuplicates::Modification as u32,
&(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string()),
),
(ColumnsDuplicates::ModificationAsSecs as u32, &(entry.modified_date)),
(ColumnsDuplicates::Color as u32, &(MAIN_ROW_COLOR.to_string())),
(ColumnsDuplicates::TextColor as u32, &(TEXT_COLOR.to_string())),
@ -261,7 +271,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let values: [(u32, &dyn ToValue); 8] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Name as u32, &(format!("{} x {} ({} {})", vector.len(), size.file_size(options::BINARY).unwrap(), size, fl!("general_bytes")))),
(
ColumnsDuplicates::Name as u32,
&(format!("{} x {} ({} {})", vector.len(), size.file_size(options::BINARY).unwrap(), size, fl!("general_bytes"))),
),
(
ColumnsDuplicates::Path as u32,
&(format!(
@ -286,7 +299,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(ColumnsDuplicates::Modification as u32, &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())),
(
ColumnsDuplicates::Modification as u32,
&(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string()),
),
(ColumnsDuplicates::ModificationAsSecs as u32, &(entry.modified_date)),
(ColumnsDuplicates::Color as u32, &(MAIN_ROW_COLOR.to_string())),
(ColumnsDuplicates::TextColor as u32, &(TEXT_COLOR.to_string())),
@ -307,9 +323,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_duplication_state.borrow_mut() = df;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::Duplicate, &["save", "delete", "select", "symlink", "hardlink", "move"], duplicates_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::Duplicate,
&["save", "delete", "select", "symlink", "hardlink", "move"],
duplicates_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -342,7 +367,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsEmptyFolders::SelectionButton as u32, &false),
(ColumnsEmptyFolders::Name as u32, &file),
(ColumnsEmptyFolders::Path as u32, &directory),
(ColumnsEmptyFolders::Modification as u32, &(NaiveDateTime::from_timestamp(hashmap.get(&path).unwrap().modified_date as i64, 0).to_string())),
(
ColumnsEmptyFolders::Modification as u32,
&(NaiveDateTime::from_timestamp(hashmap.get(&path).unwrap().modified_date as i64, 0).to_string()),
),
(ColumnsEmptyFolders::ModificationAsSecs as u32, &(hashmap.get(&path).unwrap().modified_date as u64)),
];
list_store.set(&list_store.append(), &values);
@ -354,9 +382,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_empty_folders_state.borrow_mut() = ef;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::EmptyDirectories, &["save", "delete", "select", "move"], empty_folder_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::EmptyDirectories,
&["save", "delete", "select", "move"],
empty_folder_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -390,7 +427,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsEmptyFiles::SelectionButton as u32, &false),
(ColumnsEmptyFiles::Name as u32, &file),
(ColumnsEmptyFiles::Path as u32, &directory),
(ColumnsEmptyFiles::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsEmptyFiles::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsEmptyFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)),
];
list_store.set(&list_store.append(), &values);
@ -402,9 +442,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_empty_files_state.borrow_mut() = vf;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::EmptyFiles, &["save", "delete", "select", "move"], empty_files_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::EmptyFiles,
&["save", "delete", "select", "move"],
empty_files_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -435,10 +484,16 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 7] = [
(ColumnsBigFiles::SelectionButton as u32, &false),
(ColumnsBigFiles::Size as u32, &(format!("{} ({} {})", size.file_size(options::BINARY).unwrap(), size, fl!("general_bytes")))),
(
ColumnsBigFiles::Size as u32,
&(format!("{} ({} {})", size.file_size(options::BINARY).unwrap(), size, fl!("general_bytes"))),
),
(ColumnsBigFiles::Name as u32, &file),
(ColumnsBigFiles::Path as u32, &directory),
(ColumnsBigFiles::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsBigFiles::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsBigFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)),
(ColumnsBigFiles::SizeAsBytes as u32, &(size)),
];
@ -452,9 +507,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_big_files_state.borrow_mut() = bf;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::BigFiles, &["save", "delete", "select", "move"], biggest_files_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::BigFiles,
&["save", "delete", "select", "move"],
biggest_files_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -487,7 +551,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsTemporaryFiles::SelectionButton as u32, &false),
(ColumnsTemporaryFiles::Name as u32, &file),
(ColumnsTemporaryFiles::Path as u32, &directory),
(ColumnsTemporaryFiles::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsTemporaryFiles::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsTemporaryFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)),
];
list_store.set(&list_store.append(), &values);
@ -499,9 +566,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_temporary_files_state.borrow_mut() = tf;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::Temporary, &["save", "delete", "select", "move"], temporary_files_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::Temporary,
&["save", "delete", "select", "move"],
temporary_files_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -514,7 +590,16 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let base_images_size = sf.get_similar_images().len();
entry_info.set_text(format!("{} {} {} {}.", fl!("compute_found"), fl!("compute_duplicates_for"), base_images_size, fl!("compute_similar_image")).as_str());
entry_info.set_text(
format!(
"{} {} {} {}.",
fl!("compute_found"),
fl!("compute_duplicates_for"),
base_images_size,
fl!("compute_similar_image")
)
.as_str(),
);
// Create GUI
{
@ -558,13 +643,19 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let values: [(u32, &dyn ToValue); 12] = [
(ColumnsSimilarImages::ActivatableSelectButton as u32, &true),
(ColumnsSimilarImages::SelectionButton as u32, &false),
(ColumnsSimilarImages::Similarity as u32, &(similar_images::get_string_from_similarity(&file_entry.similarity, hash_size).to_string())),
(
ColumnsSimilarImages::Similarity as u32,
&(similar_images::get_string_from_similarity(&file_entry.similarity, hash_size).to_string()),
),
(ColumnsSimilarImages::Size as u32, &file_entry.size.file_size(options::BINARY).unwrap()),
(ColumnsSimilarImages::SizeAsBytes as u32, &file_entry.size),
(ColumnsSimilarImages::Dimensions as u32, &file_entry.dimensions),
(ColumnsSimilarImages::Name as u32, &file),
(ColumnsSimilarImages::Path as u32, &directory),
(ColumnsSimilarImages::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsSimilarImages::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsSimilarImages::ModificationAsSecs as u32, &(file_entry.modified_date)),
(ColumnsSimilarImages::Color as u32, &(MAIN_ROW_COLOR.to_string())),
(ColumnsSimilarImages::TextColor as u32, &(TEXT_COLOR.to_string())),
@ -580,9 +671,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_similar_images_state.borrow_mut() = sf;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::SimilarImages, &["save", "delete", "select", "symlink", "hardlink", "move"], base_images_size > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::SimilarImages,
&["save", "delete", "select", "symlink", "hardlink", "move"],
base_images_size > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -595,7 +695,16 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let base_videos_size = ff.get_similar_videos().len();
entry_info.set_text(format!("{} {} {} {}.", fl!("compute_found"), fl!("compute_duplicates_for"), base_videos_size, fl!("compute_similar_videos")).as_str());
entry_info.set_text(
format!(
"{} {} {} {}.",
fl!("compute_found"),
fl!("compute_duplicates_for"),
base_videos_size,
fl!("compute_similar_videos")
)
.as_str(),
);
// Create GUI
{
@ -641,7 +750,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsSimilarVideos::SizeAsBytes as u32, &file_entry.size),
(ColumnsSimilarVideos::Name as u32, &file),
(ColumnsSimilarVideos::Path as u32, &directory),
(ColumnsSimilarVideos::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsSimilarVideos::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsSimilarVideos::ModificationAsSecs as u32, &(file_entry.modified_date)),
(ColumnsSimilarVideos::Color as u32, &(MAIN_ROW_COLOR.to_string())),
(ColumnsSimilarVideos::TextColor as u32, &(TEXT_COLOR.to_string())),
@ -657,9 +769,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_similar_videos_state.borrow_mut() = ff;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::SimilarVideos, &["save", "delete", "select", "symlink", "hardlink", "move"], base_videos_size > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarVideos).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::SimilarVideos,
&["save", "delete", "select", "symlink", "hardlink", "move"],
base_videos_size > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarVideos).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -765,7 +886,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsSameMusic::AlbumTitle as u32, &file_entry.album_title),
(ColumnsSameMusic::AlbumArtist as u32, &file_entry.album_artist),
(ColumnsSameMusic::Year as u32, &file_entry.year.to_string()),
(ColumnsSameMusic::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsSameMusic::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsSameMusic::ModificationAsSecs as u32, &(file_entry.modified_date)),
(ColumnsSameMusic::Color as u32, &(MAIN_ROW_COLOR.to_string())),
(ColumnsSameMusic::TextColor as u32, &(TEXT_COLOR.to_string())),
@ -780,9 +904,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_same_music_state.borrow_mut() = mf;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::SameMusic, &["save", "delete", "select", "symlink", "hardlink", "move"], same_music_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::SameMusic,
&["save", "delete", "select", "symlink", "hardlink", "move"],
same_music_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -819,7 +952,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsInvalidSymlinks::Path as u32, &directory),
(ColumnsInvalidSymlinks::DestinationPath as u32, &file_entry.destination_path.to_string_lossy().to_string()),
(ColumnsInvalidSymlinks::TypeOfError as u32, &get_text_from_invalid_symlink_cause(&file_entry.type_of_error)),
(ColumnsInvalidSymlinks::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsInvalidSymlinks::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsInvalidSymlinks::ModificationAsSecs as u32, &(file_entry.modified_date as i64)),
];
list_store.set(&list_store.append(), &values);
@ -833,7 +969,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::Symlinks, &["save", "delete", "select", "move"], invalid_symlinks > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap(), &buttons_array, &buttons_names);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -868,7 +1008,10 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
(ColumnsBrokenFiles::Name as u32, &file),
(ColumnsBrokenFiles::Path as u32, &directory),
(ColumnsBrokenFiles::ErrorType as u32, &file_entry.error_string),
(ColumnsBrokenFiles::Modification as u32, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(
ColumnsBrokenFiles::Modification as u32,
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
),
(ColumnsBrokenFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)),
];
list_store.set(&list_store.append(), &values);
@ -880,9 +1023,18 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
{
*shared_broken_files_state.borrow_mut() = br;
set_specific_buttons_as_active(&shared_buttons, &NotebookMainEnum::BrokenFiles, &["save", "delete", "select", "move"], broken_files_number > 0);
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap(), &buttons_array, &buttons_names);
set_specific_buttons_as_active(
&shared_buttons,
&NotebookMainEnum::BrokenFiles,
&["save", "delete", "select", "move"],
broken_files_number > 0,
);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap(),
&buttons_array,
&buttons_names,
);
}
}
}
@ -892,7 +1044,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
});
}
fn set_specific_buttons_as_active(buttons_array: &Rc<RefCell<HashMap<NotebookMainEnum, HashMap<String, bool>>>>, notebook_enum: &NotebookMainEnum, buttons: &[&str], value_to_set: bool) {
fn set_specific_buttons_as_active(
buttons_array: &Rc<RefCell<HashMap<NotebookMainEnum, HashMap<String, bool>>>>,
notebook_enum: &NotebookMainEnum,
buttons: &[&str],
value_to_set: bool,
) {
for i in buttons {
*buttons_array.borrow_mut().get_mut(notebook_enum).unwrap().get_mut(*i).unwrap() = value_to_set;
}

@ -58,14 +58,45 @@ pub async fn delete_things(gui_data: GuiData) {
}
if let Some(column_color) = nb_object.column_color {
if !check_button_settings_confirm_group_deletion.is_active() || !check_if_deleting_all_files_in_group(tree_view, column_color, nb_object.column_selection, &window_main, &check_button_settings_confirm_group_deletion).await {
tree_remove(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
if !check_button_settings_confirm_group_deletion.is_active()
|| !check_if_deleting_all_files_in_group(
tree_view,
column_color,
nb_object.column_selection,
&window_main,
&check_button_settings_confirm_group_deletion,
)
.await
{
tree_remove(
tree_view,
nb_object.column_name,
nb_object.column_path,
column_color,
nb_object.column_selection,
&check_button_settings_use_trash,
&text_view_errors,
);
}
} else {
if nb_number == NotebookMainEnum::EmptyDirectories as u32 {
empty_folder_remover(tree_view, nb_object.column_name, nb_object.column_path, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
empty_folder_remover(
tree_view,
nb_object.column_name,
nb_object.column_path,
nb_object.column_selection,
&check_button_settings_use_trash,
&text_view_errors,
);
} else {
basic_remove(tree_view, nb_object.column_name, nb_object.column_path, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
basic_remove(
tree_view,
nb_object.column_name,
nb_object.column_path,
nb_object.column_selection,
&check_button_settings_use_trash,
&text_view_errors,
);
}
}
@ -82,7 +113,12 @@ pub async fn delete_things(gui_data: GuiData) {
}
}
pub async fn check_if_can_delete_files(check_button_settings_confirm_deletion: &gtk::CheckButton, window_main: &gtk::Window, number_of_selected_items: u64, number_of_selected_groups: u64) -> bool {
pub async fn check_if_can_delete_files(
check_button_settings_confirm_deletion: &gtk::CheckButton,
window_main: &gtk::Window,
number_of_selected_items: u64,
number_of_selected_groups: u64,
) -> bool {
if check_button_settings_confirm_deletion.is_active() {
let (confirmation_dialog_delete, check_button) = create_dialog_ask_for_deletion(window_main, number_of_selected_items, number_of_selected_groups);
@ -109,7 +145,10 @@ fn create_dialog_ask_for_deletion(window_main: &gtk::Window, number_of_selected_
let label: gtk::Label = gtk::Label::new(Some(&fl!("delete_question_label")));
let label2: gtk::Label = match number_of_selected_groups {
0 => gtk::Label::new(Some(&fl!("delete_items_label", generate_translation_hashmap(vec![("items", number_of_selected_items.to_string())])))),
0 => gtk::Label::new(Some(&fl!(
"delete_items_label",
generate_translation_hashmap(vec![("items", number_of_selected_items.to_string())])
))),
_ => gtk::Label::new(Some(&fl!(
"delete_items_groups_label",
generate_translation_hashmap(vec![("items", number_of_selected_items.to_string()), ("groups", number_of_selected_groups.to_string())])
@ -133,7 +172,11 @@ fn create_dialog_ask_for_deletion(window_main: &gtk::Window, number_of_selected_
}
fn create_dialog_group_deletion(window_main: &gtk::Window) -> (Dialog, CheckButton) {
let dialog = gtk::Dialog::builder().title(&fl!("delete_all_files_in_group_title")).transient_for(window_main).modal(true).build();
let dialog = gtk::Dialog::builder()
.title(&fl!("delete_all_files_in_group_title"))
.transient_for(window_main)
.modal(true)
.build();
let button_ok = dialog.add_button(&fl!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&fl!("general_close_button"), ResponseType::Cancel);
@ -154,7 +197,13 @@ fn create_dialog_group_deletion(window_main: &gtk::Window) -> (Dialog, CheckButt
(dialog, check_button)
}
pub async fn check_if_deleting_all_files_in_group(tree_view: &gtk::TreeView, column_color: i32, column_selection: i32, window_main: &gtk::Window, check_button_settings_confirm_group_deletion: &gtk::CheckButton) -> bool {
pub async fn check_if_deleting_all_files_in_group(
tree_view: &gtk::TreeView,
column_color: i32,
column_selection: i32,
window_main: &gtk::Window,
check_button_settings_confirm_group_deletion: &gtk::CheckButton,
) -> bool {
let model = get_list_store(tree_view);
let mut selected_all_records: bool = true;
@ -204,7 +253,14 @@ pub async fn check_if_deleting_all_files_in_group(tree_view: &gtk::TreeView, col
false
}
pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, check_button_settings_use_trash: &CheckButton, text_view_errors: &TextView) {
pub fn empty_folder_remover(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_selection: i32,
check_button_settings_use_trash: &CheckButton,
text_view_errors: &TextView,
) {
let use_trash = check_button_settings_use_trash.is_active();
let model = get_list_store(tree_view);
@ -301,7 +357,10 @@ pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, co
}
}
if error_happened {
messages += &fl!("delete_folder_failed", generate_translation_hashmap(vec![("dir", get_full_name_from_path_name(&path, &name))]));
messages += &fl!(
"delete_folder_failed",
generate_translation_hashmap(vec![("dir", get_full_name_from_path_name(&path, &name))])
);
messages += "\n";
}
}
@ -309,7 +368,14 @@ pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, co
text_view_errors.buffer().unwrap().set_text(messages.as_str());
}
pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, check_button_settings_use_trash: &CheckButton, text_view_errors: &TextView) {
pub fn basic_remove(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_selection: i32,
check_button_settings_use_trash: &CheckButton,
text_view_errors: &TextView,
) {
let use_trash = check_button_settings_use_trash.is_active();
let model = get_list_store(tree_view);
@ -348,7 +414,11 @@ pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_pat
}
Err(e) => {
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &name)), ("reason", e.to_string())])).as_str();
messages += fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &name)), ("reason", e.to_string())])
)
.as_str();
messages += "\n";
}
}
@ -358,7 +428,11 @@ pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_pat
model.remove(&iter);
}
Err(e) => {
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &name)), ("reason", e.to_string())])).as_str();
messages += fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &name)), ("reason", e.to_string())])
)
.as_str();
messages += "\n";
}
}
@ -369,7 +443,15 @@ pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_pat
}
// Remove all occurrences - remove every element which have same path and name as even non selected ones
pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, check_button_settings_use_trash: &CheckButton, text_view_errors: &TextView) {
pub fn tree_remove(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_color: i32,
column_selection: i32,
check_button_settings_use_trash: &CheckButton,
text_view_errors: &TextView,
) {
let use_trash = check_button_settings_use_trash.is_active();
let model = get_list_store(tree_view);
@ -421,11 +503,19 @@ pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path
for file_name in vec_file_name {
if !use_trash {
if let Err(e) = fs::remove_file(get_full_name_from_path_name(&path, &file_name)) {
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &file_name)), ("reason", e.to_string())])).as_str();
messages += fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &file_name)), ("reason", e.to_string())])
)
.as_str();
messages += "\n";
}
} else if let Err(e) = trash::delete(get_full_name_from_path_name(&path, &file_name)) {
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &file_name)), ("reason", e.to_string())])).as_str();
messages += fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &file_name)), ("reason", e.to_string())])
)
.as_str();
messages += "\n";
}

@ -67,7 +67,15 @@ pub async fn sym_hard_link_things(gui_data: GuiData, hardlinking: bool) {
return;
}
hardlink_symlink(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, hardlinking, &text_view_errors);
hardlink_symlink(
tree_view,
nb_object.column_name,
nb_object.column_path,
column_color,
nb_object.column_selection,
hardlinking,
&text_view_errors,
);
match &nb_object.notebook_type {
NotebookMainEnum::SimilarImages | NotebookMainEnum::Duplicate => {
@ -82,7 +90,15 @@ pub async fn sym_hard_link_things(gui_data: GuiData, hardlinking: bool) {
}
}
pub fn hardlink_symlink(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, hardlinking: bool, text_view_errors: &TextView) {
pub fn hardlink_symlink(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_color: i32,
column_selection: i32,
hardlinking: bool,
text_view_errors: &TextView,
) {
reset_text_view(text_view_errors);
let model = get_list_store(tree_view);
@ -193,7 +209,11 @@ pub fn hardlink_symlink(tree_view: &gtk::TreeView, column_file_name: i32, column
if let Err(e) = fs::remove_file(&file_to_symlink) {
add_text_to_text_view(
text_view_errors,
fl!("delete_file_failed", generate_translation_hashmap(vec![("name", file_to_symlink.to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", file_to_symlink.to_string()), ("reason", e.to_string())])
)
.as_str(),
);
continue;
};
@ -203,7 +223,11 @@ pub fn hardlink_symlink(tree_view: &gtk::TreeView, column_file_name: i32, column
if let Err(e) = std::os::unix::fs::symlink(&symhardlink_data.original_data, &file_to_symlink) {
add_text_to_text_view(
text_view_errors,
fl!("delete_file_failed", generate_translation_hashmap(vec![("name", file_to_symlink.to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", file_to_symlink.to_string()), ("reason", e.to_string())])
)
.as_str(),
);
continue;
};
@ -213,7 +237,11 @@ pub fn hardlink_symlink(tree_view: &gtk::TreeView, column_file_name: i32, column
if let Err(e) = std::os::windows::fs::symlink_file(&symhardlink_data.original_data, &file_to_symlink) {
add_text_to_text_view(
text_view_errors,
fl!("delete_file_failed", generate_translation_hashmap(vec![("name", file_to_symlink.to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"delete_file_failed",
generate_translation_hashmap(vec![("name", file_to_symlink.to_string()), ("reason", e.to_string())])
)
.as_str(),
);
continue;
};
@ -229,7 +257,11 @@ pub fn hardlink_symlink(tree_view: &gtk::TreeView, column_file_name: i32, column
}
fn create_dialog_non_group(window_main: &gtk::Window) -> Dialog {
let dialog = gtk::Dialog::builder().title(&fl!("hard_sym_invalid_selection_title_dialog")).transient_for(window_main).modal(true).build();
let dialog = gtk::Dialog::builder()
.title(&fl!("hard_sym_invalid_selection_title_dialog"))
.transient_for(window_main)
.modal(true)
.build();
let button_ok = dialog.add_button(&fl!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&fl!("general_close_button"), ResponseType::Cancel);
@ -333,7 +365,11 @@ pub async fn check_if_can_link_files(check_button_settings_confirm_link: &gtk::C
}
fn create_dialog_ask_for_linking(window_main: &gtk::Window) -> (Dialog, CheckButton) {
let dialog = gtk::Dialog::builder().title(&fl!("hard_sym_link_title_dialog")).transient_for(window_main).modal(true).build();
let dialog = gtk::Dialog::builder()
.title(&fl!("hard_sym_link_title_dialog"))
.transient_for(window_main)
.modal(true)
.build();
let button_ok = dialog.add_button(&fl!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&fl!("general_close_button"), ResponseType::Cancel);

@ -63,7 +63,16 @@ pub fn connect_button_move(gui_data: &GuiData) {
}
// TODO add progress bar
fn move_things(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: Option<i32>, column_selection: i32, entry_info: &gtk::Entry, text_view_errors: &gtk::TextView, window_main: &gtk::Window) {
fn move_things(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_color: Option<i32>,
column_selection: i32,
entry_info: &gtk::Entry,
text_view_errors: &gtk::TextView,
window_main: &gtk::Window,
) {
reset_text_view(text_view_errors);
let chooser = gtk::FileChooserDialog::builder()
@ -100,11 +109,27 @@ fn move_things(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i3
// }
if folders.len() != 1 {
add_text_to_text_view(&text_view_errors, fl!("move_files_choose_more_than_1_path", generate_translation_hashmap(vec![("path_number", folders.len().to_string())])).as_str());
add_text_to_text_view(
&text_view_errors,
fl!(
"move_files_choose_more_than_1_path",
generate_translation_hashmap(vec![("path_number", folders.len().to_string())])
)
.as_str(),
);
} else {
let folder = folders[0].clone();
if let Some(column_color) = column_color {
move_with_tree(&tree_view, column_file_name, column_path, column_color, column_selection, folder, &entry_info, &text_view_errors);
move_with_tree(
&tree_view,
column_file_name,
column_path,
column_color,
column_selection,
folder,
&entry_info,
&text_view_errors,
);
} else {
move_with_list(&tree_view, column_file_name, column_path, column_selection, folder, &entry_info, &text_view_errors);
}
@ -114,7 +139,16 @@ fn move_things(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i3
});
}
fn move_with_tree(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, destination_folder: PathBuf, entry_info: &gtk::Entry, text_view_errors: &gtk::TextView) {
fn move_with_tree(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_color: i32,
column_selection: i32,
destination_folder: PathBuf,
entry_info: &gtk::Entry,
text_view_errors: &gtk::TextView,
) {
let model = get_list_store(tree_view);
let mut selected_rows = Vec::new();
@ -144,7 +178,15 @@ fn move_with_tree(tree_view: &gtk::TreeView, column_file_name: i32, column_path:
clean_invalid_headers(&model, column_color);
}
fn move_with_list(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, destination_folder: PathBuf, entry_info: &gtk::Entry, text_view_errors: &gtk::TextView) {
fn move_with_list(
tree_view: &gtk::TreeView,
column_file_name: i32,
column_path: i32,
column_selection: i32,
destination_folder: PathBuf,
entry_info: &gtk::Entry,
text_view_errors: &gtk::TextView,
) {
let model = get_list_store(tree_view);
let mut selected_rows = Vec::new();
@ -168,7 +210,15 @@ fn move_with_list(tree_view: &gtk::TreeView, column_file_name: i32, column_path:
move_files_common(&selected_rows, &model, column_file_name, column_path, &destination_folder, entry_info, text_view_errors)
}
fn move_files_common(selected_rows: &[TreePath], model: &gtk::ListStore, column_file_name: i32, column_path: i32, destination_folder: &Path, entry_info: &gtk::Entry, text_view_errors: &gtk::TextView) {
fn move_files_common(
selected_rows: &[TreePath],
model: &gtk::ListStore,
column_file_name: i32,
column_path: i32,
destination_folder: &Path,
entry_info: &gtk::Entry,
text_view_errors: &gtk::TextView,
) {
let mut messages: String = "".to_string();
let mut moved_files: u32 = 0;
@ -200,7 +250,13 @@ fn move_files_common(selected_rows: &[TreePath], model: &gtk::ListStore, column_
moved_files += 1;
}
entry_info.set_text(fl!("move_stats", generate_translation_hashmap(vec![("num_files", moved_files.to_string()), ("all_files", selected_rows.len().to_string())])).as_str());
entry_info.set_text(
fl!(
"move_stats",
generate_translation_hashmap(vec![("num_files", moved_files.to_string()), ("all_files", selected_rows.len().to_string())])
)
.as_str(),
);
text_view_errors.buffer().unwrap().set_text(messages.as_str());
}

@ -83,11 +83,23 @@ pub fn connect_button_save(gui_data: &GuiData) {
shared_broken_files_state.borrow_mut().save_results_to_file(file_name);
}
}
post_save_things(file_name, &to_notebook_main_enum(notebook_main.current_page().unwrap()), &shared_buttons, &entry_info, &buttons_save_clone);
post_save_things(
file_name,
&to_notebook_main_enum(notebook_main.current_page().unwrap()),
&shared_buttons,
&entry_info,
&buttons_save_clone,
);
});
}
fn post_save_things(file_name: &str, type_of_tab: &NotebookMainEnum, shared_buttons: &Rc<RefCell<HashMap<NotebookMainEnum, HashMap<String, bool>>>>, entry_info: &Entry, buttons_save: &Button) {
fn post_save_things(
file_name: &str,
type_of_tab: &NotebookMainEnum,
shared_buttons: &Rc<RefCell<HashMap<NotebookMainEnum, HashMap<String, bool>>>>,
entry_info: &Entry,
buttons_save: &Button,
) {
entry_info.set_text(fl!("save_results_to_file", generate_translation_hashmap(vec![("name", file_name.to_string())])).as_str());
// Set state
{

@ -19,7 +19,9 @@ use czkawka_core::*;
use crate::fl;
use crate::gui_data::GuiData;
use crate::help_combo_box::{DUPLICATES_CHECK_METHOD_COMBO_BOX, DUPLICATES_HASH_TYPE_COMBO_BOX, IMAGES_HASH_SIZE_COMBO_BOX, IMAGES_HASH_TYPE_COMBO_BOX, IMAGES_RESIZE_ALGORITHM_COMBO_BOX};
use crate::help_combo_box::{
DUPLICATES_CHECK_METHOD_COMBO_BOX, DUPLICATES_HASH_TYPE_COMBO_BOX, IMAGES_HASH_SIZE_COMBO_BOX, IMAGES_HASH_TYPE_COMBO_BOX, IMAGES_RESIZE_ALGORITHM_COMBO_BOX,
};
use crate::help_functions::*;
use crate::notebook_enums::*;
use crate::taskbar_progress::tbp_flags::TBPF_NOPROGRESS;
@ -391,7 +393,11 @@ pub fn connect_button_search(
let _ = glib_stop_sender.send(Message::SameMusic(mf));
});
} else {
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(), &buttons_array, &buttons_names);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(),
&buttons_array,
&buttons_names,
);
entry_info.set_text(&fl!("search_not_choosing_any_music"));
show_dialog.store(false, Ordering::Relaxed);
}

@ -14,6 +14,10 @@ pub fn connect_notebook_tabs(gui_data: &GuiData) {
let current_tab_in_main_notebook = to_notebook_main_enum(number);
// Buttons
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&current_tab_in_main_notebook).unwrap(), &buttons_array, &buttons_names);
set_buttons(
&mut *shared_buttons.borrow_mut().get_mut(&current_tab_in_main_notebook).unwrap(),
&buttons_array,
&buttons_names,
);
});
}

@ -80,7 +80,15 @@ fn popover_reverse(popover: &gtk::Popover, tree_view: &gtk::TreeView, column_but
popover.popdown();
}
fn popover_all_except_oldest_newest(popover: &gtk::Popover, tree_view: &gtk::TreeView, column_color: i32, column_modification_as_secs: i32, column_file_name: i32, column_button_selection: u32, except_oldest: bool) {
fn popover_all_except_oldest_newest(
popover: &gtk::Popover,
tree_view: &gtk::TreeView,
column_color: i32,
column_modification_as_secs: i32,
column_file_name: i32,
column_button_selection: u32,
except_oldest: bool,
) {
let model = get_list_store(tree_view);
if let Some(iter) = model.iter_first() {
@ -147,7 +155,15 @@ fn popover_all_except_oldest_newest(popover: &gtk::Popover, tree_view: &gtk::Tre
popover.popdown();
}
fn popover_one_oldest_newest(popover: &gtk::Popover, tree_view: &gtk::TreeView, column_color: i32, column_modification_as_secs: i32, column_file_name: i32, column_button_selection: u32, check_oldest: bool) {
fn popover_one_oldest_newest(
popover: &gtk::Popover,
tree_view: &gtk::TreeView,
column_color: i32,
column_modification_as_secs: i32,
column_file_name: i32,
column_button_selection: u32,
check_oldest: bool,
) {
let model = get_list_store(tree_view);
if let Some(iter) = model.iter_first() {
@ -215,7 +231,16 @@ fn popover_one_oldest_newest(popover: &gtk::Popover, tree_view: &gtk::TreeView,
popover.popdown();
}
fn popover_custom_select_unselect(popover: &gtk::Popover, window_main: &Window, tree_view: &gtk::TreeView, column_color: Option<i32>, column_file_name: i32, column_path: i32, column_button_selection: u32, select_things: bool) {
fn popover_custom_select_unselect(
popover: &gtk::Popover,
window_main: &Window,
tree_view: &gtk::TreeView,
column_color: Option<i32>,
column_file_name: i32,
column_path: i32,
column_button_selection: u32,
select_things: bool,
) {
popover.popdown();
let window_title = match select_things {
@ -453,7 +478,15 @@ fn popover_custom_select_unselect(popover: &gtk::Popover, window_main: &Window,
}
}
fn popover_all_except_biggest_smallest(popover: &gtk::Popover, tree_view: &gtk::TreeView, column_color: i32, column_size_as_bytes: i32, column_dimensions: Option<i32>, column_button_selection: u32, except_biggest: bool) {
fn popover_all_except_biggest_smallest(
popover: &gtk::Popover,
tree_view: &gtk::TreeView,
column_color: i32,
column_size_as_bytes: i32,
column_dimensions: Option<i32>,
column_button_selection: u32,
except_biggest: bool,
) {
let model = get_list_store(tree_view);
if let Some(iter) = model.iter_first() {

@ -43,7 +43,10 @@ pub fn connect_progress_window(
progress_bar_current_stage.hide();
// progress_bar_all_stages.hide();
progress_bar_all_stages.set_fraction(0 as f64);
label_stage.set_text(&fl!("progress_scanning_size", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_size",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
// Hash - first 1KB file
@ -53,7 +56,9 @@ pub fn connect_progress_window(
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);
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);
} else {
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);
@ -70,9 +75,10 @@ pub fn connect_progress_window(
if item.files_to_check != 0 {
progress_bar_all_stages.set_fraction((2f64 + (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((2 * item.files_to_check + item.files_checked) as u64, item.files_to_check as u64 * (item.max_stage + 1) as u64);
taskbar_state.borrow().set_progress_value(
(2 * item.files_to_check + item.files_checked) as u64,
item.files_to_check as u64 * (item.max_stage + 1) as u64,
);
} else {
progress_bar_all_stages.set_fraction((2f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);
@ -93,14 +99,20 @@ pub fn connect_progress_window(
label_stage.show();
grid_progress_stages.hide();
label_stage.set_text(&fl!("progress_scanning_name", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_name",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
duplicate::CheckingMethod::Size => {
label_stage.show();
grid_progress_stages.hide();
label_stage.set_text(&fl!("progress_scanning_size", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_size",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
duplicate::CheckingMethod::None => {
@ -117,7 +129,10 @@ pub fn connect_progress_window(
let taskbar_state = gui_data.taskbar_state.clone();
let future = async move {
while let Some(item) = futures_receiver_empty_files.next().await {
label_stage.set_text(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
};
@ -129,7 +144,10 @@ pub fn connect_progress_window(
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(&fl!("progress_scanning_empty_folders", generate_translation_hashmap(vec![("folder_number", item.folders_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_empty_folders",
generate_translation_hashmap(vec![("folder_number", item.folders_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
};
@ -141,7 +159,10 @@ pub fn connect_progress_window(
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(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
};
@ -158,7 +179,10 @@ pub fn connect_progress_window(
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.music_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.music_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
@ -166,7 +190,9 @@ pub fn connect_progress_window(
if item.music_to_check != 0 {
progress_bar_all_stages.set_fraction((1f64 + (item.music_checked) as f64 / item.music_to_check as f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction((item.music_checked) as f64 / item.music_to_check as f64);
taskbar_state.borrow().set_progress_value((item.music_to_check + item.music_checked) as u64, item.music_to_check as u64 * (item.max_stage + 1) as u64);
taskbar_state
.borrow()
.set_progress_value((item.music_to_check + item.music_checked) as u64, item.music_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);
@ -181,9 +207,10 @@ pub fn connect_progress_window(
if item.music_to_check != 0 {
progress_bar_all_stages.set_fraction((2f64 + (item.music_checked) as f64 / item.music_to_check as f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction((item.music_checked) as f64 / item.music_to_check as f64);
taskbar_state
.borrow()
.set_progress_value((2 * item.music_to_check + item.music_checked) as u64, item.music_to_check as u64 * (item.max_stage + 1) as u64);
taskbar_state.borrow().set_progress_value(
(2 * item.music_to_check + item.music_checked) as u64,
item.music_to_check as u64 * (item.max_stage + 1) as u64,
);
} else {
progress_bar_all_stages.set_fraction((2f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);
@ -213,7 +240,10 @@ pub fn connect_progress_window(
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.images_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.images_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
@ -221,9 +251,10 @@ pub fn connect_progress_window(
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);
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);
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,
);
} else {
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);
@ -253,7 +284,10 @@ pub fn connect_progress_window(
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.videos_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.videos_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
@ -261,9 +295,10 @@ pub fn connect_progress_window(
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);
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);
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,
);
} else {
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);
@ -288,7 +323,10 @@ pub fn connect_progress_window(
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(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
};
@ -300,7 +338,10 @@ pub fn connect_progress_window(
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(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
};
@ -317,7 +358,10 @@ pub fn connect_progress_window(
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&fl!("progress_scanning_general_file", generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])));
label_stage.set_text(&fl!(
"progress_scanning_general_file",
generate_translation_hashmap(vec![("file_number", item.files_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
@ -325,7 +369,9 @@ pub fn connect_progress_window(
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);
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);
} else {
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);

@ -80,9 +80,18 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) {
}
fn add_chosen_directories(window_main: &Window, tree_view: &TreeView, excluded_items: bool) {
let folders_to = if excluded_items { fl!("exclude_folders_dialog_title") } else { fl!("include_folders_dialog_title") };
let file_chooser = gtk::FileChooserDialog::builder().title(&folders_to).action(gtk::FileChooserAction::SelectFolder).transient_for(window_main).modal(true).build();
let folders_to = if excluded_items {
fl!("exclude_folders_dialog_title")
} else {
fl!("include_folders_dialog_title")
};
let file_chooser = gtk::FileChooserDialog::builder()
.title(&folders_to)
.action(gtk::FileChooserAction::SelectFolder)
.transient_for(window_main)
.modal(true)
.build();
file_chooser.add_button(&fl!("general_ok_button"), ResponseType::Ok);
file_chooser.add_button(&fl!("general_close_button"), ResponseType::Cancel);
@ -120,7 +129,11 @@ fn add_chosen_directories(window_main: &Window, tree_view: &TreeView, excluded_i
}
fn add_manually_directories(window_main: &Window, tree_view: &TreeView) {
let dialog = gtk::Dialog::builder().title(&fl!("include_manually_directories_dialog_title")).transient_for(window_main).modal(true).build();
let dialog = gtk::Dialog::builder()
.title(&fl!("include_manually_directories_dialog_title"))
.transient_for(window_main)
.modal(true)
.build();
dialog.add_button(&fl!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&fl!("general_close_button"), ResponseType::Cancel);

@ -143,7 +143,15 @@ pub fn connect_settings(gui_data: &GuiData) {
if response_type == ResponseType::Ok {
let mut messages: Messages = Messages::new();
for hash_size in [8, 16, 32, 64].iter() {
for image_filter in [FilterType::Lanczos3, FilterType::CatmullRom, FilterType::Gaussian, FilterType::Nearest, FilterType::Triangle].iter() {
for image_filter in [
FilterType::Lanczos3,
FilterType::CatmullRom,
FilterType::Gaussian,
FilterType::Nearest,
FilterType::Triangle,
]
.iter()
{
for hash_alg in [HashAlg::Blockhash, HashAlg::Gradient, HashAlg::DoubleGradient, HashAlg::VertGradient, HashAlg::Mean].iter() {
if let Some(cache_entries) = czkawka_core::similar_images::load_hashes_from_file(&mut messages, true, *hash_size, *hash_alg, *image_filter) {
czkawka_core::similar_images::save_hashes_to_file(&cache_entries, &mut messages, *hash_size, *hash_alg, *image_filter);

@ -317,7 +317,8 @@ impl GuiMainNotebook {
self.check_button_music_year.set_label(&fl!("music_year_checkbox"));
self.check_button_music_approximate_comparison.set_label(&fl!("music_comparison_checkbox"));
self.check_button_music_approximate_comparison.set_tooltip_text(Some(&fl!("music_comparison_checkbox_tooltip")));
self.check_button_music_approximate_comparison
.set_tooltip_text(Some(&fl!("music_comparison_checkbox_tooltip")));
self.label_duplicate_check_method.set_label(&fl!("main_label_check_method"));
self.label_duplicate_hash_type.set_label(&fl!("main_label_hash_type"));
@ -345,8 +346,10 @@ impl GuiMainNotebook {
self.combo_box_image_hash_algorithm.set_tooltip_text(Some(&fl!("image_hash_alg_tooltip")));
self.label_image_hash_type.set_tooltip_text(Some(&fl!("image_hash_alg_tooltip")));
self.check_button_image_ignore_same_size.set_tooltip_text(Some(&fl!("check_button_general_same_size_tooltip")));
self.check_button_video_ignore_same_size.set_tooltip_text(Some(&fl!("check_button_general_same_size_tooltip")));
self.check_button_image_ignore_same_size
.set_tooltip_text(Some(&fl!("check_button_general_same_size_tooltip")));
self.check_button_video_ignore_same_size
.set_tooltip_text(Some(&fl!("check_button_general_same_size_tooltip")));
self.check_button_image_ignore_same_size.set_label(&fl!("check_button_general_same_size"));
self.check_button_video_ignore_same_size.set_label(&fl!("check_button_general_same_size"));
@ -355,16 +358,20 @@ impl GuiMainNotebook {
let hash_size = IMAGES_HASH_SIZE_COMBO_BOX[hash_size_index];
match hash_size {
8 => {
self.label_similar_images_minimal_similarity.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[0][5]), 8));
self.label_similar_images_minimal_similarity
.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[0][5]), 8));
}
16 => {
self.label_similar_images_minimal_similarity.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[1][5]), 16));
self.label_similar_images_minimal_similarity
.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[1][5]), 16));
}
32 => {
self.label_similar_images_minimal_similarity.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[2][5]), 32));
self.label_similar_images_minimal_similarity
.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[2][5]), 32));
}
64 => {
self.label_similar_images_minimal_similarity.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[3][5]), 64));
self.label_similar_images_minimal_similarity
.set_text(&get_string_from_similarity(&Similarity::Similar(SIMILAR_VALUES[3][5]), 64));
}
_ => panic!(),
}
@ -388,21 +395,42 @@ impl GuiMainNotebook {
(NotebookMainEnum::Symlinks as usize, fl!("main_notebook_symlinks")),
(NotebookMainEnum::BrokenFiles as usize, fl!("main_notebook_broken_files")),
] {
self.notebook_main.tab_label(&vec_children[main_enum]).unwrap().downcast::<gtk::Label>().unwrap().set_text(&fl_thing);
self.notebook_main
.tab_label(&vec_children[main_enum])
.unwrap()
.downcast::<gtk::Label>()
.unwrap()
.set_text(&fl_thing);
}
// Change names of columns
let names_of_columns = [
vec![fl!("main_tree_view_column_file_name"), fl!("main_tree_view_column_path"), fl!("main_tree_view_column_modification")], // Duplicates
vec![fl!("main_tree_view_column_folder_name"), fl!("main_tree_view_column_path"), fl!("main_tree_view_column_modification")], // Empty Folders
vec![
fl!("main_tree_view_column_file_name"),
fl!("main_tree_view_column_path"),
fl!("main_tree_view_column_modification"),
], // Duplicates
vec![
fl!("main_tree_view_column_folder_name"),
fl!("main_tree_view_column_path"),
fl!("main_tree_view_column_modification"),
], // Empty Folders
vec![
fl!("main_tree_view_column_size"),
fl!("main_tree_view_column_file_name"),
fl!("main_tree_view_column_path"),
fl!("main_tree_view_column_modification"),
], // Big files
vec![fl!("main_tree_view_column_file_name"), fl!("main_tree_view_column_path"), fl!("main_tree_view_column_modification")], // Empty files
vec![fl!("main_tree_view_column_file_name"), fl!("main_tree_view_column_path"), fl!("main_tree_view_column_modification")], // Temporary Files
vec![
fl!("main_tree_view_column_file_name"),
fl!("main_tree_view_column_path"),
fl!("main_tree_view_column_modification"),
], // Empty files
vec![
fl!("main_tree_view_column_file_name"),
fl!("main_tree_view_column_path"),
fl!("main_tree_view_column_modification"),
], // Temporary Files
vec![
fl!("main_tree_view_column_similarity"),
fl!("main_tree_view_column_size"),

@ -94,7 +94,9 @@ impl GuiPopovers {
self.buttons_popover_select_one_newest.set_label(&fl!("popover_select_one_newest"));
self.buttons_popover_select_custom.set_label(&fl!("popover_select_custom"));
self.buttons_popover_unselect_custom.set_label(&fl!("popover_unselect_custom"));
self.buttons_popover_select_all_images_except_biggest.set_label(&fl!("popover_select_all_images_except_biggest"));
self.buttons_popover_select_all_images_except_smallest.set_label(&fl!("popover_select_all_images_except_smallest"));
self.buttons_popover_select_all_images_except_biggest
.set_label(&fl!("popover_select_all_images_except_biggest"));
self.buttons_popover_select_all_images_except_smallest
.set_label(&fl!("popover_select_all_images_except_smallest"));
}
}

@ -151,47 +151,67 @@ impl GuiSettings {
self.label_settings_general_language.set_label(&fl!("settings_language_label"));
self.check_button_settings_save_at_exit.set_tooltip_text(Some(&fl!("settings_save_at_exit_button_tooltip")));
self.check_button_settings_load_at_start.set_tooltip_text(Some(&fl!("settings_load_at_start_button_tooltip")));
self.check_button_settings_confirm_deletion.set_tooltip_text(Some(&fl!("settings_confirm_deletion_button_tooltip")));
self.check_button_settings_load_at_start
.set_tooltip_text(Some(&fl!("settings_load_at_start_button_tooltip")));
self.check_button_settings_confirm_deletion
.set_tooltip_text(Some(&fl!("settings_confirm_deletion_button_tooltip")));
self.check_button_settings_confirm_link.set_tooltip_text(Some(&fl!("settings_confirm_link_button_tooltip")));
self.check_button_settings_confirm_group_deletion.set_tooltip_text(Some(&fl!("settings_confirm_group_deletion_button_tooltip")));
self.check_button_settings_show_text_view.set_tooltip_text(Some(&fl!("settings_show_text_view_button_tooltip")));
self.check_button_settings_confirm_group_deletion
.set_tooltip_text(Some(&fl!("settings_confirm_group_deletion_button_tooltip")));
self.check_button_settings_show_text_view
.set_tooltip_text(Some(&fl!("settings_show_text_view_button_tooltip")));
self.check_button_settings_use_cache.set_tooltip_text(Some(&fl!("settings_use_cache_button_tooltip")));
self.check_button_settings_use_trash.set_tooltip_text(Some(&fl!("settings_use_trash_button_tooltip")));
self.label_settings_general_language.set_tooltip_text(Some(&fl!("settings_language_label_tooltip")));
self.check_button_settings_hide_hard_links.set_label(&fl!("settings_duplicates_hide_hard_link_button"));
self.check_button_settings_show_preview_duplicates.set_label(&fl!("settings_multiple_image_preview_checkbutton"));
self.check_button_settings_duplicates_delete_outdated_cache.set_label(&fl!("settings_multiple_delete_outdated_cache_checkbutton"));
self.check_button_settings_show_preview_duplicates
.set_label(&fl!("settings_multiple_image_preview_checkbutton"));
self.check_button_settings_duplicates_delete_outdated_cache
.set_label(&fl!("settings_multiple_delete_outdated_cache_checkbutton"));
self.button_settings_duplicates_clear_cache.set_label(&fl!("settings_multiple_clear_cache_button"));
self.check_button_duplicates_use_prehash_cache.set_label(&fl!("settings_duplicates_prehash_checkbutton"));
self.label_settings_duplicate_minimal_size_cache.set_label(&fl!("settings_duplicates_minimal_size_cache_label"));
self.label_settings_duplicate_minimal_size_cache_prehash.set_label(&fl!("settings_duplicates_minimal_size_cache_prehash_label"));
self.check_button_settings_hide_hard_links.set_tooltip_text(Some(&fl!("settings_duplicates_hide_hard_link_button_tooltip")));
self.entry_settings_cache_file_minimal_size.set_tooltip_text(Some(&fl!("settings_duplicates_minimal_size_entry_tooltip")));
self.check_button_settings_show_preview_duplicates.set_tooltip_text(Some(&fl!("settings_multiple_image_preview_checkbutton_tooltip")));
self.label_settings_duplicate_minimal_size_cache
.set_label(&fl!("settings_duplicates_minimal_size_cache_label"));
self.label_settings_duplicate_minimal_size_cache_prehash
.set_label(&fl!("settings_duplicates_minimal_size_cache_prehash_label"));
self.check_button_settings_hide_hard_links
.set_tooltip_text(Some(&fl!("settings_duplicates_hide_hard_link_button_tooltip")));
self.entry_settings_cache_file_minimal_size
.set_tooltip_text(Some(&fl!("settings_duplicates_minimal_size_entry_tooltip")));
self.check_button_settings_show_preview_duplicates
.set_tooltip_text(Some(&fl!("settings_multiple_image_preview_checkbutton_tooltip")));
self.check_button_settings_duplicates_delete_outdated_cache
.set_tooltip_text(Some(&fl!("settings_multiple_delete_outdated_cache_checkbutton_tooltip")));
self.button_settings_duplicates_clear_cache.set_tooltip_text(Some(&fl!("settings_multiple_clear_cache_button_tooltip")));
self.check_button_duplicates_use_prehash_cache.set_tooltip_text(Some(&fl!("settings_duplicates_prehash_checkbutton_tooltip")));
self.entry_settings_prehash_cache_file_minimal_size.set_tooltip_text(Some(&fl!("settings_duplicates_prehash_minimal_entry_tooltip")));
self.check_button_settings_show_preview_similar_images.set_label(&fl!("settings_multiple_image_preview_checkbutton"));
self.check_button_settings_similar_images_delete_outdated_cache.set_label(&fl!("settings_multiple_delete_outdated_cache_checkbutton"));
self.button_settings_duplicates_clear_cache
.set_tooltip_text(Some(&fl!("settings_multiple_clear_cache_button_tooltip")));
self.check_button_duplicates_use_prehash_cache
.set_tooltip_text(Some(&fl!("settings_duplicates_prehash_checkbutton_tooltip")));
self.entry_settings_prehash_cache_file_minimal_size
.set_tooltip_text(Some(&fl!("settings_duplicates_prehash_minimal_entry_tooltip")));
self.check_button_settings_show_preview_similar_images
.set_label(&fl!("settings_multiple_image_preview_checkbutton"));
self.check_button_settings_similar_images_delete_outdated_cache
.set_label(&fl!("settings_multiple_delete_outdated_cache_checkbutton"));
self.button_settings_similar_images_clear_cache.set_label(&fl!("settings_multiple_clear_cache_button"));
self.check_button_settings_show_preview_similar_images.set_tooltip_text(Some(&fl!("settings_multiple_image_preview_checkbutton_tooltip")));
self.check_button_settings_show_preview_similar_images
.set_tooltip_text(Some(&fl!("settings_multiple_image_preview_checkbutton_tooltip")));
self.check_button_settings_similar_images_delete_outdated_cache
.set_tooltip_text(Some(&fl!("settings_multiple_delete_outdated_cache_checkbutton_tooltip")));
self.button_settings_similar_images_clear_cache.set_tooltip_text(Some(&fl!("settings_multiple_clear_cache_button_tooltip")));
self.button_settings_similar_images_clear_cache
.set_tooltip_text(Some(&fl!("settings_multiple_clear_cache_button_tooltip")));
self.check_button_settings_similar_videos_delete_outdated_cache.set_label(&fl!("settings_multiple_delete_outdated_cache_checkbutton"));
self.check_button_settings_similar_videos_delete_outdated_cache
.set_label(&fl!("settings_multiple_delete_outdated_cache_checkbutton"));
self.button_settings_similar_videos_clear_cache.set_label(&fl!("settings_multiple_clear_cache_button"));
self.check_button_settings_similar_videos_delete_outdated_cache
.set_tooltip_text(Some(&fl!("settings_multiple_delete_outdated_cache_checkbutton_tooltip")));
self.button_settings_similar_videos_clear_cache.set_tooltip_text(Some(&fl!("settings_multiple_clear_cache_button_tooltip")));
self.button_settings_similar_videos_clear_cache
.set_tooltip_text(Some(&fl!("settings_multiple_clear_cache_button_tooltip")));
self.button_settings_save_configuration.set_label(&fl!("settings_saving_button"));
self.button_settings_load_configuration.set_label(&fl!("settings_loading_button"));
@ -205,7 +225,8 @@ impl GuiSettings {
self.button_settings_open_settings_folder.set_label(&fl!("settings_folder_settings_open"));
self.button_settings_open_cache_folder.set_tooltip_text(Some(&fl!("settings_folder_cache_open_tooltip")));
self.button_settings_open_settings_folder.set_tooltip_text(Some(&fl!("settings_folder_settings_open_tooltip")));
self.button_settings_open_settings_folder
.set_tooltip_text(Some(&fl!("settings_folder_settings_open_tooltip")));
let vec_children: Vec<gtk::Widget> = self.notebook_settings.children();
@ -213,9 +234,19 @@ impl GuiSettings {
// let vec_children: Vec<gtk::Widget> = get_all_children(&vec_children[1]);
// Change name of main notebook tabs
let names: [String; 4] = [fl!("settings_notebook_general"), fl!("settings_notebook_duplicates"), fl!("settings_notebook_images"), fl!("settings_notebook_videos")];
let names: [String; 4] = [
fl!("settings_notebook_general"),
fl!("settings_notebook_duplicates"),
fl!("settings_notebook_images"),
fl!("settings_notebook_videos"),
];
for (index, fl_thing) in names.iter().enumerate() {
self.notebook_settings.tab_label(&vec_children[index]).unwrap().downcast::<gtk::Label>().unwrap().set_text(fl_thing);
self.notebook_settings
.tab_label(&vec_children[index])
.unwrap()
.downcast::<gtk::Label>()
.unwrap()
.set_text(fl_thing);
}
}
}

@ -119,10 +119,12 @@ impl GuiUpperNotebook {
// get_custom_label_from_label_with_image(&self.buttons_add_excluded_directory.clone()).set_text(&fl!("upper_add_excluded_button"));
// get_custom_label_from_label_with_image(&self.buttons_remove_excluded_directory.clone()).set_text(&fl!("upper_remove_excluded_button"));
self.buttons_manual_add_included_directory.set_tooltip_text(Some(&fl!("upper_manual_add_included_button_tooltip")));
self.buttons_manual_add_included_directory
.set_tooltip_text(Some(&fl!("upper_manual_add_included_button_tooltip")));
self.buttons_add_included_directory.set_tooltip_text(Some(&fl!("upper_add_included_button_tooltip")));
self.buttons_remove_included_directory.set_tooltip_text(Some(&fl!("upper_remove_included_button_tooltip")));
self.buttons_manual_add_excluded_directory.set_tooltip_text(Some(&fl!("upper_manual_add_excluded_button_tooltip")));
self.buttons_manual_add_excluded_directory
.set_tooltip_text(Some(&fl!("upper_manual_add_excluded_button_tooltip")));
self.buttons_add_excluded_directory.set_tooltip_text(Some(&fl!("upper_add_excluded_button_tooltip")));
self.buttons_remove_excluded_directory.set_tooltip_text(Some(&fl!("upper_remove_excluded_button_tooltip")));
@ -155,7 +157,12 @@ impl GuiUpperNotebook {
(NotebookUpperEnum::ExcludedDirectories as usize, fl!("upper_notebook_excluded_directories")),
(NotebookUpperEnum::IncludedDirectories as usize, fl!("upper_notebook_included_directories")),
] {
self.notebook_upper.tab_label(&vec_children[upper_enum]).unwrap().downcast::<gtk::Label>().unwrap().set_text(&fl_thing);
self.notebook_upper
.tab_label(&vec_children[upper_enum])
.unwrap()
.downcast::<gtk::Label>()
.unwrap()
.set_text(&fl_thing);
}
}
}

@ -11,8 +11,14 @@ pub const DUPLICATES_HASH_TYPE_COMBO_BOX: [HashTypeStruct; 3] = [
eng_name: "Blake3",
hash_type: HashType::Blake3,
},
HashTypeStruct { eng_name: "CRC32", hash_type: HashType::Crc32 },
HashTypeStruct { eng_name: "XXH3", hash_type: HashType::Xxh3 },
HashTypeStruct {
eng_name: "CRC32",
hash_type: HashType::Crc32,
},
HashTypeStruct {
eng_name: "XXH3",
hash_type: HashType::Xxh3,
},
];
pub struct CheckMethodStruct {
pub eng_name: &'static str,
@ -72,7 +78,10 @@ pub const IMAGES_HASH_TYPE_COMBO_BOX: [ImageHashTypeStruct; 5] = [
eng_name: "Gradient",
hash_alg: HashAlg::Gradient,
},
ImageHashTypeStruct { eng_name: "Mean", hash_alg: HashAlg::Mean },
ImageHashTypeStruct {
eng_name: "Mean",
hash_alg: HashAlg::Mean,
},
ImageHashTypeStruct {
eng_name: "VertGradient",
hash_alg: HashAlg::VertGradient,

@ -18,7 +18,9 @@ use czkawka_core::similar_videos::MAX_TOLERANCE;
use crate::create_tree_view::*;
use crate::delete_things;
use crate::gui_data::*;
use crate::help_combo_box::{DUPLICATES_CHECK_METHOD_COMBO_BOX, DUPLICATES_HASH_TYPE_COMBO_BOX, IMAGES_HASH_SIZE_COMBO_BOX, IMAGES_HASH_TYPE_COMBO_BOX, IMAGES_RESIZE_ALGORITHM_COMBO_BOX};
use crate::help_combo_box::{
DUPLICATES_CHECK_METHOD_COMBO_BOX, DUPLICATES_HASH_TYPE_COMBO_BOX, IMAGES_HASH_SIZE_COMBO_BOX, IMAGES_HASH_TYPE_COMBO_BOX, IMAGES_RESIZE_ALGORITHM_COMBO_BOX,
};
use crate::help_functions::*;
use crate::language_functions::LANGUAGES_ALL;
use crate::localizer::generate_translation_hashmap;
@ -493,7 +495,15 @@ fn connect_event_mouse(gui_data: &GuiData) {
tree_view.connect_button_release_event(move |tree_view, _event| {
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::Duplicate as usize];
let preview_path = preview_path.clone();
show_preview(tree_view, &text_view_errors, &check_button_settings_show_preview, &image_preview, preview_path, nb_object.column_path, nb_object.column_name);
show_preview(
tree_view,
&text_view_errors,
&check_button_settings_show_preview,
&image_preview,
preview_path,
nb_object.column_path,
nb_object.column_name,
);
gtk::Inhibit(false)
});
@ -510,7 +520,15 @@ fn connect_event_mouse(gui_data: &GuiData) {
tree_view.connect_button_release_event(move |tree_view, _event| {
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::SimilarImages as usize];
let preview_path = preview_path.clone();
show_preview(tree_view, &text_view_errors, &check_button_settings_show_preview, &image_preview, preview_path, nb_object.column_path, nb_object.column_name);
show_preview(
tree_view,
&text_view_errors,
&check_button_settings_show_preview,
&image_preview,
preview_path,
nb_object.column_path,
nb_object.column_name,
);
gtk::Inhibit(false)
});
}
@ -645,7 +663,15 @@ fn connect_event_buttons(gui_data: &GuiData) {
}
}
fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_settings_show_preview: &CheckButton, image_preview: &Image, preview_path: Rc<RefCell<String>>, column_path: i32, column_name: i32) {
fn show_preview(
tree_view: &TreeView,
text_view_errors: &TextView,
check_button_settings_show_preview: &CheckButton,
image_preview: &Image,
preview_path: Rc<RefCell<String>>,
column_path: i32,
column_name: i32,
) {
let (selected_rows, tree_model) = tree_view.selection().selected_rows();
let mut created_image = false;
@ -660,13 +686,20 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
let cache_dir = proj_dirs.cache_dir();
if cache_dir.exists() {
if !cache_dir.is_dir() {
add_text_to_text_view(text_view_errors, format!("Path {} doesn't point at folder, which is needed by image preview", cache_dir.display()).as_str());
add_text_to_text_view(
text_view_errors,
format!("Path {} doesn't point at folder, which is needed by image preview", cache_dir.display()).as_str(),
);
break 'dir;
}
} else if let Err(e) = fs::create_dir_all(cache_dir) {
add_text_to_text_view(
text_view_errors,
fl!("preview_failed_to_create_cache_dir", generate_translation_hashmap(vec![("name", cache_dir.display().to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"preview_failed_to_create_cache_dir",
generate_translation_hashmap(vec![("name", cache_dir.display().to_string()), ("reason", e.to_string())])
)
.as_str(),
);
break 'dir;
}
@ -694,13 +727,20 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
Err(e) => {
add_text_to_text_view(
text_view_errors,
fl!("preview_temporary_file", generate_translation_hashmap(vec![("name", file_name.to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"preview_temporary_file",
generate_translation_hashmap(vec![("name", file_name.to_string()), ("reason", e.to_string())])
)
.as_str(),
);
break 'dir;
}
};
if img.width() == 0 || img.height() == 0 {
add_text_to_text_view(text_view_errors, fl!("preview_0_size", generate_translation_hashmap(vec![("name", file_name.to_string())])).as_str());
add_text_to_text_view(
text_view_errors,
fl!("preview_0_size", generate_translation_hashmap(vec![("name", file_name.to_string())])).as_str(),
);
break 'dir;
}
let ratio = img.width() / img.height();
@ -725,7 +765,11 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
if let Err(e) = img.save(&file_dir) {
add_text_to_text_view(
text_view_errors,
fl!("preview_temporary_image_save", generate_translation_hashmap(vec![("name", file_dir.display().to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"preview_temporary_image_save",
generate_translation_hashmap(vec![("name", file_dir.display().to_string()), ("reason", e.to_string())])
)
.as_str(),
);
let _ = fs::remove_file(&file_dir);
break 'dir;
@ -741,7 +785,11 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
if let Err(e) = fs::remove_file(&file_dir) {
add_text_to_text_view(
text_view_errors,
fl!("preview_temporary_image_remove", generate_translation_hashmap(vec![("name", file_dir.display().to_string()), ("reason", e.to_string())])).as_str(),
fl!(
"preview_temporary_image_remove",
generate_translation_hashmap(vec![("name", file_dir.display().to_string()), ("reason", e.to_string())])
)
.as_str(),
);
break 'dir;
}

@ -6,7 +6,10 @@ pub struct Language {
/// Languages should be alphabetically sorted
pub const LANGUAGES_ALL: [Language; 3] = [
Language { combo_box_text: "English", short_text: "en" },
Language {
combo_box_text: "English",
short_text: "en",
},
Language {
combo_box_text: "Italiano (Italian)",
short_text: "it",

@ -84,28 +84,58 @@ fn main() {
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<duplicate::ProgressData>, futures::channel::mpsc::UnboundedReceiver<duplicate::ProgressData>) =
futures::channel::mpsc::unbounded();
let (futures_sender_empty_files, futures_receiver_empty_files): (futures::channel::mpsc::UnboundedSender<empty_files::ProgressData>, futures::channel::mpsc::UnboundedReceiver<empty_files::ProgressData>) = futures::channel::mpsc::unbounded();
let (futures_sender_empty_folder, futures_receiver_empty_folder): (futures::channel::mpsc::UnboundedSender<empty_folder::ProgressData>, futures::channel::mpsc::UnboundedReceiver<empty_folder::ProgressData>) =
futures::channel::mpsc::unbounded();
let (futures_sender_big_file, futures_receiver_big_file): (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<same_music::ProgressData>, futures::channel::mpsc::UnboundedReceiver<same_music::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<invalid_symlinks::ProgressData>, futures::channel::mpsc::UnboundedReceiver<invalid_symlinks::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_duplicate_files, futures_receiver_duplicate_files): (
futures::channel::mpsc::UnboundedSender<duplicate::ProgressData>,
futures::channel::mpsc::UnboundedReceiver<duplicate::ProgressData>,
) = futures::channel::mpsc::unbounded();
let (futures_sender_empty_files, futures_receiver_empty_files): (
futures::channel::mpsc::UnboundedSender<empty_files::ProgressData>,
futures::channel::mpsc::UnboundedReceiver<empty_files::ProgressData>,
) = futures::channel::mpsc::unbounded();
let (futures_sender_empty_folder, futures_receiver_empty_folder): (
futures::channel::mpsc::UnboundedSender<empty_folder::ProgressData>,
futures::channel::mpsc::UnboundedReceiver<empty_folder::ProgressData>,
) = futures::channel::mpsc::unbounded();
let (futures_sender_big_file, futures_receiver_big_file): (
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<same_music::ProgressData>,
futures::channel::mpsc::UnboundedReceiver<same_music::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<invalid_symlinks::ProgressData>,
futures::channel::mpsc::UnboundedReceiver<invalid_symlinks::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();
initialize_gui(&mut gui_data);
validate_notebook_data(&gui_data); // Must be run after initialization of gui, to check if everything was properly setup
reset_configuration(false, &gui_data.upper_notebook, &gui_data.settings, &gui_data.text_view_errors); // Fallback for invalid loading setting project
load_system_language(&gui_data); // Check for default system language, must be loaded after initializing GUI and before loading settings from file
load_configuration(false, &gui_data.upper_notebook, &gui_data.settings, &gui_data.text_view_errors, &gui_data.scrolled_window_errors);
load_configuration(
false,
&gui_data.upper_notebook,
&gui_data.settings,
&gui_data.text_view_errors,
&gui_data.scrolled_window_errors,
);
// Needs to run when entire GUI is initialized and
connect_change_language(&gui_data);

@ -104,7 +104,10 @@ fn handle_tree_keypress(tree_view: &gtk::TreeView, key_code: u32, name_column: i
}
pub fn select_function_duplicates(_tree_selection: &gtk::TreeSelection, tree_model: &gtk::TreeModel, tree_path: &gtk::TreePath, _is_path_currently_selected: bool) -> bool {
let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsDuplicates::Color as i32).get::<String>().unwrap();
let color = tree_model
.value(&tree_model.iter(tree_path).unwrap(), ColumnsDuplicates::Color as i32)
.get::<String>()
.unwrap();
if color == HEADER_ROW_COLOR {
return false;
@ -114,7 +117,10 @@ pub fn select_function_duplicates(_tree_selection: &gtk::TreeSelection, tree_mod
}
pub fn select_function_same_music(_tree_selection: &gtk::TreeSelection, tree_model: &gtk::TreeModel, tree_path: &gtk::TreePath, _is_path_currently_selected: bool) -> bool {
let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsSameMusic::Color as i32).get::<String>().unwrap();
let color = tree_model
.value(&tree_model.iter(tree_path).unwrap(), ColumnsSameMusic::Color as i32)
.get::<String>()
.unwrap();
if color == HEADER_ROW_COLOR {
return false;
@ -124,7 +130,10 @@ pub fn select_function_same_music(_tree_selection: &gtk::TreeSelection, tree_mod
}
pub fn select_function_similar_images(_tree_selection: &gtk::TreeSelection, tree_model: &gtk::TreeModel, tree_path: &gtk::TreePath, _is_path_currently_selected: bool) -> bool {
let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsSimilarImages::Color as i32).get::<String>().unwrap();
let color = tree_model
.value(&tree_model.iter(tree_path).unwrap(), ColumnsSimilarImages::Color as i32)
.get::<String>()
.unwrap();
if color == HEADER_ROW_COLOR {
return false;
@ -134,7 +143,10 @@ pub fn select_function_similar_images(_tree_selection: &gtk::TreeSelection, tree
}
pub fn select_function_similar_videos(_tree_selection: &gtk::TreeSelection, tree_model: &gtk::TreeModel, tree_path: &gtk::TreePath, _is_path_currently_selected: bool) -> bool {
let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsSimilarVideos::Color as i32).get::<String>().unwrap();
let color = tree_model
.value(&tree_model.iter(tree_path).unwrap(), ColumnsSimilarVideos::Color as i32)
.get::<String>()
.unwrap();
if color == HEADER_ROW_COLOR {
return false;

@ -36,11 +36,17 @@ pub fn save_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
let config_dir = proj_dirs.config_dir();
if config_dir.exists() {
if !config_dir.is_dir() {
add_text_to_text_view(&text_view_errors, format!("Cannot create save file inside {} because this isn't a folder.", config_dir.display()).as_str());
add_text_to_text_view(
&text_view_errors,
format!("Cannot create save file inside {} because this isn't a folder.", config_dir.display()).as_str(),
);
return;
}
} else if let Err(e) = fs::create_dir_all(config_dir) {
add_text_to_text_view(&text_view_errors, format!("Failed configuration to create configuration folder {}, reason {}", config_dir.display(), e).as_str());
add_text_to_text_view(
&text_view_errors,
format!("Failed configuration to create configuration folder {}, reason {}", config_dir.display(), e).as_str(),
);
return;
}
let mut data_to_save: Vec<String> = Vec::with_capacity(16);
@ -175,7 +181,11 @@ pub fn save_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
//// language
data_to_save.push("--language:".to_string());
let combo_box_settings_language = settings.combo_box_settings_language.clone();
data_to_save.push(get_language_from_combo_box_text(combo_box_settings_language.active_text().unwrap().to_string()).short_text.to_string());
data_to_save.push(
get_language_from_combo_box_text(combo_box_settings_language.active_text().unwrap().to_string())
.short_text
.to_string(),
);
}
// Creating/Opening config file
@ -270,7 +280,9 @@ pub fn load_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
// Load here language, default system language could change value in settings so we don't want to lose this value
{
short_language = get_language_from_combo_box_text(settings.combo_box_settings_language.active_text().unwrap().to_string()).short_text.to_string();
short_language = get_language_from_combo_box_text(settings.combo_box_settings_language.active_text().unwrap().to_string())
.short_text
.to_string();
}
// Parsing Data - this are default values
@ -554,7 +566,11 @@ pub fn load_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
} else {
add_text_to_text_view(
&text_view_errors,
format!("Found invalid data in line {} \"{}\" isn't proper value(u64) when loading file {:?}", line_number, line, config_file).as_str(),
format!(
"Found invalid data in line {} \"{}\" isn't proper value(u64) when loading file {:?}",
line_number, line, config_file
)
.as_str(),
);
}
}
@ -632,7 +648,11 @@ pub fn load_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
} else {
add_text_to_text_view(
&text_view_errors,
format!("Found invalid data in line {} \"{}\" isn't proper value(u64) when loading file {:?}", line_number, line, config_file).as_str(),
format!(
"Found invalid data in line {} \"{}\" isn't proper value(u64) when loading file {:?}",
line_number, line, config_file
)
.as_str(),
);
}
}
@ -642,7 +662,11 @@ pub fn load_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
} else {
add_text_to_text_view(
&text_view_errors,
format!("Found invalid data in line {} \"{}\" isn't proper language value when loading file {:?}", line_number, line, config_file).as_str(),
format!(
"Found invalid data in line {} \"{}\" isn't proper language value when loading file {:?}",
line_number, line, config_file
)
.as_str(),
);
}
}
@ -697,8 +721,12 @@ pub fn load_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
settings.check_button_settings_show_preview_similar_images.set_active(show_previews_similar_images);
settings.check_button_settings_show_preview_duplicates.set_active(show_previews_duplicates);
settings.check_button_settings_similar_videos_delete_outdated_cache.set_active(delete_outdated_cache_similar_videos);
settings.check_button_settings_similar_images_delete_outdated_cache.set_active(delete_outdated_cache_similar_images);
settings
.check_button_settings_similar_videos_delete_outdated_cache
.set_active(delete_outdated_cache_similar_videos);
settings
.check_button_settings_similar_images_delete_outdated_cache
.set_active(delete_outdated_cache_similar_images);
settings.check_button_settings_duplicates_delete_outdated_cache.set_active(delete_outdated_cache_dupliactes);
settings.check_button_settings_show_text_view.set_active(bottom_text_panel);
@ -712,7 +740,9 @@ pub fn load_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
settings.check_button_duplicates_use_prehash_cache.set_active(use_prehash_cache);
settings.check_button_settings_use_trash.set_active(use_trash);
settings.entry_settings_cache_file_minimal_size.set_text(cache_minimal_size.to_string().as_str());
settings.entry_settings_prehash_cache_file_minimal_size.set_text(cache_prehash_minimal_size.to_string().as_str());
settings
.entry_settings_prehash_cache_file_minimal_size
.set_text(cache_prehash_minimal_size.to_string().as_str());
} else {
settings.check_button_settings_load_at_start.set_active(false);
}

@ -51,7 +51,11 @@ impl TaskbarProgress {
pub fn set_progress_value(&self, completed: u64, total: u64) {
// Don't change the value if the is_active flag is false or the value has not changed.
// If is_active is true and the value has not changed, but the progress indicator was in NOPROGRESS or INDETERMINATE state, set the value (and NORMAL state).
if ((completed, total) == *self.current_progress.borrow() && *self.current_state.borrow() != tbp_flags::TBPF_NOPROGRESS && *self.current_state.borrow() != tbp_flags::TBPF_INDETERMINATE) || !*self.is_active.borrow() {
if ((completed, total) == *self.current_progress.borrow()
&& *self.current_state.borrow() != tbp_flags::TBPF_NOPROGRESS
&& *self.current_state.borrow() != tbp_flags::TBPF_INDETERMINATE)
|| !*self.is_active.borrow()
{
return ();
}
let result = unsafe {
@ -127,7 +131,15 @@ impl From<HWND> for TaskbarProgress {
let mut taskbar_list: *mut ITaskbarList3 = ptr::null_mut();
let taskbar_list_ptr: *mut *mut ITaskbarList3 = &mut taskbar_list;
unsafe { combaseapi::CoCreateInstance(&CLSID_TaskbarList, ptr::null_mut(), CLSCTX_INPROC_SERVER, &ITaskbarList3::uuidof(), taskbar_list_ptr as *mut *mut c_void) };
unsafe {
combaseapi::CoCreateInstance(
&CLSID_TaskbarList,
ptr::null_mut(),
CLSCTX_INPROC_SERVER,
&ITaskbarList3::uuidof(),
taskbar_list_ptr as *mut *mut c_void,
)
};
TaskbarProgress {
hwnd: if taskbar_list.is_null() { ptr::null_mut() } else { hwnd },

Loading…
Cancel
Save