1
0
Fork 0
mirror of synced 2024-04-27 17:22:13 +12:00

Add option to turn off cache (#263)

This commit is contained in:
Rafał Mikrut 2021-03-04 12:09:53 +01:00 committed by GitHub
parent 1d904a858e
commit 17f97bd958
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 200 additions and 107 deletions

View file

@ -2,7 +2,7 @@ use std::fs::{File, Metadata, OpenOptions};
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{fs, thread}; use std::{fs, mem, thread};
use crate::common::Common; use crate::common::Common;
use crate::common_directory::Directories; use crate::common_directory::Directories;
@ -78,6 +78,7 @@ pub struct BrokenFiles {
recursive_search: bool, recursive_search: bool,
delete_method: DeleteMethod, delete_method: DeleteMethod,
stopped_search: bool, stopped_search: bool,
use_cache: bool,
} }
impl BrokenFiles { impl BrokenFiles {
@ -93,6 +94,7 @@ impl BrokenFiles {
delete_method: DeleteMethod::None, delete_method: DeleteMethod::None,
stopped_search: false, stopped_search: false,
broken_files: Default::default(), broken_files: Default::default(),
use_cache: true,
} }
} }
@ -130,6 +132,10 @@ impl BrokenFiles {
self.delete_method = delete_method; self.delete_method = delete_method;
} }
pub fn set_use_cache(&mut self, use_cache: bool) {
self.use_cache = use_cache;
}
pub fn set_recursive_search(&mut self, recursive_search: bool) { pub fn set_recursive_search(&mut self, recursive_search: bool) {
self.recursive_search = recursive_search; self.recursive_search = recursive_search;
} }
@ -297,27 +303,35 @@ impl BrokenFiles {
fn look_for_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::Sender<ProgressData>>) -> bool { fn look_for_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::Sender<ProgressData>>) -> bool {
let system_time = SystemTime::now(); let system_time = SystemTime::now();
let loaded_hash_map = match load_cache_from_file(&mut self.text_messages) { let loaded_hash_map;
Some(t) => t,
None => Default::default(),
};
let mut records_already_cached: HashMap<String, FileEntry> = Default::default(); let mut records_already_cached: HashMap<String, FileEntry> = Default::default();
let mut non_cached_files_to_check: HashMap<String, FileEntry> = Default::default(); let mut non_cached_files_to_check: HashMap<String, FileEntry> = Default::default();
for (name, file_entry) in &self.files_to_check {
#[allow(clippy::collapsible_if)] if self.use_cache {
if !loaded_hash_map.contains_key(name) { loaded_hash_map = match load_cache_from_file(&mut self.text_messages) {
// If loaded data doesn't contains current image info Some(t) => t,
non_cached_files_to_check.insert(name.clone(), file_entry.clone()); None => Default::default(),
} else { };
if file_entry.size != loaded_hash_map.get(name).unwrap().size || file_entry.modified_date != loaded_hash_map.get(name).unwrap().modified_date {
// When size or modification date of image changed, then it is clear that is different image for (name, file_entry) in &self.files_to_check {
#[allow(clippy::collapsible_if)]
if !loaded_hash_map.contains_key(name) {
// If loaded data doesn't contains current image info
non_cached_files_to_check.insert(name.clone(), file_entry.clone()); non_cached_files_to_check.insert(name.clone(), file_entry.clone());
} else { } else {
// Checking may be omitted when already there is entry with same size and modification date if file_entry.size != loaded_hash_map.get(name).unwrap().size || file_entry.modified_date != loaded_hash_map.get(name).unwrap().modified_date {
records_already_cached.insert(name.clone(), loaded_hash_map.get(name).unwrap().clone()); // When size or modification date of image changed, then it is clear that is different image
non_cached_files_to_check.insert(name.clone(), file_entry.clone());
} else {
// Checking may be omitted when already there is entry with same size and modification date
records_already_cached.insert(name.clone(), loaded_hash_map.get(name).unwrap().clone());
}
} }
} }
} else {
loaded_hash_map = Default::default();
mem::swap(&mut self.files_to_check, &mut non_cached_files_to_check);
} }
let check_was_breaked = AtomicBool::new(false); // Used for breaking from GUI and ending check thread let check_was_breaked = AtomicBool::new(false); // Used for breaking from GUI and ending check thread
@ -430,16 +444,18 @@ impl BrokenFiles {
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();
// Must save all results to file, old loaded from file with all currently counted results if self.use_cache {
let mut all_results: HashMap<String, FileEntry> = self.files_to_check.clone(); // Must save all results to file, old loaded from file with all currently counted results
let mut all_results: HashMap<String, FileEntry> = self.files_to_check.clone();
for file_entry in vec_file_entry { for file_entry in vec_file_entry {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry); all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
}
for (_name, file_entry) in loaded_hash_map {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
}
save_cache_to_file(&all_results, &mut self.text_messages);
} }
for (_name, file_entry) in loaded_hash_map {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
}
save_cache_to_file(&all_results, &mut self.text_messages);
self.information.number_of_broken_files = self.broken_files.len(); self.information.number_of_broken_files = self.broken_files.len();

