feat: add comprehensive keyboard shortcuts for improved navigation and productivity
Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
This commit is contained in:
163
src/main.py
163
src/main.py
@@ -72,6 +72,9 @@ class MedTrackerApp:
|
||||
# Add menu bar
|
||||
self._setup_menu()
|
||||
|
||||
# Setup keyboard shortcuts
|
||||
self._setup_keyboard_shortcuts()
|
||||
|
||||
# Center the window on screen
|
||||
self._center_window()
|
||||
|
||||
@@ -141,12 +144,12 @@ class MedTrackerApp:
|
||||
self.input_frame,
|
||||
[
|
||||
{
|
||||
"text": "Add Entry",
|
||||
"text": "Add Entry (Ctrl+S)",
|
||||
"command": self.add_new_entry,
|
||||
"fill": "both",
|
||||
"expand": True,
|
||||
},
|
||||
{"text": "Quit", "command": self.handle_window_closing},
|
||||
{"text": "Quit (Ctrl+Q)", "command": self.handle_window_closing},
|
||||
],
|
||||
)
|
||||
|
||||
@@ -172,19 +175,126 @@ class MedTrackerApp:
|
||||
# File menu
|
||||
file_menu = tk.Menu(menubar, tearoff=0)
|
||||
menubar.add_cascade(label="File", menu=file_menu)
|
||||
file_menu.add_command(label="Export Data...", command=self._open_export_window)
|
||||
file_menu.add_command(
|
||||
label="Export Data...",
|
||||
command=self._open_export_window,
|
||||
accelerator="Ctrl+E",
|
||||
)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(label="Exit", command=self.handle_window_closing)
|
||||
file_menu.add_command(
|
||||
label="Exit", command=self.handle_window_closing, accelerator="Ctrl+Q"
|
||||
)
|
||||
|
||||
# Tools menu
|
||||
tools_menu = tk.Menu(menubar, tearoff=0)
|
||||
menubar.add_cascade(label="Tools", menu=tools_menu)
|
||||
tools_menu.add_command(
|
||||
label="Manage Pathologies...", command=self._open_pathology_manager
|
||||
label="Manage Pathologies...",
|
||||
command=self._open_pathology_manager,
|
||||
accelerator="Ctrl+P",
|
||||
)
|
||||
tools_menu.add_command(
|
||||
label="Manage Medicines...", command=self._open_medicine_manager
|
||||
label="Manage Medicines...",
|
||||
command=self._open_medicine_manager,
|
||||
accelerator="Ctrl+M",
|
||||
)
|
||||
tools_menu.add_separator()
|
||||
tools_menu.add_command(
|
||||
label="Clear Entries", command=self._clear_entries, accelerator="Ctrl+N"
|
||||
)
|
||||
tools_menu.add_command(
|
||||
label="Refresh Data", command=self.refresh_data_display, accelerator="F5"
|
||||
)
|
||||
|
||||
# Help menu
|
||||
help_menu = tk.Menu(menubar, tearoff=0)
|
||||
menubar.add_cascade(label="Help", menu=help_menu)
|
||||
help_menu.add_command(
|
||||
label="Keyboard Shortcuts",
|
||||
command=self._show_keyboard_shortcuts,
|
||||
accelerator="F1",
|
||||
)
|
||||
help_menu.add_command(label="About", command=self._show_about_dialog)
|
||||
|
||||
def _setup_keyboard_shortcuts(self) -> None:
|
||||
"""Set up keyboard shortcuts for common actions."""
|
||||
# Bind keyboard shortcuts to the main window
|
||||
self.root.bind("<Control-s>", lambda e: self.add_new_entry())
|
||||
self.root.bind("<Control-S>", lambda e: self.add_new_entry())
|
||||
self.root.bind("<Control-q>", lambda e: self.handle_window_closing())
|
||||
self.root.bind("<Control-Q>", lambda e: self.handle_window_closing())
|
||||
self.root.bind("<Control-e>", lambda e: self._open_export_window())
|
||||
self.root.bind("<Control-E>", lambda e: self._open_export_window())
|
||||
self.root.bind("<Control-n>", lambda e: self._clear_entries())
|
||||
self.root.bind("<Control-N>", lambda e: self._clear_entries())
|
||||
self.root.bind("<Control-r>", lambda e: self.refresh_data_display())
|
||||
self.root.bind("<Control-R>", lambda e: self.refresh_data_display())
|
||||
self.root.bind("<F5>", lambda e: self.refresh_data_display())
|
||||
self.root.bind("<Control-m>", lambda e: self._open_medicine_manager())
|
||||
self.root.bind("<Control-M>", lambda e: self._open_medicine_manager())
|
||||
self.root.bind("<Control-p>", lambda e: self._open_pathology_manager())
|
||||
self.root.bind("<Control-P>", lambda e: self._open_pathology_manager())
|
||||
self.root.bind("<Delete>", lambda e: self._delete_selected_entry())
|
||||
self.root.bind("<Escape>", lambda e: self._clear_selection())
|
||||
self.root.bind("<F1>", lambda e: self._show_keyboard_shortcuts())
|
||||
|
||||
# Make the window focusable so it can receive key events
|
||||
self.root.focus_set()
|
||||
|
||||
logger.info("Keyboard shortcuts configured:")
|
||||
logger.info(" Ctrl+S: Save/Add new entry")
|
||||
logger.info(" Ctrl+Q: Quit application")
|
||||
logger.info(" Ctrl+E: Export data")
|
||||
logger.info(" Ctrl+N: Clear entries")
|
||||
logger.info(" Ctrl+R/F5: Refresh data")
|
||||
logger.info(" Ctrl+M: Manage medicines")
|
||||
logger.info(" Ctrl+P: Manage pathologies")
|
||||
logger.info(" Delete: Delete selected entry")
|
||||
logger.info(" Escape: Clear selection")
|
||||
logger.info(" F1: Show keyboard shortcuts help")
|
||||
|
||||
def _show_keyboard_shortcuts(self) -> None:
|
||||
"""Show a dialog with keyboard shortcuts information."""
|
||||
shortcuts_text = """Keyboard Shortcuts:
|
||||
|
||||
File Operations:
|
||||
• Ctrl+S: Save/Add new entry
|
||||
• Ctrl+Q: Quit application
|
||||
• Ctrl+E: Export data
|
||||
|
||||
Data Management:
|
||||
• Ctrl+N: Clear entries
|
||||
• Ctrl+R / F5: Refresh data
|
||||
|
||||
Window Management:
|
||||
• Ctrl+M: Manage medicines
|
||||
• Ctrl+P: Manage pathologies
|
||||
|
||||
Table Operations:
|
||||
• Delete: Delete selected entry
|
||||
• Escape: Clear selection
|
||||
• Double-click: Edit entry
|
||||
|
||||
Help:
|
||||
• F1: Show this help dialog"""
|
||||
|
||||
messagebox.showinfo("Keyboard Shortcuts", shortcuts_text, parent=self.root)
|
||||
|
||||
def _show_about_dialog(self) -> None:
|
||||
"""Show about dialog."""
|
||||
about_text = """TheChart - Medication Tracker
|
||||
|
||||
A simple application for tracking medications and pathologies.
|
||||
|
||||
Features:
|
||||
• Add daily medication and pathology entries
|
||||
• Visual graphs and charts
|
||||
• Data export capabilities
|
||||
• Keyboard shortcuts for efficiency
|
||||
|
||||
Use Ctrl+S to save entries and Ctrl+Q to quit."""
|
||||
|
||||
messagebox.showinfo("About TheChart", about_text, parent=self.root)
|
||||
|
||||
def _open_export_window(self) -> None:
|
||||
"""Open the export window."""
|
||||
@@ -231,12 +341,12 @@ class MedTrackerApp:
|
||||
self.input_frame,
|
||||
[
|
||||
{
|
||||
"text": "Add Entry",
|
||||
"text": "Add Entry (Ctrl+S)",
|
||||
"command": self.add_new_entry,
|
||||
"fill": "both",
|
||||
"expand": True,
|
||||
},
|
||||
{"text": "Quit", "command": self.handle_window_closing},
|
||||
{"text": "Quit (Ctrl+Q)", "command": self.handle_window_closing},
|
||||
],
|
||||
)
|
||||
|
||||
@@ -254,6 +364,43 @@ class MedTrackerApp:
|
||||
# Update status to show completion
|
||||
self.ui_manager.update_status("UI refreshed successfully", "success")
|
||||
|
||||
def _delete_selected_entry(self) -> None:
|
||||
"""Delete the currently selected entry in the table."""
|
||||
selection = self.tree.selection()
|
||||
if not selection:
|
||||
self.ui_manager.update_status("No entry selected for deletion", "warning")
|
||||
return
|
||||
|
||||
item_id = selection[0]
|
||||
item_values = self.tree.item(item_id, "values")
|
||||
|
||||
if messagebox.askyesno(
|
||||
"Delete Entry",
|
||||
f"Are you sure you want to delete the entry for {item_values[0]}?",
|
||||
parent=self.root,
|
||||
):
|
||||
date: str = item_values[0]
|
||||
logger.debug(f"Deleting entry with date={date}")
|
||||
|
||||
self.ui_manager.update_status("Deleting entry...", "info")
|
||||
if self.data_manager.delete_entry(date):
|
||||
self.ui_manager.update_status("Entry deleted successfully!", "success")
|
||||
messagebox.showinfo(
|
||||
"Success", "Entry deleted successfully!", parent=self.root
|
||||
)
|
||||
self.refresh_data_display()
|
||||
else:
|
||||
self.ui_manager.update_status("Failed to delete entry", "error")
|
||||
messagebox.showerror(
|
||||
"Error", "Failed to delete entry", parent=self.root
|
||||
)
|
||||
|
||||
def _clear_selection(self) -> None:
|
||||
"""Clear the current selection in the table."""
|
||||
if self.tree.selection():
|
||||
self.tree.selection_remove(self.tree.selection())
|
||||
self.ui_manager.update_status("Selection cleared", "info")
|
||||
|
||||
def handle_double_click(self, event: tk.Event) -> None:
|
||||
"""Handle double-click event to edit an entry."""
|
||||
logger.debug("Double-click event triggered on treeview.")
|
||||
|
||||
Reference in New Issue
Block a user