diff --git a/src/silx/gui/widgets/FrameBrowser.py b/src/silx/gui/widgets/FrameBrowser.py index 0f8275d458..16e744bffc 100644 --- a/src/silx/gui/widgets/FrameBrowser.py +++ b/src/silx/gui/widgets/FrameBrowser.py @@ -21,6 +21,7 @@ # THE SOFTWARE. # # ###########################################################################*/ +from __future__ import annotations """This module defines two main classes: - :class:`FrameBrowser`: a widget with 4 buttons (first, previous, next, @@ -217,36 +218,70 @@ def setValue(self, value): self._lineEdit.setText("%d" % value) self._textChangedSlot() -class SliderPlayWidgetAction(qt.QWidgetAction): - def __init__(self, parent, label=None, tooltip=None): + +class _SliderPlayWidgetAction(qt.QWidgetAction): + + sigValueChanged = qt.Signal(int) + + def __init__( + self, + parent: qt.QWidget | None = None, + label: str | None = None, + tooltip: str | None = None, + ): super().__init__(parent) self._build(label=label, tooltip=tooltip) - def _build(self, label=None, tooltip=None): + def _build(self, label: str, tooltip: str): widget = qt.QWidget() layout = qt.QHBoxLayout() widget.setLayout(layout) self._spinbox = qt.QSpinBox() self._spinbox.setToolTip(tooltip) self._spinbox.setRange(1,1000000) + self._spinbox.valueChanged.connect(self.sigValueChanged) label = qt.QLabel(label) label.setToolTip(tooltip) layout.addWidget(label) layout.addWidget(self._spinbox) self.setDefaultWidget(widget) + def value(self) -> int: + return self._spinbox.value() + + def setValue(self, value: int): + self._spinbox.setValue(value) + + class _PlayButtonContextMenu(qt.QMenu): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + + sigFrameRateChanged = qt.Signal(int) + + def __init__(self, parent: qt.QWidget | None = None): + super().__init__(parent) self._build() def _build(self): - self._framerate_action = SliderPlayWidgetAction(self, label="FPS:", tooltip="Display speed in frames per second") - self._interval_action = SliderPlayWidgetAction(self, label="Interval:", tooltip="Jump between frames") - self.addAction(self._framerate_action) - self._framerate_action._spinbox.setValue(10) - self.addAction(self._interval_action) - self._interval_action._spinbox.setValue(1) + self._framerateAction = _SliderPlayWidgetAction(self, label="FPS:", tooltip="Display speed in frames per second") + self._framerateAction.sigValueChanged.connect(self.sigFrameRateChanged) + self._stepAction = _SliderPlayWidgetAction(self, label="Step:", tooltip="Step between displayed frames") + self.addAction(self._framerateAction) + self._framerateAction.setValue(10) + self.addAction(self._stepAction) + self._stepAction.setValue(1) + + def getFrameRate(self) -> int: + return self._framerateAction.value() + + def setFrameRate(self, rate: int): + self._framerateAction.setValue(rate) + + def getStep(self) -> int: + return self._stepAction.value() + + def setStep(self, interval: int): + self._stepAction.setValue(interval) + class HorizontalSliderWithBrowser(qt.QAbstractSlider): """ @@ -294,13 +329,17 @@ def __init__(self, parent=None): self._playButton.setToolTip("Display movie with frames") self._playButton.setIcon(icons.getQIcon("camera")) self._playButton.setIconSize(iconSize) + self._playButton.setCheckable(True) self.mainLayout.addWidget(self._playButton) - self._playButton.clicked.connect(self._playStopSequence) + self._playButton.toggled.connect(self._playButtonToggled) self._menuPlaySlider = _PlayButtonContextMenu(self) + self._menuPlaySlider.sigFrameRateChanged.connect(self._frameRateChanged) + self._frameRateChanged(self.getFrameRate()) self._playButton.setMenu(self._menuPlaySlider) self._playButton.setPopupMode(qt.QToolButton.MenuButtonPopup) + def lineEdit(self): """Returns the line edit provided by this widget. @@ -360,53 +399,37 @@ def value(self): """Get selected value""" return self._slider.value() - def spinBoxFrameRate(self) -> qt.QSpinBox: - """Returns the SpinBox widget for FrameRate display.""" - return self._menuPlaySlider._framerate_action._spinbox - - def spinBoxInterval(self) -> qt.QSpinBox: - """Returns the SpinBox widget for interval display.""" - return self._menuPlaySlider._interval_action._spinbox - def setFrameRate(self, value: int): - """Set the FrameRate value for the PlaySlider""" - self.spinBoxFrameRate().setValue(value) + """Set the frame rate at which images are displayed""" + self._menuPlaySlider.setFrameRate(value) def getFrameRate(self) -> int: - """Returns the value from the FrameRate SpinBox.""" - return int(self.spinBoxFrameRate().value()) + """Get the frame rate at which images are displayed""" + return self._menuPlaySlider.getFrameRate() - def setInterval(self, value: int): - """Set the Interval value for the PlaySlider""" - self.spinBoxInterval().setValue(value) + def setPlayImageStep(self, value: int): + """Set the step between displayed images when playing""" + self._menuPlaySlider.setStep(value) - def getInterval(self) -> int: - """Returns the value from the Interval SpinBox.""" - return int(self.spinBoxInterval().value()) + def getPlayImageStep(self) -> int: + """Returns the step between displayed images""" + return self._menuPlaySlider.getStep() + + def _frameRateChanged(self, framerate: int): + """Update the timer interval""" + self.__timer.setInterval(int(1 / framerate * 1e3)) - def _playStopSequence(self): + def _playButtonToggled(self, checked: bool): """Start/Stop the slider sequence.""" - if self.__timer.isActive(): - self._stopTimer() - else: - self._startTimer() - + if checked: + self.__timer.start() + return + self.__timer.stop() + def _updateState(self): """Advance an interval number of frames in the browser sequence.""" - current_index = self._browser.getValue() - if current_index < self._browser.getRange()[-1]: - self.setValue(current_index + self.getInterval()) + currentIndex = self._browser.getValue() + if currentIndex < self._browser.getRange()[-1]: + self.setValue(currentIndex + self.getPlayImageStep()) else: - self._stopTimer() - - def _startTimer(self): - """Start the slider sequence.""" - framerate = self.getFrameRate() - waiting_time_ms = int(1 / framerate * 1e3) - self.__timer.start(waiting_time_ms) - self._playButton.setIcon(icons.getQIcon("close")) - - def _stopTimer(self): - """Stop the slider sequence.""" - self.__timer.stop() - self._playButton.setIcon(icons.getQIcon("camera")) + self._playButton.setChecked(False)