1
0
Fork 0
mirror of synced 2024-05-02 19:44:09 +12:00

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:
Rafał Mikrut 2022-01-10 12:19:28 +01:00 committed by GitHub
parent f6599f51ae
commit 5dab9286cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1120 additions and 33 deletions

View file

@ -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)))

View file

@ -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,
);

View 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: &gtk::Image,
image_compare_right: &gtk::Image,
current_group: u32,
group_number: u32,
check_button_left_preview_text: &gtk::CheckButton,
check_button_right_preview_text: &gtk::CheckButton,
scrolled_window_compare_choose_images: &gtk::ScrolledWindow,
label_group_info: &gtk::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(&gtk_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: &gtk::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: &gtk::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)
}

View file

@ -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,

View 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: &gtk::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"));
}
}

View file

@ -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();
}
}

View file

@ -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: &gtk::Bin) -> gtk::Label {
let internal_box = button.child().unwrap().downcast::<gtk::Box>().unwrap();
for child in internal_box.children() {

View file

@ -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())),

View file

@ -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);

View file

@ -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() {

View 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>

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 douvrir 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 = Lorsquelle 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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