logitech_receiver: add UnsortedNamedInts
This commit is contained in:
parent
b36b070feb
commit
29ff5e5924
|
@ -99,7 +99,7 @@ class NamedInts:
|
||||||
if the value already exists in the set (int or string), ValueError will be
|
if the value already exists in the set (int or string), ValueError will be
|
||||||
raised.
|
raised.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('__dict__', '_values', '_indexed', '_fallback')
|
__slots__ = ('__dict__', '_values', '_indexed', '_fallback', '_is_sorted')
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
def _readable_name(n):
|
def _readable_name(n):
|
||||||
|
@ -110,7 +110,9 @@ class NamedInts:
|
||||||
# print (repr(kwargs))
|
# print (repr(kwargs))
|
||||||
values = {k: NamedInt(v, _readable_name(k)) for (k, v) in kwargs.items()}
|
values = {k: NamedInt(v, _readable_name(k)) for (k, v) in kwargs.items()}
|
||||||
self.__dict__ = values
|
self.__dict__ = values
|
||||||
self._values = sorted(list(values.values()))
|
self._is_sorted = False
|
||||||
|
self._values = list(values.values())
|
||||||
|
self._sort_values()
|
||||||
self._indexed = {int(v): v for v in self._values}
|
self._indexed = {int(v): v for v in self._values}
|
||||||
# assert len(values) == len(self._indexed)
|
# assert len(values) == len(self._indexed)
|
||||||
# "(%d) %r\n=> (%d) %r" % (len(values), values, len(self._indexed), self._indexed)
|
# "(%d) %r\n=> (%d) %r" % (len(values), values, len(self._indexed), self._indexed)
|
||||||
|
@ -137,14 +139,20 @@ class NamedInts:
|
||||||
if unknown_bits:
|
if unknown_bits:
|
||||||
yield 'unknown:%06X' % unknown_bits
|
yield 'unknown:%06X' % unknown_bits
|
||||||
|
|
||||||
|
def _sort_values(self):
|
||||||
|
self._values = sorted(self._values)
|
||||||
|
self._is_sorted = True
|
||||||
|
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
if isinstance(index, int):
|
if isinstance(index, int):
|
||||||
if index in self._indexed:
|
if index in self._indexed:
|
||||||
return self._indexed[int(index)]
|
return self._indexed[int(index)]
|
||||||
if self._fallback and isinstance(index, int):
|
if self._fallback:
|
||||||
value = NamedInt(index, self._fallback(index))
|
value = NamedInt(index, self._fallback(index))
|
||||||
self._indexed[index] = value
|
self._indexed[index] = value
|
||||||
self._values = sorted(self._values + [value])
|
self._values.append(value)
|
||||||
|
self._is_sorted = False
|
||||||
|
self._sort_values()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
elif is_string(index):
|
elif is_string(index):
|
||||||
|
@ -153,21 +161,24 @@ class NamedInts:
|
||||||
return (next((x for x in self._values if str(x) == index), None))
|
return (next((x for x in self._values if str(x) == index), None))
|
||||||
|
|
||||||
elif isinstance(index, slice):
|
elif isinstance(index, slice):
|
||||||
|
values = self._values if self._is_sorted else sorted(self._values)
|
||||||
|
|
||||||
if index.start is None and index.stop is None:
|
if index.start is None and index.stop is None:
|
||||||
return self._values[:]
|
return values[:]
|
||||||
|
|
||||||
v_start = int(self._values[0]) if index.start is None else int(index.start)
|
v_start = int(values[0]) if index.start is None else int(index.start)
|
||||||
v_stop = (self._values[-1] + 1) if index.stop is None else int(index.stop)
|
v_stop = (values[-1] + 1) if index.stop is None else int(index.stop)
|
||||||
|
|
||||||
if v_start > v_stop or v_start > self._values[-1] or v_stop <= self._values[0]:
|
if v_start > v_stop or v_start > values[-1] or v_stop <= values[0]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if v_start <= self._values[0] and v_stop > self._values[-1]:
|
if v_start <= values[0] and v_stop > values[-1]:
|
||||||
return self._values[:]
|
return values[:]
|
||||||
|
|
||||||
start_index = 0
|
start_index = 0
|
||||||
stop_index = len(self._values)
|
stop_index = len(values)
|
||||||
for i, value in enumerate(self._values):
|
|
||||||
|
for i, value in enumerate(values):
|
||||||
if value < v_start:
|
if value < v_start:
|
||||||
start_index = i + 1
|
start_index = i + 1
|
||||||
elif index.stop is None:
|
elif index.stop is None:
|
||||||
|
@ -176,7 +187,7 @@ class NamedInts:
|
||||||
stop_index = i
|
stop_index = i
|
||||||
break
|
break
|
||||||
|
|
||||||
return self._values[start_index:stop_index]
|
return values[start_index:stop_index]
|
||||||
|
|
||||||
def __setitem__(self, index, name):
|
def __setitem__(self, index, name):
|
||||||
assert isinstance(index, int), type(index)
|
assert isinstance(index, int), type(index)
|
||||||
|
@ -193,7 +204,9 @@ class NamedInts:
|
||||||
if int(value) in self._indexed:
|
if int(value) in self._indexed:
|
||||||
raise ValueError('%d (%s) already known' % (int(value), value))
|
raise ValueError('%d (%s) already known' % (int(value), value))
|
||||||
|
|
||||||
self._values = sorted(self._values + [value])
|
self._values.append(value)
|
||||||
|
self._is_sorted = False
|
||||||
|
self._sort_values()
|
||||||
self.__dict__[str(value)] = value
|
self.__dict__[str(value)] = value
|
||||||
self._indexed[int(value)] = value
|
self._indexed[int(value)] = value
|
||||||
|
|
||||||
|
@ -216,6 +229,15 @@ class NamedInts:
|
||||||
return NamedInts(**self.__dict__, **other.__dict__)
|
return NamedInts(**self.__dict__, **other.__dict__)
|
||||||
|
|
||||||
|
|
||||||
|
class UnsortedNamedInts(NamedInts):
|
||||||
|
def _sort_values(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __or__(self, other):
|
||||||
|
c = UnsortedNamedInts if isinstance(other, UnsortedNamedInts) else NamedInts
|
||||||
|
return c(**self.__dict__, **other.__dict__)
|
||||||
|
|
||||||
|
|
||||||
def strhex(x):
|
def strhex(x):
|
||||||
assert x is not None
|
assert x is not None
|
||||||
"""Produce a hex-string representation of a sequence of bytes."""
|
"""Produce a hex-string representation of a sequence of bytes."""
|
||||||
|
|
|
@ -31,6 +31,7 @@ from .common import FirmwareInfo as _FirmwareInfo
|
||||||
from .common import KwException as _KwException
|
from .common import KwException as _KwException
|
||||||
from .common import NamedInt as _NamedInt
|
from .common import NamedInt as _NamedInt
|
||||||
from .common import NamedInts as _NamedInts
|
from .common import NamedInts as _NamedInts
|
||||||
|
from .common import UnsortedNamedInts as _UnsortedNamedInts
|
||||||
from .common import bytes2int as _bytes2int
|
from .common import bytes2int as _bytes2int
|
||||||
from .common import pack as _pack
|
from .common import pack as _pack
|
||||||
from .common import unpack as _unpack
|
from .common import unpack as _unpack
|
||||||
|
@ -438,18 +439,18 @@ class ReprogrammableKeyV4(ReprogrammableKey):
|
||||||
return _NamedInt(self._mapped_to, task)
|
return _NamedInt(self._mapped_to, task)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def remappable_to(self) -> List[_NamedInt]:
|
def remappable_to(self) -> _NamedInts:
|
||||||
self._device.keys._ensure_all_keys_queried()
|
self._device.keys._ensure_all_keys_queried()
|
||||||
ret = []
|
ret = _UnsortedNamedInts()
|
||||||
if self.group_mask != []: # only keys with a non-zero gmask are remappable
|
if self.group_mask != []: # only keys with a non-zero gmask are remappable
|
||||||
ret = [self.default_task] # it should always be possible to map the key to itself
|
ret[self.default_task] = self.default_task # it should always be possible to map the key to itself
|
||||||
for g in self.group_mask:
|
for g in self.group_mask:
|
||||||
g = special_keys.CID_GROUP[str(g)]
|
g = special_keys.CID_GROUP[str(g)]
|
||||||
for tgt_cid in self._device.keys.group_cids[g]:
|
for tgt_cid in self._device.keys.group_cids[g]:
|
||||||
tgt_task = str(special_keys.TASK[self._device.keys.cid_to_tid[tgt_cid]])
|
tgt_task = str(special_keys.TASK[self._device.keys.cid_to_tid[tgt_cid]])
|
||||||
tgt_task = _NamedInt(tgt_cid, tgt_task)
|
tgt_task = _NamedInt(tgt_cid, tgt_task)
|
||||||
if tgt_task != self.default_task: # don't put itself in twice
|
if tgt_task != self.default_task: # don't put itself in twice
|
||||||
ret.append(tgt_task)
|
ret[tgt_task] = tgt_task
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -23,7 +23,7 @@ from shlex import quote as shlex_quote
|
||||||
|
|
||||||
from gi.repository import Gdk, GObject, Gtk
|
from gi.repository import Gdk, GObject, Gtk
|
||||||
from logitech_receiver import diversion as _DIV
|
from logitech_receiver import diversion as _DIV
|
||||||
from logitech_receiver.common import NamedInt, NamedInts
|
from logitech_receiver.common import NamedInt, UnsortedNamedInts
|
||||||
from logitech_receiver.diversion import XK_KEYS as _XK_KEYS
|
from logitech_receiver.diversion import XK_KEYS as _XK_KEYS
|
||||||
from logitech_receiver.diversion import Key as _Key
|
from logitech_receiver.diversion import Key as _Key
|
||||||
from logitech_receiver.diversion import buttons as _buttons
|
from logitech_receiver.diversion import buttons as _buttons
|
||||||
|
@ -1655,10 +1655,16 @@ class SetUI(ActionUI):
|
||||||
Only one label per number is kept.
|
Only one label per number is kept.
|
||||||
"""
|
"""
|
||||||
if isinstance(setting, type) and issubclass(setting, _Setting):
|
if isinstance(setting, type) and issubclass(setting, _Setting):
|
||||||
return (getattr(setting, 'choices_universe', None)
|
choices = UnsortedNamedInts()
|
||||||
or NamedInts()) | (getattr(setting, 'choices_extra', None) or NamedInts())
|
universe = getattr(setting, 'choices_universe', None)
|
||||||
|
if universe:
|
||||||
|
choices |= universe
|
||||||
|
extra = getattr(setting, 'choices_extra', None)
|
||||||
|
if extra:
|
||||||
|
choices |= extra
|
||||||
|
return choices
|
||||||
settings = cls.ALL_SETTINGS.get(setting, [])
|
settings = cls.ALL_SETTINGS.get(setting, [])
|
||||||
choices = NamedInts()
|
choices = UnsortedNamedInts()
|
||||||
for s in settings:
|
for s in settings:
|
||||||
choices |= cls._all_choices(s)
|
choices |= cls._all_choices(s)
|
||||||
return choices
|
return choices
|
||||||
|
@ -1670,10 +1676,11 @@ class SetUI(ActionUI):
|
||||||
val_class = setting.validator_class if setting else None
|
val_class = setting.validator_class if setting else None
|
||||||
kind = val_class.kind if val_class else None
|
kind = val_class.kind if val_class else None
|
||||||
if kind in cls.MULTIPLE:
|
if kind in cls.MULTIPLE:
|
||||||
keys = NamedInts()
|
keys = UnsortedNamedInts()
|
||||||
for s in settings:
|
for s in settings:
|
||||||
keys |= getattr(s, 'choices_universe' if kind == _SKIND.multiple_toggle else 'keys_universe',
|
universe = getattr(s, 'choices_universe' if kind == _SKIND.multiple_toggle else 'keys_universe', None)
|
||||||
None) or NamedInts()
|
if universe:
|
||||||
|
keys |= universe
|
||||||
# only one key per number is used
|
# only one key per number is used
|
||||||
else:
|
else:
|
||||||
keys = None
|
keys = None
|
||||||
|
|
Loading…
Reference in New Issue