Add compare images tool (#568)
* Add compare images tool * Crash lord, crashes more than needed * Kluchy piertuchy * Głowa mała * Troszkę * Czokoszoki * Ajzenbiśla * Środa * Piątek * Stonk * TreePath * Czego, śpiem przecież * Mój tród skończon * Aktualizacja nazw
This commit is contained in:
parent
f6599f51ae
commit
5dab9286cb
|
@ -561,7 +561,6 @@ impl SimilarImages {
|
|||
let image;
|
||||
|
||||
if !IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS.iter().any(|e| file_name_lowercase.ends_with(e)){
|
||||
println!("Hashing {:?}", file_entry.path);
|
||||
|
||||
image = match get_dynamic_image_from_raw_image(&file_entry.path){
|
||||
Some(t) => t,
|
||||
|
@ -609,7 +608,6 @@ impl SimilarImages {
|
|||
let buf: Vec<u8> = hash.as_bytes().to_vec();
|
||||
|
||||
file_entry.hash = buf.clone();
|
||||
println!("{:?}, hash {:?}",file_entry.path,file_entry.hash);
|
||||
|
||||
Some(Some((file_entry, buf)))
|
||||
|
||||
|
|
|
@ -940,7 +940,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
|
|||
set_specific_buttons_as_active(
|
||||
&shared_buttons,
|
||||
&NotebookMainEnum::SimilarImages,
|
||||
&["save", "delete", "select", "symlink", "hardlink", "move"],
|
||||
&["save", "delete", "select", "symlink", "hardlink", "move", "compare"],
|
||||
found_any_duplicates,
|
||||
);
|
||||
|
||||
|
|
603
czkawka_gui/src/connect_button_compare.rs
Normal file
603
czkawka_gui/src/connect_button_compare.rs
Normal file
|
@ -0,0 +1,603 @@
|
|||
use czkawka_core::common::get_dynamic_image_from_raw_image;
|
||||
use czkawka_core::fl;
|
||||
use czkawka_core::similar_images::RAW_IMAGE_EXTENSIONS;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{CheckButton, Image, ListStore, Orientation, ScrolledWindow, TreeIter, TreeModel, TreePath, TreeSelection};
|
||||
use image::imageops::FilterType;
|
||||
use image::DynamicImage;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::gui_data::GuiData;
|
||||
use crate::help_functions::{
|
||||
count_number_of_groups, get_full_name_from_path_name, get_image_path_temporary, get_max_file_name, resize_dynamic_image_dimension, NotebookObject, HEADER_ROW_COLOR,
|
||||
NOTEBOOKS_INFOS,
|
||||
};
|
||||
use crate::localizer::generate_translation_hashmap;
|
||||
|
||||
const BIG_PREVIEW_SIZE: u32 = 600;
|
||||
const SMALL_PREVIEW_SIZE: u32 = 100;
|
||||
|
||||
pub fn connect_button_compare(gui_data: &GuiData) {
|
||||
let button_compare = gui_data.bottom_buttons.buttons_compare.clone();
|
||||
let window_compare = gui_data.compare_images.window_compare.clone();
|
||||
let notebook_main = gui_data.main_notebook.notebook_main.clone();
|
||||
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
|
||||
let scrolled_window_compare_choose_images = gui_data.compare_images.scrolled_window_compare_choose_images.clone();
|
||||
|
||||
let label_group_info = gui_data.compare_images.label_group_info.clone();
|
||||
|
||||
let button_go_previous_compare_group = gui_data.compare_images.button_go_previous_compare_group.clone();
|
||||
let button_go_next_compare_group = gui_data.compare_images.button_go_next_compare_group.clone();
|
||||
|
||||
let check_button_left_preview_text = gui_data.compare_images.check_button_left_preview_text.clone();
|
||||
let check_button_right_preview_text = gui_data.compare_images.check_button_right_preview_text.clone();
|
||||
|
||||
let shared_numbers_of_groups = gui_data.compare_images.shared_numbers_of_groups.clone();
|
||||
let shared_current_of_groups = gui_data.compare_images.shared_current_of_groups.clone();
|
||||
let shared_current_iter = gui_data.compare_images.shared_current_iter.clone();
|
||||
let shared_image_cache = gui_data.compare_images.shared_image_cache.clone();
|
||||
let shared_using_for_preview = gui_data.compare_images.shared_using_for_preview.clone();
|
||||
|
||||
let image_compare_left = gui_data.compare_images.image_compare_left.clone();
|
||||
let image_compare_right = gui_data.compare_images.image_compare_right.clone();
|
||||
|
||||
button_compare.connect_clicked(move |_| {
|
||||
let nb_number = notebook_main.current_page().unwrap();
|
||||
let tree_view = &main_tree_views[nb_number as usize];
|
||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||
let model = tree_view.model().unwrap();
|
||||
|
||||
let group_number = count_number_of_groups(tree_view, nb_object.column_color.unwrap());
|
||||
|
||||
if group_number == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
*shared_current_of_groups.borrow_mut() = 1;
|
||||
*shared_numbers_of_groups.borrow_mut() = group_number;
|
||||
|
||||
button_go_previous_compare_group.set_sensitive(false);
|
||||
if group_number == 1 {
|
||||
button_go_next_compare_group.set_sensitive(false);
|
||||
} else {
|
||||
button_go_next_compare_group.set_sensitive(true);
|
||||
}
|
||||
|
||||
// Check selected items
|
||||
let (current_group, tree_iter) = get_current_group_and_iter_from_selection(&model, tree_view.selection(), nb_object.column_color.unwrap());
|
||||
|
||||
populate_groups_at_start(
|
||||
nb_object,
|
||||
&model,
|
||||
shared_current_iter.clone(),
|
||||
tree_iter,
|
||||
&image_compare_left,
|
||||
&image_compare_right,
|
||||
current_group,
|
||||
group_number,
|
||||
&check_button_left_preview_text,
|
||||
&check_button_right_preview_text,
|
||||
&scrolled_window_compare_choose_images,
|
||||
&label_group_info,
|
||||
shared_image_cache.clone(),
|
||||
shared_using_for_preview.clone(),
|
||||
);
|
||||
|
||||
window_compare.show();
|
||||
});
|
||||
|
||||
let shared_image_cache = gui_data.compare_images.shared_image_cache.clone();
|
||||
let shared_current_iter = gui_data.compare_images.shared_current_iter.clone();
|
||||
let shared_using_for_preview = gui_data.compare_images.shared_using_for_preview.clone();
|
||||
let shared_current_of_groups = gui_data.compare_images.shared_current_of_groups.clone();
|
||||
let shared_numbers_of_groups = gui_data.compare_images.shared_numbers_of_groups.clone();
|
||||
let window_compare = gui_data.compare_images.window_compare.clone();
|
||||
let image_compare_left = gui_data.compare_images.image_compare_left.clone();
|
||||
let image_compare_right = gui_data.compare_images.image_compare_right.clone();
|
||||
window_compare.connect_delete_event(move |window_compare, _| {
|
||||
window_compare.hide();
|
||||
*shared_image_cache.borrow_mut() = Vec::new();
|
||||
*shared_current_iter.borrow_mut() = None;
|
||||
*shared_current_of_groups.borrow_mut() = 0;
|
||||
*shared_numbers_of_groups.borrow_mut() = 0;
|
||||
*shared_using_for_preview.borrow_mut() = (None, None);
|
||||
image_compare_left.set_from_pixbuf(None);
|
||||
image_compare_right.set_from_pixbuf(None);
|
||||
gtk::Inhibit(true)
|
||||
});
|
||||
|
||||
let button_go_previous_compare_group = gui_data.compare_images.button_go_previous_compare_group.clone();
|
||||
let button_go_next_compare_group = gui_data.compare_images.button_go_next_compare_group.clone();
|
||||
let label_group_info = gui_data.compare_images.label_group_info.clone();
|
||||
let notebook_main = gui_data.main_notebook.notebook_main.clone();
|
||||
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
|
||||
let scrolled_window_compare_choose_images = gui_data.compare_images.scrolled_window_compare_choose_images.clone();
|
||||
|
||||
let check_button_left_preview_text = gui_data.compare_images.check_button_left_preview_text.clone();
|
||||
let check_button_right_preview_text = gui_data.compare_images.check_button_right_preview_text.clone();
|
||||
|
||||
let shared_current_of_groups = gui_data.compare_images.shared_current_of_groups.clone();
|
||||
let shared_numbers_of_groups = gui_data.compare_images.shared_numbers_of_groups.clone();
|
||||
let shared_current_iter = gui_data.compare_images.shared_current_iter.clone();
|
||||
let shared_image_cache = gui_data.compare_images.shared_image_cache.clone();
|
||||
let shared_using_for_preview = gui_data.compare_images.shared_using_for_preview.clone();
|
||||
|
||||
let image_compare_left = gui_data.compare_images.image_compare_left.clone();
|
||||
let image_compare_right = gui_data.compare_images.image_compare_right.clone();
|
||||
|
||||
button_go_previous_compare_group.connect_clicked(move |button_go_previous_compare_group| {
|
||||
let nb_number = notebook_main.current_page().unwrap();
|
||||
let tree_view = &main_tree_views[nb_number as usize];
|
||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||
let model = tree_view.model().unwrap();
|
||||
|
||||
*shared_current_of_groups.borrow_mut() -= 1;
|
||||
|
||||
let current_group = *shared_current_of_groups.borrow();
|
||||
let group_number = *shared_numbers_of_groups.borrow();
|
||||
|
||||
if current_group == 1 {
|
||||
button_go_previous_compare_group.set_sensitive(false);
|
||||
}
|
||||
button_go_next_compare_group.set_sensitive(true);
|
||||
|
||||
let tree_iter = move_iter(&model, shared_current_iter.borrow().as_ref().unwrap(), nb_object.column_color.unwrap(), false);
|
||||
|
||||
populate_groups_at_start(
|
||||
nb_object,
|
||||
&model,
|
||||
shared_current_iter.clone(),
|
||||
tree_iter,
|
||||
&image_compare_left,
|
||||
&image_compare_right,
|
||||
current_group,
|
||||
group_number,
|
||||
&check_button_left_preview_text,
|
||||
&check_button_right_preview_text,
|
||||
&scrolled_window_compare_choose_images,
|
||||
&label_group_info,
|
||||
shared_image_cache.clone(),
|
||||
shared_using_for_preview.clone(),
|
||||
);
|
||||
});
|
||||
|
||||
let button_go_previous_compare_group = gui_data.compare_images.button_go_previous_compare_group.clone();
|
||||
let button_go_next_compare_group = gui_data.compare_images.button_go_next_compare_group.clone();
|
||||
let label_group_info = gui_data.compare_images.label_group_info.clone();
|
||||
let notebook_main = gui_data.main_notebook.notebook_main.clone();
|
||||
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
|
||||
let scrolled_window_compare_choose_images = gui_data.compare_images.scrolled_window_compare_choose_images.clone();
|
||||
|
||||
let check_button_left_preview_text = gui_data.compare_images.check_button_left_preview_text.clone();
|
||||
let check_button_right_preview_text = gui_data.compare_images.check_button_right_preview_text.clone();
|
||||
|
||||
let shared_current_of_groups = gui_data.compare_images.shared_current_of_groups.clone();
|
||||
let shared_numbers_of_groups = gui_data.compare_images.shared_numbers_of_groups.clone();
|
||||
let shared_current_iter = gui_data.compare_images.shared_current_iter.clone();
|
||||
let shared_image_cache = gui_data.compare_images.shared_image_cache.clone();
|
||||
let shared_using_for_preview = gui_data.compare_images.shared_using_for_preview.clone();
|
||||
|
||||
let image_compare_left = gui_data.compare_images.image_compare_left.clone();
|
||||
let image_compare_right = gui_data.compare_images.image_compare_right.clone();
|
||||
|
||||
button_go_next_compare_group.connect_clicked(move |button_go_next_compare_group| {
|
||||
let nb_number = notebook_main.current_page().unwrap();
|
||||
let tree_view = &main_tree_views[nb_number as usize];
|
||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||
let model = tree_view.model().unwrap();
|
||||
|
||||
*shared_current_of_groups.borrow_mut() += 1;
|
||||
|
||||
let current_group = *shared_current_of_groups.borrow();
|
||||
let group_number = *shared_numbers_of_groups.borrow();
|
||||
|
||||
if group_number == current_group {
|
||||
button_go_next_compare_group.set_sensitive(false);
|
||||
}
|
||||
button_go_previous_compare_group.set_sensitive(true);
|
||||
|
||||
let tree_iter = move_iter(&model, shared_current_iter.borrow().as_ref().unwrap(), nb_object.column_color.unwrap(), true);
|
||||
|
||||
populate_groups_at_start(
|
||||
nb_object,
|
||||
&model,
|
||||
shared_current_iter.clone(),
|
||||
tree_iter,
|
||||
&image_compare_left,
|
||||
&image_compare_right,
|
||||
current_group,
|
||||
group_number,
|
||||
&check_button_left_preview_text,
|
||||
&check_button_right_preview_text,
|
||||
&scrolled_window_compare_choose_images,
|
||||
&label_group_info,
|
||||
shared_image_cache.clone(),
|
||||
shared_using_for_preview.clone(),
|
||||
);
|
||||
});
|
||||
|
||||
let check_button_left_preview_text = gui_data.compare_images.check_button_left_preview_text.clone();
|
||||
let shared_using_for_preview = gui_data.compare_images.shared_using_for_preview.clone();
|
||||
let notebook_main = gui_data.main_notebook.notebook_main.clone();
|
||||
let shared_current_iter = gui_data.compare_images.shared_current_iter.clone();
|
||||
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
|
||||
check_button_left_preview_text.connect_clicked(move |check_button_left_preview_text| {
|
||||
let nb_number = notebook_main.current_page().unwrap();
|
||||
let tree_view = &main_tree_views[nb_number as usize];
|
||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||
let model = tree_view.model().unwrap().downcast::<ListStore>().unwrap();
|
||||
|
||||
let main_tree_path = model.path(shared_current_iter.borrow().as_ref().unwrap()).unwrap();
|
||||
let this_tree_path = shared_using_for_preview.borrow().0.clone().unwrap();
|
||||
if main_tree_path == this_tree_path {
|
||||
return; // Selected header, so we don't need to select result in treeview
|
||||
// TODO this should be handled by disabling entirely check box
|
||||
}
|
||||
|
||||
let is_active = check_button_left_preview_text.is_active();
|
||||
model.set_value(&model.iter(&this_tree_path).unwrap(), nb_object.column_selection as u32, &is_active.to_value());
|
||||
});
|
||||
|
||||
let check_button_right_preview_text = gui_data.compare_images.check_button_right_preview_text.clone();
|
||||
let shared_using_for_preview = gui_data.compare_images.shared_using_for_preview.clone();
|
||||
let shared_current_iter = gui_data.compare_images.shared_current_iter.clone();
|
||||
let notebook_main = gui_data.main_notebook.notebook_main.clone();
|
||||
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
|
||||
check_button_right_preview_text.connect_clicked(move |check_button_right_preview_text| {
|
||||
let nb_number = notebook_main.current_page().unwrap();
|
||||
let tree_view = &main_tree_views[nb_number as usize];
|
||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||
let model = tree_view.model().unwrap().downcast::<ListStore>().unwrap();
|
||||
|
||||
let main_tree_path = model.path(shared_current_iter.borrow().as_ref().unwrap()).unwrap();
|
||||
let this_tree_path = shared_using_for_preview.borrow().1.clone().unwrap();
|
||||
if main_tree_path == this_tree_path {
|
||||
return; // Selected header, so we don't need to select result in treeview
|
||||
// TODO this should be handled by disabling entirely check box
|
||||
}
|
||||
|
||||
let is_active = check_button_right_preview_text.is_active();
|
||||
model.set_value(&model.iter(&this_tree_path).unwrap(), nb_object.column_selection as u32, &is_active.to_value());
|
||||
});
|
||||
}
|
||||
|
||||
/// Populate all parameters for current group, it is used at start and when changing groups
|
||||
fn populate_groups_at_start(
|
||||
nb_object: &NotebookObject,
|
||||
model: &TreeModel,
|
||||
shared_current_iter: Rc<RefCell<Option<TreeIter>>>,
|
||||
tree_iter: TreeIter,
|
||||
image_compare_left: >k::Image,
|
||||
image_compare_right: >k::Image,
|
||||
current_group: u32,
|
||||
group_number: u32,
|
||||
check_button_left_preview_text: >k::CheckButton,
|
||||
check_button_right_preview_text: >k::CheckButton,
|
||||
scrolled_window_compare_choose_images: >k::ScrolledWindow,
|
||||
label_group_info: >k::Label,
|
||||
shared_image_cache: Rc<RefCell<Vec<(String, String, gtk::Image, gtk::Image, gtk::TreePath)>>>,
|
||||
shared_using_for_preview: Rc<RefCell<(Option<TreePath>, Option<TreePath>)>>,
|
||||
) {
|
||||
let all_vec = get_all_path(model, &tree_iter, nb_object.column_color.unwrap(), nb_object.column_path, nb_object.column_name);
|
||||
*shared_current_iter.borrow_mut() = Some(tree_iter);
|
||||
|
||||
let cache_all_images = generate_cache_for_results(all_vec);
|
||||
|
||||
// This is safe, because cache have at least 2 results
|
||||
image_compare_left.set_from_pixbuf(cache_all_images[0].2.pixbuf().as_ref());
|
||||
image_compare_right.set_from_pixbuf(cache_all_images[1].2.pixbuf().as_ref());
|
||||
|
||||
*shared_using_for_preview.borrow_mut() = (Some(cache_all_images[0].4.clone()), Some(cache_all_images[1].4.clone()));
|
||||
|
||||
check_button_left_preview_text.set_label(&format!("1. {}", get_max_file_name(&cache_all_images[0].0, 70)));
|
||||
check_button_right_preview_text.set_label(&format!("2. {}", get_max_file_name(&cache_all_images[1].0, 70)));
|
||||
|
||||
label_group_info.set_text(
|
||||
fl!(
|
||||
"compare_groups_number",
|
||||
generate_translation_hashmap(vec![
|
||||
("current_group", current_group.to_string()),
|
||||
("all_groups", group_number.to_string()),
|
||||
("images_in_group", cache_all_images.len().to_string())
|
||||
])
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
|
||||
populate_similar_scrolled_view(
|
||||
scrolled_window_compare_choose_images,
|
||||
&cache_all_images,
|
||||
image_compare_left,
|
||||
image_compare_right,
|
||||
shared_using_for_preview.clone(),
|
||||
shared_image_cache.clone(),
|
||||
check_button_left_preview_text,
|
||||
check_button_right_preview_text,
|
||||
model,
|
||||
nb_object.column_selection,
|
||||
);
|
||||
|
||||
*shared_image_cache.borrow_mut() = cache_all_images.clone();
|
||||
|
||||
let mut found = false;
|
||||
for i in scrolled_window_compare_choose_images.child().unwrap().downcast::<gtk::Viewport>().unwrap().children() {
|
||||
if i.widget_name() == "all_box" {
|
||||
let gtk_box = i.downcast::<gtk::Box>().unwrap();
|
||||
update_bottom_buttons(>k_box, shared_using_for_preview, shared_image_cache);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert!(found);
|
||||
|
||||
let is_active = model.value(&model.iter(&cache_all_images[0].4).unwrap(), nb_object.column_selection).get::<bool>().unwrap();
|
||||
check_button_left_preview_text.set_active(is_active);
|
||||
let is_active = model.value(&model.iter(&cache_all_images[1].4).unwrap(), nb_object.column_selection).get::<bool>().unwrap();
|
||||
check_button_right_preview_text.set_active(is_active);
|
||||
}
|
||||
|
||||
/// Generate images which will be used later as preview images without needing to open them again and again
|
||||
fn generate_cache_for_results(vector_with_path: Vec<(String, String, gtk::TreePath)>) -> Vec<(String, String, gtk::Image, gtk::Image, gtk::TreePath)> {
|
||||
// TODO use here threads,
|
||||
// For now threads cannot be used because Image and TreeIter cannot be used in threads
|
||||
let mut cache_all_images = Vec::new();
|
||||
for (full_path, name, tree_path) in vector_with_path {
|
||||
let name_lowercase = name.to_lowercase();
|
||||
let dynamic_image = if RAW_IMAGE_EXTENSIONS.iter().any(|f| name_lowercase.ends_with(f)) {
|
||||
match get_dynamic_image_from_raw_image(&full_path) {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
println!("Failed to convert rawimage {}", full_path);
|
||||
DynamicImage::new_rgb8(1, 1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match image::open(&full_path) {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
println!("Failed to open image {}", full_path);
|
||||
DynamicImage::new_rgb8(1, 1)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let big_thumbnail = resize_dynamic_image_dimension(dynamic_image, (BIG_PREVIEW_SIZE, BIG_PREVIEW_SIZE), &FilterType::Triangle);
|
||||
let big_path = get_image_path_temporary("roman", 1, "jpg");
|
||||
let _ = big_thumbnail.save(&big_path);
|
||||
let big_img = gtk::Image::new();
|
||||
big_img.set_from_file(big_path);
|
||||
|
||||
let small_thumbnail = resize_dynamic_image_dimension(big_thumbnail, (SMALL_PREVIEW_SIZE, SMALL_PREVIEW_SIZE), &FilterType::Triangle);
|
||||
let small_path = get_image_path_temporary("roman", 1, "jpg");
|
||||
let _ = small_thumbnail.save(&small_path);
|
||||
let small_img = gtk::Image::new();
|
||||
small_img.set_from_file(small_path);
|
||||
|
||||
cache_all_images.push((full_path, name, big_img, small_img, tree_path));
|
||||
}
|
||||
cache_all_images
|
||||
}
|
||||
|
||||
/// Takes info about current items in groups like path
|
||||
fn get_all_path(model: &TreeModel, current_iter: &TreeIter, column_color: i32, column_path: i32, column_name: i32) -> Vec<(String, String, gtk::TreePath)> {
|
||||
let used_iter = current_iter.clone();
|
||||
|
||||
assert_eq!(model.value(&used_iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR);
|
||||
let using_reference = !model.value(&used_iter, column_path).get::<String>().unwrap().is_empty();
|
||||
|
||||
let mut returned_vector = Vec::new();
|
||||
|
||||
if using_reference {
|
||||
let name = model.value(&used_iter, column_name).get::<String>().unwrap();
|
||||
let path = model.value(&used_iter, column_path).get::<String>().unwrap();
|
||||
|
||||
let full_name = get_full_name_from_path_name(&path, &name);
|
||||
|
||||
returned_vector.push((full_name, name, model.path(&used_iter).unwrap()));
|
||||
}
|
||||
|
||||
if !model.iter_next(&used_iter) {
|
||||
panic!("Found only header!");
|
||||
}
|
||||
|
||||
loop {
|
||||
let name = model.value(&used_iter, column_name).get::<String>().unwrap();
|
||||
let path = model.value(&used_iter, column_path).get::<String>().unwrap();
|
||||
|
||||
let full_name = get_full_name_from_path_name(&path, &name);
|
||||
|
||||
returned_vector.push((full_name, name, model.path(&used_iter).unwrap()));
|
||||
|
||||
if !model.iter_next(&used_iter) {
|
||||
break;
|
||||
}
|
||||
|
||||
let color = model.value(&used_iter, column_color).get::<String>().unwrap();
|
||||
|
||||
if color == HEADER_ROW_COLOR {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(returned_vector.len() > 1);
|
||||
|
||||
returned_vector
|
||||
}
|
||||
|
||||
/// Moves iterator to previous/next header
|
||||
fn move_iter(model: >k::TreeModel, tree_iter: &TreeIter, column_color: i32, go_next: bool) -> TreeIter {
|
||||
assert_eq!(model.value(tree_iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR);
|
||||
|
||||
if go_next {
|
||||
if !model.iter_next(tree_iter) {
|
||||
panic!("Found only header!");
|
||||
}
|
||||
} else {
|
||||
if !model.iter_previous(tree_iter) {
|
||||
panic!("Found only header!");
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
if go_next {
|
||||
if !model.iter_next(tree_iter) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if !model.iter_previous(tree_iter) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let color = model.value(tree_iter, column_color).get::<String>().unwrap();
|
||||
|
||||
if color == HEADER_ROW_COLOR {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tree_iter.clone()
|
||||
}
|
||||
|
||||
/// Populate bottom Scrolled View with small thumbnails
|
||||
fn populate_similar_scrolled_view(
|
||||
scrolled_window: &ScrolledWindow,
|
||||
image_cache: &[(String, String, Image, Image, TreePath)],
|
||||
image_compare_left: &Image,
|
||||
image_compare_right: &Image,
|
||||
shared_using_for_preview: Rc<RefCell<(Option<TreePath>, Option<TreePath>)>>,
|
||||
shared_image_cache: Rc<RefCell<Vec<(String, String, gtk::Image, gtk::Image, gtk::TreePath)>>>,
|
||||
check_button_left_preview_text: &CheckButton,
|
||||
check_button_right_preview_text: &CheckButton,
|
||||
model: &TreeModel,
|
||||
column_selection: i32,
|
||||
) {
|
||||
if let Some(child) = scrolled_window.child() {
|
||||
scrolled_window.remove(&child);
|
||||
};
|
||||
scrolled_window.set_propagate_natural_height(true);
|
||||
|
||||
let all_gtk_box = gtk::Box::new(Orientation::Horizontal, 5);
|
||||
all_gtk_box.set_widget_name("all_box");
|
||||
|
||||
for (number, (path, _name, big_thumbnail, small_thumbnail, tree_path)) in image_cache.iter().enumerate() {
|
||||
let small_box = gtk::Box::new(Orientation::Vertical, 3);
|
||||
|
||||
let smaller_box = gtk::Box::new(Orientation::Horizontal, 2);
|
||||
|
||||
let button_left = gtk::Button::builder().label(&fl!("compare_move_left_button")).build();
|
||||
let label = gtk::Label::builder().label(&(number + 1).to_string()).build();
|
||||
let button_right = gtk::Button::builder().label(&fl!("compare_move_right_button")).build();
|
||||
|
||||
let image_compare_left = image_compare_left.clone();
|
||||
let image_compare_right = image_compare_right.clone();
|
||||
|
||||
let big_thumbnail_clone = big_thumbnail.clone();
|
||||
let tree_path_clone = tree_path.clone();
|
||||
let all_gtk_box_clone = all_gtk_box.clone();
|
||||
let shared_using_for_preview_clone = shared_using_for_preview.clone();
|
||||
let shared_image_cache_clone = shared_image_cache.clone();
|
||||
let check_button_left_preview_text_clone = check_button_left_preview_text.clone();
|
||||
let model_clone = model.clone();
|
||||
let path_clone = path.clone();
|
||||
|
||||
button_left.connect_clicked(move |_button_left| {
|
||||
shared_using_for_preview_clone.borrow_mut().0 = Some(tree_path_clone.clone());
|
||||
update_bottom_buttons(&all_gtk_box_clone, shared_using_for_preview_clone.clone(), shared_image_cache_clone.clone());
|
||||
image_compare_left.set_from_pixbuf(big_thumbnail_clone.pixbuf().as_ref());
|
||||
|
||||
let is_active = model_clone.value(&model_clone.iter(&tree_path_clone).unwrap(), column_selection).get::<bool>().unwrap();
|
||||
check_button_left_preview_text_clone.set_active(is_active);
|
||||
check_button_left_preview_text_clone.set_label(&format!("{}. {}", number + 1, get_max_file_name(&path_clone, 70)));
|
||||
});
|
||||
|
||||
let big_thumbnail_clone = big_thumbnail.clone();
|
||||
let tree_path_clone = tree_path.clone();
|
||||
let all_gtk_box_clone = all_gtk_box.clone();
|
||||
let shared_using_for_preview_clone = shared_using_for_preview.clone();
|
||||
let shared_image_cache_clone = shared_image_cache.clone();
|
||||
let check_button_right_preview_text_clone = check_button_right_preview_text.clone();
|
||||
let model_clone = model.clone();
|
||||
let path_clone = path.clone();
|
||||
|
||||
button_right.connect_clicked(move |_button_right| {
|
||||
shared_using_for_preview_clone.borrow_mut().1 = Some(tree_path_clone.clone());
|
||||
update_bottom_buttons(&all_gtk_box_clone, shared_using_for_preview_clone.clone(), shared_image_cache_clone.clone());
|
||||
image_compare_right.set_from_pixbuf(big_thumbnail_clone.pixbuf().as_ref());
|
||||
|
||||
let is_active = model_clone.value(&model_clone.iter(&tree_path_clone).unwrap(), column_selection).get::<bool>().unwrap();
|
||||
check_button_right_preview_text_clone.set_active(is_active);
|
||||
check_button_right_preview_text_clone.set_label(&format!("{}. {}", number + 1, get_max_file_name(&path_clone, 70)));
|
||||
});
|
||||
|
||||
smaller_box.add(&button_left);
|
||||
smaller_box.add(&label);
|
||||
smaller_box.add(&button_right);
|
||||
|
||||
small_box.add(&smaller_box);
|
||||
small_box.add(small_thumbnail);
|
||||
|
||||
all_gtk_box.add(&small_box);
|
||||
}
|
||||
|
||||
all_gtk_box.show_all();
|
||||
scrolled_window.add(&all_gtk_box);
|
||||
}
|
||||
|
||||
/// Disables/Enables L/R buttons at the bottom scrolled view
|
||||
fn update_bottom_buttons(
|
||||
all_gtk_box: >k::Box,
|
||||
shared_using_for_preview: Rc<RefCell<(Option<TreePath>, Option<TreePath>)>>,
|
||||
image_cache: Rc<RefCell<Vec<(String, String, Image, Image, TreePath)>>>,
|
||||
) {
|
||||
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 all_gtk_box.children().into_iter().enumerate() {
|
||||
let cache_tree_path = (*image_cache.borrow())[number].4.clone();
|
||||
let is_chosen = cache_tree_path != right_tree_view && cache_tree_path != left_tree_view;
|
||||
|
||||
let bx = i.downcast::<gtk::Box>().unwrap();
|
||||
let smaller_bx = bx.children()[0].clone().downcast::<gtk::Box>().unwrap();
|
||||
for items in smaller_bx.children() {
|
||||
if let Ok(btn) = items.downcast::<gtk::Button>() {
|
||||
btn.set_sensitive(is_chosen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_current_group_and_iter_from_selection(model: &TreeModel, selection: TreeSelection, column_color: i32) -> (u32, TreeIter) {
|
||||
let mut current_group = 1;
|
||||
let mut possible_group = 1;
|
||||
let mut header_clone: TreeIter;
|
||||
let mut possible_header: TreeIter;
|
||||
|
||||
let selected_records = selection.selected_rows().0;
|
||||
|
||||
let iter = model.iter_first().unwrap(); // Checking that treeview is not empty should be done before
|
||||
header_clone = iter.clone(); // if nothing selected, use first group
|
||||
possible_header = iter.clone(); // if nothing selected, use first group
|
||||
assert_eq!(model.value(&iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR); // First element should be header
|
||||
|
||||
if !selected_records.is_empty() {
|
||||
let first_selected_record = selected_records[0].clone();
|
||||
loop {
|
||||
if !model.iter_next(&iter) {
|
||||
break;
|
||||
}
|
||||
|
||||
if model.value(&iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
||||
possible_group += 1;
|
||||
possible_header = iter.clone();
|
||||
}
|
||||
|
||||
if model.path(&iter).unwrap() == first_selected_record {
|
||||
header_clone = possible_header.clone();
|
||||
current_group = possible_group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(current_group, header_clone)
|
||||
}
|
|
@ -13,10 +13,11 @@ pub struct GuiBottomButtons {
|
|||
pub buttons_symlink: gtk::Button,
|
||||
pub buttons_hardlink: gtk::Button,
|
||||
pub buttons_move: gtk::Button,
|
||||
pub buttons_compare: gtk::Button,
|
||||
pub buttons_show_errors: gtk::Button,
|
||||
pub buttons_show_upper_notebook: gtk::Button,
|
||||
pub buttons_names: [String; 7],
|
||||
pub buttons_array: [Widget; 7],
|
||||
pub buttons_names: [String; 8],
|
||||
pub buttons_array: [Widget; 8],
|
||||
}
|
||||
|
||||
impl GuiBottomButtons {
|
||||
|
@ -28,6 +29,7 @@ impl GuiBottomButtons {
|
|||
let buttons_symlink: gtk::Button = builder.object("buttons_symlink").unwrap();
|
||||
let buttons_hardlink: gtk::Button = builder.object("buttons_hardlink").unwrap();
|
||||
let buttons_move: gtk::Button = builder.object("buttons_move").unwrap();
|
||||
let buttons_compare: gtk::Button = builder.object("buttons_compare").unwrap();
|
||||
|
||||
let buttons_show_errors: gtk::Button = builder.object("buttons_show_errors").unwrap();
|
||||
let buttons_show_upper_notebook: gtk::Button = builder.object("buttons_show_upper_notebook").unwrap();
|
||||
|
@ -40,8 +42,9 @@ impl GuiBottomButtons {
|
|||
"symlink".to_string(),
|
||||
"hardlink".to_string(),
|
||||
"move".to_string(),
|
||||
"compare".to_string(),
|
||||
];
|
||||
let buttons_array: [Widget; 7] = [
|
||||
let buttons_array = [
|
||||
buttons_search.clone().upcast::<Widget>(),
|
||||
buttons_select.clone().upcast::<Widget>(),
|
||||
buttons_delete.clone().upcast::<Widget>(),
|
||||
|
@ -49,6 +52,7 @@ impl GuiBottomButtons {
|
|||
buttons_symlink.clone().upcast::<Widget>(),
|
||||
buttons_hardlink.clone().upcast::<Widget>(),
|
||||
buttons_move.clone().upcast::<Widget>(),
|
||||
buttons_compare.clone().upcast::<Widget>(),
|
||||
];
|
||||
|
||||
buttons_select.set_popover(Some(popover_select));
|
||||
|
@ -61,6 +65,7 @@ impl GuiBottomButtons {
|
|||
buttons_symlink,
|
||||
buttons_hardlink,
|
||||
buttons_move,
|
||||
buttons_compare,
|
||||
buttons_show_errors,
|
||||
buttons_show_upper_notebook,
|
||||
buttons_names,
|
||||
|
|
80
czkawka_gui/src/gui_compare_images.rs
Normal file
80
czkawka_gui/src/gui_compare_images.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use czkawka_core::fl;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Builder, TreeIter};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GuiCompareImages {
|
||||
pub window_compare: gtk::Window,
|
||||
|
||||
pub label_group_info: gtk::Label,
|
||||
|
||||
pub button_go_previous_compare_group: gtk::Button,
|
||||
pub button_go_next_compare_group: gtk::Button,
|
||||
|
||||
pub check_button_left_preview_text: gtk::CheckButton,
|
||||
pub check_button_right_preview_text: gtk::CheckButton,
|
||||
|
||||
pub image_compare_left: gtk::Image,
|
||||
pub image_compare_right: gtk::Image,
|
||||
|
||||
pub scrolled_window_compare_choose_images: gtk::ScrolledWindow,
|
||||
|
||||
pub shared_numbers_of_groups: Rc<RefCell<u32>>,
|
||||
pub shared_current_of_groups: Rc<RefCell<u32>>,
|
||||
pub shared_current_iter: Rc<RefCell<Option<TreeIter>>>,
|
||||
pub shared_image_cache: Rc<RefCell<Vec<(String, String, gtk::Image, gtk::Image, gtk::TreePath)>>>,
|
||||
pub shared_using_for_preview: Rc<RefCell<(Option<gtk::TreePath>, Option<gtk::TreePath>)>>,
|
||||
}
|
||||
|
||||
impl GuiCompareImages {
|
||||
pub fn create_from_builder(window_main: >k::Window) -> Self {
|
||||
let glade_src = include_str!("../ui/compare_images.glade").to_string();
|
||||
let builder = Builder::from_string(glade_src.as_str());
|
||||
|
||||
let window_compare: gtk::Window = builder.object("window_compare").unwrap();
|
||||
window_compare.set_title(&fl!("window_compare_images"));
|
||||
window_compare.set_modal(true);
|
||||
window_compare.set_transient_for(Some(window_main));
|
||||
|
||||
let label_group_info: gtk::Label = builder.object("label_group_info").unwrap();
|
||||
|
||||
let button_go_previous_compare_group: gtk::Button = builder.object("button_go_previous_compare_group").unwrap();
|
||||
let button_go_next_compare_group: gtk::Button = builder.object("button_go_next_compare_group").unwrap();
|
||||
|
||||
let check_button_left_preview_text: gtk::CheckButton = builder.object("check_button_left_preview_text").unwrap();
|
||||
let check_button_right_preview_text: gtk::CheckButton = builder.object("check_button_right_preview_text").unwrap();
|
||||
|
||||
let image_compare_left: gtk::Image = builder.object("image_compare_left").unwrap();
|
||||
let image_compare_right: gtk::Image = builder.object("image_compare_right").unwrap();
|
||||
|
||||
let scrolled_window_compare_choose_images: gtk::ScrolledWindow = builder.object("scrolled_window_compare_choose_images").unwrap();
|
||||
|
||||
let shared_numbers_of_groups = Rc::new(RefCell::new(0));
|
||||
let shared_current_of_groups = Rc::new(RefCell::new(0));
|
||||
let shared_current_iter = Rc::new(RefCell::new(None));
|
||||
let shared_image_cache = Rc::new(RefCell::new(Vec::new()));
|
||||
let shared_using_for_preview = Rc::new(RefCell::new((None, None)));
|
||||
|
||||
Self {
|
||||
window_compare,
|
||||
label_group_info,
|
||||
button_go_previous_compare_group,
|
||||
button_go_next_compare_group,
|
||||
check_button_left_preview_text,
|
||||
check_button_right_preview_text,
|
||||
image_compare_left,
|
||||
image_compare_right,
|
||||
scrolled_window_compare_choose_images,
|
||||
shared_numbers_of_groups,
|
||||
shared_current_of_groups,
|
||||
shared_current_iter,
|
||||
shared_image_cache,
|
||||
shared_using_for_preview,
|
||||
}
|
||||
}
|
||||
pub fn update_language(&self) {
|
||||
self.window_compare.set_title(&fl!("window_compare_images"));
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ use czkawka_core::temporary::Temporary;
|
|||
|
||||
use crate::gui_about::GuiAbout;
|
||||
use crate::gui_bottom_buttons::GuiBottomButtons;
|
||||
use crate::gui_compare_images::GuiCompareImages;
|
||||
use crate::gui_header::GuiHeader;
|
||||
use crate::gui_main_notebook::GuiMainNotebook;
|
||||
use crate::gui_popovers::GuiPopovers;
|
||||
|
@ -49,6 +50,7 @@ pub struct GuiData {
|
|||
pub about: GuiAbout,
|
||||
pub settings: GuiSettings,
|
||||
pub header: GuiHeader,
|
||||
pub compare_images: GuiCompareImages,
|
||||
|
||||
// Taskbar state
|
||||
pub taskbar_state: Rc<RefCell<TaskbarProgress>>,
|
||||
|
@ -106,6 +108,7 @@ impl GuiData {
|
|||
let about = GuiAbout::create_from_builder(&window_main, &pixbuf);
|
||||
let header = GuiHeader::create_from_builder(&builder);
|
||||
let settings = GuiSettings::create_from_builder(&window_main);
|
||||
let compare_images = GuiCompareImages::create_from_builder(&window_main);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -166,6 +169,7 @@ impl GuiData {
|
|||
about,
|
||||
settings,
|
||||
header,
|
||||
compare_images,
|
||||
taskbar_state,
|
||||
shared_buttons,
|
||||
shared_duplication_state,
|
||||
|
@ -198,5 +202,6 @@ impl GuiData {
|
|||
self.about.update_language();
|
||||
self.header.update_language();
|
||||
self.settings.update_language();
|
||||
self.compare_images.update_language();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
use directories_next::ProjectDirs;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use gtk::prelude::*;
|
||||
use gtk::{ListStore, TextView, TreeView, Widget};
|
||||
use image::imageops::FilterType;
|
||||
use image::DynamicImage;
|
||||
use image::GenericImageView;
|
||||
|
||||
use czkawka_core::big_file::BigFile;
|
||||
use czkawka_core::broken_files::BrokenFiles;
|
||||
|
@ -684,6 +689,74 @@ pub fn check_how_much_elements_is_selected(tree_view: &TreeView, column_color: O
|
|||
(number_of_selected_items, number_of_selected_groups)
|
||||
}
|
||||
|
||||
/// Counts how much headers/groups is in treeview
|
||||
pub fn count_number_of_groups(tree_view: &TreeView, column_color: i32) -> u32 {
|
||||
let mut number_of_selected_groups = 0;
|
||||
|
||||
let model = get_list_store(tree_view);
|
||||
|
||||
if let Some(iter) = model.iter_first() {
|
||||
assert_eq!(model.value(&iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR); // First element should be header
|
||||
number_of_selected_groups += 1;
|
||||
|
||||
loop {
|
||||
if !model.iter_next(&iter) {
|
||||
break;
|
||||
}
|
||||
|
||||
if model.value(&iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
||||
number_of_selected_groups += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
number_of_selected_groups
|
||||
}
|
||||
|
||||
pub fn resize_dynamic_image_dimension(img: DynamicImage, requested_size: (u32, u32), filter_type: &FilterType) -> DynamicImage {
|
||||
let current_ratio = img.width() as f32 / img.height() as f32;
|
||||
let mut new_size;
|
||||
match current_ratio.partial_cmp(&(requested_size.0 as f32 / requested_size.1 as f32)).unwrap() {
|
||||
Ordering::Greater => {
|
||||
new_size = (requested_size.0, (img.height() * requested_size.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_size.1) / img.height(), requested_size.1);
|
||||
new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1));
|
||||
}
|
||||
Ordering::Equal => {
|
||||
new_size = (requested_size.0, requested_size.1);
|
||||
new_size = (std::cmp::max(new_size.0, 1), std::cmp::max(new_size.1, 1));
|
||||
}
|
||||
}
|
||||
img.resize(new_size.0, new_size.1, *filter_type)
|
||||
}
|
||||
|
||||
pub fn get_image_path_temporary(file_name: &str, number: u32, extension: &str) -> PathBuf {
|
||||
let path_buf;
|
||||
if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
|
||||
path_buf = PathBuf::from(proj_dirs.cache_dir());
|
||||
} else {
|
||||
path_buf = PathBuf::new().join("/var");
|
||||
}
|
||||
path_buf.join(format!("{}{}.{}", file_name, number, extension))
|
||||
}
|
||||
|
||||
pub fn get_max_file_name(file_name: &str, max_length: usize) -> String {
|
||||
assert!(max_length > 10); // Maybe in future will be supported lower values
|
||||
if file_name.len() > max_length {
|
||||
let difference = file_name.len() - max_length;
|
||||
|
||||
let mut string = "".to_string();
|
||||
string += &file_name[0..10];
|
||||
string += " ... ";
|
||||
string += &file_name[10 + difference..];
|
||||
string
|
||||
} else {
|
||||
file_name.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_custom_label_from_button_with_image(button: >k::Bin) -> gtk::Label {
|
||||
let internal_box = button.child().unwrap().downcast::<gtk::Box>().unwrap();
|
||||
for child in internal_box.children() {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::fs;
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
|
@ -38,6 +37,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
let buttons_symlink = gui_data.bottom_buttons.buttons_symlink.clone();
|
||||
let buttons_hardlink = gui_data.bottom_buttons.buttons_hardlink.clone();
|
||||
let buttons_move = gui_data.bottom_buttons.buttons_move.clone();
|
||||
let buttons_compare = gui_data.bottom_buttons.buttons_compare.clone();
|
||||
|
||||
// Disable and show buttons - only search button should be visible
|
||||
buttons_search.show();
|
||||
|
@ -47,6 +47,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
|||
buttons_symlink.hide();
|
||||
buttons_hardlink.hide();
|
||||
buttons_move.hide();
|
||||
buttons_compare.hide();
|
||||
}
|
||||
//// Initialize language combo box
|
||||
{
|
||||
|
@ -773,24 +774,7 @@ fn show_preview(
|
|||
);
|
||||
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 img = resize_dynamic_image_dimension(img, (400, 400), &FilterType::Triangle); // Triangle and Nearest is the fastest
|
||||
let file_dir = match is_raw_image {
|
||||
true => cache_dir.join("cached_file.jpg"),
|
||||
false => cache_dir.join(format!("cached_file.{}", extension.to_string_lossy().to_lowercase())),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#![windows_subsystem = "windows"]
|
||||
#![allow(clippy::collapsible_else_if)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use gtk::prelude::*;
|
||||
|
||||
|
@ -9,6 +10,7 @@ use czkawka_core::*;
|
|||
|
||||
use crate::compute_results::*;
|
||||
use crate::connect_about_buttons::*;
|
||||
use crate::connect_button_compare::*;
|
||||
use crate::connect_button_delete::*;
|
||||
use crate::connect_button_hardlink::*;
|
||||
use crate::connect_button_move::*;
|
||||
|
@ -34,6 +36,7 @@ use crate::tests::validate_notebook_data;
|
|||
|
||||
mod compute_results;
|
||||
mod connect_about_buttons;
|
||||
mod connect_button_compare;
|
||||
mod connect_button_delete;
|
||||
mod connect_button_hardlink;
|
||||
mod connect_button_move;
|
||||
|
@ -54,6 +57,7 @@ mod connect_similar_image_size_change;
|
|||
mod create_tree_view;
|
||||
mod gui_about;
|
||||
mod gui_bottom_buttons;
|
||||
mod gui_compare_images;
|
||||
mod gui_data;
|
||||
mod gui_header;
|
||||
mod gui_main_notebook;
|
||||
|
@ -161,6 +165,8 @@ fn main() {
|
|||
connect_button_stop(&gui_data);
|
||||
connect_button_hardlink_symlink(&gui_data);
|
||||
connect_button_move(&gui_data);
|
||||
connect_button_compare(&gui_data);
|
||||
|
||||
connect_duplicate_combo_box(&gui_data);
|
||||
connect_notebook_tabs(&gui_data);
|
||||
connect_selection_of_directories(&gui_data);
|
||||
|
|
|
@ -602,11 +602,17 @@ pub fn load_configuration(
|
|||
.short_text
|
||||
.to_string();
|
||||
|
||||
let included_directories = get_string_from_list_store(&upper_notebook.tree_view_included_directories, ColumnsIncludedDirectory::Path as i32, None);
|
||||
let excluded_directories = get_string_from_list_store(&upper_notebook.tree_view_excluded_directories, ColumnsExcludedDirectory::Path as i32, None);
|
||||
|
||||
let (hashmap_ls, _hashmap_sl) = create_hash_map();
|
||||
|
||||
let included_directories: Vec<String> = loaded_entries.get_vector_string(hashmap_ls.get(&LoadText::IncludedDirectories).unwrap().clone(), Vec::new());
|
||||
let excluded_directories: Vec<String> = loaded_entries.get_vector_string(hashmap_ls.get(&LoadText::ExcludedDirectories).unwrap().clone(), Vec::new());
|
||||
let excluded_items: String = loaded_entries.get_string(hashmap_ls.get(&LoadText::ExcludedItems).unwrap().clone(), "".to_string());
|
||||
let included_directories: Vec<String> = loaded_entries.get_vector_string(hashmap_ls.get(&LoadText::IncludedDirectories).unwrap().clone(), included_directories);
|
||||
let excluded_directories: Vec<String> = loaded_entries.get_vector_string(hashmap_ls.get(&LoadText::ExcludedDirectories).unwrap().clone(), excluded_directories);
|
||||
let excluded_items: String = loaded_entries.get_string(
|
||||
hashmap_ls.get(&LoadText::ExcludedItems).unwrap().clone(),
|
||||
upper_notebook.entry_excluded_items.text().to_string(),
|
||||
);
|
||||
let allowed_extensions: String = loaded_entries.get_string(hashmap_ls.get(&LoadText::AllowedExtensions).unwrap().clone(), "".to_string());
|
||||
let minimal_file_size: String = loaded_entries.get_string(hashmap_ls.get(&LoadText::MinimalFileSize).unwrap().clone(), DEFAULT_MINIMAL_FILE_SIZE.to_string());
|
||||
let maximal_file_size: String = loaded_entries.get_string(hashmap_ls.get(&LoadText::MaximalFileSize).unwrap().clone(), DEFAULT_MAXIMAL_FILE_SIZE.to_string());
|
||||
|
@ -729,6 +735,7 @@ pub fn load_configuration(
|
|||
}
|
||||
}
|
||||
|
||||
/// Function do not allow to set invalid index to combobox because this would cause to show empty value and function would crash
|
||||
fn save_proper_value_to_combo_box(combo_box: &ComboBoxText, what_to_save: u32) {
|
||||
combo_box.set_active(Some(what_to_save));
|
||||
if combo_box.active().is_none() {
|
||||
|
|
199
czkawka_gui/ui/compare_images.glade
Normal file
199
czkawka_gui/ui/compare_images.glade
Normal file
|
@ -0,0 +1,199 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.39.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkDialog" id="window_compare">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="type-hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_group_info">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="label" translatable="yes">Group XD/PER XD (99 images in current group)</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">-1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_go_next_compare_group">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">go-next</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_go_previous_compare_group">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">go-previous</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_button_left_preview_text">
|
||||
<property name="label" translatable="yes">First Game</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_button_right_preview_text">
|
||||
<property name="label" translatable="yes">Second Game</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image_compare_left">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="stock">gtk-missing-image</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image_compare_right">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="stock">gtk-missing-image</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolled_window_compare_choose_images">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -1631,6 +1631,50 @@ Author: Rafał Mikrut
|
|||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="buttons_compare">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">video-display</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Compare</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="buttons_delete">
|
||||
<property name="visible">True</property>
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Nelze získat datum úpravy ze složky { $nam
|
|||
window_settings_title = Možnosti
|
||||
window_main_title = Czkawka (Škytavka)
|
||||
window_progress_title = Skenování
|
||||
window_compare_images = Porovnat obrázky
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Zavřít
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Zobrazí potvrzovací dialogové okno př
|
|||
settings_confirm_group_deletion_button_tooltip = Zobrazí dialogové okno při pokusu o odstranění všech záznamů ze skupiny.
|
||||
settings_show_text_view_button_tooltip = Zobrazí chybový panel dole.
|
||||
settings_use_cache_button_tooltip = Možnost, která umožňuje nepoužívat funkci mezipaměti.
|
||||
settings_save_also_as_json_button_tooltip = Uložit mezipaměť do lidského formátu JSON. Je možné upravit její obsah. Mezipaměť z tohoto souboru bude automaticky čtena aplikací, pokud chybí binární mezipaměť (s příponou bin).
|
||||
settings_use_trash_button_tooltip = Pokud je povoleno, přesune soubory do koše místo jejich trvalého odstranění.
|
||||
settings_language_label_tooltip = Umožňuje vybrat jazyk rozhraní z dostupných jazyků.
|
||||
settings_save_at_exit_button = Uložit konfiguraci při ukončení
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Zobrazit dialogové okno pro pevné / symbolické
|
|||
settings_confirm_group_deletion_button = Zobrazit dialogové okno potvrzení při mazání všech souborů ve skupině
|
||||
settings_show_text_view_button = Zobrazit spodní textový panel
|
||||
settings_use_cache_button = Použít keš
|
||||
settings_save_also_as_json_button = Uložit keš také do souboru JSON
|
||||
settings_use_trash_button = Přesunout smazané soubory do koše
|
||||
settings_language_label = Jazyk
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Automaticky odstranit zastaralé položky v mezipaměti
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Nelze vytvořit náhled obrázku { $name } s šířkou nebo vý
|
|||
preview_temporary_image_save = Dočasný obrázek se nepodařilo uložit do { $name }, důvod { $reason }.
|
||||
preview_temporary_image_remove = Nepodařilo se odstranit dočasný obrázek souboru { $name }, důvod { $reason }.
|
||||
preview_failed_to_create_cache_dir = Nepodařilo se vytvořit dir { $name } potřebný náhled obrázku, důvod { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Skupina { $current_group }/{ $all_groups } ({ $images_in_group } obrázků)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Konnte das Änderungsdatum aus dem Ordner { $
|
|||
window_settings_title = Optionen
|
||||
window_main_title = Czkawka (Schluckauf)
|
||||
window_progress_title = Scannen
|
||||
window_compare_images = Bilder vergleichen
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Schließen
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Zeigt den Bestätigungsdialog an, wenn Si
|
|||
settings_confirm_group_deletion_button_tooltip = Zeigt den Dialog an, wenn versucht wird, alle Datensätze aus der Gruppe zu entfernen.
|
||||
settings_show_text_view_button_tooltip = Zeigt die Fehleranzeige unten an.
|
||||
settings_use_cache_button_tooltip = Option, bei der die Cache-Funktion nicht genutzt werden kann.
|
||||
settings_save_also_as_json_button_tooltip = Speichere Cache im menschlichen JSON-Format. Es ist möglich, den Inhalt zu ändern. Cache aus dieser Datei wird automatisch von der App gelesen, wenn der Binärformat-Cache (mit Bin Erweiterung) fehlt.
|
||||
settings_use_trash_button_tooltip = Wenn aktiviert, verschiebt es Dateien in den Papierkorb.
|
||||
settings_language_label_tooltip = Erlaubt es, die Sprache der Schnittstelle von der verfügbaren zu wählen.
|
||||
settings_save_at_exit_button = Konfiguration beim Beenden speichern
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Bestätigungsdialog anzeigen, wenn Hard/Symlinks
|
|||
settings_confirm_group_deletion_button = Bestätigungsdialog beim Löschen aller Dateien in der Gruppe anzeigen
|
||||
settings_show_text_view_button = Unteren Textbereich anzeigen
|
||||
settings_use_cache_button = Cache verwenden
|
||||
settings_save_also_as_json_button = Cache auch in JSON-Datei speichern
|
||||
settings_use_trash_button = Gelöschte Dateien in den Papierkorb verschieben
|
||||
settings_language_label = Sprache
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Veraltete Cache-Einträge automatisch löschen
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Vorschau des Bildes { $name } mit 0 Breite oder Höhe kann nich
|
|||
preview_temporary_image_save = Fehler beim Speichern der temporären Bilddatei in { $name }, Grund { $reason }.
|
||||
preview_temporary_image_remove = Fehler beim Löschen der temporären Bilddatei { $name }, Grund { $reason }.
|
||||
preview_failed_to_create_cache_dir = Fehler beim Erstellen des Verzeichnisses { $name } durch die Bildvorschau, Grund { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Gruppe { $current_group }/{ $all_groups } ({ $images_in_group } Bilder)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -19,6 +19,7 @@ core_folder_no_modification_date = Unable to get modification date from folder {
|
|||
window_settings_title = Options
|
||||
window_main_title = Czkawka (Hiccup)
|
||||
window_progress_title = Scanning
|
||||
window_compare_images = Compare Images
|
||||
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
|
@ -486,3 +487,8 @@ preview_0_size = Cannot create preview of image {$name}, with 0 width or height.
|
|||
preview_temporary_image_save = Failed to save temporary image file to {$name}, reason {$reason}.
|
||||
preview_temporary_image_remove = Failed to delete temporary image file {$name}, reason {$reason}.
|
||||
preview_failed_to_create_cache_dir = Failed to create dir {$name} needed by image preview, reason {$reason}.
|
||||
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Group { $current_group }/{ $all_groups } ({ $images_in_group } images)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = No se puede obtener la fecha de modificación
|
|||
window_settings_title = Opciones
|
||||
window_main_title = Czkawka (Hipo)
|
||||
window_progress_title = Escaneando
|
||||
window_compare_images = Comparar imágenes
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Cerrar
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Muestra el diálogo de confirmación al h
|
|||
settings_confirm_group_deletion_button_tooltip = Muestra el diálogo cuando intenta eliminar todos los registros del grupo.
|
||||
settings_show_text_view_button_tooltip = Muestra el panel de error en la parte inferior.
|
||||
settings_use_cache_button_tooltip = Opción que permite no utilizar la función de caché.
|
||||
settings_save_also_as_json_button_tooltip = Guardar caché en formato JSON humano. Es posible modificar su contenido. La caché de este archivo será leída automáticamente por la aplicación si la caché del formato binario (con la extensión binaria) faltará.
|
||||
settings_use_trash_button_tooltip = Cuando está habilitado mueve archivos a la papelera en su lugar eliminándolos permanentemente.
|
||||
settings_language_label_tooltip = Permite elegir el idioma de la interfaz entre los disponibles.
|
||||
settings_save_at_exit_button = Guardar configuración al salir
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Mostrar diálogo de confirmación cuando vincule
|
|||
settings_confirm_group_deletion_button = Mostrar diálogo de confirmación al eliminar todos los archivos del grupo
|
||||
settings_show_text_view_button = Mostrar panel de texto inferior
|
||||
settings_use_cache_button = Usar caché
|
||||
settings_save_also_as_json_button = Guardar caché también en archivo JSON
|
||||
settings_use_trash_button = Mover archivos borrados a la papelera
|
||||
settings_language_label = Idioma
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Borrar automáticamente entradas de caché obsoletas
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = No se puede crear la vista previa de la imagen { $name }, con 0
|
|||
preview_temporary_image_save = Error al guardar el archivo de imagen temporal en { $name }, razón { $reason }.
|
||||
preview_temporary_image_remove = Error al eliminar el archivo de imagen temporal { $name }, razón { $reason }.
|
||||
preview_failed_to_create_cache_dir = Error al crear el directorio { $name } necesario para la vista previa de la imagen, razón { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Grupo { $current_group }/{ $all_groups } ({ $images_in_group } imágenes)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -5,9 +5,9 @@ core_similarity_medium = Moyenne
|
|||
core_similarity_small = Basse
|
||||
core_similarity_very_small = Très basse
|
||||
core_similarity_minimal = Minimale
|
||||
core_cannot_open_dir = Impossible d'ouvrir le répertoire { $dir }, raison { $reason }
|
||||
core_cannot_read_entry_dir = Impossible de lire l'entrée dans le répertoire { $dir }, raison { $reason }
|
||||
core_cannot_read_metadata_dir = Impossible de lire les métadonnées dans le répertoire { $dir }, raison { $reason }
|
||||
core_cannot_open_dir = Impossible d’ouvrir le répertoire { $dir }, raison : { $reason }
|
||||
core_cannot_read_entry_dir = Impossible de lire l'entrée dans le répertoire { $dir }, raison : { $reason }
|
||||
core_cannot_read_metadata_dir = Impossible de lire les métadonnées dans le répertoire { $dir }, raison : { $reason }
|
||||
core_file_not_utf8_name = Le fichier { $name } n'a pas de nom UTF-8 valide (certains caractères ne peuvent pas être affichés)
|
||||
core_file_modified_before_epoch = Le fichier { $name } semble avoir été modifié avant l'époque Unix
|
||||
core_folder_modified_before_epoch = Le dossier { $name } semble avoir été modifié avant l'époque Unix
|
||||
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Impossible d'obtenir la date de modification
|
|||
window_settings_title = Options
|
||||
window_main_title = Czkawka (Hoquet)
|
||||
window_progress_title = Analyse en cours
|
||||
window_compare_images = Comparer les images
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Fermer
|
||||
|
@ -188,7 +189,7 @@ bottom_move_button = Déplacer
|
|||
bottom_search_button_tooltip = Commencer à rechercher des fichiers/dossiers.
|
||||
bottom_select_button_tooltip = Sélectionner les enregistrements. Seuls les fichiers/dossiers sélectionnés peuvent être traités plus tard.
|
||||
bottom_delete_button_tooltip = Supprimer les fichiers/dossiers sélectionnés.
|
||||
bottom_save_button_tooltip = Enregistrer les données sur la recherche dans un fichier
|
||||
bottom_save_button_tooltip = Enregistrer les données de la recherche sur un fichier
|
||||
bottom_symlink_button_tooltip =
|
||||
Crée des liens symboliques.
|
||||
Ne fonctionne que si au moins 2 résultats sont sélectionnés dans le groupe.
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Affiche la boîte de dialogue de confirma
|
|||
settings_confirm_group_deletion_button_tooltip = Affiche la boîte de dialogue lorsque vous essayez de supprimer tous les enregistrements du groupe.
|
||||
settings_show_text_view_button_tooltip = Affiche le panneau d'erreur en bas de page.
|
||||
settings_use_cache_button_tooltip = Option permettant de ne pas utiliser la fonctionnalité de cache.
|
||||
settings_save_also_as_json_button_tooltip = Enregistrer le cache en lecture au format JSON humain. Il est possible de modifier son contenu. Le cache de ce fichier sera automatiquement lu par l'application si le cache de format binaire (avec l'extension de la corbeille) est manquant.
|
||||
settings_use_trash_button_tooltip = Lorsqu’elle est activé, elle déplace les fichiers vers la corbeille au lieu de les supprimer définitivement.
|
||||
settings_language_label_tooltip = Permet de choisir la langue de l'interface à partir des langues disponibles.
|
||||
settings_save_at_exit_button = Enregistrer la configuration à la sortie
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Afficher la boîte de dialogue de confirmation lo
|
|||
settings_confirm_group_deletion_button = Afficher la boîte de dialogue de confirmation lors de la suppression de tous les fichiers du groupe
|
||||
settings_show_text_view_button = Afficher le panneau de texte du bas
|
||||
settings_use_cache_button = Utiliser le cache
|
||||
settings_save_also_as_json_button = Enregistrer le cache aussi dans le fichier JSON
|
||||
settings_use_trash_button = Déplacer les fichiers supprimés vers la corbeille
|
||||
settings_language_label = Langue
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Supprimer automatiquement les entrées de cache obsolètes
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Impossible de créer l'aperçu de l'image { $name }, avec 0 lar
|
|||
preview_temporary_image_save = Impossible d'enregistrer le fichier d'image temporaire dans { $name }, raison { $reason }.
|
||||
preview_temporary_image_remove = Impossible de supprimer le fichier d'image temporaire { $name }, raison { $reason }.
|
||||
preview_failed_to_create_cache_dir = Impossible de créer le répertoire { $name } nécessaire à l'aperçu de l'image, raison { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Groupe { $current_group }/{ $all_groups } ({ $images_in_group } images)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Impossibile recuperare data di modifica dalla
|
|||
window_settings_title = Impostazioni
|
||||
window_main_title = Singhiozzo
|
||||
window_progress_title = Ricerca
|
||||
window_compare_images = Confronta Le Immagini
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Chiudi
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Mostra richiesta di conferma alla selezio
|
|||
settings_confirm_group_deletion_button_tooltip = Mostra richiesta di conferma al tentativo di cancellare tutti gli elementi in un gruppo.
|
||||
settings_show_text_view_button_tooltip = Mostra il pannello errori in basso.
|
||||
settings_use_cache_button_tooltip = Opzione per non utilizzare la funzione di caching.
|
||||
settings_save_also_as_json_button_tooltip = Salva la cache in formato JSON umano. È possibile modificarne il contenuto. La cache da questo file verrà letta automaticamente dall'app se la cache in formato binario (con estensione bid) sarà mancante.
|
||||
settings_use_trash_button_tooltip = Se selezionata, sposterà i file el cestino anziché cancellarli definitivamente.
|
||||
settings_language_label_tooltip = Permette di selezionare la lingua dell'interfaccia tra quelle disponibili.
|
||||
settings_save_at_exit_button = Salva la configurazione all'uscita
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Mostra finestra di conferma alla creazione di col
|
|||
settings_confirm_group_deletion_button = Mostra finestra di conferma alla cancellazione di tutti gli elementi in un gruppo
|
||||
settings_show_text_view_button = Mostra il pannello testuale inferiore
|
||||
settings_use_cache_button = Utilizza cache
|
||||
settings_save_also_as_json_button = Salva la cache anche nel file JSON
|
||||
settings_use_trash_button = Sposta i file rimossi nel cestino
|
||||
settings_language_label = Lingua
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Cancella automaticamente la cache obsoleta
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Impossibile creare anteprima dell'immagine { $name }, con largh
|
|||
preview_temporary_image_save = Impossibile salvare immagine temporanea in { $name }, ragione { $reason }
|
||||
preview_temporary_image_remove = Impossibile cancellare immagine temporanea { $name }, ragione { $reason }
|
||||
preview_failed_to_create_cache_dir = Impossibile creare cartella { $name } necessaria per l'anteprima immagine, ragione { $reason }
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Gruppo { $current_group }/{ $all_groups } ({ $images_in_group } immagini)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = フォルダ { $name } から変更日を取
|
|||
window_settings_title = オプション
|
||||
window_main_title = Czkawka (しゃっくり)
|
||||
window_progress_title = スキャン中
|
||||
window_compare_images = 画像を比較
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = 閉じる
|
||||
|
@ -235,6 +236,7 @@ settings_confirm_link_button_tooltip = Hard/symlink ボタンをクリックし
|
|||
settings_confirm_group_deletion_button_tooltip = グループからすべてのレコードを削除しようとしたときにダイアログを表示します。
|
||||
settings_show_text_view_button_tooltip = 下部にエラーパネルを表示
|
||||
settings_use_cache_button_tooltip = キャッシュ機能を使用しないオプション。
|
||||
settings_save_also_as_json_button_tooltip = キャッシュを人間JSON形式で読み取り可能に保存します。コンテンツを変更することができます。 バイナリフォーマットキャッシュ(bin拡張子付き) がない場合、このファイルから自動的にキャッシュが読み込まれます。
|
||||
settings_use_trash_button_tooltip = 有効にすると、ファイルをゴミ箱に移動する代わりに永久に削除します。
|
||||
settings_language_label_tooltip = 利用可能な言語からインターフェイスの言語を選択できます。
|
||||
settings_save_at_exit_button = 終了時に設定を保存
|
||||
|
@ -244,6 +246,7 @@ settings_confirm_link_button = ハードリンク/シンボリックリンク時
|
|||
settings_confirm_group_deletion_button = グループ内のすべてのファイルを削除するときに確認ダイアログを表示する
|
||||
settings_show_text_view_button = 下部のテキストパネルを表示
|
||||
settings_use_cache_button = キャッシュを使用
|
||||
settings_save_also_as_json_button = JSONファイルにもキャッシュを保存する
|
||||
settings_use_trash_button = 削除したファイルをゴミ箱に移動する
|
||||
settings_language_label = 言語
|
||||
settings_multiple_delete_outdated_cache_checkbutton = 古いキャッシュエントリを自動的に削除
|
||||
|
@ -413,3 +416,7 @@ preview_0_size = 画像 { $name } のプレビューを作成できません。
|
|||
preview_temporary_image_save = 一時イメージファイルを { $name }、理由 { $reason } に保存できませんでした。
|
||||
preview_temporary_image_remove = 一時イメージ ファイル { $name } の削除に失敗しました、理由 { $reason }。
|
||||
preview_failed_to_create_cache_dir = 画像プレビュー、理由 { $name } で必要なdir { $reason } を作成できませんでした。
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = グループ { $current_group }/{ $all_groups } ({ $images_in_group } 画像)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Nie udało się pobrać daty modyfikacji z fo
|
|||
window_settings_title = Opcje
|
||||
window_main_title = Czkawka
|
||||
window_progress_title = Skanowanie
|
||||
window_compare_images = Porównywanie Obrazów
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Zamknij
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Wyświetla okno potwierdzające usuwanie,
|
|||
settings_confirm_group_deletion_button_tooltip = Wyświetla okno potwierdzające usuwanie, gdy wszystkie rekordy w danej grupie są zaznaczone.
|
||||
settings_show_text_view_button_tooltip = Pokazuje na dole ekranu panel tekstowy.
|
||||
settings_use_cache_button_tooltip = Umożliwia zapisywanie rekordów do pamięci podręcznej.
|
||||
settings_save_also_as_json_button_tooltip = Zapisz pamięć podręczną do pliku w formacie JSON umożliwiającym zmiany zawartości. Pamięć podręczna z tego pliku zostanie odczytana automatycznie przez aplikację, jeśli nie istnieje plik z pamięcią podręczną w formacie binarnym (z rozszerzeniem bin).
|
||||
settings_use_trash_button_tooltip = Przenosi pliki do kosza zamiast usuwać je permanentnie.
|
||||
settings_language_label_tooltip = Pozwala wybrać język interfejsu.
|
||||
settings_save_at_exit_button = Zapisuj konfigurację przy wyłączaniu
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Pokazuj potwierdzenie usuwania hard/symlinków
|
|||
settings_confirm_group_deletion_button = Pokazuj okno potwierdzające usuwanie wszystkich obiektów w grupie
|
||||
settings_show_text_view_button = Pokazuj panel tekstowy na dole
|
||||
settings_use_cache_button = Używaj pamięci podręcznej
|
||||
settings_save_also_as_json_button = Zapisz pamięć podręczną również do pliku JSON
|
||||
settings_use_trash_button = Przenoś pliki do kosza
|
||||
settings_language_label = Język
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Usuwaj automatycznie nieaktualne rekordy z pamięci podręcznej
|
||||
|
@ -270,7 +273,7 @@ settings_multiple_clear_cache_button = Usuń nieaktualne dane z pamięci podręc
|
|||
settings_duplicates_hide_hard_link_button_tooltip =
|
||||
Ukrywa wszystkie pliki oprócz jednego, jeśli wskazują na dokładnie ten sam plik(to samo inode).
|
||||
|
||||
Przykładowo - gdy program znalazł 7 plików na dokładnie ten sam plik(to samo inode) a dodatkowo jeden na inny, to w wynikach wyszukiwania wyświetlą się jedynie 2 wyniki - jeden z pierwszej grupy i drugi z drugiej.
|
||||
Przykładowo - gdy program znalazł 7 plików na dokładnie ten sam plik(z tym samym inode) a dodatkowo jeden na inny, to w wynikach wyszukiwania wyświetlą się jedynie 2 wyniki - jeden z pierwszej grupy i drugi z drugiej.
|
||||
settings_duplicates_minimal_size_entry_tooltip =
|
||||
Opcja umożliwia ustawienie minimalnej wielkości pliku, której hash będzie zapisywany do pamięci podręcznej.
|
||||
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Nie można stworzyć podglądu obrazu { $name }, z wysokością
|
|||
preview_temporary_image_save = Nie udało się zapisać tymczasowego obrazu do { $name }, powód { $reason }.
|
||||
preview_temporary_image_remove = Nie udało się usunąć tymczasowego obrazu { $name }, powód { $reason }.
|
||||
preview_failed_to_create_cache_dir = Nie udało stworzyć się katalogu { $name } wymaganego do stworzenia podglądu obrazu, powód { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Grupa { $current_group }/{ $all_groups } ({ $images_in_group } obrazów)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = P
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Não foi possível obter a data de modificaç
|
|||
window_settings_title = Opções
|
||||
window_main_title = Czkawka (Soluço)
|
||||
window_progress_title = Verificando
|
||||
window_compare_images = Comparar imagens
|
||||
# General
|
||||
general_ok_button = Ok
|
||||
general_close_button = Fechar
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Mostra o diálogo de confirmação quando
|
|||
settings_confirm_group_deletion_button_tooltip = Mostra a caixa de diálogo ao tentar remover todos os registros do grupo.
|
||||
settings_show_text_view_button_tooltip = Mostra o painel de erros embaixo.
|
||||
settings_use_cache_button_tooltip = Opção para a qual não permite usar o recurso de cache.
|
||||
settings_save_also_as_json_button_tooltip = Salve o cache para ser legível pelo formato JSON humano. É possível modificar seu conteúdo. Cache deste arquivo será lido automaticamente pelo aplicativo se o cache de formato binário (com extensão bin) estiver faltando.
|
||||
settings_use_trash_button_tooltip = Quando ativado, ele move os arquivos para a lixeira em vez de excluí-los permanentemente.
|
||||
settings_language_label_tooltip = Permite escolher o idioma da interface dos disponíveis.
|
||||
settings_save_at_exit_button = Salvar configuração ao sair
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Mostrar a caixa de diálogo de confirmação quan
|
|||
settings_confirm_group_deletion_button = Mostrar diálogo de confirmação quando apagar todos os arquivos no grupo
|
||||
settings_show_text_view_button = Mostrar painel de texto inferior
|
||||
settings_use_cache_button = Usar cache
|
||||
settings_save_also_as_json_button = Salvar o cache também em arquivo JSON
|
||||
settings_use_trash_button = Mover os arquivos apagados para a lixeira
|
||||
settings_language_label = Idioma
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Excluir entradas de cache desatualizadas automaticamente
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Não é possível criar pré-visualização da imagem { $name }
|
|||
preview_temporary_image_save = Falha ao salvar o arquivo de imagem temporário para { $name }, reason { $reason }.
|
||||
preview_temporary_image_remove = Falha ao excluir o arquivo de imagem temporária { $name }, reason { $reason }.
|
||||
preview_failed_to_create_cache_dir = Falha ao criar o diretório { $name } necessário para a pré-visualização da imagem, razão { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Grupo { $current_group }/{ $all_groups } ({ $images_in_group } imagens)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Не удается получить дату
|
|||
window_settings_title = Опции
|
||||
window_main_title = Czkawka (икота)
|
||||
window_progress_title = Сканирование
|
||||
window_compare_images = Сравнить изображения
|
||||
# General
|
||||
general_ok_button = Ок
|
||||
general_close_button = Закрыть
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Показывает диалоговое
|
|||
settings_confirm_group_deletion_button_tooltip = Показывает диалог при попытке удалить все записи из группы.
|
||||
settings_show_text_view_button_tooltip = Показывает панель ошибок внизу.
|
||||
settings_use_cache_button_tooltip = Параметр, который позволяет не использовать функцию кэша.
|
||||
settings_save_also_as_json_button_tooltip = Сохраните кэш для чтения по формату JSON. Можно изменять его содержимое. Кэш из этого файла будет прочитан автоматически приложением, если кэш двоичного формата (с расширением) не будет установлен.
|
||||
settings_use_trash_button_tooltip = При включении перемещает файлы в корзину вместо их удаления навсегда.
|
||||
settings_language_label_tooltip = Позволяет выбрать язык интерфейса из доступных языков.
|
||||
settings_save_at_exit_button = Сохранить конфигурацию при выходе
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Показывать окно подтвержд
|
|||
settings_confirm_group_deletion_button = Показывать подтверждение при удалении всех файлов в группе
|
||||
settings_show_text_view_button = Показывать нижнюю текстовую панель
|
||||
settings_use_cache_button = Использовать кэш
|
||||
settings_save_also_as_json_button = Сохранить кэш в файл JSON
|
||||
settings_use_trash_button = Переместить удаленные файлы в корзину
|
||||
settings_language_label = Язык
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Автоматически удалять устаревшие записи кэша
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Невозможно создать предварительн
|
|||
preview_temporary_image_save = Не удалось сохранить временный файл в { $name }, причина { $reason }.
|
||||
preview_temporary_image_remove = Не удалось удалить временный файл изображения { $name }, причина { $reason }.
|
||||
preview_failed_to_create_cache_dir = Не удалось создать каталог { $name } , необходимый для просмотра изображения, причина { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Группа { $current_group }/{ $all_groups } ({ $images_in_group } изображения)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = Не вдалося отримати дату
|
|||
window_settings_title = Опції
|
||||
window_main_title = Czkawka (гикавка)
|
||||
window_progress_title = Сканування
|
||||
window_compare_images = Порівняння зображень
|
||||
# General
|
||||
general_ok_button = Гаразд
|
||||
general_close_button = Закрити
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = Показувати діалогове
|
|||
settings_confirm_group_deletion_button_tooltip = Показує діалогове вікно при спробі видалення всіх записів з групи.
|
||||
settings_show_text_view_button_tooltip = Показує панель помилки знизу.
|
||||
settings_use_cache_button_tooltip = Опція, яка дозволяє не використовувати функцію кешу.
|
||||
settings_save_also_as_json_button_tooltip = Зберегти кеш для читуваного людського JSON формату. Можна змінити його вміст. Кеш з цього файлу буде автоматично читати додатком, якщо буде відсутній бінарний формат (з розширенням bit).
|
||||
settings_use_trash_button_tooltip = Якщо увімкнено, то він буде видаляти файли в смітник, а не постійно.
|
||||
settings_language_label_tooltip = Вибір мови інтерфейсу з доступних інтерфейсів.
|
||||
settings_save_at_exit_button = Зберегти конфігурацію при виході
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = Показувати вікно підтверд
|
|||
settings_confirm_group_deletion_button = Показувати вікно підтвердження при видаленні всіх файлів групи
|
||||
settings_show_text_view_button = Показувати нижню текстову панель
|
||||
settings_use_cache_button = Використання кешу
|
||||
settings_save_also_as_json_button = Зберегти кеш також у файл JSON
|
||||
settings_use_trash_button = Перемістити видалені файли в смітник
|
||||
settings_language_label = Мова
|
||||
settings_multiple_delete_outdated_cache_checkbutton = Автоматично видаляти застарілі записи кешу
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = Неможливо створити попередній пер
|
|||
preview_temporary_image_save = Не вдалося зберегти файл тимчасового зображення до { $name }, причина { $reason }.
|
||||
preview_temporary_image_remove = Не вдалося видалити файл тимчасового зображення { $name }, причина { $reason }.
|
||||
preview_failed_to_create_cache_dir = Не вдалося створити каталог { $name } потрібного при попередньому перегляді зображення. Причина { $reason }.
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = Група { $current_group }/{ $all_groups } ({ $images_in_group } зображення)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
|
@ -17,6 +17,7 @@ core_folder_no_modification_date = 无法从文件夹 { $name } 获取修改日
|
|||
window_settings_title = 备选方案
|
||||
window_main_title = Czkawka
|
||||
window_progress_title = 正在扫描
|
||||
window_compare_images = 比较图像
|
||||
# General
|
||||
general_ok_button = 好的
|
||||
general_close_button = 关闭
|
||||
|
@ -233,6 +234,7 @@ settings_confirm_link_button_tooltip = 点击硬链接/符号链接按钮时显
|
|||
settings_confirm_group_deletion_button_tooltip = 尝试从群组移除所有记录时显示对话框。
|
||||
settings_show_text_view_button_tooltip = 在底部显示错误面板。
|
||||
settings_use_cache_button_tooltip = 允许不使用缓存功能的选项。
|
||||
settings_save_also_as_json_button_tooltip = 保存缓存到可通过人类的 JSON 格式读取。可以修改其内容。 如果缺少二进制格式缓存(带bin extension),此文件的缓存将被应用自动读取。
|
||||
settings_use_trash_button_tooltip = 启用后,它会移动文件去回收站,而是永久删除它们。
|
||||
settings_language_label_tooltip = 允许从可用的接口中选择语言。
|
||||
settings_save_at_exit_button = 退出时保存配置
|
||||
|
@ -242,6 +244,7 @@ settings_confirm_link_button = 硬/符号链接任何文件时显示确认对话
|
|||
settings_confirm_group_deletion_button = 删除组中所有文件时显示确认对话框
|
||||
settings_show_text_view_button = 显示底部文本面板
|
||||
settings_use_cache_button = 使用缓存
|
||||
settings_save_also_as_json_button = 保存缓存到 JSON 文件
|
||||
settings_use_trash_button = 移动已删除的文件到回收站
|
||||
settings_language_label = 语言
|
||||
settings_multiple_delete_outdated_cache_checkbutton = 自动删除过时的缓存条目
|
||||
|
@ -411,3 +414,7 @@ preview_0_size = 无法创建图像 { $name } 的预览,宽度或高度为0。
|
|||
preview_temporary_image_save = 保存临时图像文件到 { $name } 失败,原因 { $reason }
|
||||
preview_temporary_image_remove = 无法删除临时图像文件 { $name },原因 { $reason }。
|
||||
preview_failed_to_create_cache_dir = 无法创建图像预览所需目录 { $name } ,原因 { $reason }
|
||||
# Compare images (L is short Left, R is short Right - they can't take too much space)
|
||||
compare_groups_number = 组 { $current_group }/{ $all_groups } ({ $images_in_group } 图像)
|
||||
compare_move_left_button = L
|
||||
compare_move_right_button = R
|
||||
|
|
Loading…
Reference in a new issue