181 lines
5.6 KiB
Python
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()
|