vial/src/main/python/main.py

158 lines
4.7 KiB
Python
Raw Normal View History

2020-10-14 02:39:59 -04:00
from fbs_runtime.application_context.PyQt5 import ApplicationContext
from PyQt5.QtCore import Qt
2020-10-14 15:16:14 -04:00
from PyQt5.QtWidgets import QWidget, QTabWidget, QVBoxLayout, QPushButton, QLabel, QComboBox, QToolButton, QHBoxLayout
2020-10-14 02:39:59 -04:00
import sys
2020-10-14 12:56:25 -04:00
import json
2020-10-14 15:16:14 -04:00
import struct
import lzma
2020-10-14 02:39:59 -04:00
from flowlayout import FlowLayout
2020-10-14 15:16:14 -04:00
from util import tr, find_vial_keyboards, open_device, hid_send, MSG_LEN
2020-10-14 12:56:25 -04:00
from kle_serial import Serial as KleSerial
2020-10-14 02:39:59 -04:00
class TabbedKeycodes(QTabWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.tab_basic = QWidget()
layout = FlowLayout()
2020-10-14 12:56:25 -04:00
for lbl in ["", "hello", "Esc", "A", "B", "C", "D", "E", "F"]:
2020-10-14 02:39:59 -04:00
btn = QPushButton(lbl)
btn.setFixedSize(50, 50)
layout.addWidget(btn)
self.tab_basic.setLayout(layout)
self.tab_media = QWidget()
self.tab_macro = QWidget()
2020-10-14 12:56:25 -04:00
self.addTab(self.tab_basic, tr("TabbedKeycodes", "Basic"))
self.addTab(self.tab_media, tr("TabbedKeycodes", "Media"))
self.addTab(self.tab_macro, tr("TabbedKeycodes", "Macro"))
2020-10-14 02:39:59 -04:00
KEY_WIDTH = 40
KEY_HEIGHT = KEY_WIDTH
2020-10-14 12:56:25 -04:00
KEY_SPACING = 4
2020-10-14 02:39:59 -04:00
class KeyboardContainer(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
2020-10-14 15:16:14 -04:00
self.keys = []
def rebuild(self, data):
for key in self.keys:
key.deleteLater()
self.keys = []
2020-10-14 12:56:25 -04:00
serial = KleSerial()
kb = serial.deserialize(data["layouts"]["keymap"])
2020-10-14 02:39:59 -04:00
2020-10-14 12:56:25 -04:00
max_w = max_h = 0
for key in kb.keys:
widget = QLabel(str(key.labels[0]))
2020-10-14 02:39:59 -04:00
widget.setParent(self)
2020-10-14 12:56:25 -04:00
widget.setStyleSheet('background-color:white; border: 1px solid black')
2020-10-14 02:39:59 -04:00
widget.setAlignment(Qt.AlignCenter)
2020-10-14 12:56:25 -04:00
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)
2020-10-14 15:16:14 -04:00
widget.show()
# print("{} {}x{}+{}x{}".format(key.labels, key.x, key.y, key.width, key.height))
2020-10-14 12:56:25 -04:00
max_w = max(max_w, x + w)
max_h = max(max_h, y + h)
2020-10-14 15:16:14 -04:00
self.keys.append(widget)
2020-10-14 12:56:25 -04:00
self.setFixedSize(max_w, max_h)
2020-10-14 02:39:59 -04:00
class MainWindow(QWidget):
def __init__(self):
super().__init__()
2020-10-14 15:16:14 -04:00
self.device = None
self.devices = []
2020-10-14 02:39:59 -04:00
self.keyboard_container = KeyboardContainer()
self.tabbed_keycodes = TabbedKeycodes()
2020-10-14 15:16:14 -04:00
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)
2020-10-14 02:39:59 -04:00
layout = QVBoxLayout()
2020-10-14 15:16:14 -04:00
layout.addLayout(layout_combobox)
2020-10-14 02:39:59 -04:00
layout.addWidget(self.keyboard_container)
2020-10-14 12:56:25 -04:00
layout.setAlignment(self.keyboard_container, Qt.AlignHCenter)
2020-10-14 02:39:59 -04:00
layout.addWidget(self.tabbed_keycodes)
self.setLayout(layout)
2020-10-14 15:16:14 -04:00
# make sure initial state is valid
self.on_click_refresh()
self.on_device_selected()
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:
self.device = open_device(self.devices[idx])
self.reload_layout()
def reload_layout(self):
""" Requests layout data from the current device """
# get the size
data = hid_send(self.device, b"\xFE\x01")
sz = struct.unpack("<I", data[0:4])[0]
# get the payload
payload = b""
block = 0
while sz > 0:
data = hid_send(self.device, b"\xFE\x02" + struct.pack("<I", block))
if sz < MSG_LEN:
data = data[:sz]
payload += data
block += 1
sz -= MSG_LEN
payload = json.loads(lzma.decompress(payload))
self.keyboard_container.rebuild(payload)
2020-10-14 02:39:59 -04:00
if __name__ == '__main__':
appctxt = ApplicationContext() # 1. Instantiate ApplicationContext
window = MainWindow()
window.resize(1024, 768)
window.show()
exit_code = appctxt.app.exec_() # 2. Invoke appctxt.app.exec_()
sys.exit(exit_code)