|
@@ -11,6 +11,7 @@ from src.gui.tr_widgets import TrGroupBox, TrPushButton
|
|
|
from PySide6.QtWidgets import (
|
|
from PySide6.QtWidgets import (
|
|
|
QWidget, QVBoxLayout, QFormLayout,
|
|
QWidget, QVBoxLayout, QFormLayout,
|
|
|
QDoubleSpinBox, QGridLayout, QFileDialog,
|
|
QDoubleSpinBox, QGridLayout, QFileDialog,
|
|
|
|
|
+ QCheckBox, QHBoxLayout,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@@ -26,6 +27,14 @@ _FIELDS = [
|
|
|
("block_duration_raster","Block Raster", "uss", 1e6, 0.001, 100.0, 0.01),
|
|
("block_duration_raster","Block Raster", "uss", 1e6, 0.001, 100.0, 0.01),
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
|
|
+# Поля задержек с галочкой "вставлять блок": {attr поля: attr флага в hw}.
|
|
|
|
|
+# Снятая галочка убирает вставку блока задержки (нет артефактов 1/0 тактов).
|
|
|
|
|
+_ENABLE_FLAGS = {
|
|
|
|
|
+ "RF_DELAY": "RF_DELAY_ENABLED",
|
|
|
|
|
+ "TR_DELAY": "TR_DELAY_ENABLED",
|
|
|
|
|
+ "START_DELAY": "START_DELAY_ENABLED",
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
class DelayControlsPanel(QWidget):
|
|
class DelayControlsPanel(QWidget):
|
|
|
rerun = Signal() # user clicked "Apply & Rerun"
|
|
rerun = Signal() # user clicked "Apply & Rerun"
|
|
@@ -43,6 +52,8 @@ class DelayControlsPanel(QWidget):
|
|
|
|
|
|
|
|
self._spinboxes: dict[str, tuple[QDoubleSpinBox, float]] = {}
|
|
self._spinboxes: dict[str, tuple[QDoubleSpinBox, float]] = {}
|
|
|
self._defaults: dict[str, float] = {}
|
|
self._defaults: dict[str, float] = {}
|
|
|
|
|
+ self._checkboxes: dict[str, tuple[QCheckBox, str]] = {}
|
|
|
|
|
+ self._enable_defaults: dict[str, bool] = {}
|
|
|
|
|
|
|
|
for attr, label, unit, scale, mn, mx, step in _FIELDS:
|
|
for attr, label, unit, scale, mn, mx, step in _FIELDS:
|
|
|
sb = QDoubleSpinBox()
|
|
sb = QDoubleSpinBox()
|
|
@@ -52,9 +63,28 @@ class DelayControlsPanel(QWidget):
|
|
|
sb.setSingleStep(step)
|
|
sb.setSingleStep(step)
|
|
|
sb.setStepType(QDoubleSpinBox.AdaptiveDecimalStepType)
|
|
sb.setStepType(QDoubleSpinBox.AdaptiveDecimalStepType)
|
|
|
sb.valueChanged.connect(self._mark_modified)
|
|
sb.valueChanged.connect(self._mark_modified)
|
|
|
- form.addRow(f"{label}:", sb)
|
|
|
|
|
self._spinboxes[attr] = (sb, scale)
|
|
self._spinboxes[attr] = (sb, scale)
|
|
|
|
|
|
|
|
|
|
+ flag_attr = _ENABLE_FLAGS.get(attr)
|
|
|
|
|
+ if flag_attr:
|
|
|
|
|
+ cb = QCheckBox()
|
|
|
|
|
+ cb.setChecked(True)
|
|
|
|
|
+ cb.setToolTip(
|
|
|
|
|
+ "Вставлять блок этой задержки. Снято — блок не вставляется "
|
|
|
|
|
+ "(убирает артефакты 1/0 тактов)."
|
|
|
|
|
+ )
|
|
|
|
|
+ cb.toggled.connect(self._on_enable_toggled)
|
|
|
|
|
+ self._checkboxes[attr] = (cb, flag_attr)
|
|
|
|
|
+ row = QWidget()
|
|
|
|
|
+ row_lay = QHBoxLayout(row)
|
|
|
|
|
+ row_lay.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
+ row_lay.setSpacing(4)
|
|
|
|
|
+ row_lay.addWidget(sb, stretch=1)
|
|
|
|
|
+ row_lay.addWidget(cb)
|
|
|
|
|
+ form.addRow(f"{label}:", row)
|
|
|
|
|
+ else:
|
|
|
|
|
+ form.addRow(f"{label}:", sb)
|
|
|
|
|
+
|
|
|
outer.addWidget(self._grp)
|
|
outer.addWidget(self._grp)
|
|
|
|
|
|
|
|
# 2x2 grid: prevents text overflow on narrow left panel (min 220 px)
|
|
# 2x2 grid: prevents text overflow on narrow left panel (min 220 px)
|
|
@@ -88,11 +118,21 @@ class DelayControlsPanel(QWidget):
|
|
|
sb.setValue(val * scale)
|
|
sb.setValue(val * scale)
|
|
|
sb.blockSignals(False)
|
|
sb.blockSignals(False)
|
|
|
sb.setStyleSheet("")
|
|
sb.setStyleSheet("")
|
|
|
|
|
+ for attr, (cb, flag_attr) in self._checkboxes.items():
|
|
|
|
|
+ enabled = bool(getattr(hw, flag_attr, True))
|
|
|
|
|
+ self._enable_defaults[attr] = enabled
|
|
|
|
|
+ cb.blockSignals(True)
|
|
|
|
|
+ cb.setChecked(enabled)
|
|
|
|
|
+ cb.blockSignals(False)
|
|
|
|
|
+ self._spinboxes[attr][0].setEnabled(enabled)
|
|
|
|
|
|
|
|
def get_overrides(self) -> dict:
|
|
def get_overrides(self) -> dict:
|
|
|
- """Return dict of {attr: value_in_SI_units}."""
|
|
|
|
|
- return {attr: sb.value() / scale
|
|
|
|
|
- for attr, (sb, scale) in self._spinboxes.items()}
|
|
|
|
|
|
|
+ """Return dict of {attr: value} in SI units plus *_ENABLED bool flags."""
|
|
|
|
|
+ overrides = {attr: sb.value() / scale
|
|
|
|
|
+ for attr, (sb, scale) in self._spinboxes.items()}
|
|
|
|
|
+ for cb, flag_attr in self._checkboxes.values():
|
|
|
|
|
+ overrides[flag_attr] = cb.isChecked()
|
|
|
|
|
+ return overrides
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# ------------------------------------------------------------------
|
|
|
# Private helpers
|
|
# Private helpers
|
|
@@ -112,6 +152,13 @@ class DelayControlsPanel(QWidget):
|
|
|
sb.setStyleSheet("")
|
|
sb.setStyleSheet("")
|
|
|
break
|
|
break
|
|
|
|
|
|
|
|
|
|
+ def _on_enable_toggled(self) -> None:
|
|
|
|
|
+ sender = self.sender()
|
|
|
|
|
+ for attr, (cb, flag_attr) in self._checkboxes.items():
|
|
|
|
|
+ if cb is sender:
|
|
|
|
|
+ self._spinboxes[attr][0].setEnabled(cb.isChecked())
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
def _on_reset(self) -> None:
|
|
def _on_reset(self) -> None:
|
|
|
for attr, (sb, scale) in self._spinboxes.items():
|
|
for attr, (sb, scale) in self._spinboxes.items():
|
|
|
default = self._defaults.get(attr)
|
|
default = self._defaults.get(attr)
|
|
@@ -120,6 +167,12 @@ class DelayControlsPanel(QWidget):
|
|
|
sb.setValue(default * scale)
|
|
sb.setValue(default * scale)
|
|
|
sb.blockSignals(False)
|
|
sb.blockSignals(False)
|
|
|
sb.setStyleSheet("")
|
|
sb.setStyleSheet("")
|
|
|
|
|
+ for attr, (cb, flag_attr) in self._checkboxes.items():
|
|
|
|
|
+ default = self._enable_defaults.get(attr, True)
|
|
|
|
|
+ cb.blockSignals(True)
|
|
|
|
|
+ cb.setChecked(default)
|
|
|
|
|
+ cb.blockSignals(False)
|
|
|
|
|
+ self._spinboxes[attr][0].setEnabled(default)
|
|
|
|
|
|
|
|
def _on_save(self) -> None:
|
|
def _on_save(self) -> None:
|
|
|
path, _ = QFileDialog.getSaveFileName(
|
|
path, _ = QFileDialog.getSaveFileName(
|