split main.py into several files
parent
b41c113903
commit
92a4d6e3f4
|
|
@ -0,0 +1,5 @@
|
|||
KEY_WIDTH = 40
|
||||
KEY_HEIGHT = KEY_WIDTH
|
||||
KEY_SPACING = 4
|
||||
|
||||
WINDOW_WIDTH, WINDOW_HEIGHT = 1024, 768
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
from collections import defaultdict
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QVBoxLayout
|
||||
|
||||
from clickable_label import ClickableLabel
|
||||
from keycodes import keycode_label, keycode_tooltip
|
||||
from constants import KEY_WIDTH, KEY_SPACING, KEY_HEIGHT
|
||||
from util import tr
|
||||
|
||||
|
||||
class KeyboardContainer(QWidget):
|
||||
|
||||
number_layers_changed = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.layout_layers = QHBoxLayout()
|
||||
layer_label = QLabel(tr("KeyboardContainer", "Layer"))
|
||||
|
||||
layout_labels_container = QHBoxLayout()
|
||||
layout_labels_container.addWidget(layer_label)
|
||||
layout_labels_container.addLayout(self.layout_layers)
|
||||
layout_labels_container.addStretch()
|
||||
|
||||
# contains the actual keyboard
|
||||
self.container = QWidget()
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addLayout(layout_labels_container)
|
||||
layout.addWidget(self.container)
|
||||
layout.setAlignment(self.container, Qt.AlignHCenter)
|
||||
self.setLayout(layout)
|
||||
|
||||
self.keys = []
|
||||
self.layer_labels = []
|
||||
self.rowcol = defaultdict(list)
|
||||
self.selected_key = None
|
||||
self.selected_row = -1
|
||||
self.selected_col = -1
|
||||
|
||||
def rebuild_layers(self):
|
||||
self.layers = self.keyboard.layers
|
||||
self.number_layers_changed.emit()
|
||||
|
||||
# delete old layer labels
|
||||
for label in self.layer_labels:
|
||||
label.deleteLater()
|
||||
self.layer_labels = []
|
||||
|
||||
# create new layer labels
|
||||
for x in range(self.layers):
|
||||
label = ClickableLabel(str(x))
|
||||
label.setAlignment(Qt.AlignCenter)
|
||||
label.clicked.connect(lambda idx=x: self.switch_layer(idx))
|
||||
self.layout_layers.addWidget(label)
|
||||
self.layer_labels.append(label)
|
||||
|
||||
def rebuild(self, keyboard):
|
||||
self.keyboard = keyboard
|
||||
|
||||
# delete current layout
|
||||
for key in self.keys:
|
||||
key.deleteLater()
|
||||
self.keys = []
|
||||
|
||||
# get number of layers
|
||||
self.rebuild_layers()
|
||||
|
||||
# prepare for fetching keymap
|
||||
self.rowcol = defaultdict(list)
|
||||
|
||||
max_w = max_h = 0
|
||||
|
||||
for key in keyboard.keys:
|
||||
widget = ClickableLabel()
|
||||
widget.clicked.connect(lambda w=widget: self.select_key(w))
|
||||
|
||||
if key.row is not None:
|
||||
self.rowcol[(key.row, key.col)].append(widget)
|
||||
|
||||
widget.setParent(self.container)
|
||||
widget.setAlignment(Qt.AlignCenter)
|
||||
|
||||
x = (KEY_WIDTH + KEY_SPACING) * key.x
|
||||
y = (KEY_HEIGHT + KEY_SPACING) * key.y
|
||||
w = (KEY_WIDTH + KEY_SPACING) * key.width - KEY_SPACING
|
||||
h = (KEY_HEIGHT + KEY_SPACING) * key.height - KEY_SPACING
|
||||
|
||||
widget.setFixedSize(w, h)
|
||||
widget.move(x, y)
|
||||
widget.show()
|
||||
|
||||
max_w = max(max_w, x + w)
|
||||
max_h = max(max_h, y + h)
|
||||
|
||||
self.keys.append(widget)
|
||||
|
||||
self.container.setFixedSize(max_w, max_h)
|
||||
self.current_layer = 0
|
||||
self.refresh_layer_display()
|
||||
|
||||
def refresh_layer_display(self):
|
||||
""" Refresh text on key widgets to display data corresponding to current layer """
|
||||
|
||||
for label in self.layer_labels:
|
||||
label.setStyleSheet("border: 1px solid black; padding: 5px")
|
||||
self.layer_labels[self.current_layer].setStyleSheet("border: 1px solid black; padding: 5px; background-color: black; color: white")
|
||||
|
||||
for (row, col), widgets in self.rowcol.items():
|
||||
code = self.keyboard.layout[(self.current_layer, row, col)]
|
||||
text = keycode_label(code)
|
||||
tooltip = keycode_tooltip(code)
|
||||
for widget in widgets:
|
||||
widget.setStyleSheet('background-color:white; border: 1px solid black')
|
||||
if widget == self.selected_key:
|
||||
widget.setStyleSheet('background-color:black; color: white; border: 1px solid black')
|
||||
widget.setText(text)
|
||||
widget.setToolTip(tooltip)
|
||||
|
||||
def switch_layer(self, idx):
|
||||
self.current_layer = idx
|
||||
self.selected_key = None
|
||||
self.selected_row = -1
|
||||
self.selected_col = -1
|
||||
self.refresh_layer_display()
|
||||
|
||||
def set_key(self, keycode):
|
||||
""" Change currently selected key to provided keycode """
|
||||
|
||||
if self.selected_row >= 0 and self.selected_col >= 0:
|
||||
self.keyboard.set_key(self.current_layer, self.selected_row, self.selected_col, keycode)
|
||||
self.refresh_layer_display()
|
||||
|
||||
def select_key(self, widget):
|
||||
""" Change which key is currently selected """
|
||||
|
||||
self.selected_key = widget
|
||||
for (row, col), widgets in self.rowcol.items():
|
||||
if widget in widgets:
|
||||
self.selected_row = row
|
||||
self.selected_col = col
|
||||
break
|
||||
self.refresh_layer_display()
|
||||
|
|
@ -1,270 +1,16 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from fbs_runtime.application_context.PyQt5 import ApplicationContext
|
||||
from PyQt5.QtCore import Qt, pyqtSignal
|
||||
from PyQt5.QtWidgets import QWidget, QTabWidget, QVBoxLayout, QPushButton, QLabel, QComboBox, QToolButton, QHBoxLayout, QSizePolicy
|
||||
|
||||
import sys
|
||||
import json
|
||||
import struct
|
||||
import lzma
|
||||
from collections import defaultdict
|
||||
|
||||
from flowlayout import FlowLayout
|
||||
from util import tr, find_vial_keyboards, open_device
|
||||
from clickable_label import ClickableLabel
|
||||
from keycodes import keycode_label, keycode_tooltip, recreate_layer_keycodes, KEYCODES_BASIC, KEYCODES_ISO, KEYCODES_MACRO, KEYCODES_LAYERS, KEYCODES_SPECIAL
|
||||
from keyboard import Keyboard
|
||||
|
||||
|
||||
class TabbedKeycodes(QTabWidget):
|
||||
|
||||
keycode_changed = pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.tab_basic = QWidget()
|
||||
self.tab_iso = QWidget()
|
||||
self.tab_macro = QWidget()
|
||||
self.tab_layers = QWidget()
|
||||
self.tab_special = QWidget()
|
||||
|
||||
for (tab, label, keycodes) in [
|
||||
(self.tab_basic, "Basic", KEYCODES_BASIC),
|
||||
(self.tab_iso, "ISO/JIS", KEYCODES_ISO),
|
||||
(self.tab_macro, "Macro", KEYCODES_MACRO),
|
||||
(self.tab_layers, "Layers", KEYCODES_LAYERS),
|
||||
(self.tab_special, "Special", KEYCODES_SPECIAL),
|
||||
]:
|
||||
layout = FlowLayout()
|
||||
buttons = self.create_buttons(layout, keycodes)
|
||||
tab.setLayout(layout)
|
||||
self.addTab(tab, tr("TabbedKeycodes", label))
|
||||
|
||||
self.layer_keycode_buttons = []
|
||||
|
||||
def create_buttons(self, layout, keycodes):
|
||||
buttons = []
|
||||
|
||||
for keycode in keycodes:
|
||||
btn = QPushButton(keycode.label)
|
||||
btn.setFixedSize(50, 50)
|
||||
btn.setToolTip(keycode_tooltip(keycode.code))
|
||||
btn.clicked.connect(lambda st, k=keycode: self.keycode_changed.emit(k.code))
|
||||
layout.addWidget(btn)
|
||||
buttons.append(btn)
|
||||
|
||||
return buttons
|
||||
|
||||
def recreate_layer_keycode_buttons(self):
|
||||
for btn in self.layer_keycode_buttons:
|
||||
btn.deleteLater()
|
||||
self.layer_keycode_buttons = self.create_buttons(self.tab_layers.layout(), KEYCODES_LAYERS)
|
||||
|
||||
|
||||
KEY_WIDTH = 40
|
||||
KEY_HEIGHT = KEY_WIDTH
|
||||
KEY_SPACING = 4
|
||||
|
||||
|
||||
class KeyboardContainer(QWidget):
|
||||
|
||||
number_layers_changed = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.layout_layers = QHBoxLayout()
|
||||
layer_label = QLabel(tr("KeyboardContainer", "Layer"))
|
||||
|
||||
layout_labels_container = QHBoxLayout()
|
||||
layout_labels_container.addWidget(layer_label)
|
||||
layout_labels_container.addLayout(self.layout_layers)
|
||||
layout_labels_container.addStretch()
|
||||
|
||||
# contains the actual keyboard
|
||||
self.container = QWidget()
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addLayout(layout_labels_container)
|
||||
layout.addWidget(self.container)
|
||||
layout.setAlignment(self.container, Qt.AlignHCenter)
|
||||
self.setLayout(layout)
|
||||
|
||||
self.keys = []
|
||||
self.layer_labels = []
|
||||
self.rowcol = defaultdict(list)
|
||||
self.selected_key = None
|
||||
self.selected_row = -1
|
||||
self.selected_col = -1
|
||||
|
||||
def rebuild_layers(self):
|
||||
self.layers = self.keyboard.layers
|
||||
self.number_layers_changed.emit()
|
||||
|
||||
# delete old layer labels
|
||||
for label in self.layer_labels:
|
||||
label.deleteLater()
|
||||
self.layer_labels = []
|
||||
|
||||
# create new layer labels
|
||||
for x in range(self.layers):
|
||||
label = ClickableLabel(str(x))
|
||||
label.setAlignment(Qt.AlignCenter)
|
||||
label.clicked.connect(lambda idx=x: self.switch_layer(idx))
|
||||
self.layout_layers.addWidget(label)
|
||||
self.layer_labels.append(label)
|
||||
|
||||
def rebuild(self, keyboard):
|
||||
self.keyboard = keyboard
|
||||
|
||||
# delete current layout
|
||||
for key in self.keys:
|
||||
key.deleteLater()
|
||||
self.keys = []
|
||||
|
||||
# get number of layers
|
||||
self.rebuild_layers()
|
||||
|
||||
# prepare for fetching keymap
|
||||
self.rowcol = defaultdict(list)
|
||||
|
||||
max_w = max_h = 0
|
||||
|
||||
for key in keyboard.keys:
|
||||
widget = ClickableLabel()
|
||||
widget.clicked.connect(lambda w=widget: self.select_key(w))
|
||||
|
||||
if key.row is not None:
|
||||
self.rowcol[(key.row, key.col)].append(widget)
|
||||
|
||||
widget.setParent(self.container)
|
||||
widget.setAlignment(Qt.AlignCenter)
|
||||
|
||||
x = (KEY_WIDTH + KEY_SPACING) * key.x
|
||||
y = (KEY_HEIGHT + KEY_SPACING) * key.y
|
||||
w = (KEY_WIDTH + KEY_SPACING) * key.width - KEY_SPACING
|
||||
h = (KEY_HEIGHT + KEY_SPACING) * key.height - KEY_SPACING
|
||||
|
||||
widget.setFixedSize(w, h)
|
||||
widget.move(x, y)
|
||||
widget.show()
|
||||
|
||||
max_w = max(max_w, x + w)
|
||||
max_h = max(max_h, y + h)
|
||||
|
||||
self.keys.append(widget)
|
||||
|
||||
self.container.setFixedSize(max_w, max_h)
|
||||
self.current_layer = 0
|
||||
self.refresh_layer_display()
|
||||
|
||||
def refresh_layer_display(self):
|
||||
""" Refresh text on key widgets to display data corresponding to current layer """
|
||||
|
||||
for label in self.layer_labels:
|
||||
label.setStyleSheet("border: 1px solid black; padding: 5px")
|
||||
self.layer_labels[self.current_layer].setStyleSheet("border: 1px solid black; padding: 5px; background-color: black; color: white")
|
||||
|
||||
for (row, col), widgets in self.rowcol.items():
|
||||
code = self.keyboard.layout[(self.current_layer, row, col)]
|
||||
text = keycode_label(code)
|
||||
tooltip = keycode_tooltip(code)
|
||||
for widget in widgets:
|
||||
widget.setStyleSheet('background-color:white; border: 1px solid black')
|
||||
if widget == self.selected_key:
|
||||
widget.setStyleSheet('background-color:black; color: white; border: 1px solid black')
|
||||
widget.setText(text)
|
||||
widget.setToolTip(tooltip)
|
||||
|
||||
def switch_layer(self, idx):
|
||||
self.current_layer = idx
|
||||
self.selected_key = None
|
||||
self.selected_row = -1
|
||||
self.selected_col = -1
|
||||
self.refresh_layer_display()
|
||||
|
||||
def set_key(self, keycode):
|
||||
""" Change currently selected key to provided keycode """
|
||||
|
||||
if self.selected_row >= 0 and self.selected_col >= 0:
|
||||
self.keyboard.set_key(self.current_layer, self.selected_row, self.selected_col, keycode)
|
||||
self.refresh_layer_display()
|
||||
|
||||
def select_key(self, widget):
|
||||
""" Change which key is currently selected """
|
||||
|
||||
self.selected_key = widget
|
||||
for (row, col), widgets in self.rowcol.items():
|
||||
if widget in widgets:
|
||||
self.selected_row = row
|
||||
self.selected_col = col
|
||||
break
|
||||
self.refresh_layer_display()
|
||||
|
||||
|
||||
class MainWindow(QWidget):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.device = None
|
||||
self.devices = []
|
||||
|
||||
self.keyboard_container = KeyboardContainer()
|
||||
self.keyboard_container.number_layers_changed.connect(self.on_number_layers_changed)
|
||||
|
||||
self.tabbed_keycodes = TabbedKeycodes()
|
||||
self.tabbed_keycodes.keycode_changed.connect(self.on_keycode_changed)
|
||||
|
||||
self.combobox_devices = QComboBox()
|
||||
self.combobox_devices.currentIndexChanged.connect(self.on_device_selected)
|
||||
|
||||
btn_refresh_devices = QToolButton()
|
||||
btn_refresh_devices.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
||||
btn_refresh_devices.setText(tr("MainWindow", "Refresh"))
|
||||
btn_refresh_devices.clicked.connect(self.on_click_refresh)
|
||||
|
||||
layout_combobox = QHBoxLayout()
|
||||
layout_combobox.addWidget(self.combobox_devices)
|
||||
layout_combobox.addWidget(btn_refresh_devices)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addLayout(layout_combobox)
|
||||
layout.addWidget(self.keyboard_container)
|
||||
layout.addWidget(self.tabbed_keycodes)
|
||||
self.setLayout(layout)
|
||||
|
||||
# make sure initial state is valid
|
||||
self.on_click_refresh()
|
||||
|
||||
def on_click_refresh(self):
|
||||
self.devices = find_vial_keyboards()
|
||||
self.combobox_devices.clear()
|
||||
|
||||
for dev in self.devices:
|
||||
self.combobox_devices.addItem("{} {}".format(dev["manufacturer_string"], dev["product_string"]))
|
||||
|
||||
def on_device_selected(self):
|
||||
self.device = None
|
||||
idx = self.combobox_devices.currentIndex()
|
||||
if idx >= 0:
|
||||
keyboard = Keyboard(open_device(self.devices[idx]))
|
||||
keyboard.reload()
|
||||
self.keyboard_container.rebuild(keyboard)
|
||||
|
||||
def on_number_layers_changed(self):
|
||||
recreate_layer_keycodes(self.keyboard_container.layers)
|
||||
self.tabbed_keycodes.recreate_layer_keycode_buttons()
|
||||
|
||||
def on_keycode_changed(self, code):
|
||||
self.keyboard_container.set_key(code)
|
||||
|
||||
from main_window import MainWindow
|
||||
from constants import WINDOW_WIDTH, WINDOW_HEIGHT
|
||||
|
||||
if __name__ == '__main__':
|
||||
appctxt = ApplicationContext() # 1. Instantiate ApplicationContext
|
||||
window = MainWindow()
|
||||
window.resize(1024, 768)
|
||||
window.resize(WINDOW_WIDTH, WINDOW_HEIGHT)
|
||||
window.show()
|
||||
exit_code = appctxt.app.exec_() # 2. Invoke appctxt.app.exec_()
|
||||
sys.exit(exit_code)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget, QComboBox, QToolButton, QHBoxLayout, QVBoxLayout
|
||||
|
||||
from keyboard import Keyboard
|
||||
from keyboard_container import KeyboardContainer
|
||||
from keycodes import recreate_layer_keycodes
|
||||
from tabbed_keycodes import TabbedKeycodes
|
||||
from util import tr, find_vial_keyboards, open_device
|
||||
|
||||
|
||||
class MainWindow(QWidget):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.device = None
|
||||
self.devices = []
|
||||
|
||||
self.keyboard_container = KeyboardContainer()
|
||||
self.keyboard_container.number_layers_changed.connect(self.on_number_layers_changed)
|
||||
|
||||
self.tabbed_keycodes = TabbedKeycodes()
|
||||
self.tabbed_keycodes.keycode_changed.connect(self.on_keycode_changed)
|
||||
|
||||
self.combobox_devices = QComboBox()
|
||||
self.combobox_devices.currentIndexChanged.connect(self.on_device_selected)
|
||||
|
||||
btn_refresh_devices = QToolButton()
|
||||
btn_refresh_devices.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
||||
btn_refresh_devices.setText(tr("MainWindow", "Refresh"))
|
||||
btn_refresh_devices.clicked.connect(self.on_click_refresh)
|
||||
|
||||
layout_combobox = QHBoxLayout()
|
||||
layout_combobox.addWidget(self.combobox_devices)
|
||||
layout_combobox.addWidget(btn_refresh_devices)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addLayout(layout_combobox)
|
||||
layout.addWidget(self.keyboard_container)
|
||||
layout.addWidget(self.tabbed_keycodes)
|
||||
self.setLayout(layout)
|
||||
|
||||
# make sure initial state is valid
|
||||
self.on_click_refresh()
|
||||
|
||||
def on_click_refresh(self):
|
||||
self.devices = find_vial_keyboards()
|
||||
self.combobox_devices.clear()
|
||||
|
||||
for dev in self.devices:
|
||||
self.combobox_devices.addItem("{} {}".format(dev["manufacturer_string"], dev["product_string"]))
|
||||
|
||||
def on_device_selected(self):
|
||||
self.device = None
|
||||
idx = self.combobox_devices.currentIndex()
|
||||
if idx >= 0:
|
||||
keyboard = Keyboard(open_device(self.devices[idx]))
|
||||
keyboard.reload()
|
||||
self.keyboard_container.rebuild(keyboard)
|
||||
|
||||
def on_number_layers_changed(self):
|
||||
recreate_layer_keycodes(self.keyboard_container.layers)
|
||||
self.tabbed_keycodes.recreate_layer_keycode_buttons()
|
||||
|
||||
def on_keycode_changed(self, code):
|
||||
self.keyboard_container.set_key(code)
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtWidgets import QTabWidget, QWidget, QPushButton
|
||||
|
||||
from flowlayout import FlowLayout
|
||||
from keycodes import KEYCODES_BASIC, KEYCODES_ISO, KEYCODES_MACRO, KEYCODES_LAYERS, KEYCODES_SPECIAL, keycode_tooltip
|
||||
from util import tr
|
||||
|
||||
|
||||
class TabbedKeycodes(QTabWidget):
|
||||
|
||||
keycode_changed = pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.tab_basic = QWidget()
|
||||
self.tab_iso = QWidget()
|
||||
self.tab_macro = QWidget()
|
||||
self.tab_layers = QWidget()
|
||||
self.tab_special = QWidget()
|
||||
|
||||
for (tab, label, keycodes) in [
|
||||
(self.tab_basic, "Basic", KEYCODES_BASIC),
|
||||
(self.tab_iso, "ISO/JIS", KEYCODES_ISO),
|
||||
(self.tab_macro, "Macro", KEYCODES_MACRO),
|
||||
(self.tab_layers, "Layers", KEYCODES_LAYERS),
|
||||
(self.tab_special, "Special", KEYCODES_SPECIAL),
|
||||
]:
|
||||
layout = FlowLayout()
|
||||
buttons = self.create_buttons(layout, keycodes)
|
||||
tab.setLayout(layout)
|
||||
self.addTab(tab, tr("TabbedKeycodes", label))
|
||||
|
||||
self.layer_keycode_buttons = []
|
||||
|
||||
def create_buttons(self, layout, keycodes):
|
||||
buttons = []
|
||||
|
||||
for keycode in keycodes:
|
||||
btn = QPushButton(keycode.label)
|
||||
btn.setFixedSize(50, 50)
|
||||
btn.setToolTip(keycode_tooltip(keycode.code))
|
||||
btn.clicked.connect(lambda st, k=keycode: self.keycode_changed.emit(k.code))
|
||||
layout.addWidget(btn)
|
||||
buttons.append(btn)
|
||||
|
||||
return buttons
|
||||
|
||||
def recreate_layer_keycode_buttons(self):
|
||||
for btn in self.layer_keycode_buttons:
|
||||
btn.deleteLater()
|
||||
self.layer_keycode_buttons = self.create_buttons(self.tab_layers.layout(), KEYCODES_LAYERS)
|
||||
Loading…
Reference in New Issue