View file

@ -10,7 +10,7 @@ use std::io::{self, Error, ErrorKind};
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{fs, thread}; use std::{fs, mem, thread};
use crate::common::Common; use crate::common::Common;
use crate::common_directory::Directories; use crate::common_directory::Directories;
@ -151,6 +151,7 @@ pub struct DuplicateFinder {
ignore_hard_links: bool, ignore_hard_links: bool,
dryrun: bool, dryrun: bool,
stopped_search: bool, stopped_search: bool,
use_cache: bool,
} }
impl DuplicateFinder { impl DuplicateFinder {
@ -172,6 +173,7 @@ impl DuplicateFinder {
ignore_hard_links: true, ignore_hard_links: true,
hash_type: HashType::Blake3, hash_type: HashType::Blake3,
dryrun: false, dryrun: false,
use_cache: true,
} }
} }
@ -221,6 +223,10 @@ impl DuplicateFinder {
&self.files_with_identical_names &self.files_with_identical_names
} }
pub fn set_use_cache(&mut self, use_cache: bool) {
self.use_cache = use_cache;
}
pub const fn get_files_sorted_by_size(&self) -> &BTreeMap<u64, Vec<FileEntry>> { pub const fn get_files_sorted_by_size(&self) -> &BTreeMap<u64, Vec<FileEntry>> {
&self.files_with_identical_size &self.files_with_identical_size
} }
@ -795,38 +801,46 @@ impl DuplicateFinder {
.collect(); .collect();
} }
CheckingMethod::Hash => { CheckingMethod::Hash => {
let loaded_hash_map = match load_hashes_from_file(&mut self.text_messages, &self.hash_type) { let loaded_hash_map;
Some(t) => t,
None => Default::default(),
};
let mut records_already_cached: HashMap<u64, Vec<FileEntry>> = Default::default(); let mut records_already_cached: BTreeMap<u64, Vec<FileEntry>> = Default::default();
let mut non_cached_files_to_check: HashMap<u64, Vec<FileEntry>> = Default::default(); let mut non_cached_files_to_check: BTreeMap<u64, Vec<FileEntry>> = Default::default();
for (size, vec_file_entry) in pre_checked_map {
#[allow(clippy::collapsible_if)]
if !loaded_hash_map.contains_key(&size) {
// If loaded data doesn't contains current info
non_cached_files_to_check.insert(size, vec_file_entry);
} else {
let loaded_vec_file_entry = loaded_hash_map.get(&size).unwrap();
for file_entry in vec_file_entry { if self.use_cache {
let mut found: bool = false; loaded_hash_map = match load_hashes_from_file(&mut self.text_messages, &self.hash_type) {
for loaded_file_entry in loaded_vec_file_entry { Some(t) => t,
if file_entry.path == loaded_file_entry.path && file_entry.modified_date == loaded_file_entry.modified_date { None => Default::default(),
records_already_cached.entry(file_entry.size).or_insert_with(Vec::new); };
records_already_cached.get_mut(&file_entry.size).unwrap().push(loaded_file_entry.clone());
found = true; for (size, vec_file_entry) in pre_checked_map {
break; #[allow(clippy::collapsible_if)]
if !loaded_hash_map.contains_key(&size) {
// If loaded data doesn't contains current info
non_cached_files_to_check.insert(size, vec_file_entry);
} else {
let loaded_vec_file_entry = loaded_hash_map.get(&size).unwrap();
for file_entry in vec_file_entry {
let mut found: bool = false;
for loaded_file_entry in loaded_vec_file_entry {
if file_entry.path == loaded_file_entry.path && file_entry.modified_date == loaded_file_entry.modified_date {
records_already_cached.entry(file_entry.size).or_insert_with(Vec::new);
records_already_cached.get_mut(&file_entry.size).unwrap().push(loaded_file_entry.clone());
found = true;
break;
}
} }
}
if !found { if !found {
non_cached_files_to_check.entry(file_entry.size).or_insert_with(Vec::new); non_cached_files_to_check.entry(file_entry.size).or_insert_with(Vec::new);
non_cached_files_to_check.get_mut(&file_entry.size).unwrap().push(file_entry); non_cached_files_to_check.get_mut(&file_entry.size).unwrap().push(file_entry);
}
} }
} }
} }
} else {
loaded_hash_map = Default::default();
mem::swap(&mut pre_checked_map, &mut non_cached_files_to_check);
} }
full_hash_results = non_cached_files_to_check full_hash_results = non_cached_files_to_check
@ -860,43 +874,43 @@ impl DuplicateFinder {
.while_some() .while_some()
.collect(); .collect();
// Size, Vec if self.use_cache {
'main: for (size, vec_file_entry) in records_already_cached {
'main: for (size, vec_file_entry) in records_already_cached { // Check if size already exists, if exists we must to change it outside because cannot have mut and non mut reference to full_hash_results
// Check if size already exists, if exists we must to change it outside because cannot have mut and non mut reference to full_hash_results for (full_size, full_hashmap, _errors, _bytes_read) in &mut full_hash_results {
for (full_size, full_hashmap, _errors, _bytes_read) in &mut full_hash_results { if size == *full_size {
if size == *full_size { for file_entry in vec_file_entry {
for file_entry in vec_file_entry { full_hashmap.entry(file_entry.hash.clone()).or_insert_with(Vec::new);
full_hashmap.entry(file_entry.hash.clone()).or_insert_with(Vec::new); full_hashmap.get_mut(&file_entry.hash).unwrap().push(file_entry);
full_hashmap.get_mut(&file_entry.hash).unwrap().push(file_entry); }
continue 'main;
} }
continue 'main;
} }
} // Size doesn't exists add results to files
// Size doesn't exists add results to files let mut temp_hashmap: HashMap<String, Vec<FileEntry>> = Default::default();
let mut temp_hashmap: HashMap<String, Vec<FileEntry>> = Default::default();
for file_entry in vec_file_entry {
temp_hashmap.entry(file_entry.hash.clone()).or_insert_with(Vec::new);
temp_hashmap.get_mut(&file_entry.hash).unwrap().push(file_entry);
}
full_hash_results.push((size, temp_hashmap, Vec::new(), 0));
}
// Must save all results to file, old loaded from file with all currently counted results
let mut all_results: HashMap<String, FileEntry> = Default::default();
for (_size, vec_file_entry) in loaded_hash_map {
for file_entry in vec_file_entry {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
}
}
for (_size, hashmap, _errors, _bytes_read) in &full_hash_results {
for vec_file_entry in hashmap.values() {
for file_entry in vec_file_entry { for file_entry in vec_file_entry {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry.clone()); temp_hashmap.entry(file_entry.hash.clone()).or_insert_with(Vec::new);
temp_hashmap.get_mut(&file_entry.hash).unwrap().push(file_entry);
}
full_hash_results.push((size, temp_hashmap, Vec::new(), 0));
}
// Must save all results to file, old loaded from file with all currently counted results
let mut all_results: HashMap<String, FileEntry> = Default::default();
for (_size, vec_file_entry) in loaded_hash_map {
for file_entry in vec_file_entry {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
} }
} }
for (_size, hashmap, _errors, _bytes_read) in &full_hash_results {
for vec_file_entry in hashmap.values() {
for file_entry in vec_file_entry {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry.clone());
}
}
}
save_hashes_to_file(&all_results, &mut self.text_messages, &self.hash_type);
} }
save_hashes_to_file(&all_results, &mut self.text_messages, &self.hash_type);
} }
_ => panic!("What"), _ => panic!("What"),
} }

