Similar images improvements: (#97)
Headers without data By default only checking for High Similarity(faster search)
This commit is contained in:
parent
5d4f4db8c1
commit
110d6015bc
|
@ -11,7 +11,7 @@ use czkawka_core::{
|
||||||
empty_files::{self, EmptyFiles},
|
empty_files::{self, EmptyFiles},
|
||||||
empty_folder::EmptyFolder,
|
empty_folder::EmptyFolder,
|
||||||
same_music::SameMusic,
|
same_music::SameMusic,
|
||||||
similar_files::SimilarImages,
|
similar_images::SimilarImages,
|
||||||
temporary::{self, Temporary},
|
temporary::{self, Temporary},
|
||||||
zeroed::{self, ZeroedFiles},
|
zeroed::{self, ZeroedFiles},
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub mod common_items;
|
||||||
pub mod common_messages;
|
pub mod common_messages;
|
||||||
pub mod common_traits;
|
pub mod common_traits;
|
||||||
pub mod same_music;
|
pub mod same_music;
|
||||||
pub mod similar_files;
|
pub mod similar_images;
|
||||||
pub mod zeroed;
|
pub mod zeroed;
|
||||||
|
|
||||||
pub const CZKAWKA_VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const CZKAWKA_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
|
@ -32,11 +32,6 @@ pub struct FileEntry {
|
||||||
pub modified_date: u64,
|
pub modified_date: u64,
|
||||||
pub similarity: Similarity,
|
pub similarity: Similarity,
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct StructSimilar {
|
|
||||||
pub base_image: FileEntry,
|
|
||||||
pub similar_images: Vec<FileEntry>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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];
|
||||||
|
@ -57,11 +52,12 @@ pub struct SimilarImages {
|
||||||
directories: Directories,
|
directories: Directories,
|
||||||
excluded_items: ExcludedItems,
|
excluded_items: ExcludedItems,
|
||||||
bktree: BKTree<Node, Hamming>,
|
bktree: BKTree<Node, Hamming>,
|
||||||
similar_vectors: Vec<StructSimilar>,
|
similar_vectors: Vec<Vec<FileEntry>>,
|
||||||
recursive_search: bool,
|
recursive_search: bool,
|
||||||
minimal_file_size: u64,
|
minimal_file_size: u64,
|
||||||
image_hashes: HashMap<Node, Vec<FileEntry>>, // Hashmap with image hashes and Vector with names of files
|
image_hashes: HashMap<Node, Vec<FileEntry>>, // Hashmap with image hashes and Vector with names of files
|
||||||
stopped_search: bool,
|
stopped_search: bool,
|
||||||
|
similarity: Similarity,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Info struck with helpful information's about results
|
/// Info struck with helpful information's about results
|
||||||
|
@ -98,6 +94,7 @@ impl SimilarImages {
|
||||||
minimal_file_size: 1024 * 16, // 16 KB should be enough to exclude too small images from search
|
minimal_file_size: 1024 * 16, // 16 KB should be enough to exclude too small images from search
|
||||||
image_hashes: Default::default(),
|
image_hashes: Default::default(),
|
||||||
stopped_search: false,
|
stopped_search: false,
|
||||||
|
similarity: Similarity::High,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +106,7 @@ impl SimilarImages {
|
||||||
&self.text_messages
|
&self.text_messages
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn get_similar_images(&self) -> &Vec<StructSimilar> {
|
pub const fn get_similar_images(&self) -> &Vec<Vec<FileEntry>> {
|
||||||
&self.similar_vectors
|
&self.similar_vectors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +124,9 @@ impl SimilarImages {
|
||||||
t => t,
|
t => t,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn set_similarity(&mut self, similarity: Similarity) {
|
||||||
|
self.similarity = similarity;
|
||||||
|
}
|
||||||
|
|
||||||
/// Public function used by CLI to search for empty folders
|
/// Public function used by CLI to search for empty folders
|
||||||
pub fn find_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>) {
|
pub fn find_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>) {
|
||||||
|
@ -135,6 +135,10 @@ impl SimilarImages {
|
||||||
self.stopped_search = true;
|
self.stopped_search = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if !self.sort_images(stop_receiver) {
|
||||||
|
self.stopped_search = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
// if self.delete_folders {
|
// if self.delete_folders {
|
||||||
// self.delete_empty_folders();
|
// self.delete_empty_folders();
|
||||||
// }
|
// }
|
||||||
|
@ -275,37 +279,51 @@ impl SimilarImages {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Common::print_time(start_time, SystemTime::now(), "check_for_similar_images".to_string());
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sort_images(&mut self, stop_receiver: Option<&Receiver<()>>) -> bool {
|
||||||
let hash_map_modification = SystemTime::now();
|
let hash_map_modification = SystemTime::now();
|
||||||
|
|
||||||
let mut new_vector: Vec<StructSimilar> = Vec::new();
|
//let hash_map_modification = SystemTime::now();
|
||||||
|
let similarity: u64 = match self.similarity {
|
||||||
|
Similarity::VeryHigh => 0,
|
||||||
|
Similarity::High => 1,
|
||||||
|
Similarity::Medium => 2,
|
||||||
|
Similarity::Small => 3,
|
||||||
|
_ => panic!("0-3 similarity levels are allowed, check if not added more."),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// Now is A is similar to B with VeryHigh and C with Medium
|
||||||
|
// And D is similar with C with High
|
||||||
|
// And Similarity is set to Medium(or lower)
|
||||||
|
// And A is checked before D
|
||||||
|
// Then C is shown that is similar group A, not D
|
||||||
|
|
||||||
|
let mut new_vector: Vec<Vec<FileEntry>> = Vec::new();
|
||||||
|
let mut hashes_to_check = self.image_hashes.clone();
|
||||||
for (hash, vec_file_entry) in &self.image_hashes {
|
for (hash, vec_file_entry) in &self.image_hashes {
|
||||||
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let vector_with_found_similar_hashes = self.bktree.find(hash, 3).collect::<Vec<_>>();
|
let vector_with_found_similar_hashes = self.bktree.find(hash, similarity).collect::<Vec<_>>();
|
||||||
if vector_with_found_similar_hashes.len() == 1 && vec_file_entry.len() == 1 {
|
if vector_with_found_similar_hashes.len() == 1 && vec_file_entry.len() == 1 {
|
||||||
// Exists only 1 unique picture, so there is no need to use it
|
// This one picture doesn't have similar pictures, so there is no go
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut vec_similarity_struct: Vec<StructSimilar> = Vec::new();
|
let mut vector_of_similar_images: Vec<FileEntry> = vec_file_entry
|
||||||
|
|
||||||
for file_entry in vec_file_entry.iter() {
|
|
||||||
let similar_struct = StructSimilar {
|
|
||||||
base_image: file_entry.clone(),
|
|
||||||
similar_images: vec_file_entry
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| x.path != file_entry.path)
|
.map(|fe| FileEntry {
|
||||||
.map(|x| {
|
path: fe.path.clone(),
|
||||||
let mut y = x.clone();
|
size: fe.size,
|
||||||
y.similarity = Similarity::VeryHigh;
|
dimensions: fe.dimensions.clone(),
|
||||||
y
|
modified_date: fe.modified_date,
|
||||||
|
similarity: Similarity::VeryHigh,
|
||||||
})
|
})
|
||||||
.collect::<Vec<FileEntry>>(),
|
.collect();
|
||||||
};
|
|
||||||
vec_similarity_struct.push(similar_struct);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (similarity, similar_hash) in vector_with_found_similar_hashes.iter() {
|
for (similarity, similar_hash) in vector_with_found_similar_hashes.iter() {
|
||||||
if *similarity == 0 && hash == *similar_hash {
|
if *similarity == 0 && hash == *similar_hash {
|
||||||
|
@ -315,31 +333,34 @@ impl SimilarImages {
|
||||||
panic!("I'm not sure if same hash can have distance > 0");
|
panic!("I'm not sure if same hash can have distance > 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
for file_entry in self.image_hashes.get(*similar_hash).unwrap() {
|
if let Some(vec_file_entry) = hashes_to_check.get(*similar_hash) {
|
||||||
let mut file_entry = file_entry.clone();
|
vector_of_similar_images.append(
|
||||||
file_entry.similarity = match similarity {
|
&mut (vec_file_entry
|
||||||
|
.iter()
|
||||||
|
.map(|fe| FileEntry {
|
||||||
|
path: fe.path.clone(),
|
||||||
|
size: fe.size,
|
||||||
|
dimensions: fe.dimensions.clone(),
|
||||||
|
modified_date: fe.modified_date,
|
||||||
|
similarity: match similarity {
|
||||||
0 => Similarity::VeryHigh,
|
0 => Similarity::VeryHigh,
|
||||||
1 => Similarity::High,
|
1 => Similarity::High,
|
||||||
2 => Similarity::Medium,
|
2 => Similarity::Medium,
|
||||||
3 => Similarity::Small,
|
3 => Similarity::Small,
|
||||||
_ => panic!("0-3 similarity levels are allowed, check if not added more."),
|
_ => panic!("0-3 similarity levels are allowed, check if not added more."),
|
||||||
};
|
},
|
||||||
for similarity_struct in vec_similarity_struct.iter_mut() {
|
})
|
||||||
similarity_struct.similar_images.push(file_entry.clone());
|
.collect::<Vec<_>>()),
|
||||||
|
);
|
||||||
|
hashes_to_check.remove(*similar_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
new_vector.push((*vector_of_similar_images).to_owned());
|
||||||
for similarity_struct in vec_similarity_struct.iter_mut() {
|
|
||||||
similarity_struct.similar_images.sort_by(|x, y| y.similarity.cmp(&x.similarity));
|
|
||||||
}
|
|
||||||
new_vector.append(&mut vec_similarity_struct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.similar_vectors = new_vector;
|
self.similar_vectors = new_vector;
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
Common::print_time(hash_map_modification, SystemTime::now(), "sort_images".to_string());
|
||||||
Common::print_time(hash_map_modification, SystemTime::now(), "hash_map_modification(internal)".to_string());
|
|
||||||
Common::print_time(start_time, SystemTime::now(), "check_for_similar_images".to_string());
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,13 +434,13 @@ impl SaveResults for SimilarImages {
|
||||||
if !self.similar_vectors.is_empty() {
|
if !self.similar_vectors.is_empty() {
|
||||||
write!(file, "{} images which have similar friends\n\n", self.similar_vectors.len()).unwrap();
|
write!(file, "{} images which have similar friends\n\n", self.similar_vectors.len()).unwrap();
|
||||||
|
|
||||||
for struct_similar in self.similar_vectors.iter() {
|
// for struct_similar in self.similar_vectors.iter() {
|
||||||
writeln!(file, "Image {:?} have {} similar images", struct_similar.base_image.path, struct_similar.similar_images.len()).unwrap();
|
// writeln!(file, "Image {:?} have {} similar images", struct_similar.base_image.path, struct_similar.similar_images.len()).unwrap();
|
||||||
for similar_picture in struct_similar.similar_images.iter() {
|
// for similar_picture in struct_similar.similar_images.iter() {
|
||||||
writeln!(file, "{:?} - Similarity Level: {}", similar_picture.path, get_string_from_similarity(&similar_picture.similarity)).unwrap();
|
// writeln!(file, "{:?} - Similarity Level: {}", similar_picture.path, get_string_from_similarity(&similar_picture.similarity)).unwrap();
|
||||||
}
|
// }
|
||||||
writeln!(file).unwrap();
|
// writeln!(file).unwrap();
|
||||||
}
|
// }
|
||||||
} else {
|
} else {
|
||||||
write!(file, "Not found any similar images.").unwrap();
|
write!(file, "Not found any similar images.").unwrap();
|
||||||
}
|
}
|
||||||
|
@ -432,6 +453,19 @@ impl PrintResults for SimilarImages {
|
||||||
fn print_results(&self) {
|
fn print_results(&self) {
|
||||||
if !self.similar_vectors.is_empty() {
|
if !self.similar_vectors.is_empty() {
|
||||||
println!("Found {} images which have similar friends", self.similar_vectors.len());
|
println!("Found {} images which have similar friends", self.similar_vectors.len());
|
||||||
|
|
||||||
|
for vec_file_entry in &self.similar_vectors {
|
||||||
|
for file_entry in vec_file_entry {
|
||||||
|
println!(
|
||||||
|
"{} - {} - {} - {}",
|
||||||
|
file_entry.path.display(),
|
||||||
|
file_entry.dimensions,
|
||||||
|
file_entry.size.file_size(options::BINARY).unwrap(),
|
||||||
|
get_string_from_similarity(&file_entry.similarity)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -135,8 +135,8 @@ Author: Rafał Mikrut
|
||||||
</object>
|
</object>
|
||||||
<object class="GtkWindow" id="window_main">
|
<object class="GtkWindow" id="window_main">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="default_width">1000</property>
|
<property name="default_width">1100</property>
|
||||||
<property name="default_height">700</property>
|
<property name="default_height">800</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
|
@ -8,7 +8,7 @@ use czkawka_core::duplicate::DuplicateFinder;
|
||||||
use czkawka_core::empty_files::EmptyFiles;
|
use czkawka_core::empty_files::EmptyFiles;
|
||||||
use czkawka_core::empty_folder::EmptyFolder;
|
use czkawka_core::empty_folder::EmptyFolder;
|
||||||
use czkawka_core::same_music::{MusicSimilarity, SameMusic};
|
use czkawka_core::same_music::{MusicSimilarity, SameMusic};
|
||||||
use czkawka_core::similar_files::SimilarImages;
|
use czkawka_core::similar_images::SimilarImages;
|
||||||
use czkawka_core::temporary::Temporary;
|
use czkawka_core::temporary::Temporary;
|
||||||
use czkawka_core::zeroed::ZeroedFiles;
|
use czkawka_core::zeroed::ZeroedFiles;
|
||||||
use glib::Sender;
|
use glib::Sender;
|
||||||
|
@ -42,6 +42,14 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
let check_button_music_album_artist: gtk::CheckButton = gui_data.check_button_music_album_artist.clone();
|
let check_button_music_album_artist: gtk::CheckButton = gui_data.check_button_music_album_artist.clone();
|
||||||
let check_button_music_year: gtk::CheckButton = gui_data.check_button_music_year.clone();
|
let check_button_music_year: gtk::CheckButton = gui_data.check_button_music_year.clone();
|
||||||
let shared_buttons = gui_data.shared_buttons.clone();
|
let shared_buttons = gui_data.shared_buttons.clone();
|
||||||
|
let scrolled_window_main_empty_folder_finder = gui_data.scrolled_window_main_empty_folder_finder.clone();
|
||||||
|
let scrolled_window_main_empty_files_finder = gui_data.scrolled_window_main_empty_files_finder.clone();
|
||||||
|
let scrolled_window_big_files_finder = gui_data.scrolled_window_big_files_finder.clone();
|
||||||
|
let scrolled_window_duplicate_finder = gui_data.scrolled_window_duplicate_finder.clone();
|
||||||
|
let scrolled_window_main_temporary_files_finder = gui_data.scrolled_window_main_temporary_files_finder.clone();
|
||||||
|
let scrolled_window_same_music_finder = gui_data.scrolled_window_same_music_finder.clone();
|
||||||
|
let scrolled_window_similar_images_finder = gui_data.scrolled_window_similar_images_finder.clone();
|
||||||
|
let scrolled_window_zeroed_files_finder = gui_data.scrolled_window_zeroed_files_finder.clone();
|
||||||
|
|
||||||
buttons_search_clone.connect_clicked(move |_| {
|
buttons_search_clone.connect_clicked(move |_| {
|
||||||
let included_directories = get_string_from_list_store(&scrolled_window_included_directories);
|
let included_directories = get_string_from_list_store(&scrolled_window_included_directories);
|
||||||
|
@ -59,6 +67,8 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
|
|
||||||
match notebook_main_children_names.get(notebook_main.get_current_page().unwrap() as usize).unwrap().as_str() {
|
match notebook_main_children_names.get(notebook_main.get_current_page().unwrap() as usize).unwrap().as_str() {
|
||||||
"notebook_main_duplicate_finder_label" => {
|
"notebook_main_duplicate_finder_label" => {
|
||||||
|
get_list_store(&scrolled_window_duplicate_finder).clear();
|
||||||
|
|
||||||
let check_method;
|
let check_method;
|
||||||
if radio_button_name.get_active() {
|
if radio_button_name.get_active() {
|
||||||
check_method = duplicate::CheckingMethod::Name;
|
check_method = duplicate::CheckingMethod::Name;
|
||||||
|
@ -93,6 +103,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"scrolled_window_main_empty_folder_finder" => {
|
"scrolled_window_main_empty_folder_finder" => {
|
||||||
|
get_list_store(&scrolled_window_main_empty_folder_finder).clear();
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let receiver_stop = stop_receiver.clone();
|
let receiver_stop = stop_receiver.clone();
|
||||||
|
|
||||||
|
@ -107,6 +118,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"scrolled_window_main_empty_files_finder" => {
|
"scrolled_window_main_empty_files_finder" => {
|
||||||
|
get_list_store(&scrolled_window_main_empty_files_finder).clear();
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let receiver_stop = stop_receiver.clone();
|
let receiver_stop = stop_receiver.clone();
|
||||||
|
|
||||||
|
@ -124,6 +136,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"scrolled_window_main_temporary_files_finder" => {
|
"scrolled_window_main_temporary_files_finder" => {
|
||||||
|
get_list_store(&scrolled_window_main_temporary_files_finder).clear();
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let receiver_stop = stop_receiver.clone();
|
let receiver_stop = stop_receiver.clone();
|
||||||
|
|
||||||
|
@ -140,6 +153,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"notebook_big_main_file_finder" => {
|
"notebook_big_main_file_finder" => {
|
||||||
|
get_list_store(&scrolled_window_big_files_finder).clear();
|
||||||
let numbers_of_files_to_check = match entry_big_files_number.get_text().as_str().parse::<usize>() {
|
let numbers_of_files_to_check = match entry_big_files_number.get_text().as_str().parse::<usize>() {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(_) => 50, // By default
|
Err(_) => 50, // By default
|
||||||
|
@ -163,6 +177,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
"notebook_main_similar_images_finder_label" => {
|
"notebook_main_similar_images_finder_label" => {
|
||||||
|
get_list_store(&scrolled_window_similar_images_finder).clear();
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let receiver_stop = stop_receiver.clone();
|
let receiver_stop = stop_receiver.clone();
|
||||||
|
|
||||||
|
@ -185,6 +200,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"notebook_main_zeroed_files_finder" => {
|
"notebook_main_zeroed_files_finder" => {
|
||||||
|
get_list_store(&scrolled_window_zeroed_files_finder).clear();
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let receiver_stop = stop_receiver.clone();
|
let receiver_stop = stop_receiver.clone();
|
||||||
|
|
||||||
|
@ -202,6 +218,7 @@ pub fn connect_button_search(gui_data: &GuiData, sender: Sender<Message>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"notebook_main_same_music_finder" => {
|
"notebook_main_same_music_finder" => {
|
||||||
|
get_list_store(&scrolled_window_same_music_finder).clear();
|
||||||
let minimal_file_size = match entry_same_music_minimal_size.get_text().as_str().parse::<u64>() {
|
let minimal_file_size = match entry_same_music_minimal_size.get_text().as_str().parse::<u64>() {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(_) => 1024, // By default
|
Err(_) => 1024, // By default
|
||||||
|
|
|
@ -46,20 +46,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::Duplicates(df) => {
|
Message::Duplicates(df) => {
|
||||||
if df.get_stopped_search() {
|
if df.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for duplicated was stopped by user");
|
entry_info.set_text("Searching for duplicated was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_duplicate_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = df.get_information();
|
let information = df.get_information();
|
||||||
let text_messages = df.get_text_messages();
|
let text_messages = df.get_text_messages();
|
||||||
|
@ -96,18 +82,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_duplicate_finder
|
let list_store = get_list_store(&scrolled_window_duplicate_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2, 3, 4, 5];
|
let col_indices = [0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
@ -223,20 +198,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::EmptyFolders(ef) => {
|
Message::EmptyFolders(ef) => {
|
||||||
if ef.get_stopped_search() {
|
if ef.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for empty folders was stopped by user");
|
entry_info.set_text("Searching for empty folders was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_main_empty_folder_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = ef.get_information();
|
let information = ef.get_information();
|
||||||
let text_messages = ef.get_text_messages();
|
let text_messages = ef.get_text_messages();
|
||||||
|
@ -247,18 +208,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_main_empty_folder_finder
|
let list_store = get_list_store(&scrolled_window_main_empty_folder_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2];
|
let col_indices = [0, 1, 2];
|
||||||
|
|
||||||
|
@ -290,20 +240,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::EmptyFiles(vf) => {
|
Message::EmptyFiles(vf) => {
|
||||||
if vf.get_stopped_search() {
|
if vf.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for empty files was stopped by user");
|
entry_info.set_text("Searching for empty files was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_main_empty_files_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = vf.get_information();
|
let information = vf.get_information();
|
||||||
let text_messages = vf.get_text_messages();
|
let text_messages = vf.get_text_messages();
|
||||||
|
@ -314,18 +250,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_main_empty_files_finder
|
let list_store = get_list_store(&scrolled_window_main_empty_files_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2];
|
let col_indices = [0, 1, 2];
|
||||||
|
|
||||||
|
@ -357,20 +282,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::BigFiles(bf) => {
|
Message::BigFiles(bf) => {
|
||||||
if bf.get_stopped_search() {
|
if bf.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for big files was stopped by user");
|
entry_info.set_text("Searching for big files was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_duplicate_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = bf.get_information();
|
let information = bf.get_information();
|
||||||
let text_messages = bf.get_text_messages();
|
let text_messages = bf.get_text_messages();
|
||||||
|
@ -381,18 +292,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_big_files_finder
|
let list_store = get_list_store(&scrolled_window_big_files_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2, 3];
|
let col_indices = [0, 1, 2, 3];
|
||||||
|
|
||||||
|
@ -431,20 +331,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::Temporary(tf) => {
|
Message::Temporary(tf) => {
|
||||||
if tf.get_stopped_search() {
|
if tf.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for temporary files was stopped by user");
|
entry_info.set_text("Searching for temporary files was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_duplicate_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = tf.get_information();
|
let information = tf.get_information();
|
||||||
let text_messages = tf.get_text_messages();
|
let text_messages = tf.get_text_messages();
|
||||||
|
@ -455,18 +341,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_main_temporary_files_finder
|
let list_store = get_list_store(&scrolled_window_main_temporary_files_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2];
|
let col_indices = [0, 1, 2];
|
||||||
|
|
||||||
|
@ -498,20 +373,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::SimilarImages(sf) => {
|
Message::SimilarImages(sf) => {
|
||||||
if sf.get_stopped_search() {
|
if sf.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for duplicated was stopped by user");
|
entry_info.set_text("Searching for duplicated was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_similar_images_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
//let information = sf.get_information();
|
//let information = sf.get_information();
|
||||||
let text_messages = sf.get_text_messages();
|
let text_messages = sf.get_text_messages();
|
||||||
|
@ -522,48 +383,36 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_similar_images_finder
|
let list_store = get_list_store(&scrolled_window_similar_images_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2, 3, 4, 5, 6, 7];
|
let col_indices = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||||
|
|
||||||
let vec_struct_similar = sf.get_similar_images();
|
let vec_struct_similar = sf.get_similar_images();
|
||||||
|
|
||||||
for struct_similar in vec_struct_similar.iter() {
|
for vec_file_entry in vec_struct_similar.iter() {
|
||||||
// Header
|
// Header
|
||||||
let (directory, file) = split_path(&struct_similar.base_image.path);
|
|
||||||
let values: [&dyn ToValue; 8] = [
|
let values: [&dyn ToValue; 8] = [
|
||||||
&(get_text_from_similarity(&struct_similar.base_image.similarity).to_string()),
|
&"".to_string(),
|
||||||
&struct_similar.base_image.size.file_size(options::BINARY).unwrap(),
|
&"".to_string(),
|
||||||
&struct_similar.base_image.dimensions,
|
&"".to_string(),
|
||||||
&file,
|
&"".to_string(),
|
||||||
&directory,
|
&"".to_string(),
|
||||||
&(NaiveDateTime::from_timestamp(struct_similar.base_image.modified_date as i64, 0).to_string()),
|
&"".to_string(),
|
||||||
&(HEADER_ROW_COLOR.to_string()),
|
&(HEADER_ROW_COLOR.to_string()),
|
||||||
&(TEXT_COLOR.to_string()),
|
&(TEXT_COLOR.to_string()),
|
||||||
];
|
];
|
||||||
list_store.set(&list_store.append(), &col_indices, &values);
|
list_store.set(&list_store.append(), &col_indices, &values);
|
||||||
|
|
||||||
// Meat
|
// Meat
|
||||||
for similar_images in &struct_similar.similar_images {
|
for file_entry in vec_file_entry.iter() {
|
||||||
let (directory, file) = split_path(&similar_images.path);
|
let (directory, file) = split_path(&file_entry.path);
|
||||||
let values: [&dyn ToValue; 8] = [
|
let values: [&dyn ToValue; 8] = [
|
||||||
&(get_text_from_similarity(&similar_images.similarity).to_string()),
|
&(get_text_from_similarity(&file_entry.similarity).to_string()),
|
||||||
&similar_images.size.file_size(options::BINARY).unwrap(),
|
&file_entry.size.file_size(options::BINARY).unwrap(),
|
||||||
&similar_images.dimensions,
|
&file_entry.dimensions,
|
||||||
&file,
|
&file,
|
||||||
&directory,
|
&directory,
|
||||||
&(NaiveDateTime::from_timestamp(similar_images.modified_date as i64, 0).to_string()),
|
&(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()),
|
||||||
&(MAIN_ROW_COLOR.to_string()),
|
&(MAIN_ROW_COLOR.to_string()),
|
||||||
&(TEXT_COLOR.to_string()),
|
&(TEXT_COLOR.to_string()),
|
||||||
];
|
];
|
||||||
|
@ -592,20 +441,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::ZeroedFiles(zf) => {
|
Message::ZeroedFiles(zf) => {
|
||||||
if zf.get_stopped_search() {
|
if zf.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for zeroed files was stopped by user");
|
entry_info.set_text("Searching for zeroed files was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_zeroed_files_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = zf.get_information();
|
let information = zf.get_information();
|
||||||
let text_messages = zf.get_text_messages();
|
let text_messages = zf.get_text_messages();
|
||||||
|
@ -616,18 +451,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_zeroed_files_finder
|
let list_store = get_list_store(&scrolled_window_zeroed_files_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2, 3];
|
let col_indices = [0, 1, 2, 3];
|
||||||
|
|
||||||
|
@ -664,20 +488,6 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
Message::SameMusic(mf) => {
|
Message::SameMusic(mf) => {
|
||||||
if mf.get_stopped_search() {
|
if mf.get_stopped_search() {
|
||||||
entry_info.set_text("Searching for empty files was stopped by user");
|
entry_info.set_text("Searching for empty files was stopped by user");
|
||||||
|
|
||||||
//Also clear list
|
|
||||||
scrolled_window_same_music_finder
|
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap()
|
|
||||||
.clear();
|
|
||||||
} else {
|
} else {
|
||||||
let information = mf.get_information();
|
let information = mf.get_information();
|
||||||
let text_messages = mf.get_text_messages();
|
let text_messages = mf.get_text_messages();
|
||||||
|
@ -688,18 +498,7 @@ pub fn connect_compute_results(gui_data: &GuiData, receiver: Receiver<Message>)
|
||||||
|
|
||||||
// Create GUI
|
// Create GUI
|
||||||
{
|
{
|
||||||
let list_store = scrolled_window_same_music_finder
|
let list_store = get_list_store(&scrolled_window_same_music_finder);
|
||||||
.get_children()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
.downcast::<gtk::TreeView>()
|
|
||||||
.unwrap()
|
|
||||||
.get_model()
|
|
||||||
.unwrap()
|
|
||||||
.downcast::<gtk::ListStore>()
|
|
||||||
.unwrap();
|
|
||||||
list_store.clear();
|
|
||||||
|
|
||||||
let col_indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
let col_indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let scrolled_window_duplicate_finder = gui_data.scrolled_window_duplicate_finder.clone();
|
let scrolled_window_duplicate_finder = gui_data.scrolled_window_duplicate_finder.clone();
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
buttons_popover_select_all.connect_clicked(move |_| {
|
buttons_popover_select_all.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
|
|
||||||
selection.select_all();
|
selection.select_all();
|
||||||
|
@ -25,7 +25,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let buttons_popover_unselect_all = gui_data.buttons_popover_unselect_all.clone();
|
let buttons_popover_unselect_all = gui_data.buttons_popover_unselect_all.clone();
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
buttons_popover_unselect_all.connect_clicked(move |_| {
|
buttons_popover_unselect_all.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
|
|
||||||
selection.unselect_all();
|
selection.unselect_all();
|
||||||
|
@ -39,7 +39,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
let buttons_popover_reverse = gui_data.buttons_popover_reverse.clone();
|
let buttons_popover_reverse = gui_data.buttons_popover_reverse.clone();
|
||||||
buttons_popover_reverse.connect_clicked(move |_| {
|
buttons_popover_reverse.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
|
|
||||||
let (vector_tree_path, tree_model) = selection.get_selected_rows();
|
let (vector_tree_path, tree_model) = selection.get_selected_rows();
|
||||||
|
@ -79,7 +79,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
let buttons_popover_select_all_except_oldest = gui_data.buttons_popover_select_all_except_oldest.clone();
|
let buttons_popover_select_all_except_oldest = gui_data.buttons_popover_select_all_except_oldest.clone();
|
||||||
buttons_popover_select_all_except_oldest.connect_clicked(move |_| {
|
buttons_popover_select_all_except_oldest.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
let tree_model = tree_view.get_model().unwrap();
|
let tree_model = tree_view.get_model().unwrap();
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
let buttons_popover_select_all_except_newest = gui_data.buttons_popover_select_all_except_newest.clone();
|
let buttons_popover_select_all_except_newest = gui_data.buttons_popover_select_all_except_newest.clone();
|
||||||
buttons_popover_select_all_except_newest.connect_clicked(move |_| {
|
buttons_popover_select_all_except_newest.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
let tree_model = tree_view.get_model().unwrap();
|
let tree_model = tree_view.get_model().unwrap();
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
let buttons_popover_select_one_oldest = gui_data.buttons_popover_select_one_oldest.clone();
|
let buttons_popover_select_one_oldest = gui_data.buttons_popover_select_one_oldest.clone();
|
||||||
buttons_popover_select_one_oldest.connect_clicked(move |_| {
|
buttons_popover_select_one_oldest.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
let tree_model = tree_view.get_model().unwrap();
|
let tree_model = tree_view.get_model().unwrap();
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ pub fn connect_popover_duplicate(gui_data: &GuiData) {
|
||||||
let buttons_popover_select_one_newest = gui_data.buttons_popover_select_one_newest.clone();
|
let buttons_popover_select_one_newest = gui_data.buttons_popover_select_one_newest.clone();
|
||||||
let popover_select = gui_data.popover_select.clone();
|
let popover_select = gui_data.popover_select.clone();
|
||||||
buttons_popover_select_one_newest.connect_clicked(move |_| {
|
buttons_popover_select_one_newest.connect_clicked(move |_| {
|
||||||
let tree_view = scrolled_window_duplicate_finder.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let tree_view = get_tree_view(&scrolled_window_duplicate_finder);
|
||||||
let selection = tree_view.get_selection();
|
let selection = tree_view.get_selection();
|
||||||
let tree_model = tree_view.get_model().unwrap();
|
let tree_model = tree_view.get_model().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use czkawka_core::duplicate::DuplicateFinder;
|
||||||
use czkawka_core::empty_files::EmptyFiles;
|
use czkawka_core::empty_files::EmptyFiles;
|
||||||
use czkawka_core::empty_folder::EmptyFolder;
|
use czkawka_core::empty_folder::EmptyFolder;
|
||||||
use czkawka_core::same_music::SameMusic;
|
use czkawka_core::same_music::SameMusic;
|
||||||
use czkawka_core::similar_files::SimilarImages;
|
use czkawka_core::similar_images::SimilarImages;
|
||||||
use czkawka_core::temporary::Temporary;
|
use czkawka_core::temporary::Temporary;
|
||||||
use czkawka_core::zeroed::ZeroedFiles;
|
use czkawka_core::zeroed::ZeroedFiles;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
|
|
@ -4,10 +4,11 @@ use czkawka_core::duplicate::DuplicateFinder;
|
||||||
use czkawka_core::empty_files::EmptyFiles;
|
use czkawka_core::empty_files::EmptyFiles;
|
||||||
use czkawka_core::empty_folder::EmptyFolder;
|
use czkawka_core::empty_folder::EmptyFolder;
|
||||||
use czkawka_core::same_music::SameMusic;
|
use czkawka_core::same_music::SameMusic;
|
||||||
use czkawka_core::similar_files::{SimilarImages, Similarity};
|
use czkawka_core::similar_images::{SimilarImages, Similarity};
|
||||||
use czkawka_core::temporary::Temporary;
|
use czkawka_core::temporary::Temporary;
|
||||||
use czkawka_core::zeroed::ZeroedFiles;
|
use czkawka_core::zeroed::ZeroedFiles;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
use gtk::{ListStore, TreeView};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
@ -96,8 +97,7 @@ pub const HEADER_ROW_COLOR: &str = "#272727";
|
||||||
//pub const HEADER_ROW_COLOR: &str = "#010101"; // TEST
|
//pub const HEADER_ROW_COLOR: &str = "#010101"; // TEST
|
||||||
|
|
||||||
pub fn get_string_from_list_store(scrolled_window: >k::ScrolledWindow) -> String {
|
pub fn get_string_from_list_store(scrolled_window: >k::ScrolledWindow) -> String {
|
||||||
let tree_view: gtk::TreeView = scrolled_window.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
let list_store: gtk::ListStore = get_list_store(&scrolled_window);
|
||||||
let list_store: gtk::ListStore = tree_view.get_model().unwrap().downcast::<gtk::ListStore>().unwrap();
|
|
||||||
let mut first: bool = true;
|
let mut first: bool = true;
|
||||||
|
|
||||||
let mut return_string: String = "".to_string();
|
let mut return_string: String = "".to_string();
|
||||||
|
@ -182,6 +182,15 @@ pub fn select_function_same_music(_tree_selection: >k::TreeSelection, tree_mod
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
pub fn select_function_similar_images(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool {
|
||||||
|
let color = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsSimilarImages::Color as i32).get::<String>().unwrap().unwrap();
|
||||||
|
|
||||||
|
if color == HEADER_ROW_COLOR {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_buttons(hashmap: &mut HashMap<String, bool>, buttons_array: &[gtk::Button], button_names: &[String]) {
|
pub fn set_buttons(hashmap: &mut HashMap<String, bool>, buttons_array: &[gtk::Button], button_names: &[String]) {
|
||||||
for (index, button) in buttons_array.iter().enumerate() {
|
for (index, button) in buttons_array.iter().enumerate() {
|
||||||
|
@ -217,3 +226,14 @@ pub fn get_text_from_similarity(similarity: &Similarity) -> &str {
|
||||||
Similarity::VeryHigh => "Very High",
|
Similarity::VeryHigh => "Very High",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_list_store(scrolled_window: >k::ScrolledWindow) -> ListStore {
|
||||||
|
let list_store = scrolled_window.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap().get_model().unwrap().downcast::<gtk::ListStore>().unwrap();
|
||||||
|
|
||||||
|
list_store
|
||||||
|
}
|
||||||
|
pub fn get_tree_view(scrolled_window: >k::ScrolledWindow) -> TreeView {
|
||||||
|
let tree_view = scrolled_window.get_children().get(0).unwrap().clone().downcast::<gtk::TreeView>().unwrap();
|
||||||
|
|
||||||
|
tree_view
|
||||||
|
}
|
||||||
|
|
|
@ -148,6 +148,7 @@ pub fn startup_configuration(gui_data: &GuiData) {
|
||||||
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
|
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
|
||||||
|
|
||||||
tree_view.get_selection().set_mode(SelectionMode::Multiple);
|
tree_view.get_selection().set_mode(SelectionMode::Multiple);
|
||||||
|
tree_view.get_selection().set_select_function(Some(Box::new(select_function_similar_images)));
|
||||||
|
|
||||||
create_tree_view_similar_images(&mut tree_view);
|
create_tree_view_similar_images(&mut tree_view);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue