- обновлён простой режим: тест цвета и проверка подсветки кнопок объединены в раздел «Тест подсветки» - добавлена проверка подсветки кнопок через 8-й силовой выход с автоматическим коротким тестом - упрощены описания пользовательских проверок и убраны лишние технические подробности из простого режима - изменена раскладка теста цвета, увеличена длительность шага до 1 секунды и убраны описания из PRO-блока - добавлена защита выпадающих списков от случайного изменения колесом мыши - улучшены немодальные PRO-диалоги, настройки соединения и обработка событий COM-порта - обновлены визуальные детали приложения, пользовательские ресурсы, инструкции AGENTS и Release Notes 1.3.0
135 lines
5.1 KiB
Python
135 lines
5.1 KiB
Python
from __future__ import annotations
|
||
|
||
from PySide6.QtCore import Qt
|
||
from PySide6.QtGui import QColor
|
||
from PySide6.QtWidgets import (
|
||
QFrame,
|
||
QGraphicsDropShadowEffect,
|
||
QHBoxLayout,
|
||
QLabel,
|
||
QPushButton,
|
||
QVBoxLayout,
|
||
QWidget,
|
||
)
|
||
|
||
from ..ui.icons import ICON_COLOR_PRIMARY, get_icon_color, icon
|
||
from .dialogs.commands_dialog import CommandsDialog
|
||
from .dialogs.settings_dialog import SettingsDialog
|
||
|
||
|
||
class StartTab(QWidget):
|
||
def __init__(self, on_new_connection) -> None:
|
||
super().__init__()
|
||
self._open_dialog_windows: dict[str, QWidget] = {}
|
||
layout = QVBoxLayout(self)
|
||
layout.setContentsMargins(26, 26, 26, 26)
|
||
layout.addStretch(1)
|
||
|
||
hero_card = QFrame()
|
||
hero_card.setObjectName("HeroCard")
|
||
hero_card.setMaximumWidth(560)
|
||
|
||
shadow = QGraphicsDropShadowEffect(self)
|
||
shadow.setBlurRadius(28)
|
||
shadow.setOffset(0, 8)
|
||
shadow.setColor(QColor(20, 30, 50, 45))
|
||
hero_card.setGraphicsEffect(shadow)
|
||
|
||
hero_layout = QVBoxLayout(hero_card)
|
||
hero_layout.setContentsMargins(28, 28, 28, 28)
|
||
hero_layout.setSpacing(14)
|
||
|
||
badge = QLabel("Plate Config")
|
||
badge.setObjectName("HeroBadge")
|
||
badge.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
hero_layout.addWidget(badge, alignment=Qt.AlignmentFlag.AlignHCenter)
|
||
|
||
title = QLabel("Подключение к COM-плате")
|
||
title.setObjectName("HeroTitle")
|
||
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
hero_layout.addWidget(title)
|
||
|
||
hint = QLabel("Откройте новое соединение и настройте параметры порта для работы с платой.")
|
||
hint.setObjectName("HeroHint")
|
||
hint.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
hint.setWordWrap(True)
|
||
hero_layout.addWidget(hint)
|
||
|
||
btn = QPushButton("Новое соединение")
|
||
btn.setProperty("role", "primary")
|
||
btn.setMinimumWidth(210)
|
||
btn.setMinimumHeight(40)
|
||
btn.setIcon(icon("fa5s.plus-circle", color=ICON_COLOR_PRIMARY))
|
||
btn.clicked.connect(on_new_connection)
|
||
hero_layout.addWidget(btn, alignment=Qt.AlignmentFlag.AlignHCenter)
|
||
|
||
card_wrap = QHBoxLayout()
|
||
card_wrap.addStretch(1)
|
||
card_wrap.addWidget(hero_card)
|
||
card_wrap.addStretch(1)
|
||
layout.addLayout(card_wrap)
|
||
|
||
# ── Кнопки «Команды платы» и «Настройки» ───────────────────
|
||
bottom_row = QHBoxLayout()
|
||
bottom_row.setSpacing(12)
|
||
bottom_row.addStretch(1)
|
||
|
||
self._commands_btn = QPushButton("Команды платы")
|
||
self._commands_btn.setMinimumHeight(38)
|
||
self._commands_btn.setMinimumWidth(180)
|
||
self._commands_btn.setIcon(icon("fa5s.book", color=get_icon_color()))
|
||
self._commands_btn.clicked.connect(self._open_commands)
|
||
bottom_row.addWidget(self._commands_btn)
|
||
|
||
self._settings_btn = QPushButton("Настройки приложения")
|
||
self._settings_btn.setMinimumHeight(38)
|
||
self._settings_btn.setMinimumWidth(180)
|
||
self._settings_btn.setIcon(icon("fa5s.cog", color=get_icon_color()))
|
||
self._settings_btn.clicked.connect(self._open_settings)
|
||
bottom_row.addWidget(self._settings_btn)
|
||
|
||
bottom_row.addStretch(1)
|
||
layout.addLayout(bottom_row)
|
||
|
||
layout.addStretch(2)
|
||
|
||
# ── Public ────────────────────────────────────────────────────
|
||
|
||
def refresh_icons(self) -> None:
|
||
"""Re-create icons with the current theme colour."""
|
||
clr = get_icon_color()
|
||
self._commands_btn.setIcon(icon("fa5s.book", color=clr))
|
||
self._settings_btn.setIcon(icon("fa5s.cog", color=clr))
|
||
|
||
# ── Handlers ──────────────────────────────────────────────────
|
||
|
||
def _on_dialog_destroyed(self, key: str) -> None:
|
||
self._open_dialog_windows.pop(key, None)
|
||
|
||
def _open_single_dialog(self, key: str, factory) -> None:
|
||
existing = self._open_dialog_windows.get(key)
|
||
if existing is not None:
|
||
try:
|
||
existing.show()
|
||
existing.raise_()
|
||
existing.activateWindow()
|
||
return
|
||
except RuntimeError:
|
||
self._open_dialog_windows.pop(key, None)
|
||
|
||
dlg = factory()
|
||
dlg.setModal(False)
|
||
dlg.setWindowModality(Qt.WindowModality.NonModal)
|
||
dlg.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
|
||
dlg.destroyed.connect(lambda _obj=None, k=key: self._on_dialog_destroyed(k))
|
||
self._open_dialog_windows[key] = dlg
|
||
dlg.show()
|
||
dlg.raise_()
|
||
dlg.activateWindow()
|
||
|
||
def _open_commands(self) -> None:
|
||
self._open_single_dialog("commands", lambda: CommandsDialog(self))
|
||
|
||
def _open_settings(self) -> None:
|
||
self._open_single_dialog("settings", lambda: SettingsDialog(self))
|