@ -2,7 +2,7 @@ use std::fs;
use std ::path ::PathBuf ;
use std ::path ::PathBuf ;
use gtk ::prelude ::* ;
use gtk ::prelude ::* ;
use gtk ::{ TextView, TreeIter , TreePath } ;
use gtk ::{ Align, CheckButton , Dialog , ResponseType , TextView, TreeIter , TreePath } ;
use czkawka_core ::duplicate ::make_hard_link ;
use czkawka_core ::duplicate ::make_hard_link ;
@ -11,40 +11,27 @@ use crate::help_functions::*;
use crate ::notebook_enums ::* ;
use crate ::notebook_enums ::* ;
pub fn connect_button_hardlink_symlink ( gui_data : & GuiData ) {
pub fn connect_button_hardlink_symlink ( gui_data : & GuiData ) {
{
let buttons_hardlink = gui_data . bottom_buttons . buttons_hardlink . clone ( ) ;
let buttons_hardlink = gui_data . bottom_buttons . buttons_hardlink . clone ( ) ;
let notebook_main = gui_data . main_notebook . notebook_main . clone ( ) ;
let gui_data = gui_data . clone ( ) ;
let main_tree_views = gui_data . main_notebook . get_main_tree_views ( ) ;
let image_preview_similar_images = gui_data . main_notebook . image_preview_similar_images . clone ( ) ;
let image_preview_duplicates = gui_data . main_notebook . image_preview_duplicates . clone ( ) ;
let text_view_errors = gui_data . text_view_errors . clone ( ) ;
let preview_path = gui_data . preview_path . clone ( ) ;
buttons_hardlink . connect_clicked ( move | _ | {
buttons_hardlink . connect_clicked ( move | _ | {
let nb_number = notebook_main . current_page ( ) . unwrap ( ) ;
glib ::MainContext ::default ( ) . spawn_local ( sym_hard_link_things ( gui_data . clone ( ) , false ) ) ;
let tree_view = & main_tree_views [ nb_number as usize ] ;
} ) ;
let nb_object = & NOTEBOOKS_INFOS [ nb_number as usize ] ;
}
{
let buttons_symlink = gui_data . bottom_buttons . buttons_symlink . clone ( ) ;
let column_color = nb_object . column_color . expect ( "Hardinkning can be only used for tree views with grouped results" ) ;
let gui_data = gui_data . clone ( ) ;
hardlink_symlink ( tree_view , nb_object . column_name , nb_object . column_path , column_color , nb_object . column_selection , true , & text_view_errors ) ;
match & nb_object . notebook_type {
buttons_symlink . connect_clicked ( move | _ | {
NotebookMainEnum ::SimilarImages | NotebookMainEnum ::Duplicate = > {
glib ::MainContext ::default ( ) . spawn_local ( sym_hard_link_things ( gui_data . clone ( ) , false ) ) ;
if nb_object . notebook_type = = NotebookMainEnum ::SimilarImages {
image_preview_similar_images . hide ( ) ;
} else {
image_preview_duplicates . hide ( ) ;
}
* preview_path . borrow_mut ( ) = "" . to_string ( ) ;
}
_ = > { }
}
} ) ;
} ) ;
}
}
let buttons_symlink = gui_data . bottom_buttons . buttons_symlink . clone ( ) ;
pub async fn sym_hard_link_things ( gui_data : GuiData , hardlinking : bool ) {
let notebook_main = gui_data . main_notebook . notebook_main . clone ( ) ;
let notebook_main = gui_data . main_notebook . notebook_main . clone ( ) ;
let main_tree_views = gui_data . main_notebook . get_main_tree_views ( ) ;
let main_tree_views = gui_data . main_notebook . get_main_tree_views ( ) ;
@ -52,16 +39,29 @@ pub fn connect_button_hardlink_symlink(gui_data: &GuiData) {
let image_preview_duplicates = gui_data . main_notebook . image_preview_duplicates . clone ( ) ;
let image_preview_duplicates = gui_data . main_notebook . image_preview_duplicates . clone ( ) ;
let text_view_errors = gui_data . text_view_errors . clone ( ) ;
let text_view_errors = gui_data . text_view_errors . clone ( ) ;
let preview_path = gui_data . preview_path . clone ( ) ;
let preview_path = gui_data . preview_path . clone ( ) ;
let window_main = gui_data . window_main . clone ( ) ;
buttons_symlink . connect_clicked ( move | _ | {
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 column_color = nb_object . column_color . expect ( "Symlinking can be only used for tree views with grouped results" ) ;
let column_color = nb_object . column_color . expect ( "Symlinking can be only used for tree views with grouped results" ) ;
hardlink_symlink ( tree_view , nb_object . column_name , nb_object . column_path , column_color , nb_object . column_selection , false , & text_view_errors ) ;
let check_button_settings_confirm_link = gui_data . settings . check_button_settings_confirm_link . clone ( ) ;
if ! check_if_anything_is_selected_async ( tree_view , column_color , nb_object . column_selection ) . await {
return ;
}
if ! check_if_can_link_files ( & check_button_settings_confirm_link , & window_main ) . await {
return ;
}
if ! check_if_changing_one_item_in_group_and_continue ( tree_view , column_color , nb_object . column_selection , & window_main ) . await {
return ;
}
hardlink_symlink ( tree_view , nb_object . column_name , nb_object . column_path , column_color , nb_object . column_selection , hardlinking , & text_view_errors ) ;
match & nb_object . notebook_type {
match & nb_object . notebook_type {
NotebookMainEnum ::SimilarImages | NotebookMainEnum ::Duplicate = > {
NotebookMainEnum ::SimilarImages | NotebookMainEnum ::Duplicate = > {
@ -74,7 +74,6 @@ pub fn connect_button_hardlink_symlink(gui_data: &GuiData) {
}
}
_ = > { }
_ = > { }
}
}
} ) ;
}
}
pub fn hardlink_symlink ( tree_view : & gtk ::TreeView , column_file_name : i32 , column_path : i32 , column_color : i32 , column_selection : i32 , hardlinking : bool , text_view_errors : & TextView ) {
pub fn hardlink_symlink ( tree_view : & gtk ::TreeView , column_file_name : i32 , column_path : i32 , column_color : i32 , column_selection : i32 , hardlinking : bool , text_view_errors : & TextView ) {
@ -213,3 +212,127 @@ pub fn hardlink_symlink(tree_view: >k::TreeView, column_file_name: i32, column
clean_invalid_headers ( & model , column_color ) ;
clean_invalid_headers ( & model , column_color ) ;
}
}
fn create_dialog_non_group ( window_main : & gtk ::Window ) -> Dialog {
let dialog = gtk ::Dialog ::builder ( ) . title ( "Invalid selection with some groups" ) . transient_for ( window_main ) . modal ( true ) . build ( ) ;
let button_ok = dialog . add_button ( "Ok" , ResponseType ::Ok ) ;
dialog . add_button ( "Close" , ResponseType ::Cancel ) ;
let label : gtk ::Label = gtk ::Label ::new ( Some ( "In some groups there is only 1 record selected and it will be ignored." ) ) ;
let label2 : gtk ::Label = gtk ::Label ::new ( Some ( "To be able to hard/sym link this files, at least 2 results in group needs to be selected." ) ) ;
let label3 : gtk ::Label = gtk ::Label ::new ( Some ( "First in group is recognized as original and is not changed but second and later are modified." ) ) ;
button_ok . grab_focus ( ) ;
let internal_box = get_dialog_box_child ( & dialog ) ;
internal_box . add ( & label ) ;
internal_box . add ( & label2 ) ;
internal_box . add ( & label3 ) ;
dialog . show_all ( ) ;
dialog
}
pub async fn check_if_changing_one_item_in_group_and_continue ( tree_view : & gtk ::TreeView , column_color : i32 , column_selection : i32 , window_main : & gtk ::Window ) -> bool {
let model = get_list_store ( tree_view ) ;
let mut selected_values_in_group = 0 ;
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
loop {
if ! model . iter_next ( & iter ) {
break ;
}
if model . value ( & iter , column_color ) . get ::< String > ( ) . unwrap ( ) = = HEADER_ROW_COLOR {
if selected_values_in_group = = 1 {
break ;
}
selected_values_in_group = 0 ;
} else {
if model . value ( & iter , column_selection ) . get ::< bool > ( ) . unwrap ( ) {
selected_values_in_group + = 1 ;
}
}
}
} else {
return false ; // No available records
}
if selected_values_in_group = = 1 {
let confirmation_dialog = create_dialog_non_group ( window_main ) ;
let response_type = confirmation_dialog . run_future ( ) . await ;
if response_type ! = gtk ::ResponseType ::Ok {
confirmation_dialog . hide ( ) ;
confirmation_dialog . close ( ) ;
return false ;
}
confirmation_dialog . hide ( ) ;
confirmation_dialog . close ( ) ;
}
true
}
pub async fn check_if_anything_is_selected_async ( tree_view : & gtk ::TreeView , column_color : i32 , column_selection : i32 ) -> bool {
let model = get_list_store ( tree_view ) ;
if let Some ( iter ) = model . iter_first ( ) {
assert_eq! ( model . value ( & iter , column_color ) . get ::< String > ( ) . unwrap ( ) , HEADER_ROW_COLOR ) ; // First element should be header
loop {
if ! model . iter_next ( & iter ) {
break ;
}
if model . value ( & iter , column_color ) . get ::< String > ( ) . unwrap ( ) = = MAIN_ROW_COLOR & & model . value ( & iter , column_selection ) . get ::< bool > ( ) . unwrap ( ) {
return true ;
}
}
}
false
}
pub async fn check_if_can_link_files ( check_button_settings_confirm_link : & gtk ::CheckButton , window_main : & gtk ::Window ) -> bool {
if check_button_settings_confirm_link . is_active ( ) {
let ( confirmation_dialog_link , check_button ) = create_dialog_ask_for_linking ( window_main ) ;
let response_type = confirmation_dialog_link . run_future ( ) . await ;
if response_type = = gtk ::ResponseType ::Ok {
if ! check_button . is_active ( ) {
check_button_settings_confirm_link . set_active ( false ) ;
}
confirmation_dialog_link . hide ( ) ;
confirmation_dialog_link . close ( ) ;
} else {
confirmation_dialog_link . hide ( ) ;
confirmation_dialog_link . close ( ) ;
return false ;
} ;
}
true
}
fn create_dialog_ask_for_linking ( window_main : & gtk ::Window ) -> ( Dialog , CheckButton ) {
let dialog = gtk ::Dialog ::builder ( ) . title ( "Link confirmation" ) . transient_for ( window_main ) . modal ( true ) . build ( ) ;
let button_ok = dialog . add_button ( "Ok" , ResponseType ::Ok ) ;
dialog . add_button ( "Close" , ResponseType ::Cancel ) ;
let label : gtk ::Label = gtk ::Label ::new ( Some ( "Are you sure that you want to link this 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 ( ) ;
let internal_box = get_dialog_box_child ( & dialog ) ;
internal_box . add ( & label ) ;
internal_box . add ( & check_button ) ;
dialog . show_all ( ) ;
( dialog , check_button )
}