Files
aza/AzA march 2026/aza_controller.py
2026-05-23 21:31:34 +02:00

148 lines
4.4 KiB
Python

# -*- coding: utf-8 -*-
"""
AZA Controller / Launcher — zentraler Einstieg.
Startet AZA Office, Praxis Chat, prueft Updates, zeigt Info.
Fuer Entwicklung: ``python aza_controller.py``
Produktion: spaeter ``aza_controller.exe`` im Installer.
"""
from __future__ import annotations
import sys
import tkinter as tk
from tkinter import messagebox, ttk
from aza_start_panel import start_office, start_praxischat
from aza_update_core import format_version_label, load_local_version
from aza_updater import check_updates_interactive, show_app_info
_WIN_APP_ID = "ch.aza-medwork.controller.v1"
_ACCENT = "#1a5f8a"
_ACCENT_HOVER = "#164f73"
def _ensure_win32_app_user_model_id() -> None:
if sys.platform != "win32":
return
try:
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(_WIN_APP_ID)
except Exception:
pass
def _center_window(win: tk.Tk, width: int, height: int) -> None:
win.update_idletasks()
sw = win.winfo_screenwidth()
sh = win.winfo_screenheight()
x = max(0, (sw - width) // 2)
y = max(0, (sh - height) // 2)
win.geometry(f"{width}x{height}+{x}+{y}")
class AzAController:
def __init__(self) -> None:
self.root = tk.Tk()
self.root.title("AzA — Controller")
self.root.resizable(False, False)
self.root.configure(bg="#eef3f8")
_center_window(self.root, 420, 430)
ver = format_version_label(load_local_version())
header = ttk.Frame(self.root, padding=(20, 18, 20, 8))
header.pack(fill="x")
ttk.Label(header, text="AzA", font=("Segoe UI", 20, "bold")).pack(anchor="w")
ttk.Label(
header,
text="Controller / Launcher",
font=("Segoe UI", 10),
).pack(anchor="w", pady=(2, 0))
ttk.Label(header, text=ver, font=("Segoe UI", 9)).pack(anchor="w", pady=(6, 0))
body = ttk.Frame(self.root, padding=(20, 8, 20, 16))
body.pack(fill="both", expand=True)
self._mk_btn(body, "AZA Office starten", self._on_office).pack(fill="x", pady=(0, 8))
self._mk_btn(body, "Praxis Chat starten", self._on_chat).pack(fill="x", pady=(0, 8))
self._mk_btn(body, "Updates prüfen", self._on_updates).pack(fill="x", pady=(0, 8))
self._mk_btn(body, "Einstellungen / Info", self._on_info).pack(fill="x", pady=(0, 8))
self._mk_btn(body, "Beenden", self.root.destroy, secondary=True).pack(fill="x")
ttk.Label(
self.root,
text="AzA Medwork",
font=("Segoe UI", 8),
).pack(pady=(0, 12))
ico = None
try:
from pathlib import Path
p = Path(__file__).resolve().parent / "logo.ico"
if p.is_file():
ico = str(p)
except Exception:
pass
if ico and sys.platform == "win32":
try:
self.root.iconbitmap(ico)
except Exception:
pass
def _mk_btn(self, parent, text: str, cmd, *, secondary: bool = False) -> tk.Button:
bg = "#5a6d7d" if secondary else _ACCENT
hover = "#4a5d6d" if secondary else _ACCENT_HOVER
btn = tk.Button(
parent,
text=text,
font=("Segoe UI", 10, "bold"),
fg="#ffffff",
bg=bg,
activebackground=hover,
activeforeground="#ffffff",
relief="flat",
bd=0,
padx=14,
pady=10,
cursor="hand2",
command=cmd,
)
btn.bind("<Enter>", lambda _e: btn.configure(bg=hover))
btn.bind("<Leave>", lambda _e: btn.configure(bg=bg))
return btn
def _on_office(self) -> None:
ok, msg = start_office()
if not ok:
messagebox.showerror("AZA Office", msg, parent=self.root)
else:
self.root.destroy()
def _on_chat(self) -> None:
ok, msg = start_praxischat()
if not ok:
messagebox.showerror("Praxis Chat", msg, parent=self.root)
else:
self.root.destroy()
def _on_updates(self) -> None:
check_updates_interactive(parent=self.root)
def _on_info(self) -> None:
show_app_info(parent=self.root)
def run(self) -> None:
self.root.mainloop()
def main() -> int:
_ensure_win32_app_user_model_id()
AzAController().run()
return 0
if __name__ == "__main__":
raise SystemExit(main())