diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs index 3565657..08c3f09 100644 --- a/czkawka_cli/src/main.rs +++ b/czkawka_cli/src/main.rs @@ -1,6 +1,9 @@ #![allow(clippy::needless_late_init)] +use std::process; + use clap::Parser; + use commands::Commands; #[allow(unused_imports)] // It is used in release for print_results(). use czkawka_core::common_traits::*; @@ -18,7 +21,6 @@ use czkawka_core::{ similar_videos::SimilarVideos, temporary::{self, Temporary}, }; -use std::process; mod commands; diff --git a/czkawka_core/Cargo.toml b/czkawka_core/Cargo.toml index 48121ec..92e30dc 100644 --- a/czkawka_core/Cargo.toml +++ b/czkawka_core/Cargo.toml @@ -26,7 +26,7 @@ hamming = "0.1.3" # Needed by same music bitflags = "1.3.2" -lofty= "0.7.3" +lofty = "0.7.3" # Futures - needed by async progress sender futures = "0.3.21" diff --git a/czkawka_core/src/bad_extensions.rs b/czkawka_core/src/bad_extensions.rs index b988fec..184f4d2 100644 --- a/czkawka_core/src/bad_extensions.rs +++ b/czkawka_core/src/bad_extensions.rs @@ -148,6 +148,7 @@ static WORKAROUNDS: &[(&str, &str)] = &[ ("msi", "doc"), // Not sure whe doc is not recognized ("exe", "xls"), // Not sure whe xls is not recognized ]; + #[derive(Clone)] pub struct BadFileEntry { pub path: PathBuf, diff --git a/czkawka_core/src/broken_files.rs b/czkawka_core/src/broken_files.rs index 2abd765..8b22103 100644 --- a/czkawka_core/src/broken_files.rs +++ b/czkawka_core/src/broken_files.rs @@ -794,6 +794,7 @@ fn check_extension_availability(file_name_lowercase: &str) -> TypeOfFile { TypeOfFile::Unknown } } + fn check_extension_allowed(type_of_file: &TypeOfFile, checked_types: &CheckedTypes) -> bool { ((*type_of_file == TypeOfFile::Image) && ((*checked_types & CheckedTypes::IMAGE) == CheckedTypes::IMAGE)) || ((*type_of_file == TypeOfFile::PDF) && ((*checked_types & CheckedTypes::PDF) == CheckedTypes::PDF)) diff --git a/czkawka_core/src/common.rs b/czkawka_core/src/common.rs index 9ec88d1..3ff4ddc 100644 --- a/czkawka_core/src/common.rs +++ b/czkawka_core/src/common.rs @@ -5,12 +5,11 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; use std::time::SystemTime; +#[cfg(feature = "heif")] +use anyhow::Result; use directories_next::ProjectDirs; use image::{DynamicImage, ImageBuffer, Rgb}; use imagepipe::{ImageSource, Pipeline}; - -#[cfg(feature = "heif")] -use anyhow::Result; #[cfg(feature = "heif")] use libheif_rs::{Channel, ColorSpace, HeifContext, RgbChroma}; diff --git a/czkawka_core/src/common_dir_traversal.rs b/czkawka_core/src/common_dir_traversal.rs index 3b0ab33..9093880 100644 --- a/czkawka_core/src/common_dir_traversal.rs +++ b/czkawka_core/src/common_dir_traversal.rs @@ -34,7 +34,7 @@ pub enum CheckingMethod { Hash, } -#[derive(Clone, Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct FileEntry { pub path: PathBuf, pub size: u64, @@ -47,13 +47,13 @@ pub struct FileEntry { const MAX_NUMBER_OF_SYMLINK_JUMPS: i32 = 20; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct SymlinkInfo { pub destination_path: PathBuf, pub type_of_error: ErrorType, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum ErrorType { InfiniteRecursion, NonExistentFile, diff --git a/czkawka_core/src/similar_images.rs b/czkawka_core/src/similar_images.rs index 8ef9a92..89d4fd9 100644 --- a/czkawka_core/src/similar_images.rs +++ b/czkawka_core/src/similar_images.rs @@ -21,7 +21,6 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "heif")] use crate::common::get_dynamic_image_from_heic; use crate::common::{get_dynamic_image_from_raw_image, open_cache_folder, Common, HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, LOOP_DURATION, RAW_IMAGE_EXTENSIONS}; - use crate::common_directory::Directories; use crate::common_extensions::Extensions; use crate::common_items::ExcludedItems; @@ -570,7 +569,7 @@ impl SimilarImages { break 'krztyna; } - # [cfg(feature = "heif")] + #[cfg(feature = "heif")] if HEIC_EXTENSIONS.iter().any(|e| file_name_lowercase.ends_with(e)) { image = match get_dynamic_image_from_heic(&file_entry.path.to_string_lossy().to_string()) { Ok(t) => t, diff --git a/czkawka_gui/i18n/en/czkawka_gui.ftl b/czkawka_gui/i18n/en/czkawka_gui.ftl index 11bce18..a547580 100644 --- a/czkawka_gui/i18n/en/czkawka_gui.ftl +++ b/czkawka_gui/i18n/en/czkawka_gui.ftl @@ -132,7 +132,12 @@ upper_manual_add_excluded_button = Manual Add upper_add_excluded_button = Add upper_remove_excluded_button = Remove -upper_manual_add_included_button_tooltip = Add directory name to search by hand. +upper_manual_add_included_button_tooltip = + Add directory name to search by hand. + + To add multiple paths at once, separate them by ; + + /home/roman;/home/rozkaz will add two directories /home/roman and /home/rozkaz upper_add_included_button_tooltip = Add new directory to search. upper_remove_included_button_tooltip = Delete directory from search. upper_manual_add_excluded_button_tooltip = Add excluded directory name by hand. diff --git a/czkawka_gui/src/connect_things/connect_button_compare.rs b/czkawka_gui/src/connect_things/connect_button_compare.rs index 054499a..dc323b5 100644 --- a/czkawka_gui/src/connect_things/connect_button_compare.rs +++ b/czkawka_gui/src/connect_things/connect_button_compare.rs @@ -1,14 +1,15 @@ use std::cell::RefCell; use std::rc::Rc; -#[cfg(feature = "heif")] -use czkawka_core::common::get_dynamic_image_from_heic; -use czkawka_core::common::HEIC_EXTENSIONS; use gdk4::gdk_pixbuf::{InterpType, Pixbuf}; use gtk4::prelude::*; use gtk4::{Align, CheckButton, Image, ListStore, Orientation, ScrolledWindow, TreeIter, TreeModel, TreePath, TreeSelection, Widget}; use image::DynamicImage; +#[cfg(feature = "heif")] +use czkawka_core::common::get_dynamic_image_from_heic; +use czkawka_core::common::HEIC_EXTENSIONS; + use crate::flg; use crate::gui_structs::gui_data::GuiData; use crate::help_functions::{ @@ -617,8 +618,8 @@ fn update_bottom_buttons( shared_using_for_preview: Rc, Option)>>, image_cache: Rc>>, ) { - let left_tree_view = (*shared_using_for_preview.borrow()).0.clone().unwrap(); - let right_tree_view = (*shared_using_for_preview.borrow()).1.clone().unwrap(); + let left_tree_view = (shared_using_for_preview.borrow()).0.clone().unwrap(); + let right_tree_view = (shared_using_for_preview.borrow()).1.clone().unwrap(); for (number, i) in get_all_direct_children(all_gtk_box).into_iter().enumerate() { let cache_tree_path = (*image_cache.borrow())[number].4.clone(); diff --git a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs index 2dff914..1bd3f56 100644 --- a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs +++ b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs @@ -157,20 +157,21 @@ fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded let tree_view = tree_view.clone(); dialog.connect_response(move |dialog, response_type| { if response_type == gtk4::ResponseType::Ok { - let text = entry.text().to_string().trim().to_string(); + for text in entry.text().split(';') { + let text = text.trim().to_string(); + #[cfg(target_family = "windows")] + let text = Common::normalize_windows_path(text).to_string_lossy().to_string(); - #[cfg(target_family = "windows")] - let text = Common::normalize_windows_path(text).to_string_lossy().to_string(); + if !text.is_empty() { + let list_store = get_list_store(&tree_view); - if !text.is_empty() { - let list_store = get_list_store(&tree_view); - - if excluded_items { - let values: [(u32, &dyn ToValue); 1] = [(ColumnsExcludedDirectory::Path as u32, &text)]; - list_store.set(&list_store.append(), &values); - } else { - let values: [(u32, &dyn ToValue); 2] = [(ColumnsIncludedDirectory::Path as u32, &text), (ColumnsIncludedDirectory::ReferenceButton as u32, &false)]; - list_store.set(&list_store.append(), &values); + if excluded_items { + let values: [(u32, &dyn ToValue); 1] = [(ColumnsExcludedDirectory::Path as u32, &text)]; + list_store.set(&list_store.append(), &values); + } else { + let values: [(u32, &dyn ToValue); 2] = [(ColumnsIncludedDirectory::Path as u32, &text), (ColumnsIncludedDirectory::ReferenceButton as u32, &false)]; + list_store.set(&list_store.append(), &values); + } } } } diff --git a/czkawka_gui/src/gui_structs/gui_main_notebook.rs b/czkawka_gui/src/gui_structs/gui_main_notebook.rs index 5284c88..7da8581 100644 --- a/czkawka_gui/src/gui_structs/gui_main_notebook.rs +++ b/czkawka_gui/src/gui_structs/gui_main_notebook.rs @@ -1,7 +1,7 @@ -use czkawka_core::big_file::SearchMode; use gtk4::prelude::*; use gtk4::{Builder, CheckButton, ComboBoxText, Entry, EventControllerKey, GestureClick, Image, Label, Notebook, Scale, ScrolledWindow, TreeView, Widget}; +use czkawka_core::big_file::SearchMode; use czkawka_core::common_dir_traversal::CheckingMethod; use czkawka_core::localizer_core::{fnc_get_similarity_minimal, fnc_get_similarity_very_high}; use czkawka_core::similar_images::{get_string_from_similarity, SIMILAR_VALUES}; diff --git a/czkawka_gui/src/help_combo_box.rs b/czkawka_gui/src/help_combo_box.rs index b8adbe6..525e997 100644 --- a/czkawka_gui/src/help_combo_box.rs +++ b/czkawka_gui/src/help_combo_box.rs @@ -1,6 +1,6 @@ -use czkawka_core::big_file::SearchMode; use image_hasher::{FilterType, HashAlg}; +use czkawka_core::big_file::SearchMode; use czkawka_core::common_dir_traversal::CheckingMethod; use czkawka_core::duplicate::HashType; diff --git a/czkawka_gui/src/help_functions.rs b/czkawka_gui/src/help_functions.rs index b56430e..9c20dcc 100644 --- a/czkawka_gui/src/help_functions.rs +++ b/czkawka_gui/src/help_functions.rs @@ -712,6 +712,7 @@ pub fn set_icon_of_button>(button: &P, data: &'static [u8]) { } static mut IMAGE_PREVIEW_ARRAY: OnceCell> = OnceCell::new(); + pub fn get_pixbuf_from_dynamic_image(dynamic_image: &DynamicImage) -> Result { let mut output = Vec::new(); JpegEncoder::new(&mut output).encode_image(dynamic_image).unwrap(); @@ -740,15 +741,19 @@ fn test_file_name_shortener() { assert_eq!(get_max_file_name(name_to_check, 21), "/home/rafa ... 🌈\u{fe0f}🏳\u{fe0f}\u{200d}🌈\u{fe0f}.txt"); assert_eq!(get_max_file_name(name_to_check, 20), "/home/rafa ... \u{fe0f}🏳\u{fe0f}\u{200d}🌈\u{fe0f}.txt"); assert_eq!(get_max_file_name(name_to_check, 19), "/home/rafa ... 🏳\u{fe0f}\u{200d}🌈\u{fe0f}.txt"); + assert_eq!(get_max_file_name(name_to_check, 18), "/home/rafa ... \u{fe0f}\u{200d}🌈\u{fe0f}.txt"); + assert_eq!(get_max_file_name(name_to_check, 17), "/home/rafa ... \u{200d}🌈\u{fe0f}.txt"); + assert_eq!(get_max_file_name(name_to_check, 16), "/home/rafa ... 🌈\u{fe0f}.txt"); } #[cfg(test)] mod test { - use crate::help_functions::{get_all_boxes_from_widget, get_all_direct_children, get_pixbuf_from_dynamic_image}; use gtk4::prelude::*; use gtk4::Orientation; use image::DynamicImage; + use crate::help_functions::{change_dimension_to_krotka, get_all_boxes_from_widget, get_all_direct_children, get_pixbuf_from_dynamic_image}; + #[test] fn test_pixbuf_from_dynamic_image() { let dynamic_image = DynamicImage::new_rgb8(1, 1); @@ -757,6 +762,11 @@ mod test { get_pixbuf_from_dynamic_image(&dynamic_image).unwrap(); get_pixbuf_from_dynamic_image(&dynamic_image).unwrap(); } + #[test] + fn test_change_dimension_to_krotka() { + assert_eq!(change_dimension_to_krotka("50x50".to_string()), (50, 50)); + assert_eq!(change_dimension_to_krotka("6000x6000".to_string()), (6000, 6000)); + } #[gtk4::test] fn test_get_all_direct_children() {