diff --git a/corrscope/gui/__init__.py b/corrscope/gui/__init__.py index 07b8c5c..104cecd 100644 --- a/corrscope/gui/__init__.py +++ b/corrscope/gui/__init__.py @@ -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 diff --git a/corrscope/gui/model_bind.py b/corrscope/gui/model_bind.py index 5a609bb..dee476b 100644 --- a/corrscope/gui/model_bind.py +++ b/corrscope/gui/model_bind.py @@ -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