Refactor GUI combo binding, remove parallel arrays (#222)

pull/357/head
nyanpasu64 2019-03-09 00:58:49 -08:00
rodzic adaa629828
commit 3c422632c1
2 zmienionych plików z 41 dodań i 39 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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