keyboard_comm: save and restore layout/macros in save_layout/restore_layout
parent
5d40bec15b
commit
b11e0be700
|
|
@ -1,5 +1,5 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
import base64
|
||||||
import struct
|
import struct
|
||||||
import json
|
import json
|
||||||
import lzma
|
import lzma
|
||||||
|
|
@ -175,15 +175,16 @@ class Keyboard:
|
||||||
self.macro_memory = struct.unpack(">H", data[1:3])[0]
|
self.macro_memory = struct.unpack(">H", data[1:3])[0]
|
||||||
|
|
||||||
self.macro = b""
|
self.macro = b""
|
||||||
# now retrieve the entire buffer, MACRO_CHUNK bytes at a time, as that is what fits into a packet
|
if self.macro_memory:
|
||||||
for x in range(0, self.macro_memory, BUFFER_FETCH_CHUNK):
|
# now retrieve the entire buffer, MACRO_CHUNK bytes at a time, as that is what fits into a packet
|
||||||
sz = min(BUFFER_FETCH_CHUNK, self.macro_memory - x)
|
for x in range(0, self.macro_memory, BUFFER_FETCH_CHUNK):
|
||||||
data = self.usb_send(self.dev, struct.pack(">BHB", CMD_VIA_MACRO_GET_BUFFER, x, sz))
|
sz = min(BUFFER_FETCH_CHUNK, self.macro_memory - x)
|
||||||
self.macro += data[4:4+sz]
|
data = self.usb_send(self.dev, struct.pack(">BHB", CMD_VIA_MACRO_GET_BUFFER, x, sz))
|
||||||
# macros are stored as NUL-separated strings, so let's clean up the buffer
|
self.macro += data[4:4+sz]
|
||||||
# ensuring we only get macro_count strings after we split by NUL
|
# macros are stored as NUL-separated strings, so let's clean up the buffer
|
||||||
macros = self.macro.split(b"\x00") + [b""] * self.macro_count
|
# ensuring we only get macro_count strings after we split by NUL
|
||||||
self.macro = b"\x00".join(macros[:self.macro_count]) + b"\x00"
|
macros = self.macro.split(b"\x00") + [b""] * self.macro_count
|
||||||
|
self.macro = b"\x00".join(macros[:self.macro_count]) + b"\x00"
|
||||||
|
|
||||||
def set_key(self, layer, row, col, code):
|
def set_key(self, layer, row, col, code):
|
||||||
key = (layer, row, col)
|
key = (layer, row, col)
|
||||||
|
|
@ -216,6 +217,7 @@ class Keyboard:
|
||||||
""" Serializes current layout to a binary """
|
""" Serializes current layout to a binary """
|
||||||
|
|
||||||
# TODO: increase version before release
|
# TODO: increase version before release
|
||||||
|
# TODO: store keyboard UID here as well
|
||||||
data = {"version": 0}
|
data = {"version": 0}
|
||||||
layout = []
|
layout = []
|
||||||
for l in range(self.layers):
|
for l in range(self.layers):
|
||||||
|
|
@ -228,7 +230,8 @@ class Keyboard:
|
||||||
val = self.layout.get((l, r, c), -1)
|
val = self.layout.get((l, r, c), -1)
|
||||||
row.append(val)
|
row.append(val)
|
||||||
data["layout"] = layout
|
data["layout"] = layout
|
||||||
# TODO: this should also save/restore macros, when implemented
|
data["layout_options"] = self.layout_options
|
||||||
|
data["macro"] = base64.b64encode(self.macro).decode("utf-8")
|
||||||
return json.dumps(data).encode("utf-8")
|
return json.dumps(data).encode("utf-8")
|
||||||
|
|
||||||
def restore_layout(self, data):
|
def restore_layout(self, data):
|
||||||
|
|
@ -240,3 +243,5 @@ class Keyboard:
|
||||||
for c, col in enumerate(row):
|
for c, col in enumerate(row):
|
||||||
if (l, r, c) in self.layout:
|
if (l, r, c) in self.layout:
|
||||||
self.set_key(l, r, c, col)
|
self.set_key(l, r, c, col)
|
||||||
|
self.set_layout_options(data["layout_options"])
|
||||||
|
self.set_macro(base64.b64decode(data["macro"]))
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ class MainWindow(QMainWindow):
|
||||||
with open(dialog.selectedFiles()[0], "rb") as inf:
|
with open(dialog.selectedFiles()[0], "rb") as inf:
|
||||||
data = inf.read()
|
data = inf.read()
|
||||||
self.keymap_editor.restore_layout(data)
|
self.keymap_editor.restore_layout(data)
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
def on_layout_save(self):
|
def on_layout_save(self):
|
||||||
dialog = QFileDialog()
|
dialog = QFileDialog()
|
||||||
|
|
@ -118,11 +119,14 @@ class MainWindow(QMainWindow):
|
||||||
if self.current_device is not None:
|
if self.current_device is not None:
|
||||||
self.current_device.open(self.sideload_json if self.current_device.sideload else None)
|
self.current_device.open(self.sideload_json if self.current_device.sideload else None)
|
||||||
|
|
||||||
for e in [self.layout_editor, self.keymap_editor, self.firmware_flasher, self.macro_recorder]:
|
self.rebuild()
|
||||||
e.rebuild(self.current_device)
|
|
||||||
|
|
||||||
self.refresh_tabs()
|
self.refresh_tabs()
|
||||||
|
|
||||||
|
def rebuild(self):
|
||||||
|
for e in [self.layout_editor, self.keymap_editor, self.firmware_flasher, self.macro_recorder]:
|
||||||
|
e.rebuild(self.current_device)
|
||||||
|
|
||||||
def refresh_tabs(self):
|
def refresh_tabs(self):
|
||||||
self.tabs.clear()
|
self.tabs.clear()
|
||||||
for container, lbl in self.editors:
|
for container, lbl in self.editors:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue