plate-config-app/app/widgets/dialogs/commands_dialog.py
Danil Iarosh 9fd10a3acd v1.3.0: simple mode backlight and UI polish
- обновлён простой режим: тест цвета и проверка подсветки кнопок объединены в раздел «Тест подсветки»

- добавлена проверка подсветки кнопок через 8-й силовой выход с автоматическим коротким тестом

- упрощены описания пользовательских проверок и убраны лишние технические подробности из простого режима

- изменена раскладка теста цвета, увеличена длительность шага до 1 секунды и убраны описания из PRO-блока

- добавлена защита выпадающих списков от случайного изменения колесом мыши

- улучшены немодальные PRO-диалоги, настройки соединения и обработка событий COM-порта

- обновлены визуальные детали приложения, пользовательские ресурсы, инструкции AGENTS и Release Notes 1.3.0
2026-05-26 12:59:21 +03:00

169 lines
6.5 KiB
Python
Raw 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.

"""Диалог «Команды платы» — справочник команд из CSV-файлов."""
from __future__ import annotations
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QFrame,
QHBoxLayout,
QLabel,
QLineEdit,
QScrollArea,
QVBoxLayout,
QWidget,
)
from ...services.commands_service import CommandSet, load_all_command_sets
from ...ui.icons import get_icon_color, icon
from ..no_wheel_combo_box import NoWheelComboBox
from .styled_dialog import StyledDialog
class _CommandCard(QFrame):
"""Карточка одной команды."""
def __init__(self, code: str, name: str, description: str,
parent: QWidget | None = None) -> None:
super().__init__(parent)
self.setObjectName("PanelCard")
self._code = code.lower()
self._name = name.lower()
self._desc = description.lower()
lay = QVBoxLayout(self)
lay.setContentsMargins(12, 10, 12, 10)
lay.setSpacing(4)
# Верхняя строка: код + имя
top = QHBoxLayout()
top.setSpacing(8)
code_label = QLabel(code)
code_label.setObjectName("HeroBadge")
code_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
top.addWidget(code_label)
name_label = QLabel(name)
name_label.setObjectName("SectionTitle")
name_label.setWordWrap(True)
top.addWidget(name_label, 1)
lay.addLayout(top)
# Описание
desc_label = QLabel(description)
desc_label.setObjectName("HeroHint")
desc_label.setWordWrap(True)
lay.addWidget(desc_label)
def matches(self, query: str) -> bool:
q = query.lower()
return q in self._code or q in self._name or q in self._desc
class CommandsDialog(StyledDialog):
"""Справочник команд платы: поиск + прокручиваемый список карточек."""
def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent)
self.setWindowTitle("Команды платы")
self.setMinimumWidth(420)
self.setMinimumHeight(460)
self.resize(520, 560)
lay = self.containerLayout()
lay.setSpacing(10)
# ── Строка фильтра ────────────────────────────────────────
filter_row = QHBoxLayout()
filter_row.setSpacing(8)
self._search = QLineEdit()
self._search.setPlaceholderText("Поиск по коду, названию или описанию…")
search_ico = icon("fa5s.search", color=get_icon_color())
if not search_ico.isNull():
self._search.addAction(search_ico, QLineEdit.ActionPosition.LeadingPosition)
self._search.textChanged.connect(self._apply_filter)
filter_row.addWidget(self._search, 1)
self._set_combo = NoWheelComboBox()
self._set_combo.setMinimumWidth(140)
self._set_combo.currentIndexChanged.connect(self._on_set_changed)
filter_row.addWidget(self._set_combo)
lay.addLayout(filter_row)
# ── Прокручиваемая область ────────────────────────────────
self._scroll = QScrollArea()
self._scroll.setWidgetResizable(True)
self._scroll.setFrameShape(QFrame.Shape.NoFrame)
self._scroll.setHorizontalScrollBarPolicy(
Qt.ScrollBarPolicy.ScrollBarAlwaysOff
)
self._cards_widget = QWidget()
self._cards_widget.setObjectName("CardsContainer")
self._cards_layout = QVBoxLayout(self._cards_widget)
self._cards_layout.setContentsMargins(2, 4, 6, 4)
self._cards_layout.setSpacing(6)
self._cards_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self._scroll.setWidget(self._cards_widget)
lay.addWidget(self._scroll, 1)
# ── Счётчик ───────────────────────────────────────────────
self._count_label = QLabel()
self._count_label.setObjectName("HeroHint")
self._count_label.setAlignment(Qt.AlignmentFlag.AlignRight)
lay.addWidget(self._count_label)
# ── Загрузка данных ───────────────────────────────────────
self._command_sets: list[CommandSet] = load_all_command_sets()
self._cards: list[_CommandCard] = []
if self._command_sets:
self._set_combo.blockSignals(True)
for cs in self._command_sets:
self._set_combo.addItem(cs.set_name)
self._set_combo.blockSignals(False)
self._build_cards(self._command_sets[0])
else:
self._set_combo.addItem("Нет файлов")
self._set_combo.setEnabled(False)
# ── Построение карточек ────────────────────────────────────────
def _clear_cards(self) -> None:
for card in self._cards:
self._cards_layout.removeWidget(card)
card.setParent(None) # type: ignore[call-overload]
card.deleteLater()
self._cards.clear()
def _build_cards(self, cs: CommandSet) -> None:
self._clear_cards()
for cmd in cs.commands:
card = _CommandCard(cmd.code, cmd.name, cmd.description)
self._cards_layout.addWidget(card)
self._cards.append(card)
self._apply_filter(self._search.text())
# ── Фильтрация ────────────────────────────────────────────────
def _apply_filter(self, text: str) -> None:
query = text.strip()
visible = 0
for card in self._cards:
show = card.matches(query) if query else True
card.setVisible(show)
if show:
visible += 1
total = len(self._cards)
if query:
self._count_label.setText(f"Показано {visible} из {total}")
else:
self._count_label.setText(f"Всего команд: {total}")
def _on_set_changed(self, index: int) -> None:
if 0 <= index < len(self._command_sets):
self._build_cards(self._command_sets[index])