diff --git a/src/main/python/keyboard_comm.py b/src/main/python/keyboard_comm.py index 6335ccf..64c28bf 100644 --- a/src/main/python/keyboard_comm.py +++ b/src/main/python/keyboard_comm.py @@ -298,6 +298,18 @@ class Keyboard: data = self.usb_send(self.dev, struct.pack("BB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_GET_LOCK)) return data[0] + def get_lock_keys(self): + """ Return keys users have to hold to unlock the keyboard as a list of rowcols """ + + data = self.usb_send(self.dev, struct.pack("BB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_GET_LOCK)) + rowcol = [] + for x in range(15): + row = data[2 + x * 2] + col = data[3 + x * 2] + if row != 255 and col != 255: + rowcol.append((row, col)) + return rowcol + def unlock_start(self): self.usb_send(self.dev, struct.pack("BB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_UNLOCK_START)) diff --git a/src/main/python/keyboard_widget.py b/src/main/python/keyboard_widget.py index b50d092..a0c3aa6 100644 --- a/src/main/python/keyboard_widget.py +++ b/src/main/python/keyboard_widget.py @@ -10,6 +10,8 @@ from constants import KEY_WIDTH, KEY_SPACING, KEY_HEIGHT, KEYBOARD_WIDGET_PADDIN class KeyWidget: def __init__(self, desc, shift_x=0, shift_y=0): + self.active = False + self.masked = False self.desc = desc self.text = "" self.mask_text = "" @@ -88,6 +90,9 @@ class KeyWidget: def setToolTip(self, tooltip): self.tooltip = tooltip + def setActive(self, active): + self.active = active + class EncoderWidget(KeyWidget): @@ -117,6 +122,10 @@ class KeyboardWidget(QWidget): def __init__(self, layout_editor): super().__init__() + + self.enabled = True + self.scale = 1 + self.setMouseTracking(True) self.layout_editor = layout_editor @@ -192,8 +201,8 @@ class KeyboardWidget(QWidget): max_w = max_h = 0 for key in self.widgets: p = key.polygon.boundingRect().bottomRight() - max_w = max(max_w, p.x()) - max_h = max(max_h, p.y()) + max_w = max(max_w, p.x() * self.scale) + max_h = max(max_h, p.y() * self.scale) self.width = max_w + 2 * KEYBOARD_WIDGET_PADDING self.height = max_h + 2 * KEYBOARD_WIDGET_PADDING @@ -231,11 +240,12 @@ class KeyboardWidget(QWidget): for idx, key in enumerate(self.widgets): qp.save() + qp.scale(self.scale, self.scale) qp.translate(key.rotation_x, key.rotation_y) qp.rotate(key.rotation_angle) qp.translate(-key.rotation_x, -key.rotation_y) - if self.active_key == key and not self.active_mask: + if key.active or (self.active_key == key and not self.active_mask): qp.setPen(active_pen) qp.setBrush(active_brush) @@ -277,6 +287,9 @@ class KeyboardWidget(QWidget): return None, False def mousePressEvent(self, ev): + if not self.enabled: + return + self.active_key, self.active_mask = self.hit_test(ev.pos()) if self.active_key is not None: self.clicked.emit() @@ -299,6 +312,9 @@ class KeyboardWidget(QWidget): self.update() def event(self, ev): + if not self.enabled: + super().event(ev) + if ev.type() == QEvent.ToolTip: key = self.hit_test(ev.pos())[0] if key is not None: @@ -306,3 +322,9 @@ class KeyboardWidget(QWidget): else: QToolTip.hideText() return super().event(ev) + + def set_enabled(self, val): + self.enabled = val + + def set_scale(self, scale): + self.scale = scale diff --git a/src/main/python/main_window.py b/src/main/python/main_window.py index 6fd77f6..0548ae7 100644 --- a/src/main/python/main_window.py +++ b/src/main/python/main_window.py @@ -19,8 +19,6 @@ class MainWindow(QMainWindow): def __init__(self): super().__init__() - self.unlocker = Unlocker() - self.current_device = None self.devices = [] self.sideload_json = None @@ -45,6 +43,7 @@ class MainWindow(QMainWindow): self.editors = [(self.keymap_editor, "Keymap"), (self.layout_editor, "Layout"), (self.macro_recorder, "Macros"), (self.firmware_flasher, "Firmware updater")] + self.unlocker = Unlocker(self.layout_editor) self.tabs = QTabWidget() self.refresh_tabs() diff --git a/src/main/python/unlocker.py b/src/main/python/unlocker.py index cdf2c6b..45253a3 100644 --- a/src/main/python/unlocker.py +++ b/src/main/python/unlocker.py @@ -4,12 +4,13 @@ import time from PyQt5.QtCore import QCoreApplication, Qt from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QProgressBar +from keyboard_widget import KeyboardWidget from util import tr class Unlocker(QWidget): - def __init__(self): + def __init__(self, layout_editor): super().__init__() self.keyboard = None @@ -23,7 +24,11 @@ class Unlocker(QWidget): layout.addWidget(QLabel(tr("Unlocker", "Press and hold the following keys until the progress bar " "below fills up:"))) - # TODO: add image/text reference of keys user needs to hold + self.keyboard_reference = KeyboardWidget(layout_editor) + self.keyboard_reference.set_enabled(False) + self.keyboard_reference.set_scale(0.5) + layout.addWidget(self.keyboard_reference) + layout.setAlignment(self.keyboard_reference, Qt.AlignHCenter) layout.addWidget(self.progress) @@ -36,11 +41,29 @@ class Unlocker(QWidget): def get(cls): return cls.obj + def update_reference(self, keyboard): + """ Updates keycap reference image """ + + self.keyboard_reference.set_keys(keyboard.keys, keyboard.encoders) + + # use "active" background to indicate keys to hold + lock_keys = keyboard.get_lock_keys() + for w in self.keyboard_reference.widgets: + if (w.desc.row, w.desc.col) in lock_keys: + w.setActive(True) + + self.keyboard_reference.update_layout() + self.keyboard_reference.update() + self.keyboard_reference.updateGeometry() + def perform_unlock(self, keyboard): # if it's already unlocked, don't need to do anything - if keyboard.get_lock() == 0: + lock = keyboard.get_lock() + if lock == 0: return + self.update_reference(keyboard) + self.progress.setMaximum(1) self.progress.setValue(0) @@ -64,3 +87,6 @@ class Unlocker(QWidget): # ok all done, the keyboard is now set to insecure state self.hide() + + def closeEvent(self, ev): + ev.ignore()