Skip to content

Commit 4a0d4c9

Browse files
authored
Update todo_app.py
2.1.0
1 parent 6ff4a4a commit 4a0d4c9

File tree

1 file changed

+83
-21
lines changed

1 file changed

+83
-21
lines changed

todo_app/todo_app.py

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pathlib import Path
66
from typing import List, Dict, Any
77
import sys
8+
from tkinter import PhotoImage
89

910
class TodoApp:
1011
def __init__(self, root: tk.Tk):
@@ -42,7 +43,7 @@ def setup_ui(self):
4243

4344
self.listbox = tk.Listbox(self.main_frame, selectmode=tk.EXTENDED, bd=0, highlightthickness=0,
4445
activestyle='none', font=self.get_system_font(), width=40, height=10)
45-
self.listbox.grid(row=0, column=0, columnspan=4, sticky="nsew", padx=10, pady=(10, 5))
46+
self.listbox.grid(row=0, column=0, columnspan=4, sticky="nsew", padx=10, pady=(8, 5))
4647
self.main_frame.grid_rowconfigure(0, weight=1)
4748
self.main_frame.grid_columnconfigure(0, weight=1)
4849

@@ -95,13 +96,28 @@ def setup_bindings(self):
9596

9697

9798
def on_ctrl_click(self, event):
98-
"""Handle Ctrl-click to select multiple tasks."""
99+
"""Handle robust Ctrl-click to toggle selection of individual tasks."""
99100
index = self.listbox.nearest(event.y)
100101
if index in self.listbox.curselection():
101102
self.listbox.selection_clear(index)
102103
else:
103104
self.listbox.selection_set(index)
104105

106+
return 'break'
107+
108+
def on_ctrl_click(self, event):
109+
"""Handle robust Ctrl-click to toggle selection of individual tasks."""
110+
index = self.listbox.nearest(event.y)
111+
if index in self.listbox.curselection():
112+
self.listbox.selection_clear(index)
113+
else:
114+
self.listbox.selection_set(index)
115+
116+
# Update buttons state after selection change
117+
self.update_buttons_state()
118+
119+
return 'break'
120+
105121
def on_shift_click(self, event):
106122
"""Handle Shift-click to select a range of tasks."""
107123
index = self.listbox.nearest(event.y)
@@ -281,8 +297,6 @@ def update_buttons_state(self, event=None):
281297
for button in ["➖", "✔"]:
282298
self.buttons[button]['state'] = 'normal' if has_selection else 'disabled'
283299

284-
285-
286300
def adjust_window_size(self):
287301
num_tasks = len(self.tasks)
288302
new_height = max(100, min(800, 100 + (num_tasks * 18)))
@@ -371,11 +385,20 @@ def show_about_dialog(self, event=None):
371385
about_window.title("About")
372386
about_window.resizable(False, False)
373387

388+
# Set window icon
374389
self.set_window_icon(about_window)
375390

391+
# Load and display app icon
392+
icon_path = Path(__file__).parent / 'app_logo.png'
393+
if icon_path.is_file():
394+
app_icon = PhotoImage(file=icon_path)
395+
icon_label = tk.Label(about_window, image=app_icon)
396+
icon_label.image = app_icon # Keep a reference to avoid garbage collection
397+
icon_label.pack(pady=(5, 5)) # Add some padding around the icon
398+
376399
about_text = (
377-
"To-Do App 0.2.0\n\n"
378-
"2024 Jens Lettkemann <jltk@pm.me>\n\n"
400+
"To-Do App 0.2.1\n\n"
401+
"© 2024 Jens Lettkemann <jltk@pm.me>\n\n"
379402
"This software is licensed under GPLv3+.\n"
380403
)
381404
github_link = "https://github.com/jltk/todo-app\n"
@@ -454,22 +477,61 @@ def edit_task(self):
454477
selected_indices = self.listbox.curselection()
455478
if not selected_indices:
456479
return
457-
480+
458481
index = selected_indices[0]
459482
current_task = self.tasks[index]
460-
461-
new_name = simpledialog.askstring(
462-
"Edit Task",
463-
"Edit task name:",
464-
initialvalue=current_task['name'],
465-
parent=self.root
466-
)
467-
if new_name is not None:
468-
self.tasks[index]['name'] = new_name
469-
self.populate_listbox()
470-
self.save_tasks()
471-
self.update_buttons_state()
472-
self.update_title()
483+
484+
# Create a Toplevel window for editing the task
485+
edit_window = tk.Toplevel(self.root)
486+
edit_window.title("Edit Task")
487+
edit_window.geometry("200x120") # Larger size for the edit window
488+
edit_window.transient(self.root) # Make the edit window stay on top of the root window
489+
edit_window.grab_set() # Make the edit window modal
490+
491+
self.set_window_icon(edit_window) # Set the icon for the edit window
492+
493+
# Create a frame to contain the widgets
494+
frame = tk.Frame(edit_window, padx=20, pady=20)
495+
frame.pack(fill="both", expand=True)
496+
497+
# Create a Text widget for task editing
498+
text_entry = tk.Text(frame, wrap='word', height=2, width=28)
499+
text_entry.insert(tk.END, current_task['name'])
500+
text_entry.pack(fill="both", expand=True)
501+
502+
def on_save(event=None):
503+
new_name = text_entry.get("1.0", "end-1c").strip()
504+
if new_name:
505+
self.tasks[index]['name'] = new_name
506+
self.populate_listbox()
507+
self.save_tasks()
508+
self.update_buttons_state()
509+
self.update_title()
510+
edit_window.destroy()
511+
512+
def on_cancel():
513+
edit_window.destroy()
514+
515+
# Bind Enter key to the on_save function
516+
text_entry.bind("<Return>", on_save)
517+
518+
# Create Save and Cancel buttons
519+
button_frame = tk.Frame(frame)
520+
button_frame.pack(fill="x", pady=(10, 0))
521+
522+
save_button = tk.Button(button_frame, text="Save", command=on_save)
523+
save_button.pack(side="left", padx=0) # Align to the left side of the frame
524+
525+
cancel_button = tk.Button(button_frame, text="Cancel", command=on_cancel)
526+
cancel_button.pack(side="left", padx=5) # Align to the left side of the frame
527+
528+
# Center the button_frame horizontally
529+
button_frame.pack(side="bottom", pady=(10, 0), fill="x")
530+
531+
edit_window.protocol("WM_DELETE_WINDOW", on_cancel)
532+
self.center_window_over_window(edit_window)
533+
534+
473535

474536
def show_window(self):
475537
if self.initial_geometry:
@@ -521,7 +583,7 @@ def center_window(self, default_size=None):
521583

522584
@staticmethod
523585
def get_system_font():
524-
return ('Segoe UI', 10) if sys.platform == 'win32' else ('San Francisco', 11) if sys.platform == 'darwin' else ('Segoe UI', 10)
586+
return ('Segoe UI', 10) if sys.platform == 'win32' else ('San Francisco', 11) if sys.platform == 'darwin' else ('Arial', 10)
525587

526588
def update_bulk_selection_mode(self):
527589
if self.shift_pressed:

0 commit comments

Comments
 (0)