View file

@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{fs, thread}; use std::{fs, mem, thread};
/// Type to store for each entry in the similarity BK-tree. /// Type to store for each entry in the similarity BK-tree.
type Node = [u8; 8]; type Node = [u8; 8];
@ -79,6 +79,7 @@ pub struct SimilarImages {
stopped_search: bool, stopped_search: bool,
similarity: Similarity, similarity: Similarity,
images_to_check: HashMap<String, FileEntry>, images_to_check: HashMap<String, FileEntry>,
use_cache: bool,
} }
/// Info struck with helpful information's about results /// Info struck with helpful information's about results
@ -111,6 +112,7 @@ impl SimilarImages {
stopped_search: false, stopped_search: false,
similarity: Similarity::High, similarity: Similarity::High,
images_to_check: Default::default(), images_to_check: Default::default(),
use_cache: true,
} }
} }
@ -130,6 +132,10 @@ impl SimilarImages {
&self.information &self.information
} }
pub fn set_use_cache(&mut self, use_cache: bool) {
self.use_cache = use_cache;
}
pub fn set_recursive_search(&mut self, recursive_search: bool) { pub fn set_recursive_search(&mut self, recursive_search: bool) {
self.recursive_search = recursive_search; self.recursive_search = recursive_search;
} }
@ -321,27 +327,35 @@ impl SimilarImages {
fn sort_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::Sender<ProgressData>>) -> bool { fn sort_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::Sender<ProgressData>>) -> bool {
let hash_map_modification = SystemTime::now(); let hash_map_modification = SystemTime::now();
let loaded_hash_map = match load_hashes_from_file(&mut self.text_messages) { let loaded_hash_map;
Some(t) => t,
None => Default::default(),
};
let mut records_already_cached: HashMap<String, FileEntry> = Default::default(); let mut records_already_cached: HashMap<String, FileEntry> = Default::default();
let mut non_cached_files_to_check: HashMap<String, FileEntry> = Default::default(); let mut non_cached_files_to_check: HashMap<String, FileEntry> = Default::default();
for (name, file_entry) in &self.images_to_check {
#[allow(clippy::collapsible_if)] if self.use_cache {
if !loaded_hash_map.contains_key(name) { loaded_hash_map = match load_hashes_from_file(&mut self.text_messages) {
// If loaded data doesn't contains current image info Some(t) => t,
non_cached_files_to_check.insert(name.clone(), file_entry.clone()); None => Default::default(),
} else { };
if file_entry.size != loaded_hash_map.get(name).unwrap().size || file_entry.modified_date != loaded_hash_map.get(name).unwrap().modified_date {
// When size or modification date of image changed, then it is clear that is different image for (name, file_entry) in &self.images_to_check {
#[allow(clippy::collapsible_if)]
if !loaded_hash_map.contains_key(name) {
// If loaded data doesn't contains current image info
non_cached_files_to_check.insert(name.clone(), file_entry.clone()); non_cached_files_to_check.insert(name.clone(), file_entry.clone());
} else { } else {
// Checking may be omitted when already there is entry with same size and modification date if file_entry.size != loaded_hash_map.get(name).unwrap().size || file_entry.modified_date != loaded_hash_map.get(name).unwrap().modified_date {
records_already_cached.insert(name.clone(), loaded_hash_map.get(name).unwrap().clone()); // When size or modification date of image changed, then it is clear that is different image
non_cached_files_to_check.insert(name.clone(), file_entry.clone());
} else {
// Checking may be omitted when already there is entry with same size and modification date
records_already_cached.insert(name.clone(), loaded_hash_map.get(name).unwrap().clone());
}
} }
} }
} else {
loaded_hash_map = Default::default();
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());
@ -426,12 +440,14 @@ impl SimilarImages {
self.image_hashes.get_mut(buf).unwrap().push(file_entry.clone()); self.image_hashes.get_mut(buf).unwrap().push(file_entry.clone());
} }
// Must save all results to file, old loaded from file with all currently counted results if self.use_cache {
let mut all_results: HashMap<String, FileEntry> = loaded_hash_map; // Must save all results to file, old loaded from file with all currently counted results
for (file_entry, _hash) in vec_file_entry { let mut all_results: HashMap<String, FileEntry> = loaded_hash_map;
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry); for (file_entry, _hash) in vec_file_entry {
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
}
save_hashes_to_file(&all_results, &mut self.text_messages);
} }
save_hashes_to_file(&all_results, &mut self.text_messages);
Common::print_time(hash_map_modification, SystemTime::now(), "sort_images - saving data to files".to_string()); Common::print_time(hash_map_modification, SystemTime::now(), "sort_images - saving data to files".to_string());
let hash_map_modification = SystemTime::now(); let hash_map_modification = SystemTime::now();

