From 42af7246818e46560268cf38ddadd62fd060ffb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= <41945903+qarmin@users.noreply.github.com> Date: Thu, 21 Jan 2021 07:24:28 +0100 Subject: [PATCH] Add support for moving selection by keyboard to update similar image preview (#223) --- czkawka_gui/src/initialize_gui.rs | 160 ++++++++++++++++-------------- 1 file changed, 83 insertions(+), 77 deletions(-) diff --git a/czkawka_gui/src/initialize_gui.rs b/czkawka_gui/src/initialize_gui.rs index d643a86..bc6c803 100644 --- a/czkawka_gui/src/initialize_gui.rs +++ b/czkawka_gui/src/initialize_gui.rs @@ -5,7 +5,7 @@ use crate::gui_data::*; use crate::help_functions::*; use directories_next::ProjectDirs; use gtk::prelude::*; -use gtk::{SelectionMode, TreeView}; +use gtk::{CheckButton, Image, SelectionMode, TextView, TreeView}; use image::imageops::FilterType; use image::GenericImageView; use std::cmp::Ordering; @@ -227,82 +227,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) { tree_view.connect_button_press_event(opening_double_click_function_similar_images); tree_view.connect_button_release_event(move |tree_view, _event| { - let (selected_rows, tree_model) = tree_view.get_selection().get_selected_rows(); - - let mut created_image = false; - - // Only show preview when selected is only one item, because there is no method to recognize current clicked item in multiselection - if selected_rows.len() == 1 && check_button_settings_show_preview_similar_images.get_active() { - let tree_path = selected_rows[0].clone(); - if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") { - // TODO labels on {} are in testing stage, so we just ignore for now this warning until found better idea how to fix this - #[allow(clippy::never_loop)] - 'dir: loop { - 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()); - break 'dir; - } - } else if fs::create_dir_all(cache_dir).is_err() { - add_text_to_text_view(&text_view_errors, format!("Failed to create dir {} needed by image preview", cache_dir.display()).as_str()); - break 'dir; - } - let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsSimilarImages::Path as i32).get::().unwrap().unwrap(); - let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsSimilarImages::Name as i32).get::().unwrap().unwrap(); - - let file_name = format!("{}/{}", path, name); - let file_name = file_name.as_str(); - - if let Some(extension) = Path::new(file_name).extension() { - let img = match image::open(&file_name) { - Ok(t) => t, - Err(_) => { - add_text_to_text_view(&text_view_errors, format!("Failed to open temporary image file {}", file_name).as_str()); - break 'dir; - } - }; - if img.width() == 0 || img.height() == 0 { - add_text_to_text_view(&text_view_errors, format!("Cannot create preview of image {}, with 0 width or height", file_name).as_str()); - break 'dir; - } - let ratio = img.width() / img.height(); - let requested_dimensions = (400, 400); - let mut new_size; - match ratio.cmp(&(requested_dimensions.0 / requested_dimensions.1)) { - Ordering::Greater => { - new_size = (requested_dimensions.0, (img.height() * requested_dimensions.0) / img.width()); - new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1)); - } - Ordering::Less => { - new_size = ((img.width() * requested_dimensions.1) / img.height(), requested_dimensions.1); - new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1)); - } - Ordering::Equal => { - new_size = requested_dimensions; - new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1)); - } - } - let img = img.resize(new_size.0, new_size.1, FilterType::Triangle); - let file_dir = cache_dir.join(format!("cached_file.{}", extension.to_string_lossy())); - if img.save(&file_dir).is_err() { - add_text_to_text_view(&text_view_errors, format!("Failed to save temporary image file to {}", file_dir.display()).as_str()); - break 'dir; - } - let string_dir = file_dir.to_string_lossy().to_string(); - image_preview_similar_images.set_from_file(string_dir); - created_image = true; - } - break 'dir; - } - } - } - if created_image { - image_preview_similar_images.show(); - } else { - image_preview_similar_images.hide(); - } - + show_preview(tree_view, &text_view_errors, &check_button_settings_show_preview_similar_images, &image_preview_similar_images); gtk::Inhibit(false) }); @@ -310,6 +235,9 @@ pub fn initialize_gui(gui_data: &mut GuiData) { scrolled_window_similar_images_finder.add(&tree_view); scrolled_window_similar_images_finder.show_all(); + let image_preview_similar_images = image_preview_similar_images_clone.clone(); + let text_view_errors = gui_data.text_view_errors.clone(); + let check_button_settings_show_preview_similar_images = gui_data.upper_notebook.check_button_settings_show_preview_similar_images.clone(); let gui_data = gui_data.clone(); tree_view.connect_key_release_event(move |tree_view, e| { if let Some(button_number) = e.get_keycode() { @@ -319,6 +247,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) { image_preview_similar_images_clone.hide(); } } + show_preview(tree_view, &text_view_errors, &check_button_settings_show_preview_similar_images, &image_preview_similar_images); gtk::Inhibit(false) }); } @@ -517,3 +446,80 @@ pub fn initialize_gui(gui_data: &mut GuiData) { } } } +fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_settings_show_preview_similar_images: &CheckButton, image_preview_similar_images: &Image) { + let (selected_rows, tree_model) = tree_view.get_selection().get_selected_rows(); + + let mut created_image = false; + + // Only show preview when selected is only one item, because there is no method to recognize current clicked item in multiselection + if selected_rows.len() == 1 && check_button_settings_show_preview_similar_images.get_active() { + let tree_path = selected_rows[0].clone(); + if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") { + // TODO labels on {} are in testing stage, so we just ignore for now this warning until found better idea how to fix this + #[allow(clippy::never_loop)] + 'dir: loop { + 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()); + break 'dir; + } + } else if fs::create_dir_all(cache_dir).is_err() { + add_text_to_text_view(&text_view_errors, format!("Failed to create dir {} needed by image preview", cache_dir.display()).as_str()); + break 'dir; + } + let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsSimilarImages::Path as i32).get::().unwrap().unwrap(); + let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsSimilarImages::Name as i32).get::().unwrap().unwrap(); + + let file_name = format!("{}/{}", path, name); + let file_name = file_name.as_str(); + + if let Some(extension) = Path::new(file_name).extension() { + let img = match image::open(&file_name) { + Ok(t) => t, + Err(_) => { + add_text_to_text_view(&text_view_errors, format!("Failed to open temporary image file {}", file_name).as_str()); + break 'dir; + } + }; + if img.width() == 0 || img.height() == 0 { + add_text_to_text_view(&text_view_errors, format!("Cannot create preview of image {}, with 0 width or height", file_name).as_str()); + break 'dir; + } + let ratio = img.width() / img.height(); + let requested_dimensions = (400, 400); + let mut new_size; + match ratio.cmp(&(requested_dimensions.0 / requested_dimensions.1)) { + Ordering::Greater => { + new_size = (requested_dimensions.0, (img.height() * requested_dimensions.0) / img.width()); + new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1)); + } + Ordering::Less => { + new_size = ((img.width() * requested_dimensions.1) / img.height(), requested_dimensions.1); + new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1)); + } + Ordering::Equal => { + new_size = requested_dimensions; + new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1)); + } + } + let img = img.resize(new_size.0, new_size.1, FilterType::Triangle); + let file_dir = cache_dir.join(format!("cached_file.{}", extension.to_string_lossy())); + if img.save(&file_dir).is_err() { + add_text_to_text_view(&text_view_errors, format!("Failed to save temporary image file to {}", file_dir.display()).as_str()); + break 'dir; + } + let string_dir = file_dir.to_string_lossy().to_string(); + image_preview_similar_images.set_from_file(string_dir); + created_image = true; + } + break 'dir; + } + } + } + if created_image { + image_preview_similar_images.show(); + } else { + image_preview_similar_images.hide(); + } +}