Files
2026-04-29 08:18:54 +04:00

132 lines
6.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
# gui/components/model_view/_mv_presentation.py
"""Фасад видимости сцены для применения декларативных спецификаций представления."""
from __future__ import annotations
from typing import TYPE_CHECKING
from error_logger import log_exception
if TYPE_CHECKING:
from gui.components.model_view_widget import ModelViewWidget
class ScenePresentationMixin:
"""Применение спецификаций видимости сцены через публичный API ModelView."""
@staticmethod
def _safe_call(fn, *args, **kwargs):
try:
return fn(*args, **kwargs)
except Exception as exc:
log_exception(__name__, "ScenePresentationMixin._safe_call", exc)
return None
@staticmethod
def _rack_filter_value(spec) -> str:
rack_filter = getattr(spec, "rack_filter", "")
return str(getattr(rack_filter, "value", rack_filter) or "")
def apply_scene_spec(
self: "ModelViewWidget",
spec,
*,
start_select_rack: bool = False,
select_rack_id: str | None = None,
) -> None:
"""Применить ``SceneVisibilitySpec``, созданный политикой представления."""
if self is None or spec is None:
return
zone_contour_id = getattr(spec, "zone_contour_id", None)
if zone_contour_id:
self._safe_call(self.show_zone_contour, zone_contour_id)
elif bool(getattr(spec, "zone_solids_visible", False)):
self._safe_call(self.show_all_zones)
if bool(getattr(spec, "use_facility_contour_mode", False)) and hasattr(
self, "set_zone_facility_contour_mode"
):
zone_ids = [str(zid) for zid in getattr(self, "_zones", {}).keys()]
for zid in zone_ids:
has_racks = self.has_racks_in_zone(zid) if hasattr(self, "has_racks_in_zone") else False
self._safe_call(self.set_zone_facility_contour_mode, zid, has_racks)
if bool(getattr(spec, "hide_empty_zones", False)) and hasattr(self, "has_racks_in_zone"):
zone_ids = [str(zid) for zid in getattr(self, "_zones", {}).keys()]
for zid in zone_ids:
if not self.has_racks_in_zone(zid):
self._safe_call(self.set_zone_visibility, zid, False)
else:
self._safe_call(self.set_zone_facility_contour_mode, zid, False)
self._safe_call(self.set_zone_visibility, zid, False)
self._safe_call(self.set_zone_pick_enabled, bool(getattr(spec, "zone_pick_enabled", True)))
rack_filter = self._rack_filter_value(spec)
rack_zone_id = getattr(spec, "rack_zone_id", None)
rack_id = getattr(spec, "rack_id", None)
if rack_filter == "single_rack":
isolated = False
if hasattr(self, "show_only_rack") and rack_id:
isolated = bool(self._safe_call(self.show_only_rack, rack_id, rack_zone_id))
if not isolated and rack_zone_id:
self._safe_call(self.show_only_zone_racks, rack_zone_id)
elif rack_filter == "zone_only":
self._safe_call(self.show_only_zone_racks, rack_zone_id)
else:
self._safe_call(self.show_all_racks)
rack_select_mode = bool(getattr(spec, "rack_select_mode", False))
if rack_select_mode and start_select_rack and rack_zone_id:
self._safe_call(self.start_select_rack_mode, rack_zone_id)
elif not rack_select_mode:
self._safe_call(self.stop_select_rack_mode)
if select_rack_id and hasattr(self, "select_rack_by_id"):
self._safe_call(self.select_rack_by_id, select_rack_id, rack_zone_id)
if bool(getattr(spec, "clear_hover", False)):
mgr = getattr(self, "_interaction_manager", None)
if mgr is not None:
self._safe_call(mgr.reset)
self._safe_call(self.set_top_view_navigation, bool(getattr(spec, "top_view_navigation", False)))
if hasattr(self, "update_scene"):
self._safe_call(self.update_scene)
# ---------------------------------------------------------------------------
# Module workflow notes
# ---------------------------------------------------------------------------
# 1) Задача модуля:
# Применение наборов параметров отображения сцены и безопасный вызов методов представления.
#
# 2) Последовательность действий и вызовов:
# A. Класс ScenePresentationMixin: точки входа
# Публичные методы сценария:
# - ScenePresentationMixin.apply_scene_spec(...)
#
# B. ScenePresentationMixin: основной сценарий:
# ScenePresentationMixin.apply_scene_spec(...)
# Назначение: Применить ``SceneVisibilitySpec``, созданный политикой представления.
# Последовательность внутренних вызовов:
# -> ScenePresentationMixin._safe_call(...)
# -> ScenePresentationMixin._rack_filter_value(...)
#
# C. ScenePresentationMixin: вспомогательные расчёты:
# ScenePresentationMixin._safe_call(...)
# Назначение: выполняет шаг "safe call" в рамках текущего сценария модуля.
# ScenePresentationMixin._rack_filter_value(...)
# Назначение: выполняет шаг "rack filter value" в рамках текущего сценария модуля.
#
# 3) Важные ограничения и инварианты:
# - Модуль выполняется в составе ModelViewWidget и использует согласованные поля состояния self._... .
# - Межмодульная связность: только через фасад model_view; прямые обращения между zone, rack, shelf, cell запрещены.
# - Очистка состояния должна быть идемпотентной: повторный вызов не меняет корректное состояние в ошибочное.
#
# 4) Правило сопровождения:
# - Любое изменение сценария должно сопровождаться обновлением этого блока с сохранением фактического порядка вызовов.
# - При добавлении метода указывать его место в цепочке сценария (запуск, основной шаг, завершение, вспомогательная логика).