Skip to content

Commit 929c400

Browse files
authored
Display dahsed line on trigger location (#222)
1 parent 5e19d3a commit 929c400

File tree

4 files changed

+83
-8
lines changed

4 files changed

+83
-8
lines changed

scrutiny/gui/components/locals/embedded_graph/embedded_graph_component.py

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from PySide6.QtWidgets import (
1717
QVBoxLayout, QLabel, QWidget, QSplitter, QPushButton, QScrollArea, QHBoxLayout, QMenu, QTabWidget, QCheckBox, QMessageBox
1818
)
19-
from PySide6.QtCore import Qt, QPointF, QRectF
20-
from PySide6.QtGui import QContextMenuEvent, QKeyEvent, QResizeEvent, QIcon
19+
from PySide6.QtCore import Qt, QPointF, QRectF, QRect
20+
from PySide6.QtGui import QContextMenuEvent, QKeyEvent, QResizeEvent, QIcon, QPainter, QPen
2121

2222
from scrutiny import sdk
2323
from scrutiny.sdk import EmbeddedDataType
@@ -28,7 +28,7 @@
2828
from scrutiny.sdk.client import ScrutinyClient
2929

3030
from scrutiny.gui import assets
31-
from scrutiny.gui.themes import scrutiny_get_theme
31+
from scrutiny.gui.themes import scrutiny_get_theme, scrutiny_get_theme_prop, ScrutinyThemeProperties
3232
from scrutiny.gui.tools import prompt
3333
from scrutiny.gui.widgets.watchable_line_edit import WatchableLineEdit
3434
from scrutiny.gui.components.locals.base_local_component import ScrutinyGUIBaseLocalComponent
@@ -54,6 +54,7 @@ class DisplaySource(enum.Enum):
5454

5555

5656
class State:
57+
"""The state that can be saved and reloaded when saving the dashboard"""
5758

5859
class Watchable(TypedDict):
5960
fqn: str
@@ -93,7 +94,7 @@ class EmbeddedGraphState:
9394
waiting_on_graph: bool
9495
"""Waiting on an acquisition to complete"""
9596
chart_toolbar_wanted: bool
96-
"""The suer wants to see the chart toolbar"""
97+
"""The user wants to see the chart toolbar"""
9798
has_failure_message: bool
9899
"""There's a failure message being displayed on the chartview"""
99100

@@ -142,6 +143,9 @@ def enable_reset_zoom_button(self) -> bool:
142143
def must_display_toolbar(self) -> bool:
143144
return self.can_display_toolbar() and self.chart_toolbar_wanted and self.has_content
144145

146+
def must_display_show_trigger_checkbox(self) -> bool:
147+
return self.has_content
148+
145149
def hide_chart_toolbar(self) -> None:
146150
self.chart_toolbar_wanted = False
147151

@@ -166,6 +170,47 @@ class InitialGraphListDownloadConditions:
166170
firmware_id: Optional[str]
167171

168172

173+
class EmbeddedGraphChartView(ScrutinyChartView):
174+
175+
_trigger_xval:float
176+
_show_trigger:bool
177+
_trigger_pen:QPen
178+
179+
@tools.copy_type(ScrutinyChartView.__init__)
180+
def __init__(self, *args:Any, **kwargs:Any) -> None:
181+
super().__init__(*args, **kwargs)
182+
self._trigger_xval=0
183+
self._show_trigger=False
184+
self._trigger_pen = QPen()
185+
self._trigger_pen.setStyle(Qt.PenStyle.DashLine)
186+
self._trigger_pen.setColor(scrutiny_get_theme_prop(ScrutinyThemeProperties.EMBEDDED_GRAPH_CHART_TRIGGER_COLOR))
187+
188+
def show_trigger_marker_at(self, xval:float) -> None:
189+
self._trigger_xval = xval
190+
self.show_trigger_marker()
191+
192+
def show_trigger_marker(self) -> None:
193+
self._show_trigger = True
194+
self._invalidate_forground()
195+
196+
def remove_trigger_marker(self) -> None:
197+
self._show_trigger=False
198+
self._invalidate_forground()
199+
200+
def drawForeground(self, painter: QPainter, rect: Union[QRectF, QRect]) -> None:
201+
super().drawForeground(painter, rect)
202+
xaxis = self.chart().axisX()
203+
if self._show_trigger and xaxis is not None :
204+
chart = self.chart()
205+
plotarea_mapped_to_chartview = chart.mapRectToParent(chart.plotArea())
206+
trigger_xpos_mapped_to_chart = chart.xval_to_xpos(self._trigger_xval)
207+
if trigger_xpos_mapped_to_chart:
208+
trigger_xpos = chart.mapToParent(trigger_xpos_mapped_to_chart, 0).x() # Map it to this chartview
209+
y1 = plotarea_mapped_to_chartview.y()
210+
y2 = plotarea_mapped_to_chartview.y() + plotarea_mapped_to_chartview.height()
211+
painter.setPen(self._trigger_pen)
212+
painter.drawLine(QPointF(trigger_xpos, y1), QPointF(trigger_xpos, y2))
213+
169214
class EmbeddedGraphComponent(ScrutinyGUIBaseLocalComponent):
170215
instance_name: str
171216

@@ -186,9 +231,11 @@ class EmbeddedGraphComponent(ScrutinyGUIBaseLocalComponent):
186231
"""3 section splitter separating left / center / right"""
187232
_xval_label: QLabel
188233
"""The label used to display the X-Value when moving the graph cursor (red vertical line)"""
234+
_chk_show_trigger:QCheckBox
235+
"""A checkbox to show or hide the trigger marker"""
189236
_signal_tree: GraphSignalTree
190237
"""The right side signal tree. contains the watchable we want to log / those present in the displayed graph"""
191-
_chartview: ScrutinyChartView
238+
_chartview: EmbeddedGraphChartView
192239
"""The QT element showing the chart"""
193240
_chart_toolbar: ScrutinyChartToolBar
194241
"""Custom toolbar at the top of the graph selecting the zoom mode and cursor mode"""
@@ -221,7 +268,7 @@ class EmbeddedGraphComponent(ScrutinyGUIBaseLocalComponent):
221268
_graph_browse_list_widget: GraphBrowseListWidget
222269
"""The list displaying the available acquisitions on the server"""
223270
_chk_browse_loaded_sfd_only: QCheckBox
224-
"""A checkbox that filters the content of the acquisition list by keeping only those taken by the firmware presnetly loaded"""
271+
"""A checkbox that filters the content of the acquisition list by keeping only those taken by the firmware presently loaded"""
225272
_browse_feedback_label: FeedbackLabel
226273
"""A label to display messages visible only in the "Browse" tab"""
227274
_btn_delete_all: QPushButton
@@ -268,6 +315,8 @@ def make_right_pane() -> QWidget:
268315
right_pane_layout.setContentsMargins(0, 0, 0, 0)
269316

270317
self._xval_label = QLabel()
318+
self._chk_show_trigger = QCheckBox("Show Trigger")
319+
self._chk_show_trigger.checkStateChanged.connect(self._chk_show_trigger_changed_slot)
271320

272321
# Series on continuous graph don't have their X value aligned.
273322
# We can only show the value next to each point, not all together in the tree
@@ -277,6 +326,7 @@ def make_right_pane() -> QWidget:
277326

278327
self._xval_label.setVisible(False)
279328
right_pane_layout.addWidget(self._xval_label)
329+
right_pane_layout.addWidget(self._chk_show_trigger)
280330
right_pane_layout.addWidget(self._signal_tree)
281331

282332
right_pane_scroll = QScrollArea(self)
@@ -291,7 +341,7 @@ def make_right_pane() -> QWidget:
291341
def make_center_pane() -> QWidget:
292342
chart = ScrutinyChart()
293343

294-
self._chartview = ScrutinyChartView(self)
344+
self._chartview = EmbeddedGraphChartView(self)
295345
self._chartview.setChart(chart)
296346
self._xaxis = None
297347
self._yaxes = []
@@ -599,6 +649,11 @@ def _apply_internal_state(self) -> None:
599649
self._btn_load_more.setText("Load")
600650
else:
601651
self._btn_load_more.setText("Load more")
652+
653+
if self._state.must_display_show_trigger_checkbox():
654+
self._chk_show_trigger.show()
655+
else:
656+
self._chk_show_trigger.hide()
602657

603658
self._btn_load_more.setEnabled(self._state.enable_load_more_button())
604659
self._btn_delete_all.setEnabled(self._state.enable_delete_all_button())
@@ -792,6 +847,16 @@ def _display_acquisition(self, acquisition: DataloggingAcquisition, source: Disp
792847
self._state.allow_chart_toolbar()
793848
self._chart_toolbar.disable_chart_cursor()
794849

850+
# Configure the trigger marker. It is possible that there is no trigger index
851+
if acquisition.trigger_index is not None:
852+
self._chartview.show_trigger_marker_at(xseries_data[acquisition.trigger_index])
853+
self._chk_show_trigger.setChecked(True)
854+
self._chk_show_trigger.setEnabled(True)
855+
else:
856+
self._chartview.remove_trigger_marker()
857+
self._chk_show_trigger.setChecked(False)
858+
self._chk_show_trigger.setEnabled(False)
859+
795860
# Enable the chart cursor so it can display values in the signal tree
796861
def update_xval(val: float, enabled: bool) -> None:
797862
self._xval_label.setText(f"{acquisition.xdata.name} : {val}")
@@ -949,6 +1014,12 @@ def _signal_tree_content_changed_slot(self) -> None:
9491014
"""A watchable has been added/remove from the watchable tree"""
9501015
self._graph_config_widget.update_content()
9511016

1017+
def _chk_show_trigger_changed_slot(self, state:Qt.CheckState) -> None:
1018+
if state == Qt.CheckState.Checked:
1019+
self._chartview.show_trigger_marker()
1020+
else:
1021+
self._chartview.remove_trigger_marker()
1022+
9521023
def update_emphasize_state(self) -> None:
9531024
"""Read the items in the SignalTree object (right menu with axis) and update the size/boldness of the graph series
9541025
based on wether they are selected or not"""

scrutiny/gui/themes/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class ScrutinyThemeProperties(enum.Enum):
3232
WATCHABLE_LINE_EDIT_CLEAR_BTN_PRESSED_COLOR = enum.auto()
3333

3434
WIDGET_ERROR_BACKGROUND_COLOR = enum.auto()
35+
36+
EMBEDDED_GRAPH_CHART_TRIGGER_COLOR = enum.auto()
3537

3638

3739
class ScrutinyTheme(abc.ABC):

scrutiny/gui/themes/default_theme.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class DefaultTheme(ScrutinyTheme):
4141
ScrutinyThemeProperties.WATCHABLE_LINE_EDIT_CLEAR_BTN_HOVER_COLOR: SELECTED_COLOR,
4242
ScrutinyThemeProperties.WATCHABLE_LINE_EDIT_CLEAR_BTN_PRESSED_COLOR: PRESSED_COLOR,
4343

44-
ScrutinyThemeProperties.WIDGET_ERROR_BACKGROUND_COLOR: RED_ERROR
44+
ScrutinyThemeProperties.WIDGET_ERROR_BACKGROUND_COLOR: RED_ERROR,
45+
ScrutinyThemeProperties.EMBEDDED_GRAPH_CHART_TRIGGER_COLOR : QColor(0,0,0)
4546

4647
}
4748

scrutiny/gui/themes/fusion_theme.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(self) -> None:
6060
self._prop_dict[ScrutinyThemeProperties.CHART_TOOLBAR_PRESSED_COLOR] = LIGHT_PRESSED_COLOR
6161
self._prop_dict[ScrutinyThemeProperties.CHART_TOOLBAR_SELECTED_COLOR] = LIGHT_SELECTED_COLOR
6262

63+
self._prop_dict[ScrutinyThemeProperties.EMBEDDED_GRAPH_CHART_TRIGGER_COLOR] = self.palette().text().color()
6364
self._prop_dict[ScrutinyThemeProperties.WATCHABLE_LINE_EDIT_CLEAR_BTN_HOVER_COLOR] = self._prop_dict[ScrutinyThemeProperties.CHART_TOOLBAR_SELECTED_COLOR]
6465
self._prop_dict[ScrutinyThemeProperties.WATCHABLE_LINE_EDIT_CLEAR_BTN_PRESSED_COLOR] = self._prop_dict[ScrutinyThemeProperties.CHART_TOOLBAR_PRESSED_COLOR]
6566

0 commit comments

Comments
 (0)