qmk_settings: refactor to keep integers internally

main
Ilya Zhuravlev 2021-07-06 00:40:33 -04:00
parent adcb9116c0
commit 827f4711da
2 changed files with 41 additions and 30 deletions

View File

@ -401,16 +401,14 @@ class Keyboard:
for qsid in self.supported_settings: for qsid in self.supported_settings:
from qmk_settings import QmkSettings from qmk_settings import QmkSettings
width = QmkSettings.setting_width(qsid)
if width is None: if not QmkSettings.is_qsid_supported(qsid):
continue continue
data = self.usb_send(self.dev, struct.pack("<BBH", CMD_VIA_VIAL_PREFIX, CMD_VIAL_QMK_SETTINGS_GET, qsid), data = self.usb_send(self.dev, struct.pack("<BBH", CMD_VIA_VIAL_PREFIX, CMD_VIAL_QMK_SETTINGS_GET, qsid),
retries=20) retries=20)
if data[0] != 0: if data[0] == 0:
self.settings[qsid] = None self.settings[qsid] = QmkSettings.qsid_deserialize(qsid, data[1:])
else:
self.settings[qsid] = data[1:1+width]
def reload_dynamic(self): def reload_dynamic(self):
if self.vial_protocol < 4: if self.vial_protocol < 4:
@ -720,8 +718,10 @@ class Keyboard:
return [self.macro_deserialize(x) for x in macros] return [self.macro_deserialize(x) for x in macros]
def qmk_settings_set(self, qsid, value): def qmk_settings_set(self, qsid, value):
from qmk_settings import QmkSettings
self.settings[qsid] = value self.settings[qsid] = value
data = self.usb_send(self.dev, struct.pack("<BBH", CMD_VIA_VIAL_PREFIX, CMD_VIAL_QMK_SETTINGS_SET, qsid) + value, data = self.usb_send(self.dev, struct.pack("<BBH", CMD_VIA_VIAL_PREFIX, CMD_VIAL_QMK_SETTINGS_SET, qsid)
+ QmkSettings.qsid_serialize(qsid, value),
retries=20) retries=20)
return data[0] return data[0]

View File

@ -41,8 +41,8 @@ class BooleanOption(GenericOption):
self.container.addWidget(self.checkbox, self.row, 1) self.container.addWidget(self.checkbox, self.row, 1)
def reload(self, keyboard): def reload(self, keyboard):
data = super().reload(keyboard) value = super().reload(keyboard)
checked = data[0] & (1 << self.qsid_bit) checked = value & (1 << self.qsid_bit)
self.checkbox.blockSignals(True) self.checkbox.blockSignals(True)
self.checkbox.setChecked(checked != 0) self.checkbox.setChecked(checked != 0)
@ -69,11 +69,10 @@ class IntegerOption(GenericOption):
self.container.addWidget(self.spinbox, self.row, 1) self.container.addWidget(self.spinbox, self.row, 1)
def reload(self, keyboard): def reload(self, keyboard):
data = super().reload(keyboard)[0:self.option["width"]] self.spinbox.setValue(super().reload(keyboard))
self.spinbox.setValue(int.from_bytes(data, byteorder="little"))
def value(self): def value(self):
return self.spinbox.value().to_bytes(self.option["width"], byteorder="little") return self.spinbox.value()
def delete(self): def delete(self):
super().delete() super().delete()
@ -173,15 +172,8 @@ class QmkSettings(BasicEditor):
qsid_values = defaultdict(int) qsid_values = defaultdict(int)
for tab in self.tabs: for tab in self.tabs:
for field in tab: for field in tab:
# hack for boolean options - we pack several booleans into a single byte qsid_values[field.qsid] |= field.value()
if isinstance(field, BooleanOption):
qsid_values[field.qsid] |= field.value()
else:
qsid_values[field.qsid] = field.value()
for qsid, value in qsid_values.items(): for qsid, value in qsid_values.items():
if isinstance(value, int):
value = value.to_bytes(1, byteorder="little")
self.keyboard.qmk_settings_set(qsid, value) self.keyboard.qmk_settings_set(qsid, value)
def reset_settings(self): def reset_settings(self):
@ -198,19 +190,38 @@ class QmkSettings(BasicEditor):
@classmethod @classmethod
def initialize(cls, appctx): def initialize(cls, appctx):
cls.settings_widths = dict() cls.qsid_fields = defaultdict(list)
with open(appctx.get_resource("qmk_settings.json"), "r") as inf: with open(appctx.get_resource("qmk_settings.json"), "r") as inf:
cls.settings_defs = json.load(inf) cls.settings_defs = json.load(inf)
for tab in cls.settings_defs["tabs"]: for tab in cls.settings_defs["tabs"]:
for field in tab["fields"]: for field in tab["fields"]:
if field["type"] == "boolean": cls.qsid_fields[field["qsid"]].append(field)
width = 1
elif field["type"] == "integer":
width = field["width"]
else:
raise RuntimeError("unsupported field type: {}".format(field))
cls.settings_widths[field["qsid"]] = width
@classmethod @classmethod
def setting_width(cls, qsid): def is_qsid_supported(cls, qsid):
return cls.settings_widths.get(qsid) """ Return whether this qsid is supported by the settings editor """
return qsid in cls.qsid_fields
@classmethod
def qsid_serialize(cls, qsid, data):
""" Serialize from internal representation into binary that can be sent to the firmware """
fields = cls.qsid_fields[qsid]
if fields[0]["type"] == "boolean":
assert isinstance(data, int)
return data.to_bytes(1, byteorder="little")
elif fields[0]["type"] == "integer":
assert isinstance(data, int)
assert len(fields) == 1
return data.to_bytes(fields[0]["width"], byteorder="little")
@classmethod
def qsid_deserialize(cls, qsid, data):
""" Deserialize from binary received from firmware into internal representation """
fields = cls.qsid_fields[qsid]
if fields[0]["type"] == "boolean":
return data[0]
elif fields[0]["type"] == "integer":
assert len(fields) == 1
return int.from_bytes(data[0:fields[0]["width"]], byteorder="little")
else:
raise RuntimeError("unsupported field")