View file

@ -2485,6 +2485,21 @@ This program is free to use and will always be.
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="check_button_settings_save_at_exit">
<property name="label" translatable="yes">Save configuration at exit</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child> <child>
<object class="GtkCheckButton" id="check_button_settings_confirm_deletion"> <object class="GtkCheckButton" id="check_button_settings_confirm_deletion">
<property name="label" translatable="yes">Show confirm dialog when deleting</property> <property name="label" translatable="yes">Show confirm dialog when deleting</property>
@ -2497,7 +2512,7 @@ This program is free to use and will always be.
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">3</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -2512,12 +2527,12 @@ This program is free to use and will always be.
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">5</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkCheckButton" id="check_button_settings_save_at_exit"> <object class="GtkCheckButton" id="check_button_settings_use_cache">
<property name="label" translatable="yes">Save configuration at exit</property> <property name="label" translatable="yes">Use cache</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">False</property> <property name="receives-default">False</property>

View file

@ -91,6 +91,7 @@ pub fn connect_button_search(
let radio_button_hash_type_crc32 = gui_data.main_notebook.radio_button_hash_type_crc32.clone(); let radio_button_hash_type_crc32 = gui_data.main_notebook.radio_button_hash_type_crc32.clone();
let radio_button_hash_type_xxh3 = gui_data.main_notebook.radio_button_hash_type_xxh3.clone(); let radio_button_hash_type_xxh3 = gui_data.main_notebook.radio_button_hash_type_xxh3.clone();
let check_button_settings_hide_hard_links = gui_data.settings.check_button_settings_hide_hard_links.clone(); let check_button_settings_hide_hard_links = gui_data.settings.check_button_settings_hide_hard_links.clone();
let check_button_settings_use_cache = gui_data.settings.check_button_settings_use_cache.clone();
buttons_search_clone.connect_clicked(move |_| { buttons_search_clone.connect_clicked(move |_| {
let included_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_included_directories)); let included_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_included_directories));
@ -99,6 +100,7 @@ pub fn connect_button_search(
let excluded_items = entry_excluded_items.get_text().as_str().to_string().split(',').map(|e| e.to_string()).collect::<Vec<String>>(); let excluded_items = entry_excluded_items.get_text().as_str().to_string().split(',').map(|e| e.to_string()).collect::<Vec<String>>();
let allowed_extensions = entry_allowed_extensions.get_text().as_str().to_string(); let allowed_extensions = entry_allowed_extensions.get_text().as_str().to_string();
let hide_hard_links = check_button_settings_hide_hard_links.get_active(); let hide_hard_links = check_button_settings_hide_hard_links.get_active();
let use_cache = check_button_settings_use_cache.get_active();
let show_dialog = Arc::new(AtomicBool::new(true)); let show_dialog = Arc::new(AtomicBool::new(true));
@ -167,6 +169,7 @@ pub fn connect_button_search(
df.set_check_method(check_method); df.set_check_method(check_method);
df.set_hash_type(hash_type); df.set_hash_type(hash_type);
df.set_ignore_hard_links(hide_hard_links); df.set_ignore_hard_links(hide_hard_links);
df.set_use_cache(use_cache);
df.find_duplicates(Some(&stop_receiver), Some(&futures_sender_duplicate_files)); df.find_duplicates(Some(&stop_receiver), Some(&futures_sender_duplicate_files));
let _ = glib_stop_sender.send(Message::Duplicates(df)); let _ = glib_stop_sender.send(Message::Duplicates(df));
}); });
@ -292,6 +295,7 @@ pub fn connect_button_search(
sf.set_excluded_items(excluded_items); sf.set_excluded_items(excluded_items);
sf.set_minimal_file_size(minimal_file_size); sf.set_minimal_file_size(minimal_file_size);
sf.set_similarity(similarity); sf.set_similarity(similarity);
sf.set_use_cache(use_cache);
sf.find_similar_images(Some(&stop_receiver), Some(&futures_sender_similar_images)); sf.find_similar_images(Some(&stop_receiver), Some(&futures_sender_similar_images));
let _ = glib_stop_sender.send(Message::SimilarImages(sf)); let _ = glib_stop_sender.send(Message::SimilarImages(sf));
}); });
@ -402,6 +406,7 @@ pub fn connect_button_search(
br.set_excluded_directory(excluded_directories); br.set_excluded_directory(excluded_directories);
br.set_recursive_search(recursive_search); br.set_recursive_search(recursive_search);
br.set_excluded_items(excluded_items); br.set_excluded_items(excluded_items);
br.set_use_cache(use_cache);
br.find_broken_files(Some(&stop_receiver), Some(&futures_sender_broken_files)); br.find_broken_files(Some(&stop_receiver), Some(&futures_sender_broken_files));
let _ = glib_stop_sender.send(Message::BrokenFiles(br)); let _ = glib_stop_sender.send(Message::BrokenFiles(br));
}); });

