@@ -687,6 +687,61 @@ impl CtermWindow {
687687 window. add_action ( & action) ;
688688 }
689689
690+ // Tools menu actions
691+ {
692+ let notebook = notebook. clone ( ) ;
693+ let tabs = Rc :: clone ( & tabs) ;
694+ let window_clone = window. clone ( ) ;
695+ let action = gio:: SimpleAction :: new (
696+ "run-tool-shortcut" ,
697+ Some ( & glib:: VariantType :: new ( "s" ) . unwrap ( ) ) ,
698+ ) ;
699+ action. connect_activate ( move |_, param| {
700+ if let Some ( idx_str) = param. and_then ( |p| p. get :: < String > ( ) ) {
701+ if let Ok ( idx) = idx_str. parse :: < usize > ( ) {
702+ if let Ok ( shortcuts) = cterm_app:: config:: load_tool_shortcuts ( ) {
703+ if let Some ( shortcut) = shortcuts. get ( idx) {
704+ // Get CWD from active terminal
705+ #[ cfg( unix) ]
706+ let cwd = {
707+ let tabs_borrow = tabs. borrow ( ) ;
708+ if let Some ( page_idx) = notebook. current_page ( ) {
709+ tabs_borrow
710+ . get ( page_idx as usize )
711+ . and_then ( |entry| entry. terminal . foreground_cwd ( ) )
712+ } else {
713+ None
714+ }
715+ } ;
716+ #[ cfg( not( unix) ) ]
717+ let cwd: Option < String > = None ;
718+
719+ let cwd = cwd. unwrap_or_else ( || {
720+ std:: env:: var ( "HOME" ) . unwrap_or_else ( |_| "/" . to_string ( ) )
721+ } ) ;
722+
723+ if let Err ( e) = shortcut. execute ( std:: path:: Path :: new ( & cwd) ) {
724+ let dialog = gtk4:: MessageDialog :: new (
725+ Some ( & window_clone) ,
726+ gtk4:: DialogFlags :: MODAL ,
727+ gtk4:: MessageType :: Error ,
728+ gtk4:: ButtonsType :: Ok ,
729+ format ! (
730+ "Failed to launch \" {}\" \n \n Command '{}' failed: {}" ,
731+ shortcut. name, shortcut. command, e
732+ ) ,
733+ ) ;
734+ dialog. connect_response ( |d, _| d. close ( ) ) ;
735+ dialog. present ( ) ;
736+ }
737+ }
738+ }
739+ }
740+ }
741+ } ) ;
742+ window. add_action ( & action) ;
743+ }
744+
690745 // Help menu actions
691746 {
692747 let window_clone = window. clone ( ) ;
@@ -1634,6 +1689,49 @@ impl CtermWindow {
16341689 cwd,
16351690 ) ;
16361691 } ) ;
1692+
1693+ // Rename tab (right-click context menu)
1694+ {
1695+ let tabs = Rc :: clone ( & self . tabs ) ;
1696+ let tab_bar = self . tab_bar . clone ( ) ;
1697+ let window = self . window . clone ( ) ;
1698+ self . tab_bar . set_on_rename ( move |tab_id| {
1699+ let current_title = {
1700+ let tabs = tabs. borrow ( ) ;
1701+ tabs. iter ( )
1702+ . find ( |t| t. id == tab_id)
1703+ . map ( |t| t. title . clone ( ) )
1704+ . unwrap_or_default ( )
1705+ } ;
1706+ let tabs_clone = Rc :: clone ( & tabs) ;
1707+ let tab_bar_clone = tab_bar. clone ( ) ;
1708+ dialogs:: show_set_title_dialog ( & window, & current_title, move |new_title| {
1709+ let mut tabs = tabs_clone. borrow_mut ( ) ;
1710+ if let Some ( tab) = tabs. iter_mut ( ) . find ( |t| t. id == tab_id) {
1711+ tab. title = new_title. clone ( ) ;
1712+ tab. title_locked = true ;
1713+ tab_bar_clone. set_title ( tab_id, & new_title) ;
1714+ }
1715+ } ) ;
1716+ } ) ;
1717+ }
1718+
1719+ // Set tab color (right-click context menu)
1720+ {
1721+ let tabs = Rc :: clone ( & self . tabs ) ;
1722+ let tab_bar = self . tab_bar . clone ( ) ;
1723+ let window = self . window . clone ( ) ;
1724+ self . tab_bar . set_on_set_color ( move |tab_id| {
1725+ let tab_bar_clone = tab_bar. clone ( ) ;
1726+ let tabs_clone = Rc :: clone ( & tabs) ;
1727+ dialogs:: show_set_color_dialog ( & window, move |color| {
1728+ let tabs = tabs_clone. borrow ( ) ;
1729+ if tabs. iter ( ) . any ( |t| t. id == tab_id) {
1730+ tab_bar_clone. set_color ( tab_id, color. as_deref ( ) ) ;
1731+ }
1732+ } ) ;
1733+ } ) ;
1734+ }
16371735 }
16381736
16391737 /// Set up close request handler to confirm when closing with running processes
0 commit comments