77 lines
3.1 KiB
Python
77 lines
3.1 KiB
Python
"""Matter pairing QR code on screen, so the technician can scan it from the laptop."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import segno
|
|
from PySide6.QtCore import Qt
|
|
from PySide6.QtGui import QColor, QImage, QPainter, QPixmap
|
|
from PySide6.QtWidgets import QDialog, QDialogButtonBox, QLabel, QVBoxLayout, QWidget
|
|
|
|
from ..matter.payload import SetupPayload
|
|
|
|
|
|
def qr_pixmap(text: str, size: int = 260) -> QPixmap:
|
|
"""Black-on-white QR with the quiet zone phones need (4 modules)."""
|
|
qr = segno.make(text, error="m")
|
|
matrix = [list(row) for row in qr.matrix_iter(scale=1, border=4)]
|
|
n = len(matrix)
|
|
module = max(1, size // n)
|
|
img = QImage(n * module, n * module, QImage.Format.Format_RGB32)
|
|
img.fill(QColor("white"))
|
|
p = QPainter(img)
|
|
p.setPen(Qt.PenStyle.NoPen)
|
|
p.setBrush(QColor("black"))
|
|
for y, row in enumerate(matrix):
|
|
for x, dark in enumerate(row):
|
|
if dark:
|
|
p.drawRect(x * module, y * module, module, module)
|
|
p.end()
|
|
return QPixmap.fromImage(img)
|
|
|
|
|
|
class MatterQrWidget(QWidget):
|
|
def __init__(self, payload: SetupPayload, size: int = 260, parent: QWidget | None = None):
|
|
super().__init__(parent)
|
|
self.image = QLabel()
|
|
self.image.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
self.code = QLabel()
|
|
self.code.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
self.code.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
|
|
f = self.code.font()
|
|
f.setPointSize(f.pointSize() + 4)
|
|
f.setBold(True)
|
|
self.code.setFont(f)
|
|
self.note = QLabel(wordWrap=True)
|
|
self.note.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
self.note.setStyleSheet("color:#555")
|
|
lay = QVBoxLayout(self)
|
|
lay.addWidget(self.image)
|
|
lay.addWidget(self.code)
|
|
lay.addWidget(self.note)
|
|
self._size = size
|
|
self.set_payload(payload)
|
|
|
|
def set_payload(self, payload: SetupPayload) -> None:
|
|
self.payload = payload
|
|
self.image.setPixmap(qr_pixmap(payload.qr_text(), self._size))
|
|
self.code.setText(f"Manual code: {payload.manual_code_pretty()}")
|
|
if payload.from_box:
|
|
src = "QR and manual code exactly as reported by the box (KOTA: matter line)"
|
|
else:
|
|
src = f"Discriminator {payload.discriminator} " + (
|
|
"(from this box's log)" if payload.from_log else
|
|
"(standard code of the v1.0 firmware - connect the box to confirm)")
|
|
self.note.setText(f"Scan with the Matter app (Apple Home, Google Home, ...), or type the manual code. "
|
|
f"{src}. Same as the sticker on the box.")
|
|
|
|
|
|
class MatterQrDialog(QDialog):
|
|
def __init__(self, payload: SetupPayload, parent: QWidget | None = None):
|
|
super().__init__(parent)
|
|
self.setWindowTitle("Matter pairing code")
|
|
lay = QVBoxLayout(self)
|
|
lay.addWidget(MatterQrWidget(payload, 320))
|
|
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
|
|
buttons.rejected.connect(self.reject)
|
|
lay.addWidget(buttons)
|