View file

@ -9,6 +9,7 @@ pub struct GUISettings {
pub check_button_settings_load_at_start: gtk::CheckButton, pub check_button_settings_load_at_start: gtk::CheckButton,
pub check_button_settings_confirm_deletion: gtk::CheckButton, pub check_button_settings_confirm_deletion: gtk::CheckButton,
pub check_button_settings_show_text_view: gtk::CheckButton, pub check_button_settings_show_text_view: gtk::CheckButton,
pub check_button_settings_use_cache: gtk::CheckButton,
// Duplicates // Duplicates
pub check_button_settings_hide_hard_links: gtk::CheckButton, pub check_button_settings_hide_hard_links: gtk::CheckButton,
@ -31,6 +32,7 @@ impl GUISettings {
let check_button_settings_load_at_start: gtk::CheckButton = builder.get_object("check_button_settings_load_at_start").unwrap(); let check_button_settings_load_at_start: gtk::CheckButton = builder.get_object("check_button_settings_load_at_start").unwrap();
let check_button_settings_confirm_deletion: gtk::CheckButton = builder.get_object("check_button_settings_confirm_deletion").unwrap(); let check_button_settings_confirm_deletion: gtk::CheckButton = builder.get_object("check_button_settings_confirm_deletion").unwrap();
let check_button_settings_show_text_view: gtk::CheckButton = builder.get_object("check_button_settings_show_text_view").unwrap(); let check_button_settings_show_text_view: gtk::CheckButton = builder.get_object("check_button_settings_show_text_view").unwrap();
let check_button_settings_use_cache: gtk::CheckButton = builder.get_object("check_button_settings_use_cache").unwrap();
// Duplicates // Duplicates
let check_button_settings_hide_hard_links: gtk::CheckButton = builder.get_object("check_button_settings_hide_hard_links").unwrap(); let check_button_settings_hide_hard_links: gtk::CheckButton = builder.get_object("check_button_settings_hide_hard_links").unwrap();
@ -54,6 +56,7 @@ impl GUISettings {
button_settings_reset_configuration, button_settings_reset_configuration,
check_button_settings_show_preview_similar_images, check_button_settings_show_preview_similar_images,
check_button_settings_hide_hard_links, check_button_settings_hide_hard_links,
check_button_settings_use_cache,
} }
} }
} }

