feat: Enhance preset saving functionality with themed modal dialog for name input
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import tkinter as tk
|
||||
from collections.abc import Callable
|
||||
from tkinter import messagebox, simpledialog, ttk
|
||||
from tkinter import messagebox, ttk
|
||||
|
||||
from init import logger
|
||||
from preferences import get_pref, save_preferences, set_pref
|
||||
@@ -521,11 +521,8 @@ class SearchFilterWidget:
|
||||
self._apply_filter_summary(summary)
|
||||
|
||||
def _save_preset(self) -> None:
|
||||
# Ask for a name
|
||||
name = simpledialog.askstring("Save Preset", "Preset name:", parent=self.parent)
|
||||
if not name:
|
||||
return
|
||||
name = name.strip()
|
||||
# Ask for a name via themed modal dialog
|
||||
name = self._ask_preset_name(initial=self.preset_var.get().strip())
|
||||
if not name:
|
||||
return
|
||||
presets = get_pref("filter_presets", {}) or {}
|
||||
@@ -536,6 +533,65 @@ class SearchFilterWidget:
|
||||
self.preset_var.set(name)
|
||||
self._update_status()
|
||||
|
||||
def _ask_preset_name(self, initial: str = "") -> str | None:
|
||||
"""Prompt for a preset name using a themed ttk modal dialog.
|
||||
|
||||
Returns the entered name (stripped) or None if cancelled.
|
||||
"""
|
||||
result: dict[str, str | None] = {"value": None}
|
||||
|
||||
top = tk.Toplevel(self.parent)
|
||||
top.title("Save Preset")
|
||||
top.transient(self.parent)
|
||||
top.grab_set()
|
||||
|
||||
frame = ttk.Frame(top, padding="10")
|
||||
frame.pack(fill="both", expand=True)
|
||||
|
||||
ttk.Label(frame, text="Preset name:").pack(anchor="w")
|
||||
name_var = tk.StringVar(value=initial)
|
||||
entry = ttk.Entry(frame, textvariable=name_var, width=32)
|
||||
entry.pack(fill="x", pady=(4, 10))
|
||||
|
||||
buttons = ttk.Frame(frame)
|
||||
buttons.pack(anchor="e")
|
||||
|
||||
def on_ok() -> None:
|
||||
value = (name_var.get() or "").strip()
|
||||
if not value:
|
||||
messagebox.showwarning(
|
||||
"Save Preset", "Please enter a name.", parent=top
|
||||
)
|
||||
return
|
||||
result["value"] = value
|
||||
top.destroy()
|
||||
|
||||
def on_cancel() -> None:
|
||||
result["value"] = None
|
||||
top.destroy()
|
||||
|
||||
cancel_btn = ttk.Button(buttons, text="Cancel", command=on_cancel)
|
||||
cancel_btn.pack(side="right")
|
||||
ok_btn = ttk.Button(buttons, text="Save", command=on_ok)
|
||||
ok_btn.pack(side="right", padx=(6, 0))
|
||||
|
||||
# Key bindings
|
||||
entry.bind("<Return>", lambda e: on_ok())
|
||||
entry.bind("<Escape>", lambda e: on_cancel())
|
||||
|
||||
# Center the dialog relative to parent
|
||||
top.update_idletasks()
|
||||
px, py = self.parent.winfo_rootx(), self.parent.winfo_rooty()
|
||||
pw, ph = self.parent.winfo_width(), self.parent.winfo_height()
|
||||
ww, wh = top.winfo_width(), top.winfo_height()
|
||||
x = px + (pw // 2) - (ww // 2)
|
||||
y = py + (ph // 2) - (wh // 2)
|
||||
top.geometry(f"+{x}+{y}")
|
||||
|
||||
entry.focus_set()
|
||||
top.wait_window()
|
||||
return result["value"]
|
||||
|
||||
def _delete_preset(self) -> None:
|
||||
name = self.preset_var.get().strip()
|
||||
if not name:
|
||||
|
||||
Reference in New Issue
Block a user