plate-config-app/app/widgets/sections/led_test_section.py
Danil Iarosh 0ce06fc7f8 Rename physical channels in WS2812 settings and bump version to 1.4.1
- Переименованы элементы выбора физического канала в настройках WS2812: "1-й канал" -> "2-й канал", "2-й" -> "3-й", "3-й" -> "4-й".
- Удален неиспользуемый "4-й канал (4)", так как команды 894XY не существует.
- Изменения внесены в LedTestDialog и LedTestSection.
- Версия приложения обновлена до 1.4.1.
2026-07-02 11:03:16 +03:00

211 lines
8.3 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.

"""Встраиваемая секция «Тест цвета» — цветовое чередование диодов.
Позволяет задать порядок цветов (RGB/RBG/…) командой 89
и запустить тест: красный → зелёный → синий.
"""
from __future__ import annotations
from PySide6.QtCore import Qt, QTimer
from PySide6.QtWidgets import (
QCheckBox,
QColorDialog,
QFormLayout,
QGroupBox,
QHBoxLayout,
QLabel,
QMessageBox,
QPushButton,
QSpinBox,
QVBoxLayout,
QWidget,
)
from ...services.com_service import ComConnection
from ...ui.icons import get_icon_color, icon
from ..no_wheel_combo_box import NoWheelComboBox
_COLOR_ORDERS: list[tuple[int, str]] = [
(0, "RGB"),
(1, "RBG"),
(2, "BRG"),
(3, "BGR"),
(4, "GRB"),
(5, "GBR"),
]
class LedTestSection(QWidget):
"""Inline-секция тест цвета (для базового режима)."""
def __init__(self, connection: ComConnection, parent: QWidget | None = None) -> None:
super().__init__(parent)
self._conn = connection
self._setup_ui()
# ── UI ────────────────────────────────────────────────────────────
def _setup_ui(self) -> None:
root = QVBoxLayout(self)
root.setContentsMargins(0, 0, 0, 0)
root.setSpacing(10)
# ── Настройки WS2812 (cmd 89) ──
color_group = QGroupBox("Настройки WS2812 (cmd 89)")
color_form = QFormLayout(color_group)
color_form.setSpacing(6)
desc = QLabel(
"Настройки вывода WS2812. Выберите физический канал и настройте порядок цветов, "
"яркость или гамма-коррекцию."
)
desc.setWordWrap(True)
desc.setObjectName("HelpText")
color_form.addRow(desc)
# Выбор физического канала
self._cmd89_channel_combo = NoWheelComboBox()
self._cmd89_channel_combo.addItem("Все ленты (0)", 0)
self._cmd89_channel_combo.addItem("2-й канал (1)", 1)
self._cmd89_channel_combo.addItem("3-й канал (2)", 2)
self._cmd89_channel_combo.addItem("4-й канал (3)", 3)
color_form.addRow("Физический канал:", self._cmd89_channel_combo)
# Порядок цветов
self._color_order_combo = NoWheelComboBox()
for code, name in _COLOR_ORDERS:
self._color_order_combo.addItem(f"{code} — {name}", code)
self._set_color_btn = QPushButton("Применить порядок")
self._set_color_btn.setProperty("role", "primary")
self._set_color_btn.setIcon(icon("fa5s.palette", color="#ecfdf5"))
self._set_color_btn.clicked.connect(self._send_color_order)
order_layout = QHBoxLayout()
order_layout.addWidget(self._color_order_combo, 1)
order_layout.addWidget(self._set_color_btn)
color_form.addRow("Порядок цветов:", order_layout)
# Яркость
self._cmd89_brightness_spin = QSpinBox()
self._cmd89_brightness_spin.setRange(0, 255)
self._cmd89_brightness_spin.setValue(255)
apply_bright_btn = QPushButton("Применить яркость")
apply_bright_btn.setIcon(icon("fa5s.sun", color=get_icon_color()))
apply_bright_btn.clicked.connect(self._send_brightness)
bright_layout = QHBoxLayout()
bright_layout.addWidget(self._cmd89_brightness_spin, 1)
bright_layout.addWidget(apply_bright_btn)
color_form.addRow("Яркость:", bright_layout)
# Гамма-коррекция
self._cmd89_gamma_check = QCheckBox("Включить гамма-коррекцию")
apply_gamma_btn = QPushButton("Применить гамму")
apply_gamma_btn.setIcon(icon("fa5s.adjust", color=get_icon_color()))
apply_gamma_btn.clicked.connect(self._send_gamma)
gamma_layout = QHBoxLayout()
gamma_layout.addWidget(self._cmd89_gamma_check, 1)
gamma_layout.addWidget(apply_gamma_btn)
color_form.addRow("Гамма-коррекция:", gamma_layout)
# Пользовательский цвет
self._custom_color_btn = QPushButton("Выбрать и отправить цвет")
self._custom_color_btn.setIcon(icon("fa5s.palette", color=get_icon_color()))
self._custom_color_btn.clicked.connect(self._send_custom_color)
color_form.addRow("Свой цвет (08):", self._custom_color_btn)
# Тест цвета
self._color_test_btn = QPushButton("Тест цвета")
self._color_test_btn.setProperty("role", "primary")
self._color_test_btn.setIcon(icon("fa5s.eye", color="#ecfdf5"))
self._color_test_btn.clicked.connect(self._run_color_test)
color_form.addRow(self._color_test_btn)
color_hint = QLabel("Должны вывестись: красный → зелёный → синий")
color_hint.setStyleSheet("color: #9ca3af; font-size: 11px;")
color_hint.setWordWrap(True)
color_form.addRow(color_hint)
root.addWidget(color_group)
# ── Лог ──
self._log = QLabel("")
self._log.setObjectName("LogLabel")
self._log.setWordWrap(True)
root.addWidget(self._log)
# ── Public ────────────────────────────────────────────────────────
def refresh_icons(self) -> None:
"""Нет theme-dependent иконок — ничего не делаем."""
# ── Отправка ──────────────────────────────────────────────────────
def _send_color_order(self) -> None:
ch = self._cmd89_channel_combo.currentData()
code = self._color_order_combo.currentData()
cmd = f"89{ch}0{code}"
self._send(cmd)
def _send_brightness(self) -> None:
ch = self._cmd89_channel_combo.currentData()
val = self._cmd89_brightness_spin.value()
cmd = f"89{ch}1{val}"
self._send(cmd)
def _send_gamma(self) -> None:
ch = self._cmd89_channel_combo.currentData()
val = 1 if self._cmd89_gamma_check.isChecked() else 0
cmd = f"89{ch}2{val}"
self._send(cmd)
def _send_custom_color(self) -> None:
color = QColorDialog.getColor(Qt.GlobalColor.white, self, "Выберите цвет")
if color.isValid():
ch = self._cmd89_channel_combo.currentData()
r = color.red()
g = color.green()
b = color.blue()
cmd = f"8{ch}08{r:03d}{g:03d}{b:03d}"
self._send(cmd)
def _run_color_test(self) -> None:
self._color_test_cmds = ["8003", "8004", "8005", "8002", "8000"]
self._color_test_idx = 0
self._color_test_btn.setEnabled(False)
self._color_test_timer = QTimer(self)
self._color_test_timer.setInterval(1000)
self._color_test_timer.timeout.connect(self._color_test_step)
self._color_test_step()
self._color_test_timer.start()
def _color_test_step(self) -> None:
if self._color_test_idx >= len(self._color_test_cmds):
self._color_test_timer.stop()
self._color_test_btn.setEnabled(True)
return
cmd = self._color_test_cmds[self._color_test_idx]
self._color_test_idx += 1
self._send(cmd)
def _send(self, cmd: str) -> None:
if not cmd:
return
if not self._conn.is_connected:
QMessageBox.warning(self, "Ошибка", "Порт не подключён.")
return
try:
self._conn.send_command(cmd)
self._log.setText(f"→ {cmd}")
resp = self._conn.read_response(timeout=0.3)
self._conn.release()
if resp:
self._log.setText(f"→ {cmd}\n← {resp}")
except Exception as exc:
self._conn.release()
self._log.setText(f"Ошибка: {exc}")