Show how many files will be deleted/moved (#514)
* Print proper character(\) in Windows when printing files * Show how many files will be moved/deleted. Don't show dialog when 0 files is selected
This commit is contained in:
parent
71c2e01ce4
commit
878550446d
|
@ -1,10 +1,12 @@
|
||||||
## Version 4.0.0 - ?
|
## Version 4.0.0 - ?
|
||||||
|
- Multithread support for collecting files to check(2/3x on 4 thread processor) - [#502](https://github.com/qarmin/czkawka/pull/502), [#504](https://github.com/qarmin/czkawka/pull/504)
|
||||||
|
- Add Polish and Italian translation - [#469](https://github.com/qarmin/czkawka/pull/469), [#508](https://github.com/qarmin/czkawka/pull/508)
|
||||||
- Add support for finding similar videos - [#460](https://github.com/qarmin/czkawka/pull/460)
|
- Add support for finding similar videos - [#460](https://github.com/qarmin/czkawka/pull/460)
|
||||||
- GUI code refactoring(could fix some bugs) - [#462](https://github.com/qarmin/czkawka/pull/462)
|
- GUI code refactoring(could fix some bugs) - [#462](https://github.com/qarmin/czkawka/pull/462)
|
||||||
- Fixed crash when trying to hard/symlink 0 files - [#462](https://github.com/qarmin/czkawka/pull/462)
|
- Fixed crash when trying to hard/symlink 0 files - [#462](https://github.com/qarmin/czkawka/pull/462)
|
||||||
- GTK 4 compatibility improvements for future change of toolkit - [#467](https://github.com/qarmin/czkawka/pull/467), [#468](https://github.com/qarmin/czkawka/pull/468), [#473](https://github.com/qarmin/czkawka/pull/473), [#474](https://github.com/qarmin/czkawka/pull/474)
|
- GTK 4 compatibility improvements for future change of toolkit - [#467](https://github.com/qarmin/czkawka/pull/467), [#468](https://github.com/qarmin/czkawka/pull/468), [#473](https://github.com/qarmin/czkawka/pull/473), [#474](https://github.com/qarmin/czkawka/pull/474), [#503](https://github.com/qarmin/czkawka/pull/503), [#505](https://github.com/qarmin/czkawka/pull/505)
|
||||||
- Change minimal supported OS to Ubuntu 20.04(needed by GTK) - [#468](https://github.com/qarmin/czkawka/pull/468)
|
- Change minimal supported OS to Ubuntu 20.04(needed by GTK) - [#468](https://github.com/qarmin/czkawka/pull/468)
|
||||||
- Increased performance when using image previews - [#468](https://github.com/qarmin/czkawka/pull/468)
|
- Increased performance by avoiding creating unnecessary image previews - [#468](https://github.com/qarmin/czkawka/pull/468)
|
||||||
- Improved performance due caching hash of broken/not supported images/videos = [#471](https://github.com/qarmin/czkawka/pull/471)
|
- Improved performance due caching hash of broken/not supported images/videos = [#471](https://github.com/qarmin/czkawka/pull/471)
|
||||||
- Option to not remove cache from non existent files(e.g. from unplugged pendrive) - [#472](https://github.com/qarmin/czkawka/pull/472)
|
- Option to not remove cache from non existent files(e.g. from unplugged pendrive) - [#472](https://github.com/qarmin/czkawka/pull/472)
|
||||||
- Add multiple tooltips with helpful messages - [#472](https://github.com/qarmin/czkawka/pull/472)
|
- Add multiple tooltips with helpful messages - [#472](https://github.com/qarmin/czkawka/pull/472)
|
||||||
|
@ -13,6 +15,9 @@
|
||||||
- Remove support for finding zeroed files - [#461](https://github.com/qarmin/czkawka/pull/461)
|
- Remove support for finding zeroed files - [#461](https://github.com/qarmin/czkawka/pull/461)
|
||||||
- Remove HashMB mode - [#476](https://github.com/qarmin/czkawka/pull/476)
|
- Remove HashMB mode - [#476](https://github.com/qarmin/czkawka/pull/476)
|
||||||
- Approximate comparison of music - [#483](https://github.com/qarmin/czkawka/pull/483)
|
- Approximate comparison of music - [#483](https://github.com/qarmin/czkawka/pull/483)
|
||||||
|
- Enable column sorting for simple treeview - [#487](https://github.com/qarmin/czkawka/pull/487)
|
||||||
|
- Allow to hide upper panel - [#491](https://github.com/qarmin/czkawka/pull/491)
|
||||||
|
- Make UI take less space - [#500](https://github.com/qarmin/czkawka/pull/500)
|
||||||
|
|
||||||
## Version 3.3.1 - 22.11.2021r
|
## Version 3.3.1 - 22.11.2021r
|
||||||
- Fix crash when moving buttons [#457](https://github.com/qarmin/czkawka/pull/457)
|
- Fix crash when moving buttons [#457](https://github.com/qarmin/czkawka/pull/457)
|
||||||
|
|
|
@ -41,31 +41,31 @@ pub async fn delete_things(gui_data: GuiData) {
|
||||||
let preview_path = gui_data.preview_path.clone();
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
if !check_if_can_delete_files(&check_button_settings_confirm_deletion, &window_main).await {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let nb_number = notebook_main.current_page().unwrap();
|
let nb_number = notebook_main.current_page().unwrap();
|
||||||
let tree_view = &main_tree_views[nb_number as usize];
|
let tree_view = &main_tree_views[nb_number as usize];
|
||||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||||
|
|
||||||
|
let (number_of_selected_items, number_of_selected_groups) = check_how_much_elements_is_selected(tree_view, nb_object.column_color, nb_object.column_selection);
|
||||||
|
|
||||||
|
// Nothing is selected
|
||||||
|
if number_of_selected_items == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !check_if_can_delete_files(&check_button_settings_confirm_deletion, &window_main, number_of_selected_items, number_of_selected_groups).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(column_color) = nb_object.column_color {
|
if let Some(column_color) = nb_object.column_color {
|
||||||
if !check_button_settings_confirm_group_deletion.is_active() || !check_if_deleting_all_files_in_group(tree_view, column_color, nb_object.column_selection, &window_main, &check_button_settings_confirm_group_deletion).await {
|
if !check_button_settings_confirm_group_deletion.is_active() || !check_if_deleting_all_files_in_group(tree_view, column_color, nb_object.column_selection, &window_main, &check_button_settings_confirm_group_deletion).await {
|
||||||
tree_remove(
|
tree_remove(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
|
||||||
&tree_view.clone(),
|
|
||||||
nb_object.column_name,
|
|
||||||
nb_object.column_path,
|
|
||||||
column_color,
|
|
||||||
nb_object.column_selection,
|
|
||||||
&check_button_settings_use_trash,
|
|
||||||
&text_view_errors,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if nb_number == NotebookMainEnum::EmptyDirectories as u32 {
|
if nb_number == NotebookMainEnum::EmptyDirectories as u32 {
|
||||||
empty_folder_remover(&tree_view.clone(), nb_object.column_name, nb_object.column_path, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
|
empty_folder_remover(tree_view, nb_object.column_name, nb_object.column_path, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
|
||||||
} else {
|
} else {
|
||||||
basic_remove(&tree_view.clone(), nb_object.column_name, nb_object.column_path, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
|
basic_remove(tree_view, nb_object.column_name, nb_object.column_path, nb_object.column_selection, &check_button_settings_use_trash, &text_view_errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +82,9 @@ pub async fn delete_things(gui_data: GuiData) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn check_if_can_delete_files(check_button_settings_confirm_deletion: >k::CheckButton, window_main: >k::Window) -> bool {
|
pub async fn check_if_can_delete_files(check_button_settings_confirm_deletion: >k::CheckButton, window_main: >k::Window, number_of_selected_items: u64, number_of_selected_groups: u64) -> bool {
|
||||||
if check_button_settings_confirm_deletion.is_active() {
|
if check_button_settings_confirm_deletion.is_active() {
|
||||||
let (confirmation_dialog_delete, check_button) = create_dialog_ask_for_deletion(window_main);
|
let (confirmation_dialog_delete, check_button) = create_dialog_ask_for_deletion(window_main, number_of_selected_items, number_of_selected_groups);
|
||||||
|
|
||||||
let response_type = confirmation_dialog_delete.run_future().await;
|
let response_type = confirmation_dialog_delete.run_future().await;
|
||||||
if response_type == gtk::ResponseType::Ok {
|
if response_type == gtk::ResponseType::Ok {
|
||||||
|
@ -102,12 +102,19 @@ pub async fn check_if_can_delete_files(check_button_settings_confirm_deletion: &
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_dialog_ask_for_deletion(window_main: >k::Window) -> (Dialog, CheckButton) {
|
fn create_dialog_ask_for_deletion(window_main: >k::Window, number_of_selected_items: u64, number_of_selected_groups: u64) -> (Dialog, CheckButton) {
|
||||||
let dialog = gtk::Dialog::builder().title(&fl!("delete_title_dialog")).transient_for(window_main).modal(true).build();
|
let dialog = gtk::Dialog::builder().title(&fl!("delete_title_dialog")).transient_for(window_main).modal(true).build();
|
||||||
let button_ok = dialog.add_button(&fl!("general_ok_button"), ResponseType::Ok);
|
let button_ok = dialog.add_button(&fl!("general_ok_button"), ResponseType::Ok);
|
||||||
dialog.add_button(&fl!("general_close_button"), ResponseType::Cancel);
|
dialog.add_button(&fl!("general_close_button"), ResponseType::Cancel);
|
||||||
|
|
||||||
let label: gtk::Label = gtk::Label::new(Some(&fl!("delete_question_label")));
|
let label: gtk::Label = gtk::Label::new(Some(&fl!("delete_question_label")));
|
||||||
|
let label2: gtk::Label = match number_of_selected_groups {
|
||||||
|
0 => gtk::Label::new(Some(&fl!("delete_items_label", generate_translation_hashmap(vec![("items", number_of_selected_items.to_string())])))),
|
||||||
|
_ => gtk::Label::new(Some(&fl!(
|
||||||
|
"delete_items_groups_label",
|
||||||
|
generate_translation_hashmap(vec![("items", number_of_selected_items.to_string()), ("groups", number_of_selected_groups.to_string())])
|
||||||
|
))),
|
||||||
|
};
|
||||||
let check_button: gtk::CheckButton = gtk::CheckButton::with_label(&fl!("dialogs_ask_next_time"));
|
let check_button: gtk::CheckButton = gtk::CheckButton::with_label(&fl!("dialogs_ask_next_time"));
|
||||||
check_button.set_active(true);
|
check_button.set_active(true);
|
||||||
check_button.set_halign(Align::Center);
|
check_button.set_halign(Align::Center);
|
||||||
|
@ -116,7 +123,10 @@ fn create_dialog_ask_for_deletion(window_main: >k::Window) -> (Dialog, CheckBu
|
||||||
|
|
||||||
let internal_box = get_dialog_box_child(&dialog);
|
let internal_box = get_dialog_box_child(&dialog);
|
||||||
internal_box.add(&label);
|
internal_box.add(&label);
|
||||||
|
internal_box.add(&label2);
|
||||||
internal_box.add(&check_button);
|
internal_box.add(&check_button);
|
||||||
|
internal_box.set_margin(5);
|
||||||
|
check_button.set_margin_top(5);
|
||||||
|
|
||||||
dialog.show_all();
|
dialog.show_all();
|
||||||
(dialog, check_button)
|
(dialog, check_button)
|
||||||
|
@ -227,7 +237,7 @@ pub fn empty_folder_remover(tree_view: >k::TreeView, column_file_name: i32, co
|
||||||
|
|
||||||
// We must check if folder is really empty or contains only other empty folders
|
// We must check if folder is really empty or contains only other empty folders
|
||||||
let mut error_happened = false;
|
let mut error_happened = false;
|
||||||
let mut folders_to_check: Vec<String> = vec![format!("{}/{}", path, name)];
|
let mut folders_to_check: Vec<String> = vec![get_full_name_from_path_name(&path, &name)];
|
||||||
let mut current_folder: String;
|
let mut current_folder: String;
|
||||||
let mut next_folder: String;
|
let mut next_folder: String;
|
||||||
'dir: while !folders_to_check.is_empty() {
|
'dir: while !folders_to_check.is_empty() {
|
||||||
|
@ -275,14 +285,14 @@ pub fn empty_folder_remover(tree_view: >k::TreeView, column_file_name: i32, co
|
||||||
|
|
||||||
if !error_happened {
|
if !error_happened {
|
||||||
if !use_trash {
|
if !use_trash {
|
||||||
match fs::remove_dir_all(format!("{}/{}", path, name)) {
|
match fs::remove_dir_all(get_full_name_from_path_name(&path, &name)) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
model.remove(&iter);
|
model.remove(&iter);
|
||||||
}
|
}
|
||||||
Err(_inspected) => error_happened = true,
|
Err(_inspected) => error_happened = true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match trash::delete(format!("{}/{}", path, name)) {
|
match trash::delete(get_full_name_from_path_name(&path, &name)) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
model.remove(&iter);
|
model.remove(&iter);
|
||||||
}
|
}
|
||||||
|
@ -291,7 +301,7 @@ pub fn empty_folder_remover(tree_view: >k::TreeView, column_file_name: i32, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if error_happened {
|
if error_happened {
|
||||||
messages += &fl!("delete_folder_failed", generate_translation_hashmap(vec![("dir", format!("{}/{}", path, name))]));
|
messages += &fl!("delete_folder_failed", generate_translation_hashmap(vec![("dir", get_full_name_from_path_name(&path, &name))]));
|
||||||
messages += "\n";
|
messages += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,23 +342,23 @@ pub fn basic_remove(tree_view: >k::TreeView, column_file_name: i32, column_pat
|
||||||
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
||||||
|
|
||||||
if !use_trash {
|
if !use_trash {
|
||||||
match fs::remove_file(format!("{}/{}", path, name)) {
|
match fs::remove_file(get_full_name_from_path_name(&path, &name)) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
model.remove(&iter);
|
model.remove(&iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", format!("{}/{}", path, name)), ("reason", e.to_string())])).as_str();
|
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &name)), ("reason", e.to_string())])).as_str();
|
||||||
messages += "\n";
|
messages += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match trash::delete(format!("{}/{}", path, name)) {
|
match trash::delete(get_full_name_from_path_name(&path, &name)) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
model.remove(&iter);
|
model.remove(&iter);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", format!("{}/{}", path, name)), ("reason", e.to_string())])).as_str();
|
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &name)), ("reason", e.to_string())])).as_str();
|
||||||
messages += "\n";
|
messages += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,12 +420,12 @@ pub fn tree_remove(tree_view: >k::TreeView, column_file_name: i32, column_path
|
||||||
vec_file_name.dedup();
|
vec_file_name.dedup();
|
||||||
for file_name in vec_file_name {
|
for file_name in vec_file_name {
|
||||||
if !use_trash {
|
if !use_trash {
|
||||||
if let Err(e) = fs::remove_file(format!("{}/{}", path.clone(), file_name.clone())) {
|
if let Err(e) = fs::remove_file(get_full_name_from_path_name(&path, &file_name)) {
|
||||||
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", format!("{}/{}", path, file_name)), ("reason", e.to_string())])).as_str();
|
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &file_name)), ("reason", e.to_string())])).as_str();
|
||||||
messages += "\n";
|
messages += "\n";
|
||||||
}
|
}
|
||||||
} else if let Err(e) = trash::delete(format!("{}/{}", path.clone(), file_name.clone())) {
|
} else if let Err(e) = trash::delete(get_full_name_from_path_name(&path, &file_name)) {
|
||||||
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", format!("{}/{}", path, file_name)), ("reason", e.to_string())])).as_str();
|
messages += fl!("delete_file_failed", generate_translation_hashmap(vec![("name", get_full_name_from_path_name(&path, &file_name)), ("reason", e.to_string())])).as_str();
|
||||||
messages += "\n";
|
messages += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ pub fn hardlink_symlink(tree_view: >k::TreeView, column_file_name: i32, column
|
||||||
if model.path(¤t_iter).unwrap() == selected_rows[current_selected_index] {
|
if model.path(¤t_iter).unwrap() == selected_rows[current_selected_index] {
|
||||||
let file_name = model.value(¤t_iter, column_file_name).get::<String>().unwrap();
|
let file_name = model.value(¤t_iter, column_file_name).get::<String>().unwrap();
|
||||||
let path = model.value(¤t_iter, column_path).get::<String>().unwrap();
|
let path = model.value(¤t_iter, column_path).get::<String>().unwrap();
|
||||||
let full_file_path = format!("{}/{}", path, file_name);
|
let full_file_path = get_full_name_from_path_name(&path, &file_name);
|
||||||
|
|
||||||
if current_symhardlink_data.is_some() {
|
if current_symhardlink_data.is_some() {
|
||||||
vec_tree_path_to_remove.push(model.path(¤t_iter).unwrap());
|
vec_tree_path_to_remove.push(model.path(¤t_iter).unwrap());
|
||||||
|
|
|
@ -31,6 +31,12 @@ pub fn connect_button_move(gui_data: &GuiData) {
|
||||||
let tree_view = &main_tree_views[nb_number as usize];
|
let tree_view = &main_tree_views[nb_number as usize];
|
||||||
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
let nb_object = &NOTEBOOKS_INFOS[nb_number as usize];
|
||||||
|
|
||||||
|
let (number_of_selected_items, _number_of_selected_groups) = check_how_much_elements_is_selected(tree_view, nb_object.column_color, nb_object.column_selection);
|
||||||
|
|
||||||
|
// Nothing is selected
|
||||||
|
if number_of_selected_items == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
move_things(
|
move_things(
|
||||||
tree_view,
|
tree_view,
|
||||||
nb_object.column_name,
|
nb_object.column_name,
|
||||||
|
@ -174,7 +180,7 @@ fn move_files_common(selected_rows: &[TreePath], model: >k::ListStore, column_
|
||||||
let file_name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
let file_name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
||||||
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
||||||
|
|
||||||
let thing = format!("{}/{}", path, file_name);
|
let thing = get_full_name_from_path_name(&path, &file_name);
|
||||||
let destination_file = destination_folder.join(file_name);
|
let destination_file = destination_folder.join(file_name);
|
||||||
if Path::new(&thing).is_dir() {
|
if Path::new(&thing).is_dir() {
|
||||||
if let Err(e) = fs_extra::dir::move_dir(&thing, &destination_file, &fs_extra::dir::CopyOptions::new()) {
|
if let Err(e) = fs_extra::dir::move_dir(&thing, &destination_file, &fs_extra::dir::CopyOptions::new()) {
|
||||||
|
|
|
@ -401,11 +401,8 @@ fn popover_custom_select_unselect(popover: >k::Popover, window_main: &Window,
|
||||||
let is_selected = model.value(&iter, column_button_selection as i32).get::<bool>().unwrap();
|
let is_selected = model.value(&iter, column_button_selection as i32).get::<bool>().unwrap();
|
||||||
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
||||||
let name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
let name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
||||||
#[cfg(not(target_family = "windows"))]
|
|
||||||
let character = "/";
|
let path_and_name = get_full_name_from_path_name(&path, &name);
|
||||||
#[cfg(target_family = "windows")]
|
|
||||||
let character = "\\";
|
|
||||||
let path_and_name = format!("{}{}{}", path, character, name);
|
|
||||||
|
|
||||||
let mut need_to_change_thing: bool = false;
|
let mut need_to_change_thing: bool = false;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{ListStore, TextView, Widget};
|
use gtk::{ListStore, TextView, TreeView, Widget};
|
||||||
|
|
||||||
use czkawka_core::big_file::BigFile;
|
use czkawka_core::big_file::BigFile;
|
||||||
use czkawka_core::broken_files::BrokenFiles;
|
use czkawka_core::broken_files::BrokenFiles;
|
||||||
|
@ -19,6 +19,11 @@ use czkawka_core::{fl, invalid_symlinks};
|
||||||
|
|
||||||
use crate::notebook_enums::{NotebookMainEnum, NUMBER_OF_NOTEBOOK_MAIN_TABS};
|
use crate::notebook_enums::{NotebookMainEnum, NUMBER_OF_NOTEBOOK_MAIN_TABS};
|
||||||
|
|
||||||
|
#[cfg(not(target_family = "windows"))]
|
||||||
|
pub const CHARACTER: char = '/';
|
||||||
|
#[cfg(target_family = "windows")]
|
||||||
|
pub const CHARACTER: char = '\\';
|
||||||
|
|
||||||
pub const KEY_DELETE: u32 = 119;
|
pub const KEY_DELETE: u32 = 119;
|
||||||
pub const KEY_ENTER: u32 = 36;
|
pub const KEY_ENTER: u32 = 36;
|
||||||
pub const KEY_SPACE: u32 = 65;
|
pub const KEY_SPACE: u32 = 65;
|
||||||
|
@ -470,6 +475,14 @@ pub fn get_notebook_object_from_tree_view(tree_view: >k::TreeView) -> &Noteboo
|
||||||
&NOTEBOOKS_INFOS[nb_enum as usize]
|
&NOTEBOOKS_INFOS[nb_enum as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_full_name_from_path_name(path: &str, name: &str) -> String {
|
||||||
|
let mut string = String::with_capacity(path.len() + name.len() + 1);
|
||||||
|
string.push_str(path);
|
||||||
|
string.push(CHARACTER);
|
||||||
|
string.push_str(name);
|
||||||
|
string
|
||||||
|
}
|
||||||
|
|
||||||
// After e.g. deleting files, header may become orphan or have one child, so should be deleted in this case
|
// After e.g. deleting files, header may become orphan or have one child, so should be deleted in this case
|
||||||
pub fn clean_invalid_headers(model: >k::ListStore, column_color: i32) {
|
pub fn clean_invalid_headers(model: >k::ListStore, column_color: i32) {
|
||||||
// Remove only child from header
|
// Remove only child from header
|
||||||
|
@ -541,6 +554,52 @@ pub fn clean_invalid_headers(model: >k::ListStore, column_color: i32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn check_how_much_elements_is_selected(tree_view: &TreeView, column_color: Option<i32>, column_selection: i32) -> (u64, u64) {
|
||||||
|
let mut number_of_selected_items: u64 = 0;
|
||||||
|
let mut number_of_selected_groups: u64 = 0;
|
||||||
|
|
||||||
|
let model = get_list_store(tree_view);
|
||||||
|
|
||||||
|
let mut is_item_currently_selected_in_group: bool = false;
|
||||||
|
|
||||||
|
// First iter
|
||||||
|
if let Some(iter) = model.iter_first() {
|
||||||
|
if let Some(column_color) = column_color {
|
||||||
|
assert_eq!(model.value(&iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR); // First element should be header
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if !model.iter_next(&iter) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if model.value(&iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
||||||
|
is_item_currently_selected_in_group = false;
|
||||||
|
} else {
|
||||||
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
||||||
|
number_of_selected_items += 1;
|
||||||
|
|
||||||
|
if !is_item_currently_selected_in_group {
|
||||||
|
number_of_selected_groups += 1;
|
||||||
|
}
|
||||||
|
is_item_currently_selected_in_group = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loop {
|
||||||
|
if !model.iter_next(&iter) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
||||||
|
number_of_selected_items += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(number_of_selected_items, number_of_selected_groups)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_custom_label_from_button_with_image(button: >k::Bin) -> gtk::Label {
|
pub fn get_custom_label_from_button_with_image(button: >k::Bin) -> gtk::Label {
|
||||||
let internal_box = button.child().unwrap().downcast::<gtk::Box>().unwrap();
|
let internal_box = button.child().unwrap().downcast::<gtk::Box>().unwrap();
|
||||||
|
|
|
@ -673,7 +673,7 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
|
||||||
let path = tree_model.value(&tree_model.iter(&tree_path).unwrap(), column_path).get::<String>().unwrap();
|
let path = tree_model.value(&tree_model.iter(&tree_path).unwrap(), column_path).get::<String>().unwrap();
|
||||||
let name = tree_model.value(&tree_model.iter(&tree_path).unwrap(), column_name).get::<String>().unwrap();
|
let name = tree_model.value(&tree_model.iter(&tree_path).unwrap(), column_name).get::<String>().unwrap();
|
||||||
|
|
||||||
let file_name = format!("{}/{}", path, name);
|
let file_name = get_full_name_from_path_name(&path, &name);
|
||||||
let file_name = file_name.as_str();
|
let file_name = file_name.as_str();
|
||||||
|
|
||||||
if let Some(extension) = Path::new(file_name).extension() {
|
if let Some(extension) = Path::new(file_name).extension() {
|
||||||
|
|
|
@ -80,9 +80,7 @@ fn common_open_function(tree_view: >k::TreeView, column_name: i32, column_path
|
||||||
|
|
||||||
let end_path = match opening_mode {
|
let end_path = match opening_mode {
|
||||||
OpenMode::OnlyPath => path,
|
OpenMode::OnlyPath => path,
|
||||||
OpenMode::PathAndName => {
|
OpenMode::PathAndName => get_full_name_from_path_name(&path, &name),
|
||||||
format!("{}/{}", path, name)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
open::that_in_background(&end_path);
|
open::that_in_background(&end_path);
|
||||||
|
@ -96,11 +94,9 @@ fn common_open_function(tree_view: >k::TreeView, column_name: i32, column_path
|
||||||
fn handle_tree_keypress(tree_view: >k::TreeView, key_code: u32, name_column: i32, path_column: i32, mark_column: i32) {
|
fn handle_tree_keypress(tree_view: >k::TreeView, key_code: u32, name_column: i32, path_column: i32, mark_column: i32) {
|
||||||
match key_code {
|
match key_code {
|
||||||
KEY_ENTER => {
|
KEY_ENTER => {
|
||||||
// Enter
|
|
||||||
common_open_function(tree_view, name_column, path_column, OpenMode::PathAndName);
|
common_open_function(tree_view, name_column, path_column, OpenMode::PathAndName);
|
||||||
}
|
}
|
||||||
KEY_SPACE => {
|
KEY_SPACE => {
|
||||||
// Space
|
|
||||||
common_mark_function(tree_view, mark_column);
|
common_mark_function(tree_view, mark_column);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -424,6 +424,9 @@ delete_all_files_in_group_label1 = In some groups there are selected all records
|
||||||
delete_all_files_in_group_label2 = Are you sure that you want to delete them?
|
delete_all_files_in_group_label2 = Are you sure that you want to delete them?
|
||||||
delete_folder_failed = Failed to remove folder {$dir} because folder doesn't exists, you don't have permissions or isn't empty.
|
delete_folder_failed = Failed to remove folder {$dir} because folder doesn't exists, you don't have permissions or isn't empty.
|
||||||
|
|
||||||
|
delete_items_label = { $items } files will be removed.
|
||||||
|
delete_items_groups_label = { $items } files from { $groups } groups will be removed.
|
||||||
|
|
||||||
hardlink_failed = Failed to hardlink
|
hardlink_failed = Failed to hardlink
|
||||||
hard_sym_invalid_selection_title_dialog = Invalid selection with some groups
|
hard_sym_invalid_selection_title_dialog = Invalid selection with some groups
|
||||||
hard_sym_invalid_selection_label_1 = In some groups there is only 1 record selected and it will be ignored.
|
hard_sym_invalid_selection_label_1 = In some groups there is only 1 record selected and it will be ignored.
|
||||||
|
|
|
@ -367,6 +367,8 @@ delete_all_files_in_group_title = Potwierdzenie usunięcia wszystkich plików w
|
||||||
delete_all_files_in_group_label1 = W niektórych grupach zaznaczono wszystkie rekordy.
|
delete_all_files_in_group_label1 = W niektórych grupach zaznaczono wszystkie rekordy.
|
||||||
delete_all_files_in_group_label2 = Czy na pewno je usunąć?
|
delete_all_files_in_group_label2 = Czy na pewno je usunąć?
|
||||||
delete_folder_failed = Nie udało się usunąć folderu { $name } ponieważ nie istnieje, uprawnienia nie są wystarczające lub nie jest pusty.
|
delete_folder_failed = Nie udało się usunąć folderu { $name } ponieważ nie istnieje, uprawnienia nie są wystarczające lub nie jest pusty.
|
||||||
|
delete_items_label = { $items } plików zostanie usuniętych.
|
||||||
|
delete_items_groups_label = { $items } plików z { $groups } grup będzie usuniętych.
|
||||||
hardlink_failed = Nie udało się utworzyć twardego dowiązania
|
hardlink_failed = Nie udało się utworzyć twardego dowiązania
|
||||||
hard_sym_invalid_selection_title_dialog = Niepoprawne zaznaczenie w niektórych grupach
|
hard_sym_invalid_selection_title_dialog = Niepoprawne zaznaczenie w niektórych grupach
|
||||||
hard_sym_invalid_selection_label_1 = W niektórych grupach zaznaczono tylko 1 rekord który zostanie zignorowany.
|
hard_sym_invalid_selection_label_1 = W niektórych grupach zaznaczono tylko 1 rekord który zostanie zignorowany.
|
||||||
|
|
|
@ -63,4 +63,31 @@ Next new record must be added to array.
|
||||||
combo_box_text: "Polski (Polish)",
|
combo_box_text: "Polski (Polish)",
|
||||||
short_text: "pl",
|
short_text: "pl",
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Validating translation offline
|
||||||
|
When trying to translate objects offline, due renames, adding and removing elements, may happen that translations will contain outdated entries.
|
||||||
|
|
||||||
|
To help find such keywords, special python script can be used.
|
||||||
|
|
||||||
|
To be able to use it, be sure that you are directly inside main `czkawka` folder.
|
||||||
|
Next, be sure that your language is available in array/list and also in i18n folder and then run python script `python3 misc/translation_test.py`.
|
||||||
|
Then results should be visible in console:
|
||||||
|
```
|
||||||
|
Checking pl language
|
||||||
|
Missing keyword - duplicate_mode_name_combo_box
|
||||||
|
Missing keyword - duplicate_mode_size_combo_box
|
||||||
|
Missing keyword - duplicate_mode_hash_combo_box
|
||||||
|
Missing keyword - settings_language_label_tooltip
|
||||||
|
Missing keyword - settings_language_label
|
||||||
|
Unused keyword - duplicate_mode_name_checkbox
|
||||||
|
Unused keyword - duplicate_mode_size_checkbox
|
||||||
|
Unused keyword - duplicate_mode_hash_checkbox
|
||||||
|
Unused keyword - duplicate_mode_name_checkbox_tooltip
|
||||||
|
Unused keyword - duplicate_mode_size_checkbox_tooltip
|
||||||
|
Unused keyword - duplicate_mode_hash_checkbox_tooltip
|
||||||
|
```
|
||||||
|
`Missing keyword` means that some keywords exists in base translations and texts needs to be translated.
|
||||||
|
`Unused keyword` means that keyword is no longer used. It can be renamed or entirely removed from file.
|
||||||
|
|
||||||
|
When script will not print anything except "Checking language", then this means that translation file have exactly same keys as base one.
|
Loading…
Reference in New Issue