Files
ware_house/main.py
2026-03-31 19:15:33 +02:00

181 lines
5.6 KiB
Python

"""Application entry point for the warehouse desktop tool.
This module wires together the shared async database client, the global
background event loop and the different Tk/CustomTkinter windows exposed by the
project.
"""
import asyncio
import sys
import tkinter as tk
import customtkinter as ctk
from async_loop_singleton import get_global_loop
from async_msssql_query import AsyncMSSQLClient, make_mssql_dsn
from layout_window import open_layout_window
from reset_corsie import open_reset_corsie_window
from search_pallets import open_search_window
from view_celle_multiple import open_celle_multiple_window
# Try factory, else frame, else app (senza passare conn_str all'App)
try:
from gestione_pickinglist import create_frame as create_pickinglist_frame
except Exception:
try:
from gestione_pickinglist import GestionePickingListFrame as _PLFrame
def create_pickinglist_frame(parent, db_client=None, conn_str=None):
"""Build the picking list UI using the frame-based fallback."""
ctk.set_appearance_mode("light")
ctk.set_default_color_theme("green")
return _PLFrame(parent, db_client=db_client, conn_str=conn_str)
except Exception:
from gestione_pickinglist import GestionePickingListApp as _PLApp
def create_pickinglist_frame(parent, db_client=None, conn_str=None):
"""Fallback used only by legacy app-style picking list implementations."""
app = _PLApp()
app.mainloop()
return tk.Frame(parent)
# ---- Config ----
SERVER = r"mde3\gesterp"
DBNAME = "Mediseawall"
USER = "sa"
PASSWORD = "1Password1"
if sys.platform.startswith("win"):
try:
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
except Exception:
pass
# Create one global loop and make it the default everywhere.
_loop = get_global_loop()
asyncio.set_event_loop(_loop)
def _noop(*args, **kwargs):
"""Compatibility no-op used when optional Tk DPI hooks are missing."""
return None
if not hasattr(tk.Toplevel, "block_update_dimensions_event"):
tk.Toplevel.block_update_dimensions_event = _noop # type: ignore[attr-defined]
if not hasattr(tk.Toplevel, "unblock_update_dimensions_event"):
tk.Toplevel.unblock_update_dimensions_event = _noop # type: ignore[attr-defined]
dsn_app = make_mssql_dsn(server=SERVER, database=DBNAME, user=USER, password=PASSWORD)
db_app = AsyncMSSQLClient(dsn_app)
def open_pickinglist_window(parent: tk.Misc, db_client: AsyncMSSQLClient):
"""Open the picking list window while minimizing initial flicker."""
win = ctk.CTkToplevel(parent)
win.title("Gestione Picking List")
win.geometry("1200x700+0+100")
win.minsize(1000, 560)
# Keep the toplevel hidden while its content is being created.
try:
win.withdraw()
win.attributes("-alpha", 0.0)
except Exception:
pass
frame = create_pickinglist_frame(win, db_client=db_client)
try:
frame.pack(fill="both", expand=True)
except Exception:
pass
# Show the window only when the layout is ready.
try:
win.update_idletasks()
try:
win.transient(parent)
except Exception:
pass
try:
win.deiconify()
except Exception:
pass
win.lift()
try:
win.focus_force()
except Exception:
pass
try:
win.attributes("-alpha", 1.0)
except Exception:
pass
except Exception:
pass
win.bind("<Escape>", lambda e: win.destroy())
win.protocol("WM_DELETE_WINDOW", win.destroy)
return win
class Launcher(ctk.CTk):
"""Main launcher window that exposes the available warehouse tools."""
def __init__(self):
"""Create the launcher toolbar and wire every button to a feature window."""
super().__init__()
self.title("Warehouse 1.0.0")
self.geometry("1200x70+0+0")
wrap = ctk.CTkFrame(self)
wrap.pack(pady=10, fill="x")
ctk.CTkButton(
wrap,
text="Gestione Corsie",
command=lambda: open_reset_corsie_window(self, db_app),
).grid(row=0, column=0, padx=6, pady=6, sticky="ew")
ctk.CTkButton(
wrap,
text="Gestione Layout",
command=lambda: open_layout_window(self, db_app),
).grid(row=0, column=1, padx=6, pady=6, sticky="ew")
ctk.CTkButton(
wrap,
text="UDC Fantasma",
command=lambda: open_celle_multiple_window(self, db_app),
).grid(row=0, column=2, padx=6, pady=6, sticky="ew")
ctk.CTkButton(
wrap,
text="Ricerca UDC",
command=lambda: open_search_window(self, db_app),
).grid(row=0, column=3, padx=6, pady=6, sticky="ew")
ctk.CTkButton(
wrap,
text="Gestione Picking List",
command=lambda: open_pickinglist_window(self, db_app),
).grid(row=0, column=4, padx=6, pady=6, sticky="ew")
for i in range(5):
wrap.grid_columnconfigure(i, weight=1)
def _on_close():
"""Dispose shared resources before closing the launcher."""
try:
fut = asyncio.run_coroutine_threadsafe(db_app.dispose(), _loop)
try:
fut.result(timeout=2)
except Exception:
pass
finally:
self.destroy()
self.protocol("WM_DELETE_WINDOW", _on_close)
if __name__ == "__main__":
ctk.set_appearance_mode("light")
ctk.set_default_color_theme("green")
Launcher().mainloop()