First upload, 18 controller version
This commit is contained in:
193
app/ui/mapping_assignment_preview.py
Normal file
193
app/ui/mapping_assignment_preview.py
Normal file
@@ -0,0 +1,193 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.qt_compat import (
|
||||
QColor,
|
||||
QFont,
|
||||
QLinearGradient,
|
||||
QPainter,
|
||||
QPainterPath,
|
||||
QPen,
|
||||
QRectF,
|
||||
Qt,
|
||||
Signal,
|
||||
QWidget,
|
||||
event_posf,
|
||||
)
|
||||
|
||||
from app.config.device_assignment import tile_matches_device
|
||||
from app.config.models import InfinityMirrorConfig
|
||||
from app.network.wled import DiscoveredWledDevice, normalize_mac_address
|
||||
from app.ui.preview_layout import compute_preview_layout
|
||||
|
||||
|
||||
class MappingAssignmentPreview(QWidget):
|
||||
tileClicked = Signal(str)
|
||||
|
||||
def __init__(self, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
self._config = InfinityMirrorConfig()
|
||||
self._discovered_devices: list[DiscoveredWledDevice] = []
|
||||
self._active_device: DiscoveredWledDevice | None = None
|
||||
self._selected_tile_id: str | None = None
|
||||
self._tile_rects: dict[str, QRectF] = {}
|
||||
|
||||
self.setMinimumSize(520, 360)
|
||||
self.setMouseTracking(True)
|
||||
|
||||
def set_assignment_state(
|
||||
self,
|
||||
config: InfinityMirrorConfig,
|
||||
discovered_devices: list[DiscoveredWledDevice],
|
||||
*,
|
||||
active_device: DiscoveredWledDevice | None = None,
|
||||
selected_tile_id: str | None = None,
|
||||
) -> None:
|
||||
self._config = config
|
||||
self._discovered_devices = list(discovered_devices)
|
||||
self._active_device = active_device
|
||||
self._selected_tile_id = selected_tile_id
|
||||
self.update()
|
||||
|
||||
def mousePressEvent(self, event) -> None:
|
||||
point = event_posf(event)
|
||||
for tile_id, rect in self._tile_rects.items():
|
||||
if rect.contains(point):
|
||||
self.tileClicked.emit(tile_id)
|
||||
break
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def paintEvent(self, event) -> None: # type: ignore[override]
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing, True)
|
||||
painter.setRenderHint(QPainter.TextAntialiasing, True)
|
||||
|
||||
rect = QRectF(self.rect())
|
||||
background = QLinearGradient(rect.topLeft(), rect.bottomRight())
|
||||
background.setColorAt(0.0, QColor("#12161D"))
|
||||
background.setColorAt(1.0, QColor("#1B2230"))
|
||||
painter.fillRect(rect, background)
|
||||
|
||||
if not self._config.tiles:
|
||||
painter.setPen(QColor("#A8B3C7"))
|
||||
painter.drawText(rect, Qt.AlignCenter, "Open a mapping to assign WLED devices.")
|
||||
return
|
||||
|
||||
layout = compute_preview_layout(rect, self._config)
|
||||
self._tile_rects = layout.tile_rects
|
||||
self._draw_canvas_shell(painter, layout.canvas_rect)
|
||||
|
||||
discovered_ips = {device.ip_address for device in self._discovered_devices}
|
||||
discovered_macs = {normalize_mac_address(device.mac_address) for device in self._discovered_devices if device.mac_address}
|
||||
active_tile_id = None
|
||||
if self._active_device is not None:
|
||||
for tile in self._config.sorted_tiles():
|
||||
if tile_matches_device(tile, self._active_device):
|
||||
active_tile_id = tile.tile_id
|
||||
break
|
||||
|
||||
for tile in self._config.sorted_tiles():
|
||||
tile_rect = layout.tile_rects[tile.tile_id]
|
||||
tile_assigned = bool(tile.controller_ip.strip() or tile.controller_mac.strip())
|
||||
tile_is_active = active_tile_id == tile.tile_id
|
||||
tile_is_selected = self._selected_tile_id == tile.tile_id
|
||||
|
||||
if tile_is_active:
|
||||
fill_color = QColor("#1D4E89")
|
||||
outline_color = QColor("#90CAF9")
|
||||
subtitle = self._active_device.instance_name or self._active_device.ip_address
|
||||
status = "Active Device"
|
||||
elif not tile_assigned:
|
||||
fill_color = QColor("#2A2F3A")
|
||||
outline_color = QColor("#4A5568")
|
||||
subtitle = "Unmapped"
|
||||
status = "Click to assign"
|
||||
elif (tile.controller_mac and normalize_mac_address(tile.controller_mac) in discovered_macs) or tile.controller_ip.strip() in discovered_ips:
|
||||
fill_color = QColor("#1D5A45")
|
||||
outline_color = QColor("#81E6D9")
|
||||
subtitle = tile.controller_name or tile.controller_host or tile.controller_ip
|
||||
status = "Mapped"
|
||||
else:
|
||||
fill_color = QColor("#6B4F1D")
|
||||
outline_color = QColor("#F6AD55")
|
||||
subtitle = tile.controller_name or tile.controller_host or tile.controller_ip
|
||||
status = "Assigned, not seen"
|
||||
|
||||
self._draw_tile(
|
||||
painter,
|
||||
rect=tile_rect,
|
||||
tile_id=tile.tile_id,
|
||||
row=tile.row,
|
||||
col=tile.col,
|
||||
subtitle=subtitle,
|
||||
status=status,
|
||||
fill_color=fill_color,
|
||||
outline_color=outline_color,
|
||||
selected=tile_is_selected,
|
||||
)
|
||||
|
||||
def _draw_canvas_shell(self, painter: QPainter, rect: QRectF) -> None:
|
||||
path = QPainterPath()
|
||||
path.addRoundedRect(rect, 10.0, 10.0)
|
||||
painter.fillPath(path, QColor("#202632"))
|
||||
painter.setPen(QPen(QColor("#334155"), 1.0))
|
||||
painter.drawPath(path)
|
||||
|
||||
def _draw_tile(
|
||||
self,
|
||||
painter: QPainter,
|
||||
*,
|
||||
rect: QRectF,
|
||||
tile_id: str,
|
||||
row: int,
|
||||
col: int,
|
||||
subtitle: str,
|
||||
status: str,
|
||||
fill_color: QColor,
|
||||
outline_color: QColor,
|
||||
selected: bool,
|
||||
) -> None:
|
||||
base = min(rect.width(), rect.height())
|
||||
rounding = max(4.0, base * 0.045)
|
||||
tile_path = QPainterPath()
|
||||
tile_path.addRoundedRect(rect, rounding, rounding)
|
||||
|
||||
painter.fillPath(tile_path, fill_color)
|
||||
|
||||
highlight = QLinearGradient(rect.topLeft(), rect.bottomLeft())
|
||||
highlight.setColorAt(0.0, QColor(255, 255, 255, 24))
|
||||
highlight.setColorAt(0.18, QColor(255, 255, 255, 8))
|
||||
highlight.setColorAt(1.0, QColor(0, 0, 0, 0))
|
||||
painter.fillPath(tile_path, highlight)
|
||||
|
||||
painter.setPen(QPen(outline_color, 1.3))
|
||||
painter.drawPath(tile_path)
|
||||
|
||||
if selected:
|
||||
painter.setPen(QPen(QColor("#E2E8F0"), 2.1))
|
||||
painter.drawRoundedRect(rect.adjusted(-3, -3, 3, 3), rounding + 2.0, rounding + 2.0)
|
||||
|
||||
padding_x = max(12.0, rect.width() * 0.08)
|
||||
padding_top = max(10.0, rect.height() * 0.08)
|
||||
padding_bottom = max(12.0, rect.height() * 0.08)
|
||||
|
||||
title_font = QFont()
|
||||
title_font.setPointSizeF(max(13.0, base * 0.1))
|
||||
title_font.setWeight(QFont.DemiBold)
|
||||
painter.setFont(title_font)
|
||||
painter.setPen(QColor("#F8FAFC"))
|
||||
painter.drawText(
|
||||
rect.adjusted(padding_x, padding_top, -padding_x, -rect.height() * 0.56),
|
||||
Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap,
|
||||
tile_id,
|
||||
)
|
||||
|
||||
meta_font = QFont(title_font)
|
||||
meta_font.setPointSizeF(max(9.2, base * 0.06))
|
||||
meta_font.setWeight(QFont.Normal)
|
||||
painter.setFont(meta_font)
|
||||
painter.setPen(QColor(235, 244, 249, 175))
|
||||
painter.drawText(
|
||||
rect.adjusted(padding_x, rect.height() * 0.48, -padding_x, -padding_bottom),
|
||||
Qt.AlignLeft | Qt.AlignBottom | Qt.TextWordWrap,
|
||||
f"{subtitle}\n{status} | R{row} C{col}",
|
||||
)
|
||||
Reference in New Issue
Block a user