2
0
mirror of https://github.com/qarmin/czkawka synced 2024-10-31 21:20:19 +00:00

Allow to put files to trash instead fully remove them (#284)

This commit is contained in:
Rafał Mikrut 2021-03-11 14:31:59 +01:00 committed by GitHub
parent 8ad0b907ec
commit 8c1140e40d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 17 deletions

26
Cargo.lock generated
View File

@ -230,9 +230,9 @@ checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
[[package]]
name = "byteorder"
version = "1.4.2"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
@ -599,6 +599,7 @@ dependencies = [
"humansize",
"image",
"open",
"trash",
"winapi",
]
@ -1654,9 +1655,9 @@ checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "open"
version = "1.5.1"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2033f93630dd4b04768ecf5e16bcd3002a89e1e1dbef375bf290dd67e2b7a4d"
checksum = "a7e9f1bdf15cd1f5a00cc9002a733a6ee6d0ff562491852d59652471c4a389f7"
dependencies = [
"which",
"winapi",
@ -2298,9 +2299,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
[[package]]
name = "syn"
version = "1.0.61"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5"
checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717"
dependencies = [
"proc-macro2",
"quote",
@ -2475,6 +2476,15 @@ dependencies = [
"strength_reduce",
]
[[package]]
name = "trash"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90df96afb154814e214f37eac04920c66886fd95962f22febb4d537b0dacd512"
dependencies = [
"winapi",
]
[[package]]
name = "typenum"
version = "1.12.0"
@ -2745,9 +2755,9 @@ dependencies = [
[[package]]
name = "xxhash-rust"
version = "0.8.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b92e16d90ed01ad0736f1123137630b5bcef5f5bafee62468283e027c1c85d"
checksum = "e575e15bedf6e57b5c2d763ffc6c3c760143466cbd09d762d539680ab5992ded"
[[package]]
name = "zip"

View File

@ -31,6 +31,9 @@ open = "1.4.0"
# To get image preview
image = "0.23.12"
# Move files to trash
trash = "1.3.0"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["combaseapi", "objbase", "shobjidl_core", "windef", "winerror", "wtypesbase", "winuser"] }

View File

@ -2554,6 +2554,21 @@ This program is free to use and will always be.
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="check_button_settings_use_trash">
<property name="label" translatable="yes">Move deleted files to trash</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>

View File

@ -225,6 +225,7 @@ pub fn check_if_deleting_all_files_in_group(tree_view: &gtk::TreeView, column_co
pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, gui_data: &GuiData) {
let text_view_errors = gui_data.text_view_errors.clone();
let use_trash = gui_data.settings.check_button_settings_use_trash.clone().get_active();
let selection = tree_view.get_selection();
@ -290,11 +291,20 @@ pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, co
}
if !error_happened {
match fs::remove_dir_all(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.get_iter(tree_path).unwrap());
if !use_trash {
match fs::remove_dir_all(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.get_iter(tree_path).unwrap());
}
Err(_) => error_happened = true,
}
} else {
match trash::delete(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.get_iter(tree_path).unwrap());
}
Err(_) => error_happened = true,
}
Err(_) => error_happened = true,
}
}
if error_happened {
@ -308,6 +318,7 @@ pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, co
pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, gui_data: &GuiData) {
let text_view_errors = gui_data.text_view_errors.clone();
let use_trash = gui_data.settings.check_button_settings_use_trash.clone().get_active();
let selection = tree_view.get_selection();
@ -324,11 +335,20 @@ pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_pat
let name = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), column_file_name).get::<String>().unwrap().unwrap();
let path = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), column_path).get::<String>().unwrap().unwrap();
match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.get_iter(tree_path).unwrap());
if !use_trash {
match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.get_iter(tree_path).unwrap());
}
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
}
} else {
match trash::delete(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.get_iter(tree_path).unwrap());
}
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
}
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
}
}
@ -339,6 +359,7 @@ pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_pat
// Remove all occurrences - remove every element which have same path and name as even non selected ones
pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, gui_data: &GuiData) {
let text_view_errors = gui_data.text_view_errors.clone();
let use_trash = gui_data.settings.check_button_settings_use_trash.clone().get_active();
let selection = tree_view.get_selection();
@ -369,13 +390,22 @@ pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path
vec_file_name.sort();
vec_file_name.dedup();
for file_name in vec_file_name {
if fs::remove_file(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
if !use_trash {
if fs::remove_file(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
messages += format!(
"Failed to remove file {}/{}. It is possible that you already deleted it, because similar images shows all possible file doesn't exists or you don't have permissions.\n",
path, file_name
)
.as_str()
}
} else if trash::delete(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
messages += format!(
"Failed to remove file {}/{}. It is possible that you already deleted it, because similar images shows all possible file doesn't exists or you don't have permissions.\n",
path, file_name
)
.as_str()
}
vec_path_to_delete.push((path.clone(), file_name.clone()));
}
}

View File

@ -11,6 +11,7 @@ pub struct GUISettings {
pub check_button_settings_confirm_group_deletion: gtk::CheckButton,
pub check_button_settings_show_text_view: gtk::CheckButton,
pub check_button_settings_use_cache: gtk::CheckButton,
pub check_button_settings_use_trash: gtk::CheckButton,
// Duplicates
pub check_button_settings_hide_hard_links: gtk::CheckButton,
@ -35,6 +36,7 @@ impl GUISettings {
let check_button_settings_confirm_group_deletion: gtk::CheckButton = builder.get_object("check_button_settings_confirm_group_deletion").unwrap();
let check_button_settings_show_text_view: gtk::CheckButton = builder.get_object("check_button_settings_show_text_view").unwrap();
let check_button_settings_use_cache: gtk::CheckButton = builder.get_object("check_button_settings_use_cache").unwrap();
let check_button_settings_use_trash: gtk::CheckButton = builder.get_object("check_button_settings_use_trash").unwrap();
// Duplicates
let check_button_settings_hide_hard_links: gtk::CheckButton = builder.get_object("check_button_settings_hide_hard_links").unwrap();
@ -60,6 +62,7 @@ impl GUISettings {
check_button_settings_show_preview_similar_images,
check_button_settings_hide_hard_links,
check_button_settings_use_cache,
check_button_settings_use_trash,
}
}
}

View File

@ -126,6 +126,11 @@ pub fn save_configuration(gui_data: &GuiData, manual_execution: bool) {
data_to_save.push("--use_cache:".to_string());
let check_button_settings_use_cache = gui_data.settings.check_button_settings_use_cache.clone();
data_to_save.push(check_button_settings_use_cache.get_active().to_string());
//// Delete to trash
data_to_save.push("--use_trash:".to_string());
let check_button_settings_use_trash = gui_data.settings.check_button_settings_use_trash.clone();
data_to_save.push(check_button_settings_use_trash.get_active().to_string());
}
// Creating/Opening config file
@ -176,6 +181,7 @@ enum TypeOfLoadedData {
BottomTextPanel,
HideHardLinks,
UseCache,
UseTrash,
}
pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
@ -221,6 +227,7 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
let mut bottom_text_panel: bool = true;
let mut hide_hard_links: bool = true;
let mut use_cache: bool = true;
let mut use_trash: bool = false;
let mut current_type = TypeOfLoadedData::None;
for (line_number, line) in loaded_data.replace("\r\n", "\n").split('\n').enumerate() {
@ -252,6 +259,8 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
current_type = TypeOfLoadedData::HideHardLinks;
} else if line.starts_with("--use_cache") {
current_type = TypeOfLoadedData::UseCache;
} else if line.starts_with("--use_trash") {
current_type = TypeOfLoadedData::UseTrash;
} else if line.starts_with("--") {
current_type = TypeOfLoadedData::None;
add_text_to_text_view(
@ -382,6 +391,19 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
);
}
}
TypeOfLoadedData::UseTrash => {
let line = line.to_lowercase();
if line == "1" || line == "true" {
use_trash = true;
} else if line == "0" || line == "false" {
use_trash = false;
} else {
add_text_to_text_view(
&text_view_errors,
format!("Found invalid data in line {} \"{}\" isn't proper value(0/1/true/false) when loading file {:?}", line_number, line, config_file).as_str(),
);
}
}
}
}
}
@ -435,6 +457,7 @@ pub fn load_configuration(gui_data: &GuiData, manual_execution: bool) {
}
gui_data.settings.check_button_settings_hide_hard_links.set_active(hide_hard_links);
gui_data.settings.check_button_settings_use_cache.set_active(use_cache);
gui_data.settings.check_button_settings_use_trash.set_active(use_trash);
} else {
gui_data.settings.check_button_settings_load_at_start.set_active(false);
}
@ -517,6 +540,7 @@ pub fn reset_configuration(gui_data: &GuiData, manual_clearing: bool) {
gui_data.settings.check_button_settings_show_text_view.set_active(true);
gui_data.settings.check_button_settings_hide_hard_links.set_active(true);
gui_data.settings.check_button_settings_use_cache.set_active(true);
gui_data.settings.check_button_settings_use_trash.set_active(false);
}
if manual_clearing {
add_text_to_text_view(&text_view_errors, "Current configuration was cleared.");