1 use czkawka_core::big_file::BigFile;
2 use czkawka_core::broken_files::BrokenFiles;
3 use czkawka_core::common_messages::Messages;
4 use czkawka_core::duplicate::DuplicateFinder;
5 use czkawka_core::empty_files::EmptyFiles;
6 use czkawka_core::empty_folder::EmptyFolder;
7 use czkawka_core::invalid_symlinks;
8 use czkawka_core::invalid_symlinks::InvalidSymlinks;
9 use czkawka_core::same_music::SameMusic;
10 use czkawka_core::similar_images::SimilarImages;
11 use czkawka_core::temporary::Temporary;
12 use czkawka_core::zeroed::ZeroedFiles;
13 use gtk::prelude::*;
14 use gtk::{ListStore, TextView};
15 use std::collections::HashMap;
16 use std::path::{Path, PathBuf};
17
18 pub enum Message {
19 Duplicates(DuplicateFinder),
20 EmptyFolders(EmptyFolder),
21 EmptyFiles(EmptyFiles),
22 BigFiles(BigFile),
23 Temporary(Temporary),
24 SimilarImages(SimilarImages),
25 ZeroedFiles(ZeroedFiles),
26 SameMusic(SameMusic),
27 InvalidSymlinks(InvalidSymlinks),
28 BrokenFiles(BrokenFiles),
29 }
30
31 #[derive(Debug)]
32 pub enum ColumnsDuplicates {
33 // Columns for duplicate treeview
34 ActivatableSelectButton = 0,
35 ActiveSelectButton,
36 Name,
37 Path,
38 Modification,
39 ModificationAsSecs,
40 Color,
41 TextColor,
42 }
43
44 pub enum ColumnsEmptyFolders {
45 // Columns for empty folder treeview
46 ActiveSelectButton = 0,
47 Name,
48 Path,
49 Modification,
50 }
51 pub enum ColumnsDirectory {
52 // Columns for Included and Excluded Directories in upper Notebook
53 Path = 0,
54 }
55 pub enum ColumnsBigFiles {
56 ActiveSelectButton = 0,
57 Size,
58 Name,
59 Path,
60 Modification,
61 }
62 pub enum ColumnsEmptyFiles {
63 ActiveSelectButton = 0,
64 Name,
65 Path,
66 Modification,
67 }
68 pub enum ColumnsTemporaryFiles {
69 ActiveSelectButton = 0,
70 Name,
71 Path,
72 Modification,
73 }
74 pub enum ColumnsSimilarImages {
75 ActivatableSelectButton = 0,
76 ActiveSelectButton,
77 Similarity,
78 Size,
79 SizeAsBytes,
80 Dimensions,
81 Name,
82 Path,
83 Modification,
84 ModificationAsSecs,
85 Color,
86 TextColor,
87 }
88 pub enum ColumnsZeroedFiles {
89 ActiveSelectButton = 0,
90 Size,
91 SizeAsBytes,
92 Name,
93 Path,
94 Modification,
95 }
96 pub enum ColumnsSameMusic {
97 ActivatableSelectButton = 0,
98 ActiveSelectButton,
99 Size,
100 SizeAsBytes,
101 Name,
102 Path,
103 Title,
104 Artist,
105 AlbumTitle,
106 AlbumArtist,
107 Year,
108 Modification,
109 ModificationAsSecs,
110 Color,
111 TextColor,
112 }
113 pub enum ColumnsInvalidSymlinks {
114 ActiveSelectButton = 0,
115 Name,
116 Path,
117 DestinationPath,
118 TypeOfError,
119 Modification,
120 }
121
122 pub enum ColumnsBrokenFiles {
123 ActiveSelectButton = 0,
124 Name,
125 Path,
126 ErrorType,
127 Modification,
128 }
129
130 pub const TEXT_COLOR: &str = "#ffffff";
131 pub const MAIN_ROW_COLOR: &str = "#343434";
132 pub const HEADER_ROW_COLOR: &str = "#272727";
133 //pub const MAIN_ROW_COLOR: &str = "#f4f434"; // TEST
134 //pub const HEADER_ROW_COLOR: &str = "#010101"; // TEST
135
get_string_from_list_store(tree_view: >k::TreeView) -> Vec<String>136 pub fn get_string_from_list_store(tree_view: >k::TreeView) -> Vec<String> {
137 let list_store: gtk::ListStore = get_list_store(tree_view);
138
139 let mut string_vector: Vec<String> = Vec::new();
140
141 let tree_iter = match list_store.iter_first() {
142 Some(t) => t,
143 None => {
144 return string_vector;
145 }
146 };
147 loop {
148 string_vector.push(list_store.value(&tree_iter, 0).get::<String>().unwrap());
149 if !list_store.iter_next(&tree_iter) {
150 return string_vector;
151 }
152 }
153 }
get_path_buf_from_vector_of_strings(vec_string: Vec<String>) -> Vec<PathBuf>154 pub fn get_path_buf_from_vector_of_strings(vec_string: Vec<String>) -> Vec<PathBuf> {
155 vec_string.iter().map(PathBuf::from).collect()
156 }
157
split_path(path: &Path) -> (String, String)158 pub fn split_path(path: &Path) -> (String, String) {
159 match (path.parent(), path.file_name()) {
160 (Some(dir), Some(file)) => (dir.display().to_string(), file.to_string_lossy().into_owned()),
161 (Some(dir), None) => (dir.display().to_string(), String::new()),
162 (None, _) => (String::new(), String::new()),
163 }
164 }
165
print_text_messages_to_text_view(text_messages: &Messages, text_view: >k::TextView)166 pub fn print_text_messages_to_text_view(text_messages: &Messages, text_view: >k::TextView) {
167 let mut messages: String = String::from("");
168 if !text_messages.messages.is_empty() {
169 messages += "############### MESSAGES ###############\n";
170 }
171 for text in &text_messages.messages {
172 messages += text.as_str();
173 messages += "\n";
174 }
175 if !text_messages.messages.is_empty() {
176 messages += "\n";
177 }
178 if !text_messages.warnings.is_empty() {
179 messages += "############### WARNINGS ###############\n";
180 }
181 for text in &text_messages.warnings {
182 messages += text.as_str();
183 messages += "\n";
184 }
185 if !text_messages.warnings.is_empty() {
186 messages += "\n";
187 }
188 if !text_messages.errors.is_empty() {
189 messages += "############### ERRORS ###############\n";
190 }
191 for text in &text_messages.errors {
192 messages += text.as_str();
193 messages += "\n";
194 }
195 if !text_messages.errors.is_empty() {
196 messages += "\n";
197 }
198
199 text_view.buffer().unwrap().set_text(messages.as_str());
200 }
201
reset_text_view(text_view: &TextView)202 pub fn reset_text_view(text_view: &TextView) {
203 text_view.buffer().unwrap().set_text("");
204 }
205
add_text_to_text_view(text_view: &TextView, string_to_append: &str)206 pub fn add_text_to_text_view(text_view: &TextView, string_to_append: &str) {
207 let buffer = text_view.buffer().unwrap();
208 let current_text = match buffer.text(&buffer.start_iter(), &buffer.end_iter(), true) {
209 Some(t) => t.to_string(),
210 None => "".to_string(),
211 };
212 buffer.set_text(format!("{}\n{}", current_text, string_to_append).as_str());
213 }
214
select_function_duplicates(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool215 pub fn select_function_duplicates(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool {
216 // let name = tree_model.value(&tree_model.iter(tree_path).unwrap(),ColumnsDuplicates::Name as i32).get::<String>().unwrap();
217 // let path = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsDuplicates::Path as i32).get::<String>().unwrap();
218 // let modification = tree_model.value(&tree_model.iter(tree_path).unwrap(),ColumnsDuplicates::Modification as i32).get::<String>().unwrap();
219 let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsDuplicates::Color as i32).get::<String>().unwrap();
220
221 if color == HEADER_ROW_COLOR {
222 return false;
223 }
224
225 true
226 }
select_function_same_music(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool227 pub fn select_function_same_music(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool {
228 let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsSameMusic::Color as i32).get::<String>().unwrap();
229
230 if color == HEADER_ROW_COLOR {
231 return false;
232 }
233
234 true
235 }
select_function_similar_images(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool236 pub fn select_function_similar_images(_tree_selection: >k::TreeSelection, tree_model: >k::TreeModel, tree_path: >k::TreePath, _is_path_currently_selected: bool) -> bool {
237 let color = tree_model.value(&tree_model.iter(tree_path).unwrap(), ColumnsSimilarImages::Color as i32).get::<String>().unwrap();
238
239 if color == HEADER_ROW_COLOR {
240 return false;
241 }
242
243 true
244 }
245
set_buttons(hashmap: &mut HashMap<String, bool>, buttons_array: &[gtk::Button], button_names: &[String])246 pub fn set_buttons(hashmap: &mut HashMap<String, bool>, buttons_array: &[gtk::Button], button_names: &[String]) {
247 for (index, button) in buttons_array.iter().enumerate() {
248 if *hashmap.get_mut(button_names[index].as_str()).unwrap() {
249 button.show();
250 } else {
251 button.hide();
252 }
253 }
254 }
hide_all_buttons(buttons_array: &[gtk::Button])255 pub fn hide_all_buttons(buttons_array: &[gtk::Button]) {
256 for button in buttons_array {
257 button.hide();
258 }
259 }
260
get_text_from_invalid_symlink_cause(error: &invalid_symlinks::ErrorType) -> &str261 pub fn get_text_from_invalid_symlink_cause(error: &invalid_symlinks::ErrorType) -> &str {
262 match error {
263 invalid_symlinks::ErrorType::InfiniteRecursion => "Infinite recursion",
264 invalid_symlinks::ErrorType::NonExistentFile => "Non existent destination file",
265 }
266 }
267
get_list_store(tree_view: >k::TreeView) -> ListStore268 pub fn get_list_store(tree_view: >k::TreeView) -> ListStore {
269 tree_view.model().unwrap().downcast::<gtk::ListStore>().unwrap()
270 }
get_dialog_box_child(dialog: >k::Dialog) -> gtk::Box271 pub fn get_dialog_box_child(dialog: >k::Dialog) -> gtk::Box {
272 dialog.children()[0].clone().downcast::<gtk::Box>().unwrap()
273 }
274
change_dimension_to_krotka(dimensions: String) -> (u64, u64)275 pub fn change_dimension_to_krotka(dimensions: String) -> (u64, u64) {
276 #[allow(clippy::single_char_pattern)]
277 let vec = dimensions.split::<&str>("x").collect::<Vec<_>>();
278 assert_eq!(vec.len(), 2); // 400x400 - should only have two elements, if have more, then something is not good
279 let number1 = vec[0].parse::<u64>().expect("Invalid data in image dimension in position 0");
280 let number2 = vec[1].parse::<u64>().expect("Invalid data in image dimension in position 1");
281 (number1, number2)
282 }
283