Coverage for src / ezqt_app / domain / ports / main_window.py: 50.00%
6 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-06 13:12 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-06 13:12 +0000
1# ///////////////////////////////////////////////////////////////
2# DOMAIN.PORTS.MAIN_WINDOW - Main window structural contract
3# Project: ezqt_app
4# ///////////////////////////////////////////////////////////////
6"""Structural Protocol for the main application window.
8UI services interact with the main window through this contract instead of
9``Any``. This makes all required attributes explicit and enables static
10analysis without coupling the domain layer to PySide6 at runtime (all Qt
11imports are guarded by ``TYPE_CHECKING``).
13Sub-protocols model the ``window.ui.*`` sub-objects accessed by UI services.
14"""
16from __future__ import annotations
18# ///////////////////////////////////////////////////////////////
19# IMPORTS
20# ///////////////////////////////////////////////////////////////
21# Standard library imports
22from typing import TYPE_CHECKING, Any, Protocol
24if TYPE_CHECKING:
25 from PySide6.QtCore import QPoint, QPropertyAnimation, QSize, Qt
26 from PySide6.QtGui import QIcon
27 from PySide6.QtWidgets import (
28 QGraphicsDropShadowEffect,
29 QSizeGrip,
30 QToolButton,
31 QWidget,
32 )
35# ///////////////////////////////////////////////////////////////
36# SUB-PROTOCOLS — window.ui.*
37# ///////////////////////////////////////////////////////////////
38class StyleSheetWidgetProtocol(Protocol):
39 """Minimal contract for the style-sheet target widget (``ui.style_sheet``)."""
41 def setStyleSheet(self, style: str) -> None: ...
44class AppMarginsLayoutProtocol(Protocol):
45 """Minimal contract for the outer margin layout (``ui.app_margins_layout``)."""
47 def setContentsMargins(
48 self, left: int, top: int, right: int, bottom: int
49 ) -> None: ...
52class _AppButtonProtocol(Protocol):
53 """Minimal contract for a single header action button."""
55 clicked: Any # PySide6 Signal — typed as Any to stay Qt-agnostic
57 def hide(self) -> None: ...
58 def setToolTip(self, tip: str) -> None: ...
59 def setIcon(self, icon: QIcon) -> None: ...
62class HeaderContainerProtocol(Protocol):
63 """Minimal contract for the title-bar / header widget (``ui.header_container``)."""
65 minimize_btn: _AppButtonProtocol
66 maximize_restore_btn: _AppButtonProtocol
67 close_btn: _AppButtonProtocol
68 mouseDoubleClickEvent: Any # settable event handler
69 mouseMoveEvent: Any # settable event handler
71 def set_app_name(self, name: str) -> None: ...
72 def set_app_description(self, description: str) -> None: ...
73 def set_settings_panel_open(self, is_open: bool) -> None: ...
76class _SizeGripSlotProtocol(Protocol):
77 """Minimal contract for the size-grip placeholder in the bottom bar."""
79 def hide(self) -> None: ...
80 def show(self) -> None: ...
83class BottomBarProtocol(Protocol):
84 """Minimal contract for the bottom status bar (``ui.bottom_bar``)."""
86 size_grip_spacer: _SizeGripSlotProtocol
89class _TopMenuProtocol(Protocol):
90 """Minimal contract for the top-menu widget (``ui.menu_container.top_menu``)."""
92 def findChildren(self, child_type: type[QToolButton]) -> list[QToolButton]: ...
95class MenuContainerProtocol(Protocol):
96 """Minimal contract for the collapsible left menu (``ui.menu_container``)."""
98 top_menu: _TopMenuProtocol
99 toggle_button: Any
101 def width(self) -> int: ...
102 def get_extended_width(self) -> int: ...
103 def get_shrink_width(self) -> int: ...
106class SettingsPanelProtocol(Protocol):
107 """Minimal contract for the settings slide-in panel (``ui.settings_panel``)."""
109 def width(self) -> int: ...
110 def get_theme_selector(self) -> Any: ...
113class PageContainerProtocol(Protocol):
114 """Minimal contract for the central page receptacle (``ui.pages_container``)."""
116 def add_page(self, name: str) -> QWidget: ...
117 def set_current_widget(self, widget: QWidget) -> None: ...
120class BgAppProtocol(Protocol):
121 """Minimal contract for the background app widget (``ui.bg_app_frame``)."""
123 def setGraphicsEffect(self, effect: QGraphicsDropShadowEffect) -> None: ...
126class MainUiProtocol(Protocol):
127 """Aggregated contract for the ``window.ui`` object."""
129 style_sheet: StyleSheetWidgetProtocol
130 app_margins_layout: AppMarginsLayoutProtocol
131 header_container: HeaderContainerProtocol
132 bottom_bar: BottomBarProtocol
133 menu_container: MenuContainerProtocol
134 settings_panel: SettingsPanelProtocol
135 pages_container: PageContainerProtocol
136 bg_app_frame: BgAppProtocol
139# ///////////////////////////////////////////////////////////////
140# SUB-PROTOCOL — window grips
141# ///////////////////////////////////////////////////////////////
142class GripProtocol(Protocol):
143 """Minimal contract for a custom resize grip handle."""
145 def hide(self) -> None: ...
146 def show(self) -> None: ...
147 def setGeometry(self, x: int, y: int, w: int, h: int) -> None: ...
150# ///////////////////////////////////////////////////////////////
151# MAIN PROTOCOL
152# ///////////////////////////////////////////////////////////////
153class MainWindowProtocol(Protocol):
154 """Structural contract expected by UI services from the main application window.
156 Services use this type instead of ``Any`` for their *window* parameters,
157 making all accessed attributes explicit and verifiable by static analysis.
159 Attributes that are *written* by services (grips, shadow, animations…) are
160 included because other services read them later; their presence is guaranteed
161 by the call ordering in the boot sequence.
162 """
164 # ── UI sub-object ──────────────────────────────────────────
165 ui: MainUiProtocol
167 # ── Custom resize grips (set + read by services) ───────────
168 left_grip: GripProtocol
169 right_grip: GripProtocol
170 top_grip: GripProtocol
171 bottom_grip: GripProtocol
173 # ── Dynamic state attributes (set by services) ─────────────
174 dragPos: QPoint
175 shadow: QGraphicsDropShadowEffect
176 sizegrip: QSizeGrip
177 menu_animation: QPropertyAnimation
178 settings_animation: QPropertyAnimation
180 # ── Standard QWidget / QMainWindow methods ─────────────────
181 def showMaximized(self) -> None: ...
182 def showNormal(self) -> None: ...
183 def showMinimized(self) -> None: ...
184 def close(self) -> bool: ...
185 def resize(self, w: int, h: int) -> None: ...
186 def move(self, pos: QPoint) -> None: ...
187 def pos(self) -> QPoint: ...
188 def width(self) -> int: ...
189 def height(self) -> int: ...
190 def setMinimumSize(self, size: QSize) -> None: ...
191 def setWindowFlags(self, flags: Qt.WindowType) -> None: ...
192 def setAttribute(self, attribute: Qt.WidgetAttribute) -> None: ...