kopia lustrzana https://github.com/corrscope/corrscope
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
rodzic
ecfa452255
commit
eed5ffddb8
|
@ -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"))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue