ui: add support to TestBytes
This commit is contained in:
parent
f327e3ad38
commit
588d7ae533
|
@ -588,7 +588,7 @@ class TestBytes(Condition):
|
||||||
return self.function(feature, notification.address, notification.data)
|
return self.function(feature, notification.address, notification.data)
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
return {'TestBytes': str(self.test)}
|
return {'TestBytes': self.test[:]}
|
||||||
|
|
||||||
|
|
||||||
class MouseGesture(Condition):
|
class MouseGesture(Condition):
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
import string
|
import string
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict, namedtuple
|
||||||
from contextlib import contextmanager as contextlib_contextmanager
|
from contextlib import contextmanager as contextlib_contextmanager
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
@ -512,11 +512,12 @@ class DiversionDialog:
|
||||||
[
|
[
|
||||||
(_('Feature'), _DIV.Feature, FeatureUI.FEATURES_WITH_DIVERSION[0]),
|
(_('Feature'), _DIV.Feature, FeatureUI.FEATURES_WITH_DIVERSION[0]),
|
||||||
(_('Process'), _DIV.Process, ''),
|
(_('Process'), _DIV.Process, ''),
|
||||||
(_('MouseProcess'), _DIV.MouseProcess, ''),
|
(_('Mouse process'), _DIV.MouseProcess, ''),
|
||||||
(_('Report'), _DIV.Report, 0),
|
(_('Report'), _DIV.Report, 0),
|
||||||
(_('Modifiers'), _DIV.Modifiers, []),
|
(_('Modifiers'), _DIV.Modifiers, []),
|
||||||
(_('Key'), _DIV.Key, ''),
|
(_('Key'), _DIV.Key, ''),
|
||||||
(_('Test'), _DIV.Test, next(iter(_DIV.TESTS))),
|
(_('Test'), _DIV.Test, next(iter(_DIV.TESTS))),
|
||||||
|
(_('Test bytes'), _DIV.TestBytes, [0, 1, 0]),
|
||||||
(_('Mouse Gesture'), _DIV.MouseGesture, ''),
|
(_('Mouse Gesture'), _DIV.MouseGesture, ''),
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
@ -1394,6 +1395,123 @@ class TestUI(ConditionUI):
|
||||||
return str(component.test)
|
return str(component.test)
|
||||||
|
|
||||||
|
|
||||||
|
_TestBytesElement = namedtuple('TestBytesElement', ['id', 'label', 'min', 'max'])
|
||||||
|
_TestBytesMode = namedtuple('TestBytesMode', ['label', 'elements', 'label_fn'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestBytesUI(ConditionUI):
|
||||||
|
|
||||||
|
CLASS = _DIV.TestBytes
|
||||||
|
|
||||||
|
_common_elements = [
|
||||||
|
_TestBytesElement('begin', _('begin (inclusive)'), 0, 16),
|
||||||
|
_TestBytesElement('end', _('end (exclusive)'), 0, 16)
|
||||||
|
]
|
||||||
|
|
||||||
|
_global_min = -2**31
|
||||||
|
_global_max = 2**31 - 1
|
||||||
|
|
||||||
|
_modes = {
|
||||||
|
'range':
|
||||||
|
_TestBytesMode(
|
||||||
|
_('range'),
|
||||||
|
_common_elements + [
|
||||||
|
_TestBytesElement('minimum', _('minimum'), _global_min, _global_max), # uint32
|
||||||
|
_TestBytesElement('maximum', _('maximum'), _global_min, _global_max),
|
||||||
|
],
|
||||||
|
lambda e: _('bytes %(0)d to %(1)d, ranging from %(2)d to %(3)d' % {str(i): v
|
||||||
|
for i, v in enumerate(e)})
|
||||||
|
),
|
||||||
|
'mask':
|
||||||
|
_TestBytesMode(
|
||||||
|
_('mask'), _common_elements + [_TestBytesElement('mask', _('mask'), _global_min, _global_max)],
|
||||||
|
lambda e: _('bytes %(0)d to %(1)d, mask %(2)d' % {str(i): v
|
||||||
|
for i, v in enumerate(e)})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_widgets(self):
|
||||||
|
self.fields = {}
|
||||||
|
self.field_labels = {}
|
||||||
|
self.widgets = {}
|
||||||
|
col = 0
|
||||||
|
mode_col = 2
|
||||||
|
self.mode_field = Gtk.ComboBox.new_with_model(Gtk.ListStore(str, str))
|
||||||
|
mode_renderer = Gtk.CellRendererText()
|
||||||
|
self.mode_field.set_id_column(0)
|
||||||
|
self.mode_field.pack_start(mode_renderer, True)
|
||||||
|
self.mode_field.add_attribute(mode_renderer, 'text', 1)
|
||||||
|
self.widgets[self.mode_field] = (mode_col, 1, 1, 1)
|
||||||
|
mode_label = Gtk.Label(_('type'), margin_top=20)
|
||||||
|
self.widgets[mode_label] = (mode_col, 0, 1, 1)
|
||||||
|
for mode_id, mode in TestBytesUI._modes.items():
|
||||||
|
self.mode_field.get_model().append([mode_id, mode.label])
|
||||||
|
for element in mode.elements:
|
||||||
|
if element.id not in self.fields:
|
||||||
|
field = Gtk.SpinButton.new_with_range(element.min, element.max, 1)
|
||||||
|
field.set_value(0)
|
||||||
|
field.set_size_request(150, 0)
|
||||||
|
field.connect('value-changed', self._on_update)
|
||||||
|
label = Gtk.Label(element.label, margin_top=20)
|
||||||
|
self.fields[element.id] = field
|
||||||
|
self.field_labels[element.id] = label
|
||||||
|
self.widgets[label] = (col, 0, 1, 1)
|
||||||
|
self.widgets[field] = (col, 1, 1, 1)
|
||||||
|
col += 1 if col != mode_col - 1 else 2
|
||||||
|
self.mode_field.connect('changed', lambda cb: (self._on_update(), self._only_mode(cb.get_active_id())))
|
||||||
|
self.mode_field.set_active_id('range')
|
||||||
|
|
||||||
|
def show(self, component, editable):
|
||||||
|
super().show(component, editable)
|
||||||
|
|
||||||
|
with self.ignore_changes():
|
||||||
|
mode_id = {3: 'mask', 4: 'range'}.get(len(component.test), None)
|
||||||
|
self._only_mode(mode_id)
|
||||||
|
if not mode_id:
|
||||||
|
return
|
||||||
|
self.mode_field.set_active_id(mode_id)
|
||||||
|
if mode_id:
|
||||||
|
mode = TestBytesUI._modes[mode_id]
|
||||||
|
for i, element in enumerate(mode.elements):
|
||||||
|
self.fields[element.id].set_value(component.test[i])
|
||||||
|
|
||||||
|
def collect_value(self):
|
||||||
|
mode_id = self.mode_field.get_active_id()
|
||||||
|
return [self.fields[element.id].get_value_as_int() for element in TestBytesUI._modes[mode_id].elements]
|
||||||
|
|
||||||
|
def _only_mode(self, mode_id):
|
||||||
|
if not mode_id:
|
||||||
|
return
|
||||||
|
keep = {element.id for element in TestBytesUI._modes[mode_id].elements}
|
||||||
|
for element_id, f in self.fields.items():
|
||||||
|
visible = element_id in keep
|
||||||
|
f.set_visible(visible)
|
||||||
|
self.field_labels[element_id].set_visible(visible)
|
||||||
|
|
||||||
|
def _on_update(self, *args):
|
||||||
|
super()._on_update(*args)
|
||||||
|
if not self.component:
|
||||||
|
return
|
||||||
|
begin, end, *etc = self.component.test
|
||||||
|
icon = 'dialog-warning' if end <= begin else ''
|
||||||
|
self.fields['end'].set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon)
|
||||||
|
if len(self.component.test) == 4:
|
||||||
|
*etc, minimum, maximum = self.component.test
|
||||||
|
icon = 'dialog-warning' if maximum < minimum else ''
|
||||||
|
self.fields['maximum'].set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def left_label(cls, component):
|
||||||
|
return _('Test bytes')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def right_label(cls, component):
|
||||||
|
mode_id = {3: 'mask', 4: 'range'}.get(len(component.test), None)
|
||||||
|
if not mode_id:
|
||||||
|
return str(component.test)
|
||||||
|
return TestBytesUI._modes[mode_id].label_fn(component.test)
|
||||||
|
|
||||||
|
|
||||||
class MouseGestureUI(ConditionUI):
|
class MouseGestureUI(ConditionUI):
|
||||||
|
|
||||||
CLASS = _DIV.MouseGesture
|
CLASS = _DIV.MouseGesture
|
||||||
|
@ -2234,6 +2352,7 @@ COMPONENT_UI = {
|
||||||
_DIV.Modifiers: ModifiersUI,
|
_DIV.Modifiers: ModifiersUI,
|
||||||
_DIV.Key: KeyUI,
|
_DIV.Key: KeyUI,
|
||||||
_DIV.Test: TestUI,
|
_DIV.Test: TestUI,
|
||||||
|
_DIV.TestBytes: TestBytesUI,
|
||||||
_DIV.MouseGesture: MouseGestureUI,
|
_DIV.MouseGesture: MouseGestureUI,
|
||||||
_DIV.KeyPress: KeyPressUI,
|
_DIV.KeyPress: KeyPressUI,
|
||||||
_DIV.MouseScroll: MouseScrollUI,
|
_DIV.MouseScroll: MouseScrollUI,
|
||||||
|
|
Loading…
Reference in New Issue