Give the app an icon and a place in the application menu
icon.svg is the source; make_icons.py rasterises it into assets/icon-<size>.png at the six sizes a window manager asks for. Tk 8.6 reads PNG but not SVG, so the icon has to ship pre-rendered, and the glyph is laid on a rounded plate in the app's own colours — light on dark stays legible against both a light and a dark dock, which slate grey on nothing does not. ui.py loads whichever of those files exist and passes them all to iconphoto(), letting the WM pick per context (title bar, alt-tab, dock). The images are kept on the instance because Tk holds only a weak reference to a PhotoImage and the icon blanks out when it is collected. A missing or unreadable file is ignored rather than allowed to fail a launch. It also passes className="lektor-ai", which lands in WM_CLASS. Without it Tk calls itself "Tk" and that is what the dock shows on hover; the readable name comes from the desktop entry, which matches the window through StartupWMClass. install_desktop.sh writes ~/.local/share/applications/lektor-ai.desktop and copies the icons into the hicolor theme, so the app appears in the menu and can be pinned. Everything it installs lives under ~/.local and comes back out with --uninstall. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NkWDx9dVB7xBpqntvjvm6A
This commit is contained in:
@@ -45,6 +45,11 @@ import lektor_ai_comfy as core # noqa: E402 (path set above)
|
||||
|
||||
CLI = HERE / "lektor_ai_comfy.py"
|
||||
|
||||
# Window icon. Tk 8.6 reads PNG but not SVG, so assets/ holds sizes rendered
|
||||
# from icon.svg; the WM picks whichever fits its title bar, alt-tab and dock.
|
||||
ICON_DIR = HERE / "assets"
|
||||
ICON_SIZES = (256, 128, 64, 48, 32, 16)
|
||||
|
||||
# ── Palette, sampled from the mock-up ───────────────────────────────────────
|
||||
BG = "#3c3c3c" # body
|
||||
BAR = "#2b2b2b" # top strip
|
||||
@@ -1061,7 +1066,11 @@ class SimplePrompt(tk.Toplevel):
|
||||
|
||||
class LektorUI(tk.Tk):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# className lands in WM_CLASS; without it Tk reports itself as "Tk" and
|
||||
# that is what the dock shows on hover. Tk lowercases everything past
|
||||
# the first letter, so this is kept as a plain identifier — the pretty
|
||||
# name comes from lektor-ai.desktop, which matches on StartupWMClass.
|
||||
super().__init__(className="lektor-ai")
|
||||
self.title("lektor_ai — voiceover queue")
|
||||
self.geometry("1180x900")
|
||||
self.minsize(1000, 600)
|
||||
@@ -1080,6 +1089,7 @@ class LektorUI(tk.Tk):
|
||||
self.out_q = queue.Queue()
|
||||
self._in_redraw = False
|
||||
|
||||
self._set_icon()
|
||||
self._style()
|
||||
self._build()
|
||||
self.after(80, self._drain_output)
|
||||
@@ -1093,6 +1103,27 @@ class LektorUI(tk.Tk):
|
||||
self.log(" 'sudo apt install python3-tk', then run with plain python3.")
|
||||
self.log("Add videos with 'Add videos...' or the + button, then press GENERATE.")
|
||||
|
||||
# ── window icon ─────────────────────────────────────────────────────────
|
||||
def _set_icon(self):
|
||||
"""Icon for the title bar, alt-tab and the dock.
|
||||
|
||||
Kept on self because Tk holds only a weak reference to PhotoImages —
|
||||
drop it and the icon blanks out. Missing or unreadable files are not
|
||||
worth failing a launch over, so any trouble here is simply ignored.
|
||||
"""
|
||||
self._icons = []
|
||||
for size in ICON_SIZES:
|
||||
path = ICON_DIR / f"icon-{size}.png"
|
||||
if not path.is_file():
|
||||
continue
|
||||
try:
|
||||
self._icons.append(tk.PhotoImage(file=str(path)))
|
||||
except tk.TclError:
|
||||
pass
|
||||
if self._icons:
|
||||
# True: also the default for dialogs opened later.
|
||||
self.iconphoto(True, *self._icons)
|
||||
|
||||
# ── theming ─────────────────────────────────────────────────────────────
|
||||
def _style(self):
|
||||
st = ttk.Style(self)
|
||||
|
||||
Reference in New Issue
Block a user