diff --git a/Cargo.lock b/Cargo.lock index ef47709..49633ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -496,6 +496,7 @@ dependencies = [ "crossbeam-channel", "czkawka_core", "directories-next", + "fs_extra", "futures", "gdk", "glib", @@ -628,6 +629,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + [[package]] name = "futures" version = "0.3.17" diff --git a/README.md b/README.md index a3a1a26..acc6d4b 100644 --- a/README.md +++ b/README.md @@ -118,8 +118,8 @@ Bleachbit is a master at finding and removing temporary files, while Czkawka onl ## Other apps There are many similar applications to Czkawka on the Internet, which do some things better and some things worse. - [DupeGuru](https://github.com/arsenetar/dupeguru) - A lot of options to customize -- [FSlint](https://github.com/pixelb/fslint) - A little outdated, but have a lot of helpful tools -- [Fclones](https://github.com/pkolaczk/fclones) - One of the fastest tools to find duplicates, but only in CLI +- [FSlint](https://github.com/pixelb/fslint) - A little outdated, but still have some tools not available in Czkawka +- [Fclones](https://github.com/pkolaczk/fclones) - One of the fastest tools to find duplicates, it is written also in Rust but only in CLI ## Contributions Contributions to this repository are welcome. diff --git a/czkawka_core/src/similar_images.rs b/czkawka_core/src/similar_images.rs index 4e5eb71..b07c6ea 100644 --- a/czkawka_core/src/similar_images.rs +++ b/czkawka_core/src/similar_images.rs @@ -527,7 +527,7 @@ impl SimilarImages { let temp_max_similarity = match self.hash_size { 4 => SIMILAR_VALUES[0][5], 8 => SIMILAR_VALUES[1][5], - 16 => SIMILAR_VALUES[1][5], + 16 => SIMILAR_VALUES[2][5], _ => panic!(), }; diff --git a/czkawka_gui/Cargo.toml b/czkawka_gui/Cargo.toml index 1828fc8..92658c6 100644 --- a/czkawka_gui/Cargo.toml +++ b/czkawka_gui/Cargo.toml @@ -37,6 +37,9 @@ img_hash = "3.2.0" # Move files to trash trash = "1.3.0" +# For moving files(why std::fs doesn't have such features) +fs_extra = "1.2.0" + [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.9", features = ["combaseapi", "objbase", "shobjidl_core", "windef", "winerror", "wtypesbase", "winuser"] } diff --git a/czkawka_gui/src/connect_about_buttons.rs b/czkawka_gui/src/connect_about_buttons.rs index 6654cc5..889961e 100644 --- a/czkawka_gui/src/connect_about_buttons.rs +++ b/czkawka_gui/src/connect_about_buttons.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use gtk::prelude::*; diff --git a/czkawka_gui/src/connect_button_delete.rs b/czkawka_gui/src/connect_button_delete.rs index f322c8b..d6d3d27 100644 --- a/czkawka_gui/src/connect_button_delete.rs +++ b/czkawka_gui/src/connect_button_delete.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; diff --git a/czkawka_gui/src/connect_button_hardlink.rs b/czkawka_gui/src/connect_button_hardlink.rs index 4e40291..96a69c6 100644 --- a/czkawka_gui/src/connect_button_hardlink.rs +++ b/czkawka_gui/src/connect_button_hardlink.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; diff --git a/czkawka_gui/src/connect_button_move.rs b/czkawka_gui/src/connect_button_move.rs new file mode 100644 index 0000000..43309fe --- /dev/null +++ b/czkawka_gui/src/connect_button_move.rs @@ -0,0 +1,338 @@ +use crate::gui_data::GuiData; +use crate::help_functions::*; +use crate::notebook_enums::*; +use gtk::prelude::*; +use std::path::{Path, PathBuf}; + +pub fn connect_button_move(gui_data: &GuiData) { + let gui_data = gui_data.clone(); + + let buttons_move = gui_data.bottom_buttons.buttons_move.clone(); + let notebook_main = gui_data.main_notebook.notebook_main.clone(); + + let tree_view_duplicate_finder = gui_data.main_notebook.tree_view_duplicate_finder.clone(); + let tree_view_empty_folder_finder = gui_data.main_notebook.tree_view_empty_folder_finder.clone(); + let tree_view_big_files_finder = gui_data.main_notebook.tree_view_big_files_finder.clone(); + let tree_view_empty_files_finder = gui_data.main_notebook.tree_view_empty_files_finder.clone(); + let tree_view_temporary_files_finder = gui_data.main_notebook.tree_view_temporary_files_finder.clone(); + let tree_view_similar_images_finder = gui_data.main_notebook.tree_view_similar_images_finder.clone(); + let tree_view_zeroed_files_finder = gui_data.main_notebook.tree_view_zeroed_files_finder.clone(); + let tree_view_same_music_finder = gui_data.main_notebook.tree_view_same_music_finder.clone(); + let tree_view_invalid_symlinks = gui_data.main_notebook.tree_view_invalid_symlinks.clone(); + let tree_view_broken_files = gui_data.main_notebook.tree_view_broken_files.clone(); + + let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone(); + + buttons_move.connect_clicked(move |_| match to_notebook_main_enum(notebook_main.current_page().unwrap()) { + NotebookMainEnum::Duplicate => { + move_things( + tree_view_duplicate_finder.clone(), + ColumnsDuplicates::Name as i32, + ColumnsDuplicates::Path as i32, + Some(ColumnsDuplicates::Color as i32), + ColumnsDuplicates::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::SameMusic => { + move_things( + tree_view_same_music_finder.clone(), + ColumnsSameMusic::Name as i32, + ColumnsSameMusic::Path as i32, + Some(ColumnsDuplicates::Color as i32), + ColumnsSameMusic::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::SimilarImages => { + move_things( + tree_view_similar_images_finder.clone(), + ColumnsSimilarImages::Name as i32, + ColumnsSimilarImages::Path as i32, + Some(ColumnsDuplicates::Color as i32), + ColumnsSimilarImages::ActiveSelectButton as i32, + &gui_data, + ); + image_preview_similar_images.hide(); + } + NotebookMainEnum::BigFiles => { + move_things( + tree_view_big_files_finder.clone(), + ColumnsBigFiles::Name as i32, + ColumnsBigFiles::Path as i32, + None, + ColumnsBigFiles::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::Zeroed => { + move_things( + tree_view_zeroed_files_finder.clone(), + ColumnsZeroedFiles::Name as i32, + ColumnsZeroedFiles::Path as i32, + None, + ColumnsZeroedFiles::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::BrokenFiles => { + move_things( + tree_view_broken_files.clone(), + ColumnsBrokenFiles::Name as i32, + ColumnsBrokenFiles::Path as i32, + None, + ColumnsBrokenFiles::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::EmptyDirectories => { + move_things( + tree_view_empty_folder_finder.clone(), + ColumnsEmptyFolders::Name as i32, + ColumnsEmptyFolders::Path as i32, + None, + ColumnsEmptyFolders::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::EmptyFiles => { + move_things( + tree_view_empty_files_finder.clone(), + ColumnsEmptyFiles::Name as i32, + ColumnsEmptyFiles::Path as i32, + None, + ColumnsEmptyFiles::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::Symlinks => { + move_things( + tree_view_invalid_symlinks.clone(), + ColumnsInvalidSymlinks::Name as i32, + ColumnsInvalidSymlinks::Path as i32, + None, + ColumnsInvalidSymlinks::ActiveSelectButton as i32, + &gui_data, + ); + } + NotebookMainEnum::Temporary => { + move_things( + tree_view_temporary_files_finder.clone(), + ColumnsTemporaryFiles::Name as i32, + ColumnsTemporaryFiles::Path as i32, + None, + ColumnsTemporaryFiles::ActiveSelectButton as i32, + &gui_data, + ); + } + }); +} + +// TODO create and show folder chooser where user can select path +fn move_things(tree_view: gtk::TreeView, column_file_name: i32, column_path: i32, column_color: Option, column_selection: i32, gui_data: &GuiData) { + let text_view_errors = gui_data.text_view_errors.clone(); + let window_main = gui_data.window_main.clone(); + + reset_text_view(&text_view_errors); + + let chooser = gtk::FileChooserDialog::with_buttons( + Some("Choose folder to which you want to move duplicated files"), + Some(&window_main), + gtk::FileChooserAction::SelectFolder, + &[("Ok", gtk::ResponseType::Ok), ("Close", gtk::ResponseType::Cancel)], + ); + chooser.set_select_multiple(true); + chooser.show_all(); + let response_type = chooser.run(); + if response_type == gtk::ResponseType::Ok { + let folders = chooser.filenames(); + if folders.len() != 1 { + add_text_to_text_view(&text_view_errors, format!("Only 1 path must be selected to be able to copy there duplicated files, found {:?}", folders).as_str()); + } else { + let folder = folders[0].clone(); + if let Some(column_color) = column_color { + move_with_tree(tree_view, column_file_name, column_path, column_color, column_selection, gui_data, folder); + } else { + move_with_list(tree_view, column_file_name, column_path, column_selection, gui_data, folder); + } + } + } + chooser.close(); +} +fn move_with_tree(tree_view: gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, gui_data: &GuiData, destination_folder: PathBuf) { + let text_view_errors = gui_data.text_view_errors.clone(); + let entry_info = gui_data.entry_info.clone(); + + let model = get_list_store(&tree_view); + + let mut messages: String = "".to_string(); + + let mut selection_rows = Vec::new(); + + if let Some(iter) = model.iter_first() { + loop { + if model.value(&iter, column_selection).get::().unwrap() { + // TODO, this maybe isn't required if we will be sure that any header cannot be selected + if model.value(&iter, column_color).get::().unwrap() == MAIN_ROW_COLOR { + selection_rows.push(model.path(&iter).unwrap()); + } else { + println!("ERROR: This should not happen model.value(&iter, column_color).get::().unwrap() != MAIN_ROW_COLOR"); + } + } + + if !model.iter_next(&iter) { + break; + } + } + } + + let mut moved_files: u32 = 0; + + // Save to variable paths of files, and remove it when not removing all occurrences. + 'next_result: for tree_path in selection_rows.iter().rev() { + let iter = model.iter(tree_path).unwrap(); + + let file_name = model.value(&iter, column_file_name).get::().unwrap(); + let path = model.value(&iter, column_path).get::().unwrap(); + + let thing = format!("{}/{}", path, file_name); + let destination_file = destination_folder.join(file_name); + if Path::new(&thing).is_dir() { + if let Err(e) = fs_extra::dir::move_dir(&thing, &destination_file, &fs_extra::dir::CopyOptions::new()) { + messages += format!("Failed to move folder, reason {}\n", e).as_str(); + continue 'next_result; + } + } else { + if let Err(e) = fs_extra::file::move_file(&thing, &destination_file, &fs_extra::file::CopyOptions::new()) { + messages += format!("Failed to move file, reason {}\n", e).as_str(); + continue 'next_result; + } + } + model.remove(&iter); + moved_files += 1; + } + entry_info.set_text(format!("Properly moved {}/{} files/folders", moved_files, selection_rows.len()).as_str()); + + // TODO move this to different function, this is used in different places + // Remove only child from header + if let Some(first_iter) = model.iter_first() { + let mut vec_tree_path_to_delete: Vec = Vec::new(); + let mut current_iter = first_iter; + if model.value(¤t_iter, column_color).get::().unwrap() != HEADER_ROW_COLOR { + panic!("First deleted element, should be a header"); // First element should be header + }; + + let mut next_iter; + let mut next_next_iter; + 'main: loop { + if model.value(¤t_iter, column_color).get::().unwrap() != HEADER_ROW_COLOR { + panic!("First deleted element, should be a header"); // First element should be header + }; + + next_iter = current_iter.clone(); + if !model.iter_next(&next_iter) { + // There is only single header left (H1 -> END) -> (NOTHING) + vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap()); + break 'main; + } + + if model.value(&next_iter, column_color).get::().unwrap() == HEADER_ROW_COLOR { + // There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2) + vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap()); + current_iter = next_iter.clone(); + continue 'main; + } + + next_next_iter = next_iter.clone(); + if !model.iter_next(&next_next_iter) { + // There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING) + vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap()); + vec_tree_path_to_delete.push(model.path(&next_iter).unwrap()); + break 'main; + } + + if model.value(&next_next_iter, column_color).get::().unwrap() == HEADER_ROW_COLOR { + // One child between two headers, we can remove them (H1 -> C1 -> H2) -> (H2) + vec_tree_path_to_delete.push(model.path(¤t_iter).unwrap()); + vec_tree_path_to_delete.push(model.path(&next_iter).unwrap()); + current_iter = next_next_iter.clone(); + continue 'main; + } + + loop { + // (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD) + if !model.iter_next(&next_next_iter) { + break 'main; + } + // Move to next header + if model.value(&next_next_iter, column_color).get::().unwrap() == HEADER_ROW_COLOR { + current_iter = next_next_iter.clone(); + continue 'main; + } + } + } + for tree_path in vec_tree_path_to_delete.iter().rev() { + model.remove(&model.iter(tree_path).unwrap()); + } + } + + // Last step, remove orphan header if exists + if let Some(iter) = model.iter_first() { + if !model.iter_next(&iter) { + model.clear(); + } + } + + text_view_errors.buffer().unwrap().set_text(messages.as_str()); +} +fn move_with_list(tree_view: gtk::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, gui_data: &GuiData, destination_folder: PathBuf) { + let text_view_errors = gui_data.text_view_errors.clone(); + let entry_info = gui_data.entry_info.clone(); + + let model = get_list_store(&tree_view); + + let mut messages: String = "".to_string(); + + let mut selection_rows = Vec::new(); + + if let Some(iter) = model.iter_first() { + loop { + if model.value(&iter, column_selection).get::().unwrap() { + selection_rows.push(model.path(&iter).unwrap()); + } + + if !model.iter_next(&iter) { + break; + } + } + } + + let mut moved_files: u32 = 0; + + // Save to variable paths of files, and remove it when not removing all occurrences. + 'next_result: for tree_path in selection_rows.iter().rev() { + let iter = model.iter(tree_path).unwrap(); + + let file_name = model.value(&iter, column_file_name).get::().unwrap(); + let path = model.value(&iter, column_path).get::().unwrap(); + + let thing = format!("{}/{}", path, file_name); + let destination_file = destination_folder.join(file_name); + if Path::new(&thing).is_dir() { + if let Err(e) = fs_extra::dir::move_dir(&thing, &destination_file, &fs_extra::dir::CopyOptions::new()) { + messages += format!("Failed to move folder, reason {}\n", e).as_str(); + continue 'next_result; + } + } else { + if let Err(e) = fs_extra::file::move_file(&thing, &destination_file, &fs_extra::file::CopyOptions::new()) { + messages += format!("Failed to move file, reason {}\n", e).as_str(); + continue 'next_result; + } + } + model.remove(&iter); + moved_files += 1; + } + entry_info.set_text(format!("Properly moved {}/{} files/folders", moved_files, selection_rows.len()).as_str()); + + text_view_errors.buffer().unwrap().set_text(messages.as_str()); +} diff --git a/czkawka_gui/src/connect_button_save.rs b/czkawka_gui/src/connect_button_save.rs index 18f9efb..2afc7cf 100644 --- a/czkawka_gui/src/connect_button_save.rs +++ b/czkawka_gui/src/connect_button_save.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::notebook_enums::*; use czkawka_core::common_traits::SaveResults; diff --git a/czkawka_gui/src/connect_button_search.rs b/czkawka_gui/src/connect_button_search.rs index 802ce91..4bdb4c1 100644 --- a/czkawka_gui/src/connect_button_search.rs +++ b/czkawka_gui/src/connect_button_search.rs @@ -1,6 +1,5 @@ use czkawka_core::*; -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; diff --git a/czkawka_gui/src/connect_button_select.rs b/czkawka_gui/src/connect_button_select.rs index 3a0b27d..aac2809 100644 --- a/czkawka_gui/src/connect_button_select.rs +++ b/czkawka_gui/src/connect_button_select.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::notebook_enums::*; use gtk::prelude::*; diff --git a/czkawka_gui/src/connect_button_stop.rs b/czkawka_gui/src/connect_button_stop.rs index 98338a7..b4eea96 100644 --- a/czkawka_gui/src/connect_button_stop.rs +++ b/czkawka_gui/src/connect_button_stop.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use gtk::prelude::*; diff --git a/czkawka_gui/src/connect_button_symlink.rs b/czkawka_gui/src/connect_button_symlink.rs index 79fb2f6..8fbb675 100644 --- a/czkawka_gui/src/connect_button_symlink.rs +++ b/czkawka_gui/src/connect_button_symlink.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::connect_button_hardlink::hardlink_symlink; use crate::gui_data::GuiData; use crate::help_functions::*; diff --git a/czkawka_gui/src/connect_compute_results.rs b/czkawka_gui/src/connect_compute_results.rs index af42a5d..588a465 100644 --- a/czkawka_gui/src/connect_compute_results.rs +++ b/czkawka_gui/src/connect_compute_results.rs @@ -1,6 +1,5 @@ use humansize::{file_size_opts as options, FileSize}; -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; @@ -272,12 +271,14 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("select").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("symlink").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("hardlink").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("select").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("symlink").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("hardlink").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap(), &buttons_array, &buttons_names); } @@ -322,10 +323,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap(), &buttons_array, &buttons_names); } @@ -371,10 +374,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap(), &buttons_array, &buttons_names); } @@ -426,10 +431,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap(), &buttons_array, &buttons_names); } @@ -475,10 +482,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap(), &buttons_array, &buttons_names); } @@ -565,12 +574,14 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("select").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("symlink").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("hardlink").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("select").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("symlink").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("hardlink").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap(), &buttons_array, &buttons_names); } @@ -623,10 +634,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap(), &buttons_array, &buttons_names); } @@ -755,12 +768,14 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("select").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("symlink").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("hardlink").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("select").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("symlink").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("hardlink").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(), &buttons_array, &buttons_names); } @@ -814,10 +829,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap(), &buttons_array, &buttons_names); } @@ -869,10 +886,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver< *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("save").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("delete").unwrap() = true; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("select").unwrap() = true; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("move").unwrap() = true; } else { *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("save").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("delete").unwrap() = false; *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("select").unwrap() = false; + *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap().get_mut("move").unwrap() = false; } set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap(), &buttons_array, &buttons_names); } diff --git a/czkawka_gui/src/connect_header_buttons.rs b/czkawka_gui/src/connect_header_buttons.rs index f5d0c6e..6468663 100644 --- a/czkawka_gui/src/connect_header_buttons.rs +++ b/czkawka_gui/src/connect_header_buttons.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use gtk::prelude::*; use gtk::{ResponseType, WindowPosition}; diff --git a/czkawka_gui/src/connect_hide_text_view_errors.rs b/czkawka_gui/src/connect_hide_text_view_errors.rs index 08311c1..1584ce6 100644 --- a/czkawka_gui/src/connect_hide_text_view_errors.rs +++ b/czkawka_gui/src/connect_hide_text_view_errors.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use gtk::prelude::*; diff --git a/czkawka_gui/src/connect_notebook_tabs.rs b/czkawka_gui/src/connect_notebook_tabs.rs index 953343b..e73dbc9 100644 --- a/czkawka_gui/src/connect_notebook_tabs.rs +++ b/czkawka_gui/src/connect_notebook_tabs.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; diff --git a/czkawka_gui/src/connect_popovers.rs b/czkawka_gui/src/connect_popovers.rs index 3750b29..9e58a25 100644 --- a/czkawka_gui/src/connect_popovers.rs +++ b/czkawka_gui/src/connect_popovers.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::*; use crate::notebook_enums::*; diff --git a/czkawka_gui/src/connect_selection_of_directories.rs b/czkawka_gui/src/connect_selection_of_directories.rs index 64eb4de..a83fcf6 100644 --- a/czkawka_gui/src/connect_selection_of_directories.rs +++ b/czkawka_gui/src/connect_selection_of_directories.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::help_functions::get_list_store; use gtk::prelude::*; diff --git a/czkawka_gui/src/connect_settings.rs b/czkawka_gui/src/connect_settings.rs index f8bf67f..613c812 100644 --- a/czkawka_gui/src/connect_settings.rs +++ b/czkawka_gui/src/connect_settings.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use crate::saving_loading::{load_configuration, reset_configuration, save_configuration}; use gtk::prelude::*; diff --git a/czkawka_gui/src/connect_similar_image_size_change.rs b/czkawka_gui/src/connect_similar_image_size_change.rs index 529399f..5e41643 100644 --- a/czkawka_gui/src/connect_similar_image_size_change.rs +++ b/czkawka_gui/src/connect_similar_image_size_change.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_data::GuiData; use czkawka_core::similar_images::SIMILAR_VALUES; use gtk::prelude::*; diff --git a/czkawka_gui/src/gui_bottom_buttons.rs b/czkawka_gui/src/gui_bottom_buttons.rs index 5e5eb1e..8c60a55 100644 --- a/czkawka_gui/src/gui_bottom_buttons.rs +++ b/czkawka_gui/src/gui_bottom_buttons.rs @@ -9,9 +9,10 @@ pub struct GuiBottomButtons { pub buttons_save: gtk::Button, pub buttons_symlink: gtk::Button, pub buttons_hardlink: gtk::Button, + pub buttons_move: gtk::Button, pub buttons_show_errors: gtk::Button, - pub buttons_names: [String; 6], - pub buttons_array: [Button; 6], + pub buttons_names: [String; 7], + pub buttons_array: [Button; 7], } impl GuiBottomButtons { @@ -22,11 +23,28 @@ impl GuiBottomButtons { let buttons_save: gtk::Button = builder.object("buttons_save").unwrap(); 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_show_errors: gtk::Button = builder.object("buttons_show_errors").unwrap(); - let buttons_names = ["search".to_string(), "select".to_string(), "delete".to_string(), "save".to_string(), "symlink".to_string(), "hardlink".to_string()]; - let buttons_array = [buttons_search.clone(), buttons_select.clone(), buttons_delete.clone(), buttons_save.clone(), buttons_symlink.clone(), buttons_hardlink.clone()]; + let buttons_names = [ + "search".to_string(), + "select".to_string(), + "delete".to_string(), + "save".to_string(), + "symlink".to_string(), + "hardlink".to_string(), + "move".to_string(), + ]; + let buttons_array = [ + buttons_search.clone(), + buttons_select.clone(), + buttons_delete.clone(), + buttons_save.clone(), + buttons_symlink.clone(), + buttons_hardlink.clone(), + buttons_move.clone(), + ]; Self { buttons_search, buttons_select, @@ -34,6 +52,7 @@ impl GuiBottomButtons { buttons_save, buttons_symlink, buttons_hardlink, + buttons_move, buttons_show_errors, buttons_names, buttons_array, diff --git a/czkawka_gui/src/gui_data.rs b/czkawka_gui/src/gui_data.rs index 0dde280..66741dd 100644 --- a/czkawka_gui/src/gui_data.rs +++ b/czkawka_gui/src/gui_data.rs @@ -1,4 +1,3 @@ -extern crate gtk; use crate::gui_about::GuiAbout; use crate::gui_bottom_buttons::GuiBottomButtons; use crate::gui_header::GuiHeader; diff --git a/czkawka_gui/src/main.rs b/czkawka_gui/src/main.rs index 18c95c2..b882a88 100644 --- a/czkawka_gui/src/main.rs +++ b/czkawka_gui/src/main.rs @@ -5,6 +5,7 @@ mod connect_about_buttons; mod connect_button_delete; mod connect_button_hardlink; +mod connect_button_move; mod connect_button_save; mod connect_button_search; mod connect_button_select; @@ -42,10 +43,10 @@ mod taskbar_progress_win; use czkawka_core::*; -extern crate gtk; use crate::connect_about_buttons::*; use crate::connect_button_delete::*; use crate::connect_button_hardlink::*; +use crate::connect_button_move::*; use crate::connect_button_save::*; use crate::connect_button_search::*; use crate::connect_button_select::*; @@ -128,6 +129,7 @@ fn main() { connect_button_stop(&gui_data); connect_button_symlink(&gui_data); connect_button_hardlink(&gui_data); + connect_button_move(&gui_data); connect_notebook_tabs(&gui_data); connect_selection_of_directories(&gui_data); connect_popovers(&gui_data); diff --git a/czkawka_gui/ui/main_window.glade b/czkawka_gui/ui/main_window.glade index 908f751..814141b 100644 --- a/czkawka_gui/ui/main_window.glade +++ b/czkawka_gui/ui/main_window.glade @@ -2025,6 +2025,50 @@ Author: Rafał Mikrut 1 + + + True + True + True + + + True + False + center + 2 + + + True + False + folder + + + False + True + 0 + + + + + True + False + Move + + + False + True + 1 + + + + + + + False + True + 2 + + True @@ -2066,7 +2110,7 @@ Author: Rafał Mikrut False True - 2 + 3 @@ -2110,7 +2154,7 @@ Author: Rafał Mikrut False True - 3 + 4 @@ -2154,7 +2198,7 @@ Author: Rafał Mikrut False True - 4 + 5