Merge branch 'tap-dance' into next
commit
b777d861d7
|
|
@ -0,0 +1,61 @@
|
||||||
|
from PyQt5.QtCore import pyqtSignal
|
||||||
|
|
||||||
|
from any_keycode_dialog import AnyKeycodeDialog
|
||||||
|
from keyboard_widget import KeyboardWidget
|
||||||
|
from kle_serial import Key
|
||||||
|
from tabbed_keycodes import TabbedKeycodes
|
||||||
|
from util import KeycodeDisplay
|
||||||
|
|
||||||
|
|
||||||
|
class KeyWidget(KeyboardWidget):
|
||||||
|
|
||||||
|
changed = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(None)
|
||||||
|
|
||||||
|
self.padding = 1
|
||||||
|
|
||||||
|
self.keycode = 0
|
||||||
|
|
||||||
|
key = Key()
|
||||||
|
key.row = key.col = 0
|
||||||
|
key.layout_index = key.layout_option = -1
|
||||||
|
self.set_keys([key], [])
|
||||||
|
|
||||||
|
self.anykey.connect(self.on_anykey)
|
||||||
|
|
||||||
|
def mousePressEvent(self, ev):
|
||||||
|
super().mousePressEvent(ev)
|
||||||
|
if self.active_key is not None:
|
||||||
|
TabbedKeycodes.open_tray(self)
|
||||||
|
else:
|
||||||
|
TabbedKeycodes.close_tray()
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
ev.accept()
|
||||||
|
|
||||||
|
def on_keycode_changed(self, keycode):
|
||||||
|
""" Unlike set_keycode, this handles setting masked keycode inside the mask """
|
||||||
|
|
||||||
|
if self.active_mask:
|
||||||
|
if keycode > 0xFF:
|
||||||
|
return
|
||||||
|
keycode = (self.keycode & 0xFF00) | keycode
|
||||||
|
self.set_keycode(keycode)
|
||||||
|
|
||||||
|
def on_anykey(self):
|
||||||
|
if self.active_key is None:
|
||||||
|
return
|
||||||
|
dlg = AnyKeycodeDialog(self.keycode)
|
||||||
|
if dlg.exec_() and dlg.value >= 0:
|
||||||
|
self.set_keycode(dlg.value)
|
||||||
|
|
||||||
|
def set_keycode(self, kc):
|
||||||
|
if kc == self.keycode:
|
||||||
|
return
|
||||||
|
self.keycode = kc
|
||||||
|
KeycodeDisplay.display_keycode(self.widgets[0], self.keycode)
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
self.changed.emit()
|
||||||
|
|
@ -57,6 +57,12 @@ CMD_VIAL_QMK_SETTINGS_GET = 0x0A
|
||||||
CMD_VIAL_QMK_SETTINGS_SET = 0x0B
|
CMD_VIAL_QMK_SETTINGS_SET = 0x0B
|
||||||
CMD_VIAL_QMK_SETTINGS_RESET = 0x0C
|
CMD_VIAL_QMK_SETTINGS_RESET = 0x0C
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
# how much of a macro/keymap buffer we can read/write per packet
|
# how much of a macro/keymap buffer we can read/write per packet
|
||||||
BUFFER_FETCH_CHUNK = 28
|
BUFFER_FETCH_CHUNK = 28
|
||||||
|
|
||||||
|
|
@ -207,6 +213,7 @@ class Keyboard:
|
||||||
self.reload_keymap()
|
self.reload_keymap()
|
||||||
self.reload_macros()
|
self.reload_macros()
|
||||||
self.reload_rgb()
|
self.reload_rgb()
|
||||||
|
self.reload_dynamic()
|
||||||
|
|
||||||
def reload_layers(self):
|
def reload_layers(self):
|
||||||
""" Get how many layers the keyboard has """
|
""" Get how many layers the keyboard has """
|
||||||
|
|
@ -374,6 +381,22 @@ class Keyboard:
|
||||||
self.backlight_effect = self.usb_send(
|
self.backlight_effect = self.usb_send(
|
||||||
self.dev, struct.pack(">BB", CMD_VIA_LIGHTING_GET_VALUE, QMK_BACKLIGHT_EFFECT), retries=20)[2]
|
self.dev, struct.pack(">BB", CMD_VIA_LIGHTING_GET_VALUE, QMK_BACKLIGHT_EFFECT), retries=20)[2]
|
||||||
|
|
||||||
|
def reload_dynamic(self):
|
||||||
|
if self.vial_protocol < 4:
|
||||||
|
self.tap_dance_count = 0
|
||||||
|
self.tap_dance_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.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,
|
||||||
|
DYNAMIC_VIAL_TAP_DANCE_GET, x), retries=20)
|
||||||
|
if data[0] != 0:
|
||||||
|
raise RuntimeError("failed retrieving tapdance entry {} from the device".format(x))
|
||||||
|
self.tap_dance_entries.append(struct.unpack("<HHHHH", data[1:11]))
|
||||||
|
|
||||||
def set_key(self, layer, row, col, code):
|
def set_key(self, layer, row, col, code):
|
||||||
if code < 0:
|
if code < 0:
|
||||||
return
|
return
|
||||||
|
|
@ -477,6 +500,7 @@ class Keyboard:
|
||||||
data["macro"] = self.save_macro()
|
data["macro"] = self.save_macro()
|
||||||
data["vial_protocol"] = self.vial_protocol
|
data["vial_protocol"] = self.vial_protocol
|
||||||
data["via_protocol"] = self.via_protocol
|
data["via_protocol"] = self.via_protocol
|
||||||
|
data["tap_dance"] = self.tap_dance_entries
|
||||||
|
|
||||||
return json.dumps(data).encode("utf-8")
|
return json.dumps(data).encode("utf-8")
|
||||||
|
|
||||||
|
|
@ -508,6 +532,10 @@ class Keyboard:
|
||||||
self.set_layout_options(data["layout_options"])
|
self.set_layout_options(data["layout_options"])
|
||||||
self.restore_macros(data.get("macro"))
|
self.restore_macros(data.get("macro"))
|
||||||
|
|
||||||
|
for x, e in enumerate(data.get("tap_dance", [])):
|
||||||
|
if x < self.tap_dance_count:
|
||||||
|
self.tap_dance_set(x, e)
|
||||||
|
|
||||||
def restore_macros(self, macros):
|
def restore_macros(self, macros):
|
||||||
if not isinstance(macros, list):
|
if not isinstance(macros, list):
|
||||||
return
|
return
|
||||||
|
|
@ -670,6 +698,17 @@ class Keyboard:
|
||||||
def qmk_settings_reset(self):
|
def qmk_settings_reset(self):
|
||||||
self.usb_send(self.dev, struct.pack("BB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_QMK_SETTINGS_RESET))
|
self.usb_send(self.dev, struct.pack("BB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_QMK_SETTINGS_RESET))
|
||||||
|
|
||||||
|
def tap_dance_get(self, idx):
|
||||||
|
return self.tap_dance_entries[idx]
|
||||||
|
|
||||||
|
def tap_dance_set(self, idx, entry):
|
||||||
|
if self.tap_dance_entries[idx] == entry:
|
||||||
|
return
|
||||||
|
self.tap_dance_entries[idx] = entry
|
||||||
|
serialized = struct.pack("<HHHHH", *self.tap_dance_entries[idx])
|
||||||
|
self.usb_send(self.dev, struct.pack("BBBB", CMD_VIA_VIAL_PREFIX, CMD_VIAL_DYNAMIC_ENTRY_OP,
|
||||||
|
DYNAMIC_VIAL_TAP_DANCE_SET, idx) + serialized, retries=20)
|
||||||
|
|
||||||
|
|
||||||
class DummyKeyboard(Keyboard):
|
class DummyKeyboard(Keyboard):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ from PyQt5.QtGui import QPainter, QColor, QPainterPath, QTransform, QBrush, QPol
|
||||||
from PyQt5.QtWidgets import QWidget, QToolTip, QApplication
|
from PyQt5.QtWidgets import QWidget, QToolTip, QApplication
|
||||||
from PyQt5.QtCore import Qt, QSize, QRect, QPointF, pyqtSignal, QEvent, QRectF
|
from PyQt5.QtCore import Qt, QSize, QRect, QPointF, pyqtSignal, QEvent, QRectF
|
||||||
|
|
||||||
from constants import KEY_SIZE_RATIO, KEY_SPACING_RATIO, KEYBOARD_WIDGET_PADDING, KEYBOARD_WIDGET_MASK_PADDING, KEYBOARD_WIDGET_MASK_HEIGHT, KEY_ROUNDNESS
|
from constants import KEY_SIZE_RATIO, KEY_SPACING_RATIO, KEYBOARD_WIDGET_PADDING, KEYBOARD_WIDGET_MASK_PADDING,\
|
||||||
|
KEYBOARD_WIDGET_MASK_HEIGHT, KEY_ROUNDNESS
|
||||||
|
|
||||||
|
|
||||||
class KeyWidget:
|
class KeyWidget:
|
||||||
|
|
@ -166,6 +167,7 @@ class KeyboardWidget(QWidget):
|
||||||
|
|
||||||
self.enabled = True
|
self.enabled = True
|
||||||
self.scale = 1
|
self.scale = 1
|
||||||
|
self.padding = KEYBOARD_WIDGET_PADDING
|
||||||
|
|
||||||
self.setMouseTracking(True)
|
self.setMouseTracking(True)
|
||||||
|
|
||||||
|
|
@ -215,7 +217,7 @@ class KeyboardWidget(QWidget):
|
||||||
|
|
||||||
# place common widgets, that is, ones which are always displayed and require no extra transforms
|
# place common widgets, that is, ones which are always displayed and require no extra transforms
|
||||||
for widget in self.common_widgets:
|
for widget in self.common_widgets:
|
||||||
widget.update_position(scale_factor, -top_x + KEYBOARD_WIDGET_PADDING, -top_y + KEYBOARD_WIDGET_PADDING)
|
widget.update_position(scale_factor, -top_x + self.padding, -top_y + self.padding)
|
||||||
self.widgets.append(widget)
|
self.widgets.append(widget)
|
||||||
|
|
||||||
# top-left position for specific layout
|
# top-left position for specific layout
|
||||||
|
|
@ -236,7 +238,7 @@ class KeyboardWidget(QWidget):
|
||||||
if opt == self.layout_editor.get_choice(idx):
|
if opt == self.layout_editor.get_choice(idx):
|
||||||
shift_x = layout_x[idx][opt] - layout_x[idx][0]
|
shift_x = layout_x[idx][opt] - layout_x[idx][0]
|
||||||
shift_y = layout_y[idx][opt] - layout_y[idx][0]
|
shift_y = layout_y[idx][opt] - layout_y[idx][0]
|
||||||
widget.update_position(scale_factor, -shift_x - top_x + KEYBOARD_WIDGET_PADDING, -shift_y - top_y + KEYBOARD_WIDGET_PADDING)
|
widget.update_position(scale_factor, -shift_x - top_x + self.padding, -shift_y - top_y + self.padding)
|
||||||
self.widgets.append(widget)
|
self.widgets.append(widget)
|
||||||
|
|
||||||
def update_layout(self):
|
def update_layout(self):
|
||||||
|
|
@ -255,8 +257,8 @@ class KeyboardWidget(QWidget):
|
||||||
max_w = max(max_w, p.x() * self.scale)
|
max_w = max(max_w, p.x() * self.scale)
|
||||||
max_h = max(max_h, p.y() * self.scale)
|
max_h = max(max_h, p.y() * self.scale)
|
||||||
|
|
||||||
self.width = max_w + 2 * KEYBOARD_WIDGET_PADDING
|
self.width = max_w + 2 * self.padding
|
||||||
self.height = max_h + 2 * KEYBOARD_WIDGET_PADDING
|
self.height = max_h + 2 * self.padding
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
self.updateGeometry()
|
self.updateGeometry()
|
||||||
|
|
|
||||||
|
|
@ -524,6 +524,8 @@ KEYCODES_MEDIA = [
|
||||||
K(132, "KC_LSCR", "Locking\nScroll", "Locking Scroll Lock", alias=["KC_LOCKING_SCROLL"]),
|
K(132, "KC_LSCR", "Locking\nScroll", "Locking Scroll Lock", alias=["KC_LOCKING_SCROLL"]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
KEYCODES_TAP_DANCE = []
|
||||||
|
|
||||||
KEYCODES_USER = []
|
KEYCODES_USER = []
|
||||||
|
|
||||||
KEYCODES_MACRO = []
|
KEYCODES_MACRO = []
|
||||||
|
|
@ -544,8 +546,8 @@ def recreate_keycodes():
|
||||||
|
|
||||||
KEYCODES.clear()
|
KEYCODES.clear()
|
||||||
KEYCODES.extend(KEYCODES_SPECIAL + KEYCODES_BASIC + KEYCODES_SHIFTED + KEYCODES_ISO + KEYCODES_LAYERS +
|
KEYCODES.extend(KEYCODES_SPECIAL + KEYCODES_BASIC + KEYCODES_SHIFTED + KEYCODES_ISO + KEYCODES_LAYERS +
|
||||||
KEYCODES_QUANTUM + KEYCODES_BACKLIGHT + KEYCODES_MEDIA + KEYCODES_MACRO + KEYCODES_USER +
|
KEYCODES_QUANTUM + KEYCODES_BACKLIGHT + KEYCODES_MEDIA + KEYCODES_TAP_DANCE + KEYCODES_MACRO +
|
||||||
KEYCODES_HIDDEN)
|
KEYCODES_USER + KEYCODES_HIDDEN)
|
||||||
|
|
||||||
|
|
||||||
def create_user_keycodes():
|
def create_user_keycodes():
|
||||||
|
|
@ -608,6 +610,10 @@ def recreate_keyboard_keycodes(keyboard):
|
||||||
lbl = "M{}".format(x)
|
lbl = "M{}".format(x)
|
||||||
KEYCODES_MACRO.append(Keycode(0x5F12 + x, lbl, lbl))
|
KEYCODES_MACRO.append(Keycode(0x5F12 + x, lbl, lbl))
|
||||||
|
|
||||||
|
for x in range(keyboard.tap_dance_count):
|
||||||
|
lbl = "TD({})".format(x)
|
||||||
|
KEYCODES_TAP_DANCE.append(Keycode(QK_TAP_DANCE | x, lbl, lbl))
|
||||||
|
|
||||||
# Check if custom keycodes are defined in keyboard, and if so add them to user keycodes
|
# Check if custom keycodes are defined in keyboard, and if so add them to user keycodes
|
||||||
if keyboard.custom_keycodes is not None and len(keyboard.custom_keycodes) > 0:
|
if keyboard.custom_keycodes is not None and len(keyboard.custom_keycodes) > 0:
|
||||||
create_custom_user_keycodes(keyboard.custom_keycodes)
|
create_custom_user_keycodes(keyboard.custom_keycodes)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from PyQt5.QtGui import QPalette
|
from PyQt5.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QMessageBox
|
||||||
from PyQt5.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QMessageBox, QApplication
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
from any_keycode_dialog import AnyKeycodeDialog
|
from any_keycode_dialog import AnyKeycodeDialog
|
||||||
|
|
@ -12,7 +11,7 @@ from keycodes import recreate_keyboard_keycodes, Keycode
|
||||||
from keymaps import KEYMAPS
|
from keymaps import KEYMAPS
|
||||||
from square_button import SquareButton
|
from square_button import SquareButton
|
||||||
from tabbed_keycodes import TabbedKeycodes
|
from tabbed_keycodes import TabbedKeycodes
|
||||||
from util import tr
|
from util import tr, KeycodeDisplay
|
||||||
from vial_device import VialKeyboard
|
from vial_device import VialKeyboard
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -48,8 +47,6 @@ class KeymapEditor(BasicEditor):
|
||||||
|
|
||||||
layout_editor.changed.connect(self.on_layout_changed)
|
layout_editor.changed.connect(self.on_layout_changed)
|
||||||
|
|
||||||
self.keymap_override = KEYMAPS[0][1]
|
|
||||||
|
|
||||||
self.container.anykey.connect(self.on_any_keycode)
|
self.container.anykey.connect(self.on_any_keycode)
|
||||||
|
|
||||||
self.tabbed_keycodes = TabbedKeycodes()
|
self.tabbed_keycodes = TabbedKeycodes()
|
||||||
|
|
@ -60,6 +57,7 @@ class KeymapEditor(BasicEditor):
|
||||||
self.addWidget(self.tabbed_keycodes)
|
self.addWidget(self.tabbed_keycodes)
|
||||||
|
|
||||||
self.device = None
|
self.device = None
|
||||||
|
KeycodeDisplay.notify_keymap_override(self)
|
||||||
|
|
||||||
def on_container_clicked(self):
|
def on_container_clicked(self):
|
||||||
""" Called when a mouse click event is bubbled up to the editor's container """
|
""" Called when a mouse click event is bubbled up to the editor's container """
|
||||||
|
|
@ -115,6 +113,7 @@ class KeymapEditor(BasicEditor):
|
||||||
|
|
||||||
recreate_keyboard_keycodes(self.keyboard)
|
recreate_keyboard_keycodes(self.keyboard)
|
||||||
self.tabbed_keycodes.recreate_keycode_buttons()
|
self.tabbed_keycodes.recreate_keycode_buttons()
|
||||||
|
TabbedKeycodes.tray.recreate_keycode_buttons()
|
||||||
self.refresh_layer_display()
|
self.refresh_layer_display()
|
||||||
self.container.setEnabled(self.valid())
|
self.container.setEnabled(self.valid())
|
||||||
|
|
||||||
|
|
@ -135,11 +134,6 @@ class KeymapEditor(BasicEditor):
|
||||||
self.keyboard.restore_layout(data)
|
self.keyboard.restore_layout(data)
|
||||||
self.refresh_layer_display()
|
self.refresh_layer_display()
|
||||||
|
|
||||||
def set_keymap_override(self, override):
|
|
||||||
self.keymap_override = override
|
|
||||||
self.refresh_layer_display()
|
|
||||||
self.tabbed_keycodes.set_keymap_override(override)
|
|
||||||
|
|
||||||
def on_any_keycode(self):
|
def on_any_keycode(self):
|
||||||
if self.container.active_key is None:
|
if self.container.active_key is None:
|
||||||
return
|
return
|
||||||
|
|
@ -148,17 +142,6 @@ class KeymapEditor(BasicEditor):
|
||||||
if dlg.exec_() and dlg.value >= 0:
|
if dlg.exec_() and dlg.value >= 0:
|
||||||
self.on_keycode_changed(dlg.value)
|
self.on_keycode_changed(dlg.value)
|
||||||
|
|
||||||
def code_is_overriden(self, code):
|
|
||||||
""" Check whether a country-specific keymap overrides a code """
|
|
||||||
key = Keycode.find_outer_keycode(code)
|
|
||||||
return key is not None and key.qmk_id in self.keymap_override
|
|
||||||
|
|
||||||
def get_label(self, code):
|
|
||||||
""" Get label for a specific keycode """
|
|
||||||
if self.code_is_overriden(code):
|
|
||||||
return self.keymap_override[Keycode.find_outer_keycode(code).qmk_id]
|
|
||||||
return Keycode.label(code)
|
|
||||||
|
|
||||||
def code_for_widget(self, widget):
|
def code_for_widget(self, widget):
|
||||||
if widget.desc.row is not None:
|
if widget.desc.row is not None:
|
||||||
return self.keyboard.layout[(self.current_layer, widget.desc.row, widget.desc.col)]
|
return self.keyboard.layout[(self.current_layer, widget.desc.row, widget.desc.col)]
|
||||||
|
|
@ -177,20 +160,7 @@ class KeymapEditor(BasicEditor):
|
||||||
|
|
||||||
for widget in self.container.widgets:
|
for widget in self.container.widgets:
|
||||||
code = self.code_for_widget(widget)
|
code = self.code_for_widget(widget)
|
||||||
text = self.get_label(code)
|
KeycodeDisplay.display_keycode(widget, code)
|
||||||
tooltip = Keycode.tooltip(code)
|
|
||||||
mask = Keycode.is_mask(code)
|
|
||||||
mask_text = self.get_label(code & 0xFF)
|
|
||||||
if mask:
|
|
||||||
text = text.split("\n")[0]
|
|
||||||
widget.masked = mask
|
|
||||||
widget.setText(text)
|
|
||||||
widget.setMaskText(mask_text)
|
|
||||||
widget.setToolTip(tooltip)
|
|
||||||
if self.code_is_overriden(code):
|
|
||||||
widget.setColor(QApplication.palette().color(QPalette.Link))
|
|
||||||
else:
|
|
||||||
widget.setColor(None)
|
|
||||||
self.container.update()
|
self.container.update()
|
||||||
self.container.updateGeometry()
|
self.container.updateGeometry()
|
||||||
|
|
||||||
|
|
@ -245,3 +215,6 @@ class KeymapEditor(BasicEditor):
|
||||||
|
|
||||||
self.refresh_layer_display()
|
self.refresh_layer_display()
|
||||||
self.keyboard.set_layout_options(self.layout_editor.pack())
|
self.keyboard.set_layout_options(self.layout_editor.pack())
|
||||||
|
|
||||||
|
def on_keymap_override(self):
|
||||||
|
self.refresh_layer_display()
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@ from layout_editor import LayoutEditor
|
||||||
from macro_recorder import MacroRecorder
|
from macro_recorder import MacroRecorder
|
||||||
from qmk_settings import QmkSettings
|
from qmk_settings import QmkSettings
|
||||||
from rgb_configurator import RGBConfigurator
|
from rgb_configurator import RGBConfigurator
|
||||||
|
from tabbed_keycodes import TabbedKeycodes
|
||||||
|
from tap_dance import TapDance
|
||||||
from unlocker import Unlocker
|
from unlocker import Unlocker
|
||||||
from util import tr, find_vial_devices, EXAMPLE_KEYBOARDS
|
from util import tr, find_vial_devices, EXAMPLE_KEYBOARDS, KeycodeDisplay
|
||||||
from vial_device import VialKeyboard
|
from vial_device import VialKeyboard
|
||||||
from matrix_test import MatrixTest
|
from matrix_test import MatrixTest
|
||||||
|
|
||||||
|
|
@ -58,12 +60,14 @@ class MainWindow(QMainWindow):
|
||||||
self.keymap_editor = KeymapEditor(self.layout_editor)
|
self.keymap_editor = KeymapEditor(self.layout_editor)
|
||||||
self.firmware_flasher = FirmwareFlasher(self)
|
self.firmware_flasher = FirmwareFlasher(self)
|
||||||
self.macro_recorder = MacroRecorder()
|
self.macro_recorder = MacroRecorder()
|
||||||
|
self.tap_dance = TapDance()
|
||||||
self.qmk_settings = QmkSettings(self.appctx)
|
self.qmk_settings = QmkSettings(self.appctx)
|
||||||
self.matrix_tester = MatrixTest(self.layout_editor)
|
self.matrix_tester = MatrixTest(self.layout_editor)
|
||||||
self.rgb_configurator = RGBConfigurator()
|
self.rgb_configurator = RGBConfigurator()
|
||||||
|
|
||||||
self.editors = [(self.keymap_editor, "Keymap"), (self.layout_editor, "Layout"), (self.macro_recorder, "Macros"),
|
self.editors = [(self.keymap_editor, "Keymap"), (self.layout_editor, "Layout"), (self.macro_recorder, "Macros"),
|
||||||
(self.rgb_configurator, "Lighting"), (self.qmk_settings, "QMK Settings"),
|
(self.rgb_configurator, "Lighting"), (self.tap_dance, "Tap Dance"),
|
||||||
|
(self.qmk_settings, "QMK Settings"),
|
||||||
(self.matrix_tester, "Matrix tester"), (self.firmware_flasher, "Firmware updater")]
|
(self.matrix_tester, "Matrix tester"), (self.firmware_flasher, "Firmware updater")]
|
||||||
|
|
||||||
Unlocker.global_layout_editor = self.layout_editor
|
Unlocker.global_layout_editor = self.layout_editor
|
||||||
|
|
@ -88,6 +92,10 @@ class MainWindow(QMainWindow):
|
||||||
layout.addWidget(self.tabs)
|
layout.addWidget(self.tabs)
|
||||||
layout.addWidget(self.lbl_no_devices)
|
layout.addWidget(self.lbl_no_devices)
|
||||||
layout.setAlignment(self.lbl_no_devices, Qt.AlignHCenter)
|
layout.setAlignment(self.lbl_no_devices, Qt.AlignHCenter)
|
||||||
|
self.tray_keycodes = TabbedKeycodes()
|
||||||
|
self.tray_keycodes.make_tray()
|
||||||
|
layout.addWidget(self.tray_keycodes)
|
||||||
|
self.tray_keycodes.hide()
|
||||||
w = QWidget()
|
w = QWidget()
|
||||||
w.setLayout(layout)
|
w.setLayout(layout)
|
||||||
self.setCentralWidget(w)
|
self.setCentralWidget(w)
|
||||||
|
|
@ -257,7 +265,7 @@ class MainWindow(QMainWindow):
|
||||||
self.current_device.keyboard.reload()
|
self.current_device.keyboard.reload()
|
||||||
|
|
||||||
for e in [self.layout_editor, self.keymap_editor, self.firmware_flasher, self.macro_recorder,
|
for e in [self.layout_editor, self.keymap_editor, self.firmware_flasher, self.macro_recorder,
|
||||||
self.qmk_settings, self.matrix_tester, self.rgb_configurator]:
|
self.tap_dance, self.qmk_settings, self.matrix_tester, self.rgb_configurator]:
|
||||||
e.rebuild(self.current_device)
|
e.rebuild(self.current_device)
|
||||||
|
|
||||||
def refresh_tabs(self):
|
def refresh_tabs(self):
|
||||||
|
|
@ -327,7 +335,7 @@ class MainWindow(QMainWindow):
|
||||||
|
|
||||||
def change_keyboard_layout(self, index):
|
def change_keyboard_layout(self, index):
|
||||||
self.settings.setValue("keymap", KEYMAPS[index][0])
|
self.settings.setValue("keymap", KEYMAPS[index][0])
|
||||||
self.keymap_editor.set_keymap_override(KEYMAPS[index][1])
|
KeycodeDisplay.set_keymap_override(KEYMAPS[index][1])
|
||||||
|
|
||||||
def get_theme(self):
|
def get_theme(self):
|
||||||
return self.settings.value("theme", "Dark")
|
return self.settings.value("theme", "Dark")
|
||||||
|
|
@ -340,6 +348,7 @@ class MainWindow(QMainWindow):
|
||||||
msg.exec_()
|
msg.exec_()
|
||||||
|
|
||||||
def on_tab_changed(self, index):
|
def on_tab_changed(self, index):
|
||||||
|
TabbedKeycodes.close_tray()
|
||||||
old_tab = self.current_tab
|
old_tab = self.current_tab
|
||||||
new_tab = None
|
new_tab = None
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,9 @@ from PyQt5.QtGui import QPalette
|
||||||
from constants import KEYCODE_BTN_RATIO
|
from constants import KEYCODE_BTN_RATIO
|
||||||
from flowlayout import FlowLayout
|
from flowlayout import FlowLayout
|
||||||
from keycodes import KEYCODES_BASIC, KEYCODES_ISO, KEYCODES_MACRO, KEYCODES_LAYERS, KEYCODES_QUANTUM, \
|
from keycodes import KEYCODES_BASIC, KEYCODES_ISO, KEYCODES_MACRO, KEYCODES_LAYERS, KEYCODES_QUANTUM, \
|
||||||
KEYCODES_BACKLIGHT, KEYCODES_MEDIA, KEYCODES_SPECIAL, KEYCODES_SHIFTED, KEYCODES_USER, Keycode
|
KEYCODES_BACKLIGHT, KEYCODES_MEDIA, KEYCODES_SPECIAL, KEYCODES_SHIFTED, KEYCODES_USER, Keycode, KEYCODES_TAP_DANCE
|
||||||
from keymaps import KEYMAPS
|
|
||||||
from square_button import SquareButton
|
from square_button import SquareButton
|
||||||
from util import tr
|
from util import tr, KeycodeDisplay
|
||||||
|
|
||||||
|
|
||||||
class TabbedKeycodes(QTabWidget):
|
class TabbedKeycodes(QTabWidget):
|
||||||
|
|
@ -21,7 +20,8 @@ class TabbedKeycodes(QTabWidget):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.keymap_override = None
|
self.target = None
|
||||||
|
self.is_tray = False
|
||||||
|
|
||||||
self.tab_basic = QScrollArea()
|
self.tab_basic = QScrollArea()
|
||||||
self.tab_iso = QScrollArea()
|
self.tab_iso = QScrollArea()
|
||||||
|
|
@ -29,6 +29,7 @@ class TabbedKeycodes(QTabWidget):
|
||||||
self.tab_quantum = QScrollArea()
|
self.tab_quantum = QScrollArea()
|
||||||
self.tab_backlight = QScrollArea()
|
self.tab_backlight = QScrollArea()
|
||||||
self.tab_media = QScrollArea()
|
self.tab_media = QScrollArea()
|
||||||
|
self.tab_tap_dance = QScrollArea()
|
||||||
self.tab_user = QScrollArea()
|
self.tab_user = QScrollArea()
|
||||||
self.tab_macro = QScrollArea()
|
self.tab_macro = QScrollArea()
|
||||||
|
|
||||||
|
|
@ -41,12 +42,15 @@ class TabbedKeycodes(QTabWidget):
|
||||||
(self.tab_quantum, "Quantum", KEYCODES_QUANTUM),
|
(self.tab_quantum, "Quantum", KEYCODES_QUANTUM),
|
||||||
(self.tab_backlight, "Backlight", KEYCODES_BACKLIGHT),
|
(self.tab_backlight, "Backlight", KEYCODES_BACKLIGHT),
|
||||||
(self.tab_media, "App, Media and Mouse", KEYCODES_MEDIA),
|
(self.tab_media, "App, Media and Mouse", KEYCODES_MEDIA),
|
||||||
|
(self.tab_tap_dance, "Tap Dance", KEYCODES_TAP_DANCE),
|
||||||
(self.tab_user, "User", KEYCODES_USER),
|
(self.tab_user, "User", KEYCODES_USER),
|
||||||
(self.tab_macro, "Macro", KEYCODES_MACRO),
|
(self.tab_macro, "Macro", KEYCODES_MACRO),
|
||||||
]:
|
]:
|
||||||
layout = FlowLayout()
|
layout = FlowLayout()
|
||||||
if tab == self.tab_layers:
|
if tab == self.tab_layers:
|
||||||
self.layout_layers = layout
|
self.layout_layers = layout
|
||||||
|
elif tab == self.tab_tap_dance:
|
||||||
|
self.layout_tap_dance = layout
|
||||||
elif tab == self.tab_macro:
|
elif tab == self.tab_macro:
|
||||||
self.layout_macro = layout
|
self.layout_macro = layout
|
||||||
elif tab == self.tab_user:
|
elif tab == self.tab_user:
|
||||||
|
|
@ -71,16 +75,17 @@ class TabbedKeycodes(QTabWidget):
|
||||||
self.addTab(tab, tr("TabbedKeycodes", label))
|
self.addTab(tab, tr("TabbedKeycodes", label))
|
||||||
|
|
||||||
self.layer_keycode_buttons = []
|
self.layer_keycode_buttons = []
|
||||||
|
self.tap_dance_keycode_buttons = []
|
||||||
self.macro_keycode_buttons = []
|
self.macro_keycode_buttons = []
|
||||||
self.user_keycode_buttons = []
|
self.user_keycode_buttons = []
|
||||||
self.set_keymap_override(KEYMAPS[0][1])
|
KeycodeDisplay.notify_keymap_override(self)
|
||||||
|
|
||||||
def create_buttons(self, layout, keycodes, wordWrap = False):
|
def create_buttons(self, layout, keycodes, word_wrap=False):
|
||||||
buttons = []
|
buttons = []
|
||||||
|
|
||||||
for keycode in keycodes:
|
for keycode in keycodes:
|
||||||
btn = SquareButton()
|
btn = SquareButton()
|
||||||
btn.setWordWrap(wordWrap)
|
btn.setWordWrap(word_wrap)
|
||||||
btn.setRelSize(KEYCODE_BTN_RATIO)
|
btn.setRelSize(KEYCODE_BTN_RATIO)
|
||||||
btn.setToolTip(Keycode.tooltip(keycode.code))
|
btn.setToolTip(Keycode.tooltip(keycode.code))
|
||||||
btn.clicked.connect(lambda st, k=keycode: self.keycode_changed.emit(k.code))
|
btn.clicked.connect(lambda st, k=keycode: self.keycode_changed.emit(k.code))
|
||||||
|
|
@ -91,28 +96,63 @@ class TabbedKeycodes(QTabWidget):
|
||||||
return buttons
|
return buttons
|
||||||
|
|
||||||
def recreate_keycode_buttons(self):
|
def recreate_keycode_buttons(self):
|
||||||
for btn in self.layer_keycode_buttons + self.macro_keycode_buttons + self.user_keycode_buttons:
|
for btn in self.layer_keycode_buttons + self.tap_dance_keycode_buttons + self.macro_keycode_buttons \
|
||||||
|
+ self.user_keycode_buttons:
|
||||||
self.widgets.remove(btn)
|
self.widgets.remove(btn)
|
||||||
btn.hide()
|
btn.hide()
|
||||||
btn.deleteLater()
|
btn.deleteLater()
|
||||||
self.layer_keycode_buttons = self.create_buttons(self.layout_layers, KEYCODES_LAYERS)
|
self.layer_keycode_buttons = self.create_buttons(self.layout_layers, KEYCODES_LAYERS)
|
||||||
|
self.tap_dance_keycode_buttons = self.create_buttons(self.layout_tap_dance, KEYCODES_TAP_DANCE)
|
||||||
self.macro_keycode_buttons = self.create_buttons(self.layout_macro, KEYCODES_MACRO)
|
self.macro_keycode_buttons = self.create_buttons(self.layout_macro, KEYCODES_MACRO)
|
||||||
self.user_keycode_buttons = self.create_buttons(self.layout_user, KEYCODES_USER, wordWrap=True)
|
self.user_keycode_buttons = self.create_buttons(self.layout_user, KEYCODES_USER, word_wrap=True)
|
||||||
self.widgets += self.layer_keycode_buttons + self.macro_keycode_buttons + self.user_keycode_buttons
|
self.widgets += self.layer_keycode_buttons + self.tap_dance_keycode_buttons + \
|
||||||
|
self.macro_keycode_buttons + self.user_keycode_buttons
|
||||||
self.relabel_buttons()
|
self.relabel_buttons()
|
||||||
|
|
||||||
def set_keymap_override(self, override):
|
def on_keymap_override(self):
|
||||||
self.keymap_override = override
|
|
||||||
self.relabel_buttons()
|
self.relabel_buttons()
|
||||||
|
|
||||||
def relabel_buttons(self):
|
def relabel_buttons(self):
|
||||||
for widget in self.widgets:
|
for widget in self.widgets:
|
||||||
qmk_id = widget.keycode.qmk_id
|
qmk_id = widget.keycode.qmk_id
|
||||||
if qmk_id in self.keymap_override:
|
if qmk_id in KeycodeDisplay.keymap_override:
|
||||||
label = self.keymap_override[qmk_id]
|
label = KeycodeDisplay.keymap_override[qmk_id]
|
||||||
highlight_color = QApplication.palette().color(QPalette.Link).getRgb()
|
highlight_color = QApplication.palette().color(QPalette.Link).getRgb()
|
||||||
widget.setStyleSheet("QPushButton {color: rgb"+str(highlight_color)+";}")
|
widget.setStyleSheet("QPushButton {color: rgb"+str(highlight_color)+";}")
|
||||||
else:
|
else:
|
||||||
label = widget.keycode.label
|
label = widget.keycode.label
|
||||||
widget.setStyleSheet("QPushButton {}")
|
widget.setStyleSheet("QPushButton {}")
|
||||||
widget.setText(label.replace("&", "&&"))
|
widget.setText(label.replace("&", "&&"))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_tray(cls, tray):
|
||||||
|
cls.tray = tray
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def open_tray(cls, target):
|
||||||
|
cls.tray.show()
|
||||||
|
if cls.tray.target is not None and cls.tray.target != target:
|
||||||
|
cls.tray.target.deselect()
|
||||||
|
cls.tray.target = target
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def close_tray(cls):
|
||||||
|
if cls.tray.target is not None:
|
||||||
|
cls.tray.target.deselect()
|
||||||
|
cls.tray.target = None
|
||||||
|
cls.tray.hide()
|
||||||
|
|
||||||
|
def make_tray(self):
|
||||||
|
self.is_tray = True
|
||||||
|
TabbedKeycodes.set_tray(self)
|
||||||
|
|
||||||
|
self.keycode_changed.connect(self.on_tray_keycode_changed)
|
||||||
|
self.anykey.connect(self.on_tray_anykey)
|
||||||
|
|
||||||
|
def on_tray_keycode_changed(self, kc):
|
||||||
|
if self.target is not None:
|
||||||
|
self.target.on_keycode_changed(kc)
|
||||||
|
|
||||||
|
def on_tray_anykey(self):
|
||||||
|
if self.target is not None:
|
||||||
|
self.target.on_anykey()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
# 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, QLineEdit, QHBoxLayout, \
|
||||||
|
QPushButton, QSpinBox
|
||||||
|
|
||||||
|
from key_widget import KeyWidget
|
||||||
|
from tabbed_keycodes import TabbedKeycodes
|
||||||
|
from util import tr
|
||||||
|
from vial_device import VialKeyboard
|
||||||
|
from basic_editor import BasicEditor
|
||||||
|
|
||||||
|
|
||||||
|
class TapDanceEntryUI(QObject):
|
||||||
|
|
||||||
|
key_changed = pyqtSignal()
|
||||||
|
timing_changed = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, idx):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.idx = idx
|
||||||
|
self.container = QGridLayout()
|
||||||
|
self.populate_container()
|
||||||
|
|
||||||
|
w = QWidget()
|
||||||
|
w.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
|
||||||
|
w.setLayout(self.container)
|
||||||
|
l = QVBoxLayout()
|
||||||
|
l.addStretch()
|
||||||
|
l.addSpacing(10)
|
||||||
|
l.addWidget(w)
|
||||||
|
l.setAlignment(w, QtCore.Qt.AlignHCenter)
|
||||||
|
l.addSpacing(10)
|
||||||
|
lbl = QLabel("Use <code>TD({})</code> to set up this action in the keymap.".format(self.idx))
|
||||||
|
l.addWidget(lbl)
|
||||||
|
l.setAlignment(lbl, QtCore.Qt.AlignHCenter)
|
||||||
|
l.addStretch()
|
||||||
|
self.w2 = QWidget()
|
||||||
|
self.w2.setLayout(l)
|
||||||
|
|
||||||
|
def populate_container(self):
|
||||||
|
self.container.addWidget(QLabel("On tap"), 0, 0)
|
||||||
|
self.kc_on_tap = KeyWidget()
|
||||||
|
self.kc_on_tap.changed.connect(self.on_key_changed)
|
||||||
|
self.container.addWidget(self.kc_on_tap, 0, 1)
|
||||||
|
self.container.addWidget(QLabel("On hold"), 1, 0)
|
||||||
|
self.kc_on_hold = KeyWidget()
|
||||||
|
self.kc_on_hold.changed.connect(self.on_key_changed)
|
||||||
|
self.container.addWidget(self.kc_on_hold, 1, 1)
|
||||||
|
self.container.addWidget(QLabel("On double tap"), 2, 0)
|
||||||
|
self.kc_on_double_tap = KeyWidget()
|
||||||
|
self.kc_on_double_tap.changed.connect(self.on_key_changed)
|
||||||
|
self.container.addWidget(self.kc_on_double_tap, 2, 1)
|
||||||
|
self.container.addWidget(QLabel("On tap + hold"), 3, 0)
|
||||||
|
self.kc_on_tap_hold = KeyWidget()
|
||||||
|
self.kc_on_tap_hold.changed.connect(self.on_key_changed)
|
||||||
|
self.container.addWidget(self.kc_on_tap_hold, 3, 1)
|
||||||
|
self.container.addWidget(QLabel("Tapping term (ms)"), 4, 0)
|
||||||
|
self.txt_tapping_term = QSpinBox()
|
||||||
|
self.txt_tapping_term.valueChanged.connect(self.on_timing_changed)
|
||||||
|
self.txt_tapping_term.setMinimum(0)
|
||||||
|
self.txt_tapping_term.setMaximum(10000)
|
||||||
|
self.container.addWidget(self.txt_tapping_term, 4, 1)
|
||||||
|
|
||||||
|
def widget(self):
|
||||||
|
return self.w2
|
||||||
|
|
||||||
|
def load(self, data):
|
||||||
|
objs = [self.kc_on_tap, self.kc_on_hold, self.kc_on_double_tap, self.kc_on_tap_hold, self.txt_tapping_term]
|
||||||
|
for o in objs:
|
||||||
|
o.blockSignals(True)
|
||||||
|
|
||||||
|
self.kc_on_tap.set_keycode(data[0])
|
||||||
|
self.kc_on_hold.set_keycode(data[1])
|
||||||
|
self.kc_on_double_tap.set_keycode(data[2])
|
||||||
|
self.kc_on_tap_hold.set_keycode(data[3])
|
||||||
|
self.txt_tapping_term.setValue(data[4])
|
||||||
|
|
||||||
|
for o in objs:
|
||||||
|
o.blockSignals(False)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
return (
|
||||||
|
self.kc_on_tap.keycode,
|
||||||
|
self.kc_on_hold.keycode,
|
||||||
|
self.kc_on_double_tap.keycode,
|
||||||
|
self.kc_on_tap_hold.keycode,
|
||||||
|
self.txt_tapping_term.value()
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_key_changed(self):
|
||||||
|
self.key_changed.emit()
|
||||||
|
|
||||||
|
def on_timing_changed(self):
|
||||||
|
self.timing_changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
class CustomTabWidget(QTabWidget):
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
TabbedKeycodes.close_tray()
|
||||||
|
|
||||||
|
|
||||||
|
class TapDance(BasicEditor):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.keyboard = None
|
||||||
|
|
||||||
|
self.tap_dance_entries = []
|
||||||
|
self.tap_dance_entries_available = []
|
||||||
|
self.tabs = CustomTabWidget()
|
||||||
|
for x in range(128):
|
||||||
|
entry = TapDanceEntryUI(x)
|
||||||
|
entry.key_changed.connect(self.on_key_changed)
|
||||||
|
entry.timing_changed.connect(self.on_timing_changed)
|
||||||
|
self.tap_dance_entries_available.append(entry)
|
||||||
|
|
||||||
|
self.addWidget(self.tabs)
|
||||||
|
buttons = QHBoxLayout()
|
||||||
|
buttons.addStretch()
|
||||||
|
self.btn_save = QPushButton(tr("TapDance", "Save"))
|
||||||
|
self.btn_save.clicked.connect(self.on_save)
|
||||||
|
btn_revert = QPushButton(tr("TapDance", "Revert"))
|
||||||
|
btn_revert.clicked.connect(self.on_revert)
|
||||||
|
buttons.addWidget(self.btn_save)
|
||||||
|
buttons.addWidget(btn_revert)
|
||||||
|
self.addLayout(buttons)
|
||||||
|
|
||||||
|
def rebuild_ui(self):
|
||||||
|
while self.tabs.count() > 0:
|
||||||
|
self.tabs.removeTab(0)
|
||||||
|
self.tap_dance_entries = self.tap_dance_entries_available[:self.keyboard.tap_dance_count]
|
||||||
|
for x, e in enumerate(self.tap_dance_entries):
|
||||||
|
self.tabs.addTab(e.widget(), str(x))
|
||||||
|
self.reload_ui()
|
||||||
|
|
||||||
|
def reload_ui(self):
|
||||||
|
for x, e in enumerate(self.tap_dance_entries):
|
||||||
|
e.load(self.keyboard.tap_dance_get(x))
|
||||||
|
self.update_modified_state()
|
||||||
|
|
||||||
|
def on_save(self):
|
||||||
|
for x, e in enumerate(self.tap_dance_entries):
|
||||||
|
self.keyboard.tap_dance_set(x, self.tap_dance_entries[x].save())
|
||||||
|
self.update_modified_state()
|
||||||
|
|
||||||
|
def on_revert(self):
|
||||||
|
self.keyboard.reload_dynamic()
|
||||||
|
self.reload_ui()
|
||||||
|
|
||||||
|
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.tap_dance_count > 0)
|
||||||
|
|
||||||
|
def on_key_changed(self):
|
||||||
|
self.on_save()
|
||||||
|
|
||||||
|
def update_modified_state(self):
|
||||||
|
""" Update indication of which tabs are modified, and keep Save button enabled only if it's needed """
|
||||||
|
has_changes = False
|
||||||
|
for x, e in enumerate(self.tap_dance_entries):
|
||||||
|
if self.tap_dance_entries[x].save() != self.keyboard.tap_dance_get(x):
|
||||||
|
has_changes = True
|
||||||
|
self.tabs.setTabText(x, "{}*".format(x))
|
||||||
|
else:
|
||||||
|
self.tabs.setTabText(x, str(x))
|
||||||
|
self.btn_save.setEnabled(has_changes)
|
||||||
|
|
||||||
|
def on_timing_changed(self):
|
||||||
|
self.update_modified_state()
|
||||||
|
|
@ -5,9 +5,12 @@ import time
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication, QStandardPaths
|
from PyQt5.QtCore import QCoreApplication, QStandardPaths
|
||||||
|
from PyQt5.QtGui import QPalette
|
||||||
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
from hidproxy import hid
|
from hidproxy import hid
|
||||||
|
from keycodes import Keycode
|
||||||
|
from keymaps import KEYMAPS
|
||||||
|
|
||||||
tr = QCoreApplication.translate
|
tr = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
@ -147,3 +150,50 @@ def init_logger():
|
||||||
handler = RotatingFileHandler(path, maxBytes=5 * 1024 * 1024, backupCount=5)
|
handler = RotatingFileHandler(path, maxBytes=5 * 1024 * 1024, backupCount=5)
|
||||||
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s"))
|
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s"))
|
||||||
logging.getLogger().addHandler(handler)
|
logging.getLogger().addHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
|
class KeycodeDisplay:
|
||||||
|
|
||||||
|
keymap_override = KEYMAPS[0][1]
|
||||||
|
clients = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_label(cls, code):
|
||||||
|
""" Get label for a specific keycode """
|
||||||
|
if cls.code_is_overriden(code):
|
||||||
|
return cls.keymap_override[Keycode.find_outer_keycode(code).qmk_id]
|
||||||
|
return Keycode.label(code)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def code_is_overriden(cls, code):
|
||||||
|
""" Check whether a country-specific keymap overrides a code """
|
||||||
|
key = Keycode.find_outer_keycode(code)
|
||||||
|
return key is not None and key.qmk_id in cls.keymap_override
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def display_keycode(cls, widget, code):
|
||||||
|
text = cls.get_label(code)
|
||||||
|
tooltip = Keycode.tooltip(code)
|
||||||
|
mask = Keycode.is_mask(code)
|
||||||
|
mask_text = cls.get_label(code & 0xFF)
|
||||||
|
if mask:
|
||||||
|
text = text.split("\n")[0]
|
||||||
|
widget.masked = mask
|
||||||
|
widget.setText(text)
|
||||||
|
widget.setMaskText(mask_text)
|
||||||
|
widget.setToolTip(tooltip)
|
||||||
|
if cls.code_is_overriden(code):
|
||||||
|
widget.setColor(QApplication.palette().color(QPalette.Link))
|
||||||
|
else:
|
||||||
|
widget.setColor(None)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_keymap_override(cls, override):
|
||||||
|
cls.keymap_override = override
|
||||||
|
for client in cls.clients:
|
||||||
|
client.on_keymap_override()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def notify_keymap_override(cls, client):
|
||||||
|
cls.clients.append(client)
|
||||||
|
client.on_keymap_override()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue