mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-13 01:58:08 +00:00
45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
from typing import Sequence
|
|
|
|
from trezor import ui
|
|
from trezor.ui.constants import QR_SIDE_MAX
|
|
|
|
_QR_WIDTHS = (21, 25, 29, 33, 37, 41, 45, 49, 53, 57)
|
|
_THRESHOLDS_BINARY = (14, 26, 42, 62, 84, 106, 122, 152, 180, 213)
|
|
_THRESHOLDS_ALPHANUM = (20, 38, 61, 90, 122, 154, 178, 221, 262, 311)
|
|
|
|
|
|
def _qr_version_index(data: str, thresholds: Sequence[int]) -> int:
|
|
for i, threshold in enumerate(thresholds):
|
|
if len(data) <= threshold:
|
|
return i
|
|
raise ValueError # data too long
|
|
|
|
|
|
def is_alphanum_only(data: str) -> bool:
|
|
return all(c in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $*+-./:" for c in data)
|
|
|
|
|
|
class Qr(ui.Component):
|
|
def __init__(self, data: str, case_sensitive: bool, x: int, y: int) -> None:
|
|
super().__init__()
|
|
if case_sensitive and not is_alphanum_only(data):
|
|
# must encode in BINARY mode
|
|
version_idx = _qr_version_index(data, _THRESHOLDS_BINARY)
|
|
else:
|
|
# can make the QR code more readable by using the best version
|
|
version_idx = _qr_version_index(data, _THRESHOLDS_ALPHANUM)
|
|
if len(data) > _THRESHOLDS_BINARY[version_idx]:
|
|
data = data.upper()
|
|
|
|
size = _QR_WIDTHS[version_idx]
|
|
|
|
self.data = data
|
|
self.x = x
|
|
self.y = y
|
|
self.scale = QR_SIDE_MAX // size
|
|
|
|
def on_render(self) -> None:
|
|
if self.repaint:
|
|
ui.display.qrcode(self.x, self.y, self.data, self.scale)
|
|
self.repaint = False
|