2020-11-05 06:15:06 +13:00
|
|
|
use std::collections::BTreeMap;
|
2020-11-01 02:23:31 +13:00
|
|
|
use std::fs;
|
|
|
|
use std::fs::Metadata;
|
|
|
|
|
2021-11-28 08:49:20 +13:00
|
|
|
use gtk::prelude::*;
|
2021-12-01 01:53:04 +13:00
|
|
|
use gtk::{Align, CheckButton, Dialog, ResponseType, TextView};
|
2021-11-28 08:49:20 +13:00
|
|
|
|
|
|
|
use crate::gui_data::GuiData;
|
|
|
|
use crate::help_functions::*;
|
|
|
|
use crate::notebook_enums::*;
|
2021-11-29 23:38:38 +13:00
|
|
|
use crate::validate_notebook_data;
|
2021-11-28 08:49:20 +13:00
|
|
|
|
2020-12-22 04:09:39 +13:00
|
|
|
// TODO add support for checking if really symlink doesn't point to correct directory/file
|
|
|
|
|
2020-11-01 02:23:31 +13:00
|
|
|
pub fn connect_button_delete(gui_data: &GuiData) {
|
2021-01-11 08:12:08 +13:00
|
|
|
let buttons_delete = gui_data.bottom_buttons.buttons_delete.clone();
|
2021-11-28 04:44:30 +13:00
|
|
|
|
|
|
|
let gui_data = gui_data.clone(); // TODO this maybe can be replaced, not sure if worth to do it
|
|
|
|
|
|
|
|
buttons_delete.connect_clicked(move |_| {
|
|
|
|
glib::MainContext::default().spawn_local(delete_things(gui_data.clone()));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn delete_things(gui_data: GuiData) {
|
2021-11-29 23:38:38 +13:00
|
|
|
validate_notebook_data(&gui_data); // TODO, disable this - only used as test if ever
|
|
|
|
|
2021-01-11 08:12:08 +13:00
|
|
|
let notebook_main = gui_data.main_notebook.notebook_main.clone();
|
2020-11-01 02:23:31 +13:00
|
|
|
let window_main = gui_data.window_main.clone();
|
2021-02-23 21:40:19 +13:00
|
|
|
let check_button_settings_confirm_deletion = gui_data.settings.check_button_settings_confirm_deletion.clone();
|
2021-03-07 03:56:39 +13:00
|
|
|
let check_button_settings_confirm_group_deletion = gui_data.settings.check_button_settings_confirm_group_deletion.clone();
|
2021-01-11 08:12:08 +13:00
|
|
|
let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone();
|
2021-11-25 20:36:49 +13:00
|
|
|
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
|
|
|
|
|
|
|
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
|
|
|
|
|
|
|
|
let check_button_settings_use_trash = gui_data.settings.check_button_settings_use_trash.clone();
|
|
|
|
|
|
|
|
let text_view_errors = gui_data.text_view_errors.clone();
|
2021-11-28 04:44:30 +13:00
|
|
|
if !check_if_can_delete_files(&check_button_settings_confirm_deletion, &window_main).await {
|
|
|
|
return;
|
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-11-28 04:44:30 +13:00
|
|
|
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];
|
|
|
|
|
|
|
|
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 {
|
|
|
|
tree_remove(
|
|
|
|
&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,
|
|
|
|
);
|
2020-11-01 02:23:31 +13:00
|
|
|
}
|
2021-11-28 04:44:30 +13:00
|
|
|
} else {
|
|
|
|
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);
|
2021-11-25 20:36:49 +13:00
|
|
|
} else {
|
2021-11-28 04:44:30 +13:00
|
|
|
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);
|
2021-11-25 20:36:49 +13:00
|
|
|
}
|
2021-11-28 04:44:30 +13:00
|
|
|
}
|
2021-11-25 20:36:49 +13:00
|
|
|
|
2021-11-28 04:44:30 +13:00
|
|
|
match &nb_object.notebook_type {
|
|
|
|
NotebookMainEnum::SimilarImages => {
|
|
|
|
image_preview_similar_images.hide();
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
2021-11-28 04:44:30 +13:00
|
|
|
NotebookMainEnum::Duplicate => {
|
|
|
|
image_preview_duplicates.hide();
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-11-28 04:44:30 +13:00
|
|
|
pub async fn check_if_can_delete_files(check_button_settings_confirm_deletion: >k::CheckButton, window_main: >k::Window) -> bool {
|
2021-06-26 04:07:13 +12:00
|
|
|
if check_button_settings_confirm_deletion.is_active() {
|
2021-11-28 04:44:30 +13:00
|
|
|
let (confirmation_dialog_delete, check_button) = create_dialog_ask_for_deletion(window_main);
|
|
|
|
|
|
|
|
let response_type = confirmation_dialog_delete.run_future().await;
|
2021-03-07 20:57:48 +13:00
|
|
|
if response_type == gtk::ResponseType::Ok {
|
2021-06-26 04:07:13 +12:00
|
|
|
if !check_button.is_active() {
|
2021-03-07 20:57:48 +13:00
|
|
|
check_button_settings_confirm_deletion.set_active(false);
|
|
|
|
}
|
|
|
|
confirmation_dialog_delete.hide();
|
|
|
|
confirmation_dialog_delete.close();
|
|
|
|
} else {
|
|
|
|
confirmation_dialog_delete.hide();
|
|
|
|
confirmation_dialog_delete.close();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
2021-11-28 08:57:10 +13:00
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
fn create_dialog_ask_for_deletion(window_main: >k::Window) -> (Dialog, CheckButton) {
|
|
|
|
let dialog = gtk::Dialog::builder().title("Delete confirmation").transient_for(window_main).build();
|
|
|
|
let button_ok = dialog.add_button("Ok", ResponseType::Ok);
|
|
|
|
dialog.add_button("Close", ResponseType::Cancel);
|
2021-12-01 01:53:04 +13:00
|
|
|
|
2021-11-28 04:44:30 +13:00
|
|
|
let label: gtk::Label = gtk::Label::new(Some("Are you sure that you want to delete files?"));
|
|
|
|
let check_button: gtk::CheckButton = gtk::CheckButton::with_label("Ask next time");
|
|
|
|
check_button.set_active(true);
|
|
|
|
check_button.set_halign(Align::Center);
|
|
|
|
|
|
|
|
button_ok.grab_focus();
|
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
let internal_box = get_dialog_box_child(&dialog);
|
2021-11-28 04:44:30 +13:00
|
|
|
internal_box.add(&label);
|
|
|
|
internal_box.add(&check_button);
|
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
dialog.show_all();
|
|
|
|
(dialog, check_button)
|
2021-11-28 04:44:30 +13:00
|
|
|
}
|
2021-03-07 20:57:48 +13:00
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
fn create_dialog_group_deletion(window_main: >k::Window) -> (Dialog, CheckButton) {
|
|
|
|
let dialog = gtk::Dialog::builder().title("Confirmation of deleting all files in group").transient_for(window_main).build();
|
|
|
|
let button_ok = dialog.add_button("Ok", ResponseType::Ok);
|
|
|
|
dialog.add_button("Close", ResponseType::Cancel);
|
2021-12-01 01:53:04 +13:00
|
|
|
|
2021-11-28 04:44:30 +13:00
|
|
|
let label: gtk::Label = gtk::Label::new(Some("In some groups there are selected all records."));
|
|
|
|
let label2: gtk::Label = gtk::Label::new(Some("Are you sure that you want to delete them?"));
|
|
|
|
let check_button: gtk::CheckButton = gtk::CheckButton::with_label("Ask next time");
|
|
|
|
check_button.set_active(true);
|
|
|
|
check_button.set_halign(Align::Center);
|
|
|
|
|
|
|
|
button_ok.grab_focus();
|
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
let internal_box = get_dialog_box_child(&dialog);
|
2021-11-28 04:44:30 +13:00
|
|
|
internal_box.add(&label);
|
|
|
|
internal_box.add(&label2);
|
|
|
|
internal_box.add(&check_button);
|
|
|
|
|
2021-12-01 23:09:47 +13:00
|
|
|
dialog.show_all();
|
|
|
|
(dialog, check_button)
|
2021-11-28 04:44:30 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn check_if_deleting_all_files_in_group(tree_view: >k::TreeView, column_color: i32, column_selection: i32, window_main: >k::Window, check_button_settings_confirm_group_deletion: >k::CheckButton) -> bool {
|
2021-07-30 17:16:35 +12:00
|
|
|
let model = get_list_store(tree_view);
|
2021-03-07 03:56:39 +13:00
|
|
|
|
|
|
|
let mut selected_all_records: bool = true;
|
|
|
|
|
2021-07-16 16:51:54 +12:00
|
|
|
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
|
2021-03-07 03:56:39 +13:00
|
|
|
|
|
|
|
loop {
|
2021-07-16 16:51:54 +12:00
|
|
|
if !model.iter_next(&iter) {
|
2021-03-07 03:56:39 +13:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-07-16 16:51:54 +12:00
|
|
|
if model.value(&iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
|
2021-03-07 03:56:39 +13:00
|
|
|
if selected_all_records {
|
|
|
|
break;
|
|
|
|
}
|
2021-07-16 16:51:54 +12:00
|
|
|
selected_all_records = true;
|
2021-03-07 03:56:39 +13:00
|
|
|
} else {
|
2021-07-16 16:51:54 +12:00
|
|
|
if !model.value(&iter, column_selection).get::<bool>().unwrap() {
|
|
|
|
selected_all_records = false;
|
|
|
|
}
|
2021-03-07 03:56:39 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if !selected_all_records {
|
|
|
|
return false;
|
|
|
|
} else {
|
2021-11-28 04:44:30 +13:00
|
|
|
let (confirmation_dialog_group_delete, check_button) = create_dialog_group_deletion(window_main);
|
|
|
|
|
|
|
|
let response_type = confirmation_dialog_group_delete.run_future().await;
|
2021-03-07 03:56:39 +13:00
|
|
|
if response_type == gtk::ResponseType::Ok {
|
2021-06-26 04:07:13 +12:00
|
|
|
if !check_button.is_active() {
|
2021-03-07 03:56:39 +13:00
|
|
|
check_button_settings_confirm_group_deletion.set_active(false);
|
|
|
|
}
|
|
|
|
} else {
|
2021-03-07 20:57:48 +13:00
|
|
|
confirmation_dialog_group_delete.hide();
|
|
|
|
confirmation_dialog_group_delete.close();
|
2021-03-07 03:56:39 +13:00
|
|
|
return true;
|
|
|
|
}
|
2021-03-07 20:57:48 +13:00
|
|
|
confirmation_dialog_group_delete.hide();
|
|
|
|
confirmation_dialog_group_delete.close();
|
2021-03-07 03:56:39 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
pub fn empty_folder_remover(tree_view: >k::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, check_button_settings_use_trash: &CheckButton, text_view_errors: &TextView) {
|
|
|
|
let use_trash = check_button_settings_use_trash.is_active();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-07-30 17:16:35 +12:00
|
|
|
let model = get_list_store(tree_view);
|
2020-11-05 06:15:06 +13:00
|
|
|
|
2021-07-16 16:51:54 +12:00
|
|
|
let mut selected_rows = Vec::new();
|
|
|
|
|
|
|
|
if let Some(iter) = model.iter_first() {
|
|
|
|
loop {
|
|
|
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
|
|
|
selected_rows.push(model.path(&iter).unwrap());
|
|
|
|
}
|
|
|
|
if !model.iter_next(&iter) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
if selected_rows.is_empty() {
|
|
|
|
return; // No selected rows
|
|
|
|
}
|
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
let mut messages: String = "".to_string();
|
|
|
|
|
|
|
|
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
|
2021-07-16 16:51:54 +12:00
|
|
|
for tree_path in selected_rows.iter().rev() {
|
|
|
|
let iter = model.iter(tree_path).unwrap();
|
|
|
|
|
|
|
|
let name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
|
|
|
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
2020-11-05 06:15:06 +13:00
|
|
|
|
|
|
|
// We must check if folder is really empty or contains only other empty folders
|
|
|
|
let mut error_happened = false;
|
|
|
|
let mut folders_to_check: Vec<String> = vec![format!("{}/{}", path, name)];
|
|
|
|
let mut current_folder: String;
|
|
|
|
let mut next_folder: String;
|
|
|
|
'dir: while !folders_to_check.is_empty() {
|
|
|
|
current_folder = folders_to_check.pop().unwrap();
|
|
|
|
let read_dir = match fs::read_dir(¤t_folder) {
|
|
|
|
Ok(t) => t,
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(_inspected) => {
|
2020-11-05 06:15:06 +13:00
|
|
|
error_happened = true;
|
|
|
|
break 'dir;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for entry in read_dir {
|
|
|
|
let entry_data = match entry {
|
|
|
|
Ok(t) => t,
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(_inspected) => {
|
2020-11-05 06:15:06 +13:00
|
|
|
error_happened = true;
|
|
|
|
break 'dir;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let metadata: Metadata = match entry_data.metadata() {
|
|
|
|
Ok(t) => t,
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(_inspected) => {
|
2020-11-05 06:15:06 +13:00
|
|
|
error_happened = true;
|
|
|
|
break 'dir;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if metadata.is_dir() {
|
|
|
|
next_folder = "".to_owned()
|
|
|
|
+ ¤t_folder
|
|
|
|
+ "/"
|
|
|
|
+ match &entry_data.file_name().into_string() {
|
2020-11-01 02:23:31 +13:00
|
|
|
Ok(t) => t,
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(_inspected) => {
|
2020-11-01 02:23:31 +13:00
|
|
|
error_happened = true;
|
|
|
|
break 'dir;
|
|
|
|
}
|
|
|
|
};
|
2020-11-05 06:15:06 +13:00
|
|
|
folders_to_check.push(next_folder.clone());
|
|
|
|
} else {
|
|
|
|
error_happened = true;
|
2020-11-01 02:23:31 +13:00
|
|
|
}
|
|
|
|
}
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
if !error_happened {
|
2021-03-12 02:31:59 +13:00
|
|
|
if !use_trash {
|
|
|
|
match fs::remove_dir_all(format!("{}/{}", path, name)) {
|
|
|
|
Ok(_) => {
|
2021-07-16 16:51:54 +12:00
|
|
|
model.remove(&iter);
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(_inspected) => error_happened = true,
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
match trash::delete(format!("{}/{}", path, name)) {
|
|
|
|
Ok(_) => {
|
2021-07-16 16:51:54 +12:00
|
|
|
model.remove(&iter);
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(_inspected) => error_happened = true,
|
2020-11-01 02:23:31 +13:00
|
|
|
}
|
|
|
|
}
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
|
|
|
if error_happened {
|
|
|
|
messages += format!("Failed to remove folder {}/{} because folder doesn't exists, you don't have permissions or isn't empty.\n", path, name).as_str()
|
|
|
|
}
|
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-06-26 04:07:13 +12:00
|
|
|
text_view_errors.buffer().unwrap().set_text(messages.as_str());
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
pub fn basic_remove(tree_view: >k::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, check_button_settings_use_trash: &CheckButton, text_view_errors: &TextView) {
|
|
|
|
let use_trash = check_button_settings_use_trash.is_active();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-07-30 17:16:35 +12:00
|
|
|
let model = get_list_store(tree_view);
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
let mut messages: String = "".to_string();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
let mut selected_rows = Vec::new();
|
2021-07-16 16:51:54 +12:00
|
|
|
|
|
|
|
if let Some(iter) = model.iter_first() {
|
|
|
|
loop {
|
|
|
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
2021-11-25 20:36:49 +13:00
|
|
|
selected_rows.push(model.path(&iter).unwrap());
|
2021-07-16 16:51:54 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
if !model.iter_next(&iter) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
if selected_rows.is_empty() {
|
|
|
|
return; // No selected rows
|
|
|
|
}
|
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
|
2021-11-25 20:36:49 +13:00
|
|
|
for tree_path in selected_rows.iter().rev() {
|
2021-07-16 16:51:54 +12:00
|
|
|
let iter = model.iter(tree_path).unwrap();
|
|
|
|
|
|
|
|
let name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
|
|
|
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-03-12 02:31:59 +13:00
|
|
|
if !use_trash {
|
|
|
|
match fs::remove_file(format!("{}/{}", path, name)) {
|
|
|
|
Ok(_) => {
|
2021-07-16 16:51:54 +12:00
|
|
|
model.remove(&iter);
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(e) => messages += format!("Failed to remove file {}/{}, reason {}\n", path, name, e).as_str(),
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
match trash::delete(format!("{}/{}", path, name)) {
|
|
|
|
Ok(_) => {
|
2021-07-16 16:51:54 +12:00
|
|
|
model.remove(&iter);
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
2021-11-15 03:53:55 +13:00
|
|
|
Err(e) => messages += format!("Failed to remove file {}/{}, reason {}\n", path, name, e).as_str(),
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-06-26 04:07:13 +12:00
|
|
|
text_view_errors.buffer().unwrap().set_text(messages.as_str());
|
2020-11-09 22:09:22 +13:00
|
|
|
}
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2020-11-09 22:09:22 +13:00
|
|
|
// Remove all occurrences - remove every element which have same path and name as even non selected ones
|
2021-11-25 20:36:49 +13:00
|
|
|
pub fn tree_remove(tree_view: >k::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, check_button_settings_use_trash: &CheckButton, text_view_errors: &TextView) {
|
|
|
|
let use_trash = check_button_settings_use_trash.is_active();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-07-30 17:16:35 +12:00
|
|
|
let model = get_list_store(tree_view);
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
let mut messages: String = "".to_string();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
let mut vec_path_to_delete: Vec<(String, String)> = Vec::new();
|
|
|
|
let mut map_with_path_to_delete: BTreeMap<String, Vec<String>> = Default::default(); // BTreeMap<Path,Vec<FileName>>
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
let mut selected_rows = Vec::new();
|
2021-07-16 16:51:54 +12:00
|
|
|
|
|
|
|
if let Some(iter) = model.iter_first() {
|
|
|
|
loop {
|
|
|
|
if model.value(&iter, column_selection).get::<bool>().unwrap() {
|
|
|
|
if model.value(&iter, column_color).get::<String>().unwrap() == MAIN_ROW_COLOR {
|
2021-11-25 20:36:49 +13:00
|
|
|
selected_rows.push(model.path(&iter).unwrap());
|
2021-11-22 18:48:07 +13:00
|
|
|
} else {
|
2021-11-25 20:36:49 +13:00
|
|
|
panic!("Header row shouldn't be selected, please report bug.");
|
2021-07-16 16:51:54 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !model.iter_next(&iter) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
if selected_rows.is_empty() {
|
|
|
|
return; // No selected rows
|
|
|
|
}
|
|
|
|
|
2020-11-09 22:09:22 +13:00
|
|
|
// Save to variable paths of files, and remove it when not removing all occurrences.
|
2021-11-25 20:36:49 +13:00
|
|
|
for tree_path in selected_rows.iter().rev() {
|
2021-07-16 16:51:54 +12:00
|
|
|
let iter = model.iter(tree_path).unwrap();
|
|
|
|
|
|
|
|
let file_name = model.value(&iter, column_file_name).get::<String>().unwrap();
|
|
|
|
let path = model.value(&iter, column_path).get::<String>().unwrap();
|
2020-11-01 02:23:31 +13:00
|
|
|
|
2021-07-16 16:51:54 +12:00
|
|
|
model.remove(&iter);
|
2020-11-09 23:24:01 +13:00
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
map_with_path_to_delete.entry(path.clone()).or_insert_with(Vec::new);
|
|
|
|
map_with_path_to_delete.get_mut(path.as_str()).unwrap().push(file_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete duplicated entries, and remove real files
|
|
|
|
for (path, mut vec_file_name) in map_with_path_to_delete {
|
|
|
|
vec_file_name.sort();
|
|
|
|
vec_file_name.dedup();
|
|
|
|
for file_name in vec_file_name {
|
2021-03-12 02:31:59 +13:00
|
|
|
if !use_trash {
|
2021-11-15 03:53:55 +13:00
|
|
|
if let Err(e) = fs::remove_file(format!("{}/{}", path.clone(), file_name.clone())) {
|
|
|
|
messages += format!("Failed to remove file {}/{}, reason {}\n", path, file_name, e).as_str()
|
2021-03-12 02:31:59 +13:00
|
|
|
}
|
2021-11-15 03:53:55 +13:00
|
|
|
} else if let Err(e) = trash::delete(format!("{}/{}", path.clone(), file_name.clone())) {
|
|
|
|
messages += format!("Failed to remove file {}/{}, reason {}\n", path, file_name, e).as_str()
|
2020-11-05 06:15:06 +13:00
|
|
|
}
|
2021-03-12 02:31:59 +13:00
|
|
|
|
2020-11-05 06:15:06 +13:00
|
|
|
vec_path_to_delete.push((path.clone(), file_name.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:36:49 +13:00
|
|
|
clean_invalid_headers(&model, column_color);
|
2020-11-05 06:15:06 +13:00
|
|
|
|
2021-06-26 04:07:13 +12:00
|
|
|
text_view_errors.buffer().unwrap().set_text(messages.as_str());
|
2020-11-01 02:23:31 +13:00
|
|
|
}
|