kopia lustrzana https://github.com/corrscope/corrscope
Refactor GUI combo binding, remove parallel arrays (#222)
rodzic
adaa629828
commit
3c422632c1
|
@ -1,7 +1,6 @@
|
|||
import functools
|
||||
import sys
|
||||
import traceback
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
from types import MethodType
|
||||
from typing import Optional, List, Any, Tuple, Callable, Union, Dict, Sequence
|
||||
|
@ -31,7 +30,8 @@ from corrscope.gui.model_bind import (
|
|||
behead,
|
||||
rgetattr,
|
||||
rsetattr,
|
||||
Symbol,
|
||||
Value,
|
||||
ValueText,
|
||||
)
|
||||
from corrscope.gui.util import color2hex, Locked, find_ranges, TracebackDialog
|
||||
from corrscope.gui.view_mainwindow import MainWindow as Ui_MainWindow
|
||||
|
@ -630,19 +630,13 @@ assert set(flatten_modes.keys()) == set(Flatten.modes) # type: ignore
|
|||
|
||||
class ConfigModel(PresentationModel):
|
||||
cfg: Config
|
||||
combo_symbols: Dict[str, Sequence[Symbol]] = {}
|
||||
combo_text: Dict[str, Sequence[str]] = {}
|
||||
combo_value_text: Dict[str, Sequence[ValueText]] = {}
|
||||
|
||||
master_audio = path_fix_property("master_audio")
|
||||
|
||||
# Stereo flattening
|
||||
for path, symbol_map in [
|
||||
["trigger_stereo", flatten_no_stereo],
|
||||
["render_stereo", flatten_modes],
|
||||
]:
|
||||
combo_symbols[path] = list(symbol_map.keys())
|
||||
combo_text[path] = list(symbol_map.values())
|
||||
del path, symbol_map
|
||||
combo_value_text["trigger_stereo"] = list(flatten_no_stereo.items())
|
||||
combo_value_text["render_stereo"] = list(flatten_modes.items())
|
||||
|
||||
# Trigger
|
||||
@property
|
||||
|
@ -656,8 +650,10 @@ class ConfigModel(PresentationModel):
|
|||
scfg = SpectrumConfig() if gui else None
|
||||
self.cfg.trigger.pitch_tracking = scfg
|
||||
|
||||
combo_symbols["trigger__edge_direction"] = [1, -1]
|
||||
combo_text["trigger__edge_direction"] = ["Rising (+1)", "Falling (-1)"]
|
||||
combo_value_text["trigger__edge_direction"] = [
|
||||
(1, "Rising (+1)"),
|
||||
(-1, "Falling (-1)"),
|
||||
]
|
||||
|
||||
# Render
|
||||
@property
|
||||
|
@ -694,15 +690,12 @@ class ConfigModel(PresentationModel):
|
|||
_orientations = [["h", "Horizontal"], ["v", "Vertical"]]
|
||||
_stereo_orientations = _orientations + [["overlay", "Overlay"]]
|
||||
|
||||
for path, cls, symbol_map in [
|
||||
["layout__orientation", Orientation, _orientations],
|
||||
["layout__stereo_orientation", StereoOrientation, _stereo_orientations],
|
||||
]:
|
||||
symbol_map = OrderedDict(symbol_map)
|
||||
# comprehensions fail in class scope
|
||||
combo_symbols[path] = list(map(cls, symbol_map.keys()))
|
||||
combo_text[path] = list(symbol_map.values())
|
||||
del path, cls, symbol_map
|
||||
combo_value_text["layout__orientation"] = [
|
||||
(Orientation(key), name) for key, name in _orientations
|
||||
]
|
||||
combo_value_text["layout__stereo_orientation"] = [
|
||||
(StereoOrientation(key), name) for key, name in _stereo_orientations
|
||||
]
|
||||
|
||||
|
||||
# End ConfigModel
|
||||
|
|
|
@ -19,14 +19,24 @@ if TYPE_CHECKING:
|
|||
|
||||
assert Enum
|
||||
|
||||
__all__ = ["PresentationModel", "map_gui", "behead", "rgetattr", "rsetattr", "Symbol"]
|
||||
__all__ = [
|
||||
"PresentationModel",
|
||||
"map_gui",
|
||||
"behead",
|
||||
"rgetattr",
|
||||
"rsetattr",
|
||||
"Value",
|
||||
"ValueText",
|
||||
]
|
||||
|
||||
|
||||
Signal = Any
|
||||
WidgetUpdater = Callable[[], None]
|
||||
Symbol = Hashable
|
||||
Value = Hashable
|
||||
|
||||
|
||||
ValueText = Tuple[Value, str]
|
||||
|
||||
# Data binding presentation-model
|
||||
class PresentationModel(qc.QObject):
|
||||
""" Key-value MVP presentation-model.
|
||||
|
@ -38,8 +48,7 @@ class PresentationModel(qc.QObject):
|
|||
|
||||
# These fields are specific to each subclass, and assigned there.
|
||||
# Although less explicit, these can be assigned using __init_subclass__.
|
||||
combo_symbols: Dict[str, Sequence[Symbol]]
|
||||
combo_text: Dict[str, Sequence[str]]
|
||||
combo_value_text: Dict[str, Sequence[ValueText]]
|
||||
edited = qc.pyqtSignal()
|
||||
|
||||
def __init__(self, cfg: DumpableAttrs):
|
||||
|
@ -268,28 +277,27 @@ class BoundCheckBox(qw.QCheckBox, BoundWidget):
|
|||
|
||||
|
||||
class BoundComboBox(qw.QComboBox, BoundWidget):
|
||||
combo_symbols: Sequence[Symbol]
|
||||
symbol2idx: Dict[Symbol, int]
|
||||
combo_value_text: Sequence[ValueText]
|
||||
value2idx: Dict[Value, int]
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
def bind_widget(self, model: PresentationModel, path: str, *args, **kwargs) -> None:
|
||||
# Effectively enum values.
|
||||
self.combo_symbols = model.combo_symbols[path]
|
||||
self.combo_value_text = model.combo_value_text[path]
|
||||
|
||||
# symbol2idx[str] = int
|
||||
self.symbol2idx = {}
|
||||
# value2idx[enum] = combo-box index
|
||||
self.value2idx = {}
|
||||
|
||||
# Pretty-printed text
|
||||
combo_text = model.combo_text[path]
|
||||
for i, symbol in enumerate(self.combo_symbols):
|
||||
self.symbol2idx[symbol] = i
|
||||
self.addItem(combo_text[i])
|
||||
for i, (value, text) in enumerate(self.combo_value_text):
|
||||
self.value2idx[value] = i
|
||||
# Pretty-printed text
|
||||
self.addItem(text)
|
||||
|
||||
BoundWidget.bind_widget(self, model, path, *args, **kwargs)
|
||||
|
||||
# combobox.index = pmodel.attr
|
||||
def set_gui(self, symbol: Symbol) -> None:
|
||||
combo_index = self.symbol2idx[symbol]
|
||||
def set_gui(self, value: Value) -> None:
|
||||
combo_index = self.value2idx[value]
|
||||
self.setCurrentIndex(combo_index)
|
||||
|
||||
gui_changed = alias("currentIndexChanged")
|
||||
|
@ -298,7 +306,8 @@ class BoundComboBox(qw.QComboBox, BoundWidget):
|
|||
@pyqtSlot(int)
|
||||
def set_model(self, combo_index: int):
|
||||
assert isinstance(combo_index, int)
|
||||
self.pmodel[self.path] = self.combo_symbols[combo_index]
|
||||
value, _ = self.combo_value_text[combo_index]
|
||||
self.pmodel[self.path] = value
|
||||
|
||||
|
||||
# Color-specific widgets
|
||||
|
|
Ładowanie…
Reference in New Issue