1- use crate :: state:: FmState ;
21use crate :: files_panel;
2+ use crate :: state:: FmState ;
33use gtk4:: {
44 Box as GtkBox , Label , ListView , Popover , SignalListItemFactory , SingleSelection , StringList ,
55 gio, glib, prelude:: * ,
66} ;
7+ use std:: path:: PathBuf ;
78use std:: { cell:: RefCell , env, path:: Path , process:: Command , rc:: Rc } ;
89
910struct MenuItem < ' a > {
@@ -13,7 +14,7 @@ struct MenuItem<'a> {
1314 show_if_dir : bool ,
1415}
1516
16- pub fn get_empty_right_click ( content_area : & GtkBox , fmstate : Rc < RefCell < FmState > > ) -> Popover {
17+ pub fn get_empty_right_click ( content_area : & GtkBox , fmstate : Rc < RefCell < FmState > > , files_list : & gtk4 :: StringList ) -> Popover {
1718 let popover = Popover :: new ( ) ;
1819 popover. set_parent ( content_area) ;
1920
@@ -24,6 +25,12 @@ pub fn get_empty_right_click(content_area: &GtkBox, fmstate: Rc<RefCell<FmState>
2425 show_if_file: true ,
2526 show_if_dir: true ,
2627 } ) ,
28+ Rc :: new( MenuItem {
29+ label: "Paste" ,
30+ icon_name: "edit-paste-symbolic" ,
31+ show_if_file: true ,
32+ show_if_dir: true ,
33+ } ) ,
2734 Rc :: new( MenuItem {
2835 label: "Open Terminal Here" ,
2936 icon_name: "utilities-terminal-symbolic" ,
@@ -75,6 +82,8 @@ pub fn get_empty_right_click(content_area: &GtkBox, fmstate: Rc<RefCell<FmState>
7582 selection_model. connect_selected_notify ( glib:: clone!(
7683 #[ weak]
7784 popover,
85+ #[ weak]
86+ files_list,
7887 #[ strong]
7988 fmstate,
8089 move |sel| {
@@ -84,6 +93,9 @@ pub fn get_empty_right_click(content_area: &GtkBox, fmstate: Rc<RefCell<FmState>
8493
8594 match text. as_str( ) {
8695 "New Folder" => println!( "New Folder clicked" ) ,
96+ "Paste" => {
97+ paste_function( fmstate. clone( ) , & files_list)
98+ }
8799 "Open Terminal Here" => {
88100 let terminal_cmd =
89101 env:: var( "TERMINAL" ) . unwrap_or_else( |_| "xterm" . to_string( ) ) ;
@@ -121,6 +133,7 @@ pub fn get_file_right_click(
121133 content_area : & GtkBox ,
122134 fmstate : Rc < RefCell < FmState > > ,
123135 files_list : & gtk4:: StringList ,
136+ filespanel_list_view : & gtk4:: ListView ,
124137) -> Popover {
125138 let popover = Popover :: new ( ) ;
126139 popover. set_parent ( content_area) ;
@@ -130,6 +143,8 @@ pub fn get_file_right_click(
130143 fmstate,
131144 #[ weak]
132145 files_list,
146+ #[ weak]
147+ filespanel_list_view,
133148 move |popover| {
134149 let fmstate_ref = fmstate. borrow( ) ;
135150 if let Some ( path) = & fmstate_ref. popup_focused_file {
@@ -231,6 +246,8 @@ pub fn get_file_right_click(
231246 #[ weak]
232247 files_list,
233248 #[ weak]
249+ filespanel_list_view,
250+ #[ weak]
234251 popover,
235252 move |sel| {
236253 if let Some ( item) = sel. selected_item( ) {
@@ -246,9 +263,27 @@ pub fn get_file_right_click(
246263 }
247264 }
248265 }
249- "Cut" => { }
250- "Copy" => { }
251- "Paste" => { }
266+ "Cut" => {
267+ let mut fmstate_mut = fmstate. borrow_mut( ) ;
268+ if let Some ( path_str) = & fmstate_mut. popup_focused_file {
269+ let path = PathBuf :: from( path_str) ;
270+ fmstate_mut. clipboard. clear( ) ;
271+ fmstate_mut. clipboard. push( path) ;
272+ fmstate_mut. clipboard_is_cut = true ;
273+ }
274+ }
275+ "Copy" => {
276+ let mut fmstate_mut = fmstate. borrow_mut( ) ;
277+ if let Some ( path_str) = & fmstate_mut. popup_focused_file {
278+ let path = PathBuf :: from( path_str) ;
279+ fmstate_mut. clipboard. clear( ) ;
280+ fmstate_mut. clipboard. push( path) ;
281+ fmstate_mut. clipboard_is_cut = false ;
282+ }
283+ }
284+ "Paste" => {
285+ paste_function( fmstate. clone( ) , & files_list)
286+ }
252287 "Open in Terminal" => {
253288 let terminal_cmd = env:: var( "TERMINAL" )
254289 . unwrap_or_else( |_| "xterm" . to_string( ) ) ;
@@ -298,7 +333,7 @@ pub fn get_file_right_click(
298333 & file,
299334 & files_list,
300335 & current_path,
301- show_hidden
336+ show_hidden,
302337 ) ;
303338 }
304339 }
@@ -326,7 +361,7 @@ fn rename_file_dialog(
326361 file_path : & gio:: File ,
327362 files_list : & gtk4:: StringList ,
328363 current_path : & gio:: File ,
329- show_hidden : bool
364+ show_hidden : bool ,
330365) {
331366 let file_name: String = file_path
332367 . basename ( )
@@ -381,3 +416,57 @@ fn rename_file_dialog(
381416
382417 dialog. show ( ) ;
383418}
419+
420+ fn get_selected_index ( list_view : & gtk4:: ListView ) -> Option < u32 > {
421+ list_view
422+ . model ( )
423+ . and_then ( |m| m. downcast :: < gtk4:: SingleSelection > ( ) . ok ( ) )
424+ . and_then ( |sel| Some ( sel. selected ( ) ) )
425+ }
426+
427+ fn paste_function ( fmstate : Rc < RefCell < FmState > > , files_list : & gtk4:: StringList ) {
428+ let mut state = fmstate. borrow_mut ( ) ;
429+ for src_path in & state. clipboard {
430+ let src_file = gio:: File :: for_path ( src_path) ;
431+ let dest_file = state
432+ . current_path
433+ . child ( src_path. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ) ;
434+
435+ let flags = gio:: FileCopyFlags :: OVERWRITE ;
436+
437+ let result = if state. clipboard_is_cut {
438+ src_file. move_ (
439+ & dest_file,
440+ flags,
441+ None :: < & gio:: Cancellable > ,
442+ None ,
443+ )
444+ } else {
445+ src_file. copy (
446+ & dest_file,
447+ flags,
448+ None :: < & gio:: Cancellable > ,
449+ None ,
450+ )
451+ } ;
452+
453+ if let Err ( e) = result {
454+ eprintln ! (
455+ "Failed to paste {}: {}" ,
456+ src_path. display( ) ,
457+ e
458+ ) ;
459+ }
460+ }
461+
462+ if state. clipboard_is_cut {
463+ state. clipboard . clear ( ) ;
464+ state. clipboard_is_cut = false ;
465+ }
466+
467+ files_panel:: populate_files_list (
468+ & files_list,
469+ & state. current_path ,
470+ & state. settings . show_hidden ,
471+ ) ;
472+ }
0 commit comments