From 3ea387dee971a833e61105fa8c3ce937625aad05 Mon Sep 17 00:00:00 2001 From: Ilya Zhuravlev Date: Sun, 4 Jul 2021 10:13:16 -0400 Subject: [PATCH] combos: add initial --- src/main/python/combos.py | 118 +++++++++++++++++++++++++++++++ src/main/python/keyboard_comm.py | 26 +++++++ src/main/python/main_window.py | 6 +- 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/main/python/combos.py diff --git a/src/main/python/combos.py b/src/main/python/combos.py new file mode 100644 index 0000000..ee17965 --- /dev/null +++ b/src/main/python/combos.py @@ -0,0 +1,118 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +from PyQt5 import QtCore +from PyQt5.QtCore import pyqtSignal, QObject +from PyQt5.QtWidgets import QTabWidget, QWidget, QSizePolicy, QGridLayout, QVBoxLayout, QLabel + +from key_widget import KeyWidget +from tabbed_keycodes import TabbedKeycodes +from vial_device import VialKeyboard +from basic_editor import BasicEditor + + +class ComboEntryUI(QObject): + + key_changed = pyqtSignal() + + def __init__(self, idx): + super().__init__() + + self.idx = idx + self.container = QGridLayout() + self.kc_inputs = [] + self.populate_container() + + w = QWidget() + w.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + w.setLayout(self.container) + l = QVBoxLayout() + l.addWidget(w) + l.setAlignment(w, QtCore.Qt.AlignHCenter) + self.w2 = QWidget() + self.w2.setLayout(l) + + def populate_container(self): + for x in range(4): + kc_widget = KeyWidget() + kc_widget.changed.connect(self.on_key_changed) + self.container.addWidget(QLabel("Key {}".format(x + 1)), x, 0) + self.container.addWidget(kc_widget, x, 1) + self.kc_inputs.append(kc_widget) + + self.kc_output = KeyWidget() + self.kc_output.changed.connect(self.on_key_changed) + self.container.addWidget(QLabel("Output key"), 4, 0) + self.container.addWidget(self.kc_output, 4, 1) + + def widget(self): + return self.w2 + + def load(self, data): + objs = self.kc_inputs + [self.kc_output] + for o in objs: + o.blockSignals(True) + + for x in range(4): + self.kc_inputs[x].set_keycode(data[x]) + self.kc_output.set_keycode(data[4]) + + for o in objs: + o.blockSignals(False) + + def save(self): + return ( + self.kc_inputs[0].keycode, + self.kc_inputs[1].keycode, + self.kc_inputs[2].keycode, + self.kc_inputs[3].keycode, + self.kc_output.keycode + ) + + def on_key_changed(self): + self.key_changed.emit() + + +class CustomTabWidget(QTabWidget): + + def mouseReleaseEvent(self, ev): + TabbedKeycodes.close_tray() + + +class Combos(BasicEditor): + + def __init__(self): + super().__init__() + self.keyboard = None + + self.combo_entries = [] + self.combo_entries_available = [] + self.tabs = CustomTabWidget() + for x in range(128): + entry = ComboEntryUI(x) + entry.key_changed.connect(self.on_key_changed) + self.combo_entries_available.append(entry) + + self.addWidget(self.tabs) + + def rebuild_ui(self): + while self.tabs.count() > 0: + self.tabs.removeTab(0) + self.combo_entries = self.combo_entries_available[:self.keyboard.combo_count] + for x, e in enumerate(self.combo_entries): + self.tabs.addTab(e.widget(), str(x + 1)) + for x, e in enumerate(self.combo_entries): + e.load(self.keyboard.combo_get(x)) + + def rebuild(self, device): + super().rebuild(device) + if self.valid(): + self.keyboard = device.keyboard + self.rebuild_ui() + + def valid(self): + return isinstance(self.device, VialKeyboard) and \ + (self.device.keyboard and self.device.keyboard.vial_protocol >= 4 + and self.device.keyboard.combo_count > 0) + + def on_key_changed(self): + for x, e in enumerate(self.combo_entries): + self.keyboard.combo_set(x, self.combo_entries[x].save()) diff --git a/src/main/python/keyboard_comm.py b/src/main/python/keyboard_comm.py index 33eb7bf..784fdc3 100644 --- a/src/main/python/keyboard_comm.py +++ b/src/main/python/keyboard_comm.py @@ -62,6 +62,8 @@ CMD_VIAL_DYNAMIC_ENTRY_OP = 0x0D DYNAMIC_VIAL_GET_NUMBER_OF_ENTRIES = 0x00 DYNAMIC_VIAL_TAP_DANCE_GET = 0x01 DYNAMIC_VIAL_TAP_DANCE_SET = 0x02 +DYNAMIC_VIAL_COMBO_GET = 0x03 +DYNAMIC_VIAL_COMBO_SET = 0x04 # how much of a macro/keymap buffer we can read/write per packet BUFFER_FETCH_CHUNK = 28 @@ -385,10 +387,14 @@ class Keyboard: if self.vial_protocol < 4: self.tap_dance_count = 0 self.tap_dance_entries = [] + self.combo_count = 0 + self.combo_entries = [] return data = self.usb_send(self.dev, struct.pack("BBB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_DYNAMIC_ENTRY_OP, DYNAMIC_VIAL_GET_NUMBER_OF_ENTRIES), retries=20) self.tap_dance_count = data[0] + self.combo_count = data[1] + self.tap_dance_entries = [] for x in range(self.tap_dance_count): data = self.usb_send(self.dev, struct.pack("BBBB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_DYNAMIC_ENTRY_OP, @@ -397,6 +403,15 @@ class Keyboard: raise RuntimeError("failed retrieving tapdance entry {} from the device".format(x)) self.tap_dance_entries.append(struct.unpack("