Refactor and reorganize trigger GUI (#236)

- Separate trigger options into groups
- Enhance GUI framework
    - `append_widget(name, layout, **kwargs)`
    - `add_row(**kwargs{name=})`
pull/357/head
nyanpasu64 2019-03-21 03:09:57 -07:00 zatwierdzone przez GitHub
rodzic ecfa452255
commit eed5ffddb8
2 zmienionych plików z 123 dodań i 79 usunięć

Wyświetl plik

@ -248,76 +248,88 @@ class MainWindow(QWidget):
pass
# Trigger config
with append_widget(s, QGroupBox) as self.optionTrigger:
set_layout(s, QVBoxLayout)
# Top row
with append_widget(s, QGridLayout):
with add_grid_col(s, "", BoundComboBox) as (
self.trigger__edge_direction
with append_widget(s, QVBoxLayout):
with append_widget(s, QHBoxLayout):
with append_widget(
s, QGroupBox, title=tr("Wave Alignment"), layout=QGridLayout
):
pass
with add_grid_col(
s,
tr("Buffer Strength"),
BoundDoubleSpinBox,
name="trigger__buffer_strength",
):
pass
with add_grid_col(
s,
tr("Buffer Responsiveness"),
BoundDoubleSpinBox,
name="trigger__responsiveness",
maximum=1.0,
singleStep=0.1,
):
pass
with add_grid_col(
s,
tr("Mean Responsiveness"),
BoundDoubleSpinBox,
name="trigger__mean_responsiveness",
) as w: # type: BoundDoubleSpinBox
w.setMaximum(1.0)
w.setSingleStep(0.1)
with add_grid_col(s, BoundCheckBox, Both) as (
self.trigger__pitch_tracking
):
assert isinstance(self.trigger__pitch_tracking, QWidget)
with add_grid_col(s, "", BoundDoubleSpinBox) as (
self.trigger__edge_strength
with append_widget(
s, QGroupBox, title=tr("Edge Search"), layout=QGridLayout
):
self.trigger__edge_strength.setMinimum(0.0)
with add_grid_col(s, "", BoundComboBox) as (
self.trigger__edge_direction
):
pass
with add_grid_col(s, "", BoundDoubleSpinBox) as (
self.trigger__edge_strength
):
self.trigger__edge_strength.setMinimum(0.0)
with add_grid_col(
s,
tr("Slope Strength"),
BoundDoubleSpinBox,
name="trigger__slope_strength",
with append_widget(s, QHBoxLayout):
with append_widget(
s, QGroupBox, title=tr("Slope Search"), layout=QGridLayout
):
s.widget.setSingleStep(10)
s.widget.setMaximum(200)
with add_grid_col(
s,
tr("Slope Strength"),
BoundDoubleSpinBox,
name="trigger__slope_strength",
):
s.widget.setSingleStep(10)
s.widget.setMaximum(200)
with add_grid_col(
s,
tr("Slope Width"),
BoundDoubleSpinBox,
name="trigger__slope_width",
):
s.widget.setMinimum(0)
s.widget.setMaximum(0.5)
s.widget.setSingleStep(0.02)
with add_grid_col(
s,
tr("Slope Width"),
BoundDoubleSpinBox,
name="trigger__slope_width",
with append_widget(
s, QGroupBox, title=tr("Post Triggering"), layout=QGridLayout
):
s.widget.setMinimum(0)
s.widget.setMaximum(0.5)
s.widget.setSingleStep(0.02)
with add_grid_col(
s, tr("Post Trigger"), TypeComboBox
) as self.trigger__post_trigger:
pass
with add_grid_col(s, "", BoundDoubleSpinBox) as (
self.trigger__responsiveness
):
self.trigger__responsiveness.setMaximum(1.0)
self.trigger__responsiveness.setSingleStep(0.1)
with add_grid_col(
s,
tr("Mean Responsiveness"),
BoundDoubleSpinBox,
name="trigger__mean_responsiveness",
) as w: # type: BoundDoubleSpinBox
w.setMaximum(1.0)
w.setSingleStep(0.1)
with append_widget(s, HLine):
pass
# Bottom row
with append_widget(s, QGridLayout):
with add_grid_col(s, BoundCheckBox, Both) as (
self.trigger__pitch_tracking
):
assert isinstance(self.trigger__pitch_tracking, QWidget)
with add_grid_col(
s, tr("Post Trigger"), TypeComboBox
) as self.trigger__post_trigger:
pass
with add_grid_col(
s, tr("Post Trigger Radius"), BoundSpinBox
) as self.trigger__post_radius:
pass
# self.trigger__post_radius: BoundSpinBox
# self.trigger__post_radius.setMinimum(0)
with add_grid_col(
s, tr("Post Trigger Radius"), BoundSpinBox
) as self.trigger__post_radius:
pass
# self.trigger__post_radius: BoundSpinBox
# self.trigger__post_radius.setMinimum(0)
def add_channels_list(self, s):
tr = self.tr
@ -423,9 +435,7 @@ class MainWindow(QWidget):
self.render__res_divisorL.setText(tr("Resolution Divisor"))
self.master_audio.setText(tr("/"))
self.master_audio_browse.setText(tr("&Browse..."))
self.optionTrigger.setTitle(tr("Trigger"))
self.trigger__edge_strengthL.setText(tr("Edge Strength"))
self.trigger__responsivenessL.setText(tr("Responsiveness"))
self.trigger__pitch_tracking.setText(tr("Pitch Tracking"))
self.trigger__edge_directionL.setText(tr("Edge Direction"))

Wyświetl plik

@ -13,20 +13,39 @@ SomeQW = TypeVar("SomeQW", bound=QWidget)
WidgetOrLayout = TypeVar("WidgetOrLayout", bound=Union[QWidget, QLayout])
# TODO
# React-style component layouts
# @singledispatch
# new_widget_or_layout(type)
# LayoutStack.push(instance)
# Like HTML document.createElement()
def new_widget_or_layout(
item_type: Union[Type[WidgetOrLayout], str], parent: QWidget
item_type: Union[Type[WidgetOrLayout], str], parent: QWidget, attributes=None
) -> WidgetOrLayout:
"""Creates a widget or layout, for insertion into an existing layout.
Do NOT use for filling a widget with a layout!"""
if attributes is None:
attributes = {}
if isinstance(item_type, str):
return QLabel(item_type, parent)
item = QLabel(item_type, parent)
elif issubclass(item_type, QWidget):
return item_type(parent)
item = item_type(parent)
else:
assert issubclass(item_type, QLayout)
# new_widget_or_layout is used to add sublayouts, which do NOT have a parent.
# Only widgets' root layouts have parents.
return item_type(None)
item = item_type(None)
if "name" in attributes:
item.setObjectName(attributes.pop("name"))
for key, value in attributes.items():
qt_setattr(item, key, value)
return item
@attr.dataclass
@ -89,21 +108,24 @@ def assert_peek(stack: LayoutStack, cls):
assert isinstance(stack.widget, cls)
def central_widget(stack: LayoutStack, widget_type: Type[SomeQW] = QWidget):
def central_widget(stack: LayoutStack, widget_type: Type[SomeQW] = QWidget, **kwargs):
assert_peek(stack, QMainWindow)
# do NOT orphan=True
return _new_widget(stack, widget_type, exit_action="setCentralWidget")
return _new_widget(stack, widget_type, exit_action="setCentralWidget", **kwargs)
def orphan_widget(stack: LayoutStack, widget_type: Type[SomeQW] = QWidget):
return _new_widget(stack, widget_type, orphan=True)
def orphan_widget(stack: LayoutStack, widget_type: Type[SomeQW] = QWidget, **kwargs):
return _new_widget(stack, widget_type, orphan=True, **kwargs)
@contextmanager
def append_widget(
stack: LayoutStack, item_type: Type[WidgetOrLayout], layout_args: list = []
stack: LayoutStack,
item_type: Type[WidgetOrLayout],
layout_args: list = [],
**kwargs,
) -> ctx[WidgetOrLayout]:
with _new_widget(stack, item_type) as item:
with _new_widget(stack, item_type, **kwargs) as item:
yield item
_insert_widget_or_layout(stack.layout, item, *layout_args)
@ -152,6 +174,9 @@ def _new_widget(
item_type: Type[WidgetOrLayout],
orphan=False,
exit_action: Union[Callable[[Any, Any], Any], str] = "",
*,
layout: Optional[Type[QLayout]] = None,
**kwargs,
) -> ctx[WidgetOrLayout]:
"""
- Constructs item_type using parent.
@ -163,7 +188,9 @@ def _new_widget(
else:
parent = None
with stack.push(new_widget_or_layout(item_type, parent)) as item:
with stack.push(new_widget_or_layout(item_type, parent, kwargs)) as item:
if layout:
set_layout(stack, layout)
yield item
real_parent = stack.widget
@ -173,6 +200,11 @@ def _new_widget(
getattr(real_parent, exit_action)(item)
def qt_setattr(obj, key: str, value) -> None:
key = "set" + key[0].capitalize() + key[1:]
getattr(obj, key)(value)
def append_stretch(stack: LayoutStack):
cast(QBoxLayout, stack.layout).addStretch()
@ -191,21 +223,23 @@ Both = _Both()
def widget_pair_inserter(append_widgets: Callable):
@contextmanager
def add_row_col(stack: LayoutStack, left_type, right_type, *, name=None):
def add_row_col(stack: LayoutStack, left_type, right_type, *, name=None, **kwargs):
parent = stack.widget
left = new_widget_or_layout(left_type, parent)
left_is_label = isinstance(left, QLabel)
if right_type is Both:
left = new_widget_or_layout(left_type, parent, kwargs)
right = Both
push = left
else:
right = new_widget_or_layout(right_type, parent)
left = new_widget_or_layout(left_type, parent)
right = new_widget_or_layout(right_type, parent, kwargs)
push = right
if name:
(right or left).setObjectName(name)
left_is_label = isinstance(left, QLabel)
with stack.push(push):
if right is Both:
yield left