View file

@ -112,10 +112,15 @@ pub fn save_configuration(gui_data: &GuiData, manual_execution: bool) {
let check_button_settings_show_text_view = gui_data.settings.check_button_settings_show_text_view.clone(); let check_button_settings_show_text_view = gui_data.settings.check_button_settings_show_text_view.clone();
data_to_save.push(check_button_settings_show_text_view.get_active().to_string()); data_to_save.push(check_button_settings_show_text_view.get_active().to_string());
//// Show bottom text panel with errors //// Hide/Show hard linked files, with same inodes
data_to_save.push("--hide_hard_links:".to_string()); data_to_save.push("--hide_hard_links:".to_string());
let check_button_settings_hide_hard_links = gui_data.settings.check_button_settings_hide_hard_links.clone(); let check_button_settings_hide_hard_links = gui_data.settings.check_button_settings_hide_hard_links.clone();
data_to_save.push(check_button_settings_hide_hard_links.get_active().to_string()); data_to_save.push(check_button_settings_hide_hard_links.get_active().to_string());
//// Use cache system
data_to_save.push("--use_cache:".to_string());
let check_button_settings_use_cache = gui_data.settings.check_button_settings_use_cache.clone();
data_to_save.push(check_button_settings_use_cache.get_active().to_string());
} }
// Creating/Opening config file // Creating/Opening config file
@ -143,9 +148,9 @@ pub fn save_configuration(gui_data: &GuiData, manual_execution: bool) {
} }
} }
if data_saved { if data_saved {
add_text_to_text_view(&text_view_errors, format!("Saved configuration to file {}", config_dir.display()).as_str()); add_text_to_text_view(&text_view_errors, format!("Saved configuration to file {}", config_file.display()).as_str());
} else { } else {
add_text_to_text_view(&text_view_errors, format!("Failed to save configuration data to file {}", config_dir.display()).as_str()); add_text_to_text_view(&text_view_errors, format!("Failed to save configuration data to file {}", config_file.display()).as_str());
} }
} else { } else {
add_text_to_text_view(&text_view_errors, "Failed to get home directory, so can't save file."); add_text_to_text_view(&text_view_errors, "Failed to get home directory, so can't save file.");
@ -164,6 +169,7 @@ enum TypeOfLoadedData {
ShowPreviews, ShowPreviews,
BottomTextPanel, BottomTextPanel,
HideHardLinks, HideHardLinks,
UseCache,
} }
pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) { pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
@ -207,6 +213,7 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
let mut show_previews: bool = true; let mut show_previews: bool = true;
let mut bottom_text_panel: bool = true; let mut bottom_text_panel: bool = true;
let mut hide_hard_links: bool = true; let mut hide_hard_links: bool = true;
let mut use_cache: bool = true;
let mut current_type = TypeOfLoadedData::None; let mut current_type = TypeOfLoadedData::None;
for (line_number, line) in loaded_data.replace("\r\n", "\n").split('\n').enumerate() { for (line_number, line) in loaded_data.replace("\r\n", "\n").split('\n').enumerate() {
@ -234,6 +241,8 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
current_type = TypeOfLoadedData::BottomTextPanel; current_type = TypeOfLoadedData::BottomTextPanel;
} else if line.starts_with("--hide_hard_links") { } else if line.starts_with("--hide_hard_links") {
current_type = TypeOfLoadedData::HideHardLinks; current_type = TypeOfLoadedData::HideHardLinks;
} else if line.starts_with("--use_cache") {
current_type = TypeOfLoadedData::UseCache;
} else if line.starts_with("--") { } else if line.starts_with("--") {
current_type = TypeOfLoadedData::None; current_type = TypeOfLoadedData::None;
add_text_to_text_view( add_text_to_text_view(
@ -338,6 +347,19 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
); );
} }
} }
TypeOfLoadedData::UseCache => {
let line = line.to_lowercase();
if line == "1" || line == "true" {
use_cache = true;
} else if line == "0" || line == "false" {
use_cache = false;
} else {
add_text_to_text_view(
&text_view_errors,
format!("Found invalid data in line {} \"{}\" isn't proper value(0/1/true/false) when loading file {:?}", line_number, line, config_file).as_str(),
);
}
}
} }
} }
} }
@ -389,6 +411,7 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
gui_data.scrolled_window_errors.show(); gui_data.scrolled_window_errors.show();
} }
gui_data.settings.check_button_settings_hide_hard_links.set_active(hide_hard_links); gui_data.settings.check_button_settings_hide_hard_links.set_active(hide_hard_links);
gui_data.settings.check_button_settings_use_cache.set_active(use_cache);
} else { } else {
gui_data.settings.check_button_settings_load_at_start.set_active(false); gui_data.settings.check_button_settings_load_at_start.set_active(false);
} }
@ -469,6 +492,7 @@ pub fn reset_configuration(gui_data: &GuiData, manual_clearing: bool) {
gui_data.settings.check_button_settings_show_preview_similar_images.set_active(true); gui_data.settings.check_button_settings_show_preview_similar_images.set_active(true);
gui_data.settings.check_button_settings_show_text_view.set_active(true); gui_data.settings.check_button_settings_show_text_view.set_active(true);
gui_data.settings.check_button_settings_hide_hard_links.set_active(true); gui_data.settings.check_button_settings_hide_hard_links.set_active(true);
gui_data.settings.check_button_settings_use_cache.set_active(true);
} }
if manual_clearing { if manual_clearing {
add_text_to_text_view(&text_view_errors, "Current configuration was cleared."); add_text_to_text_view(&text_view_errors, "Current configuration was cleared.");