Remove recently used connections, keep only saved connections with alphabetical sorting
This commit is contained in:
162
rdp_client.py
162
rdp_client.py
@@ -366,33 +366,16 @@ class RDPClient:
|
||||
left_frame = ttk.Frame(main_frame)
|
||||
left_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 10))
|
||||
left_frame.rowconfigure(1, weight=1)
|
||||
left_frame.rowconfigure(3, weight=1)
|
||||
left_frame.rowconfigure(1, weight=1) # Only saved connections now
|
||||
left_frame.columnconfigure(0, weight=1)
|
||||
|
||||
# Recent Connections
|
||||
recent_label = ttk.Label(left_frame, text="Recent Connections", font=('Arial', 10, 'bold'))
|
||||
recent_label.grid(row=0, column=0, sticky=tk.W, pady=(0, 5))
|
||||
|
||||
# Recent connections frame with listbox and scrollbar
|
||||
recent_frame = ttk.Frame(left_frame)
|
||||
recent_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
|
||||
recent_frame.rowconfigure(0, weight=1)
|
||||
recent_frame.columnconfigure(0, weight=1)
|
||||
|
||||
self.recent_listbox = tk.Listbox(recent_frame, font=('Arial', 9), height=6, width=30)
|
||||
recent_scrollbar = ttk.Scrollbar(recent_frame, orient="vertical", command=self.recent_listbox.yview)
|
||||
self.recent_listbox.configure(yscrollcommand=recent_scrollbar.set)
|
||||
|
||||
self.recent_listbox.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
recent_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
|
||||
|
||||
# Saved Connections
|
||||
# Saved Connections (now the main/only connections list)
|
||||
saved_label = ttk.Label(left_frame, text="Saved Connections", font=('Arial', 10, 'bold'))
|
||||
saved_label.grid(row=2, column=0, sticky=tk.W, pady=(10, 5))
|
||||
saved_label.grid(row=0, column=0, sticky=tk.W, pady=(0, 5))
|
||||
|
||||
# Saved connections frame with listbox and scrollbar
|
||||
saved_frame = ttk.Frame(left_frame)
|
||||
saved_frame.grid(row=3, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
saved_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
saved_frame.rowconfigure(0, weight=1)
|
||||
saved_frame.columnconfigure(0, weight=1)
|
||||
|
||||
@@ -405,7 +388,7 @@ class RDPClient:
|
||||
|
||||
# Connection buttons
|
||||
conn_buttons_frame = ttk.Frame(left_frame)
|
||||
conn_buttons_frame.grid(row=4, column=0, pady=(10, 0), sticky=(tk.W, tk.E))
|
||||
conn_buttons_frame.grid(row=2, column=0, pady=(10, 0), sticky=(tk.W, tk.E))
|
||||
|
||||
ttk.Button(conn_buttons_frame, text="Connect",
|
||||
command=self._connect_selected).pack(side=tk.LEFT, padx=(0, 5))
|
||||
@@ -465,8 +448,6 @@ class RDPClient:
|
||||
# Bind listbox selection
|
||||
self.connections_listbox.bind('<<ListboxSelect>>', self._on_connection_select)
|
||||
self.connections_listbox.bind('<Double-Button-1>', self._connect_selected)
|
||||
self.recent_listbox.bind('<<ListboxSelect>>', self._on_recent_select)
|
||||
self.recent_listbox.bind('<Double-Button-1>', self._connect_recent)
|
||||
|
||||
# Keyboard shortcuts
|
||||
self._setup_keyboard_shortcuts()
|
||||
@@ -503,55 +484,16 @@ class RDPClient:
|
||||
self.connections_listbox.bind('<F2>', lambda e: self._edit_selected())
|
||||
self.connections_listbox.bind('<Control-t>', lambda e: self._test_selected_connection())
|
||||
|
||||
self.recent_listbox.bind('<Return>', lambda e: self._connect_selected())
|
||||
self.recent_listbox.bind('<Delete>', lambda e: self._delete_selected())
|
||||
self.recent_listbox.bind('<F2>', lambda e: self._edit_selected())
|
||||
self.recent_listbox.bind('<Control-t>', lambda e: self._test_selected_connection())
|
||||
|
||||
# Set focus handling
|
||||
self.root.bind('<Tab>', self._handle_tab_focus)
|
||||
self.root.bind('<Shift-Tab>', self._handle_shift_tab_focus)
|
||||
# Set initial focus
|
||||
self.connections_listbox.focus_set()
|
||||
if self.connections_listbox.size() > 0:
|
||||
self.connections_listbox.selection_set(0)
|
||||
|
||||
# Add tooltip information for shortcuts
|
||||
self._add_keyboard_shortcuts_info()
|
||||
|
||||
def _handle_tab_focus(self, event):
|
||||
"""Handle Tab key for focus navigation"""
|
||||
current_focus = self.root.focus_get()
|
||||
|
||||
if current_focus == self.recent_listbox:
|
||||
self.connections_listbox.focus_set()
|
||||
if self.connections_listbox.size() > 0:
|
||||
self.connections_listbox.selection_set(0)
|
||||
elif current_focus == self.connections_listbox:
|
||||
self.recent_listbox.focus_set()
|
||||
if self.recent_listbox.size() > 0:
|
||||
self.recent_listbox.selection_set(0)
|
||||
else:
|
||||
self.recent_listbox.focus_set()
|
||||
if self.recent_listbox.size() > 0:
|
||||
self.recent_listbox.selection_set(0)
|
||||
|
||||
return "break" # Prevent default Tab behavior
|
||||
|
||||
def _handle_shift_tab_focus(self, event):
|
||||
"""Handle Shift+Tab key for reverse focus navigation"""
|
||||
current_focus = self.root.focus_get()
|
||||
|
||||
if current_focus == self.connections_listbox:
|
||||
self.recent_listbox.focus_set()
|
||||
if self.recent_listbox.size() > 0:
|
||||
self.recent_listbox.selection_set(0)
|
||||
elif current_focus == self.recent_listbox:
|
||||
self.connections_listbox.focus_set()
|
||||
if self.connections_listbox.size() > 0:
|
||||
self.connections_listbox.selection_set(0)
|
||||
else:
|
||||
self.connections_listbox.focus_set()
|
||||
if self.connections_listbox.size() > 0:
|
||||
self.connections_listbox.selection_set(0)
|
||||
|
||||
return "break" # Prevent default Shift+Tab behavior
|
||||
# Add tooltip information for shortcuts
|
||||
self._add_keyboard_shortcuts_info()
|
||||
|
||||
def _add_keyboard_shortcuts_info(self):
|
||||
"""Add keyboard shortcuts information to the status bar or help"""
|
||||
@@ -563,11 +505,9 @@ class RDPClient:
|
||||
def clear_shortcuts_hint(event):
|
||||
self.status_var.set("Ready")
|
||||
|
||||
# Show shortcuts hint when certain widgets get focus
|
||||
# Show shortcuts hint when connections listbox gets focus
|
||||
self.connections_listbox.bind('<FocusIn>', show_shortcuts_hint)
|
||||
self.recent_listbox.bind('<FocusIn>', show_shortcuts_hint)
|
||||
self.connections_listbox.bind('<FocusOut>', clear_shortcuts_hint)
|
||||
self.recent_listbox.bind('<FocusOut>', clear_shortcuts_hint)
|
||||
|
||||
def _show_help(self):
|
||||
"""Show keyboard shortcuts help dialog"""
|
||||
@@ -588,15 +528,12 @@ Connection List Shortcuts:
|
||||
• Double-click - Connect to selected connection
|
||||
• Delete - Delete selected connection
|
||||
• F2 - Edit selected connection
|
||||
• Tab - Switch between Recent and Saved connections
|
||||
|
||||
Navigation:
|
||||
• Tab - Move between Recent and Saved connections
|
||||
• Shift+Tab - Move between connections (reverse)
|
||||
• Arrow keys - Navigate within lists
|
||||
• Arrow keys - Navigate within connections list
|
||||
|
||||
Tips:
|
||||
• Recent connections show usage count (e.g., "Server (5x)")
|
||||
• Connections are sorted alphabetically by name
|
||||
• Double-click any connection to connect quickly
|
||||
• Use Test Connection to verify server availability
|
||||
• Import/Export to backup or share connection profiles
|
||||
@@ -612,50 +549,17 @@ Multi-Monitor Support:
|
||||
messagebox.showinfo("Keyboard Shortcuts", help_text)
|
||||
|
||||
def _refresh_connections_list(self):
|
||||
"""Refresh the connections listbox"""
|
||||
"""Refresh the connections listbox with sorted saved connections"""
|
||||
self.connections_listbox.delete(0, tk.END)
|
||||
for name in sorted(self.connections.keys()):
|
||||
# Sort connections by name (case-insensitive)
|
||||
for name in sorted(self.connections.keys(), key=str.lower):
|
||||
self.connections_listbox.insert(tk.END, name)
|
||||
|
||||
# Refresh recent connections
|
||||
self.recent_listbox.delete(0, tk.END)
|
||||
for entry in self.history[:10]: # Show last 10 recent connections
|
||||
name = entry.get('name', '')
|
||||
count = entry.get('count', 0)
|
||||
if name in self.connections: # Only show if connection still exists
|
||||
display_text = f"{name} ({count}x)"
|
||||
self.recent_listbox.insert(tk.END, display_text)
|
||||
|
||||
# Clear details if no connections
|
||||
if not self.connections:
|
||||
for label in self.details_labels.values():
|
||||
label.config(text="")
|
||||
|
||||
def _on_recent_select(self, event=None):
|
||||
"""Handle recent connection selection"""
|
||||
selection = self.recent_listbox.curselection()
|
||||
if selection:
|
||||
display_text = self.recent_listbox.get(selection[0])
|
||||
# Extract connection name (everything before " (")
|
||||
name = display_text.split(' (')[0]
|
||||
if name in self.connections:
|
||||
# Clear saved connections selection
|
||||
self.connections_listbox.selection_clear(0, tk.END)
|
||||
# Update details
|
||||
conn = self.connections[name]
|
||||
self._update_details(conn)
|
||||
|
||||
def _connect_recent(self, event=None):
|
||||
"""Connect to selected recent connection"""
|
||||
selection = self.recent_listbox.curselection()
|
||||
if not selection:
|
||||
return
|
||||
|
||||
display_text = self.recent_listbox.get(selection[0])
|
||||
name = display_text.split(' (')[0]
|
||||
if name in self.connections:
|
||||
self._connect_to(name)
|
||||
|
||||
def _update_details(self, conn):
|
||||
"""Update the details panel with connection info"""
|
||||
self.details_labels["server"].config(text=conn.get("server", ""))
|
||||
@@ -676,8 +580,6 @@ Multi-Monitor Support:
|
||||
name = self.connections_listbox.get(selection[0])
|
||||
conn = self.connections[name]
|
||||
|
||||
# Clear recent connections selection
|
||||
self.recent_listbox.selection_clear(0, tk.END)
|
||||
# Update details
|
||||
self._update_details(conn)
|
||||
|
||||
@@ -706,7 +608,7 @@ Multi-Monitor Support:
|
||||
self.credentials[name]["password"] = self._encrypt_password(dialog.result["password"])
|
||||
self._save_credentials()
|
||||
|
||||
# Add new connection to history so it appears in recent connections
|
||||
# Add new connection to history
|
||||
self._add_to_history(name)
|
||||
|
||||
self._refresh_connections_list()
|
||||
@@ -714,16 +616,12 @@ Multi-Monitor Support:
|
||||
|
||||
def _edit_selected(self):
|
||||
"""Edit selected connection"""
|
||||
# Check which listbox has a selection
|
||||
# Check saved connections selection
|
||||
saved_selection = self.connections_listbox.curselection()
|
||||
recent_selection = self.recent_listbox.curselection()
|
||||
|
||||
name = None
|
||||
if saved_selection:
|
||||
name = self.connections_listbox.get(saved_selection[0])
|
||||
elif recent_selection:
|
||||
display_text = self.recent_listbox.get(recent_selection[0])
|
||||
name = display_text.split(' (')[0]
|
||||
|
||||
if not name:
|
||||
messagebox.showwarning("No Selection", "Please select a connection to edit.")
|
||||
@@ -782,16 +680,12 @@ Multi-Monitor Support:
|
||||
|
||||
def _delete_selected(self):
|
||||
"""Delete selected connection"""
|
||||
# Check which listbox has a selection
|
||||
# Check saved connections selection
|
||||
saved_selection = self.connections_listbox.curselection()
|
||||
recent_selection = self.recent_listbox.curselection()
|
||||
|
||||
name = None
|
||||
if saved_selection:
|
||||
name = self.connections_listbox.get(saved_selection[0])
|
||||
elif recent_selection:
|
||||
display_text = self.recent_listbox.get(recent_selection[0])
|
||||
name = display_text.split(' (')[0]
|
||||
|
||||
if not name:
|
||||
messagebox.showwarning("No Selection", "Please select a connection to delete.")
|
||||
@@ -817,18 +711,12 @@ Multi-Monitor Support:
|
||||
|
||||
def _connect_selected(self, event=None):
|
||||
"""Connect to selected connection"""
|
||||
# Check which listbox has a selection
|
||||
# Check saved connections selection
|
||||
saved_selection = self.connections_listbox.curselection()
|
||||
recent_selection = self.recent_listbox.curselection()
|
||||
|
||||
if saved_selection:
|
||||
name = self.connections_listbox.get(saved_selection[0])
|
||||
self._connect_to(name)
|
||||
elif recent_selection:
|
||||
display_text = self.recent_listbox.get(recent_selection[0])
|
||||
name = display_text.split(' (')[0]
|
||||
if name in self.connections:
|
||||
self._connect_to(name)
|
||||
else:
|
||||
messagebox.showwarning("No Selection", "Please select a connection to connect.")
|
||||
|
||||
@@ -853,7 +741,7 @@ Multi-Monitor Support:
|
||||
# Build and execute RDP command
|
||||
self._add_to_history(name)
|
||||
self._execute_rdp_connection(conn, password)
|
||||
self._refresh_connections_list() # Refresh to update recent connections
|
||||
self._refresh_connections_list() # Refresh connections list
|
||||
|
||||
def _execute_rdp_connection(self, conn, password):
|
||||
"""Execute the RDP connection in a separate thread"""
|
||||
@@ -1225,16 +1113,12 @@ Multi-Monitor Support:
|
||||
|
||||
def _test_selected_connection(self):
|
||||
"""Test the selected connection for reachability"""
|
||||
# Check which listbox has a selection
|
||||
# Check saved connections selection
|
||||
saved_selection = self.connections_listbox.curselection()
|
||||
recent_selection = self.recent_listbox.curselection()
|
||||
|
||||
name = None
|
||||
if saved_selection:
|
||||
name = self.connections_listbox.get(saved_selection[0])
|
||||
elif recent_selection:
|
||||
display_text = self.recent_listbox.get(recent_selection[0])
|
||||
name = display_text.split(' (')[0]
|
||||
|
||||
if not name:
|
||||
messagebox.showwarning("No Selection", "Please select a connection to test.")
|
||||
|
||||
Reference in New Issue
Block a user