1- # --- START OF FILE teatype.py ---
2-
31import wx
42import json
53import os
1614
1715class MainFrame (wx .Frame , SettingsMenuMixin ):
1816 def __init__ (self ):
19- # --- FIX: Renamed application ---
2017 super ().__init__ (None , title = "Teatype - Server Manager" , size = (600 , 400 ))
21-
2218 SettingsMenuMixin .__init__ (self )
23-
2419 self .servers = []
25-
2620 panel = wx .Panel (self )
2721 vbox = wx .BoxSizer (wx .VERTICAL )
28-
2922 self .list_ctrl = wx .ListCtrl (panel , style = wx .LC_REPORT | wx .LC_SINGLE_SEL )
3023 self .list_ctrl .InsertColumn (0 , "Name" , width = 150 )
3124 self .list_ctrl .InsertColumn (1 , "Hostname" , width = 150 )
3225 self .list_ctrl .InsertColumn (2 , "Port" , width = 60 )
3326 self .list_ctrl .InsertColumn (3 , "Username" , width = 120 )
3427 vbox .Add (self .list_ctrl , 1 , wx .EXPAND | wx .ALL , 5 )
35-
3628 hbox = wx .BoxSizer (wx .HORIZONTAL )
3729 self .connect_btn = wx .Button (panel , label = "&Connect" )
3830 self .add_btn = wx .Button (panel , label = "&Add" )
3931 self .edit_btn = wx .Button (panel , label = "&Edit" )
4032 self .remove_btn = wx .Button (panel , label = "&Remove" )
41-
4233 hbox .Add (self .connect_btn )
4334 hbox .Add (self .add_btn , flag = wx .LEFT , border = 5 )
4435 hbox .Add (self .edit_btn , flag = wx .LEFT , border = 5 )
4536 hbox .Add (self .remove_btn , flag = wx .LEFT , border = 5 )
4637 vbox .Add (hbox , 0 , wx .ALIGN_CENTER | wx .BOTTOM | wx .TOP , 5 )
47-
4838 panel .SetSizer (vbox )
49-
5039 self .Bind (wx .EVT_BUTTON , self .on_connect , self .connect_btn )
5140 self .Bind (wx .EVT_BUTTON , self .on_add , self .add_btn )
5241 self .Bind (wx .EVT_BUTTON , self .on_edit , self .edit_btn )
5342 self .Bind (wx .EVT_BUTTON , self .on_remove , self .remove_btn )
5443 self .list_ctrl .Bind (wx .EVT_LIST_ITEM_ACTIVATED , self .on_connect )
5544 self .list_ctrl .Bind (wx .EVT_LIST_ITEM_SELECTED , self .on_selection_changed )
5645 self .list_ctrl .Bind (wx .EVT_LIST_ITEM_DESELECTED , self .on_selection_changed )
57-
5846 theme .apply_dark_theme (self )
59-
6047 self .load_servers ()
6148 self .populate_list ()
6249 self .Centre ()
6350 self .Show ()
64-
65- # ... (The rest of the file is unchanged) ...
51+
52+ def update_server_last_path (self , server_name , last_path ):
53+ """Finds a server by name and updates its last_path."""
54+ for server in self .servers :
55+ if server .get ("name" ) == server_name :
56+ server ["last_path" ] = last_path
57+ self .save_servers ()
58+ break
59+
6660 def update_button_states (self ):
6761 has_selection = self .list_ctrl .GetFirstSelected () != - 1
6862 self .connect_btn .Enable (has_selection )
6963 self .remove_btn .Enable (has_selection )
7064 self .edit_btn .Enable (has_selection )
65+
7166 def on_selection_changed (self , event ):
7267 self .update_button_states ()
7368 event .Skip ()
69+
7470 def load_servers (self ):
7571 if os .path .exists (SERVERS_FILE ):
7672 try :
7773 with open (SERVERS_FILE , "r" ) as f : self .servers = json .load (f )
7874 except json .JSONDecodeError : self .servers = []
7975 else : self .servers = []
76+
8077 def save_servers (self ):
8178 with open (SERVERS_FILE , "w" ) as f : json .dump (self .servers , f , indent = 4 )
79+
8280 def populate_list (self ):
8381 self .list_ctrl .DeleteAllItems ()
8482 for i , server in enumerate (self .servers ):
@@ -87,6 +85,7 @@ def populate_list(self):
8785 self .list_ctrl .SetItem (i , 2 , str (server ["port" ]))
8886 self .list_ctrl .SetItem (i , 3 , server ["user" ])
8987 self .update_button_states ()
88+
9089 def on_add (self , event ):
9190 with AddServerDialog (self , title = "Add SSH Server" ) as dlg :
9291 if dlg .ShowModal () == wx .ID_OK :
@@ -107,6 +106,7 @@ def on_add(self, event):
107106 self .servers .append (new_server )
108107 self .save_servers ()
109108 self .populate_list ()
109+
110110 def on_edit (self , event ):
111111 selected_index = self .list_ctrl .GetFirstSelected ()
112112 if selected_index == - 1 : return
@@ -124,20 +124,26 @@ def on_edit(self, event):
124124 store_password (server_name = new_data ["name" ], host = new_data ["host" ], user = new_data ["user" ], password = new_data ["password" ])
125125 elif new_data ["auth_method" ] == "key" and new_data ["passphrase" ]:
126126 store_passphrase (server_name = new_data ["name" ], host = new_data ["host" ], user = new_data ["user" ], passphrase = new_data ["passphrase" ])
127- updated_server = {
127+
128+ updated_server = original_server .copy ()
129+ updated_server .update ({
128130 "name" : new_data ["name" ], "host" : new_data ["host" ], "port" : new_data ["port" ],
129131 "user" : new_data ["user" ], "auth_method" : new_data ["auth_method" ],
130132 "password_stored" : new_data ["store_credential" ]
131- }
133+ })
134+
132135 if new_data ["auth_method" ] == "key" :
133136 updated_server ["key_path" ] = new_data ["key_path" ]
134137 if new_data ["passphrase" ]:
135138 updated_server ["has_passphrase" ] = True
136139 else :
137- updated_server ["has_passphrase" ] = original_server .get ("has_passphrase" , False )
140+ # If the passphrase field was cleared, we must update has_passphrase
141+ updated_server ["has_passphrase" ] = False
142+
138143 self .servers [selected_index ] = updated_server
139144 self .save_servers ()
140145 self .populate_list ()
146+
141147 def on_remove (self , event ):
142148 selected_index = self .list_ctrl .GetFirstSelected ()
143149 if selected_index != - 1 :
@@ -153,6 +159,7 @@ def on_remove(self, event):
153159 self .servers .pop (selected_index )
154160 self .save_servers ()
155161 self .populate_list ()
162+
156163 def on_connect (self , event ):
157164 selected_index = - 1
158165 if isinstance (event , wx .ListEvent ):
@@ -181,7 +188,7 @@ def on_connect(self, event):
181188 if server_info .get ("password_stored" ):
182189 passphrase = get_passphrase (server_name = server_info ["name" ], host = server_info ["host" ], user = server_info ["user" ])
183190 if passphrase is None and server_info .get ("has_passphrase" , False ):
184- with wx .PasswordEntryDialog (self , f"Enter passphrase for key\n { server_info ['key_path' ]} " , "Passphrase Required" ) as dlg :
191+ with wx .PasswordEntryDialog (self , f"Enter passphrase for key\n { server_info ['key_path' ]} " , "Passphrase Required" , "Passphrase Required (leave blank if none)" ) as dlg :
185192 if dlg .ShowModal () == wx .ID_OK : passphrase = dlg .GetValue ()
186193 else : return
187194 connect_kwargs ['passphrase' ] = passphrase
0 commit comments