diff --git a/pydm/tests/widgets/test_analog_indicator.py b/pydm/tests/widgets/test_analog_indicator.py index cc2f5d965..c7cf55d8b 100644 --- a/pydm/tests/widgets/test_analog_indicator.py +++ b/pydm/tests/widgets/test_analog_indicator.py @@ -37,3 +37,62 @@ def test_construct(qtbot, init_channel): # ("Internal C++ object (PyDMDateTimeLabel) already deleted") parent.deleteLater() pydm_analog_indicator.deleteLater() + + +def test_title_default(qtbot): + parent = QWidget() + qtbot.addWidget(parent) + indicator = PyDMAnalogIndicator(parent=parent) + qtbot.addWidget(indicator) + + assert indicator.title == "" + assert indicator.title_label.isHidden() + + parent.deleteLater() + indicator.deleteLater() + + +def test_title_set_and_get(qtbot): + parent = QWidget() + qtbot.addWidget(parent) + indicator = PyDMAnalogIndicator(parent=parent) + qtbot.addWidget(indicator) + + indicator.title = "Test Title" + assert indicator.title == "Test Title" + assert indicator.title_label.text() == "Test Title" + assert not indicator.title_label.isHidden() + + parent.deleteLater() + indicator.deleteLater() + + +def test_title_clear_hides_label(qtbot): + parent = QWidget() + qtbot.addWidget(parent) + indicator = PyDMAnalogIndicator(parent=parent) + qtbot.addWidget(indicator) + + indicator.title = "Visible" + assert not indicator.title_label.isHidden() + + indicator.title = "" + assert indicator.title_label.isHidden() + + parent.deleteLater() + indicator.deleteLater() + + +def test_title_reset(qtbot): + parent = QWidget() + qtbot.addWidget(parent) + indicator = PyDMAnalogIndicator(parent=parent) + qtbot.addWidget(indicator) + + indicator.title = "Something" + indicator.resetTitle() + assert indicator.title == "" + assert indicator.title_label.isHidden() + + parent.deleteLater() + indicator.deleteLater() diff --git a/pydm/widgets/analog_indicator.py b/pydm/widgets/analog_indicator.py index b8a3f3b33..1eba4b5dc 100644 --- a/pydm/widgets/analog_indicator.py +++ b/pydm/widgets/analog_indicator.py @@ -1,6 +1,6 @@ from .base import PyDMWidget from qtpy.QtGui import QColor, QPolygon, QPainter, QFontMetrics -from qtpy.QtWidgets import QFrame, QSizePolicy +from qtpy.QtWidgets import QFrame, QLabel, QSizePolicy from qtpy.QtCore import Qt, QPoint, QSize from .scale import QScale, PyDMScaleIndicator from pydm.utilities import ACTIVE_QT_WRAPPER, QtWrapperTypes @@ -261,6 +261,8 @@ def paintEvent(self, event): ---------- event : QPaintEvent """ + if self.width() <= 0 or self.height() <= 0: + return self.adjust_transformation() self._painter.begin(self) self._painter.translate(0, self._painter_translation_y) # Draw vertically if needed @@ -419,6 +421,10 @@ def __init__(self, parent=None, init_channel=None): self._show_limits = False self.scale_indicator = QScaleAlarmed() + self.title_label = QLabel() + self.title_label.setAlignment(Qt.AlignCenter) + self.title_label.hide() + self._value_position = Qt.RightEdge self._minor_alarm_from_channel = True self._major_alarm_from_channel = True @@ -438,6 +444,31 @@ def sizeHint(self): """ return QSize(250, 70) + def _grid_row_offset(self): + return 1 if hasattr(self, "title_label") else 0 + + def setup_widgets_for_orientation(self, new_orientation, flipped, inverted, value_position): + super().setup_widgets_for_orientation(new_orientation, flipped, inverted, value_position) + if hasattr(self, "title_label"): + num_cols = self.widget_layout.columnCount() + self.widget_layout.addWidget(self.title_label, 0, 0, 1, num_cols) + + def readTitle(self) -> str: + return self.title_label.text() + + def setTitle(self, title: str) -> None: + title = str(title) + self.title_label.setText(title) + if title: + self.title_label.show() + else: + self.title_label.hide() + + def resetTitle(self) -> None: + self.setTitle("") + + title = Property(str, readTitle, setTitle, resetTitle) + def lower_warning_limit_changed(self, new_minor_alarm): """ Callback updates the lower minor alarm boundary diff --git a/pydm/widgets/scale.py b/pydm/widgets/scale.py index 109e875e6..6ecbf379e 100644 --- a/pydm/widgets/scale.py +++ b/pydm/widgets/scale.py @@ -491,6 +491,7 @@ def setup_widgets_for_orientation( """ self.limits_layout = None self.widget_layout = None + r = self._grid_row_offset() if new_orientation == Qt.Horizontal or new_orientation == 1: self.limits_layout = QHBoxLayout() if not inverted: @@ -503,21 +504,21 @@ def setup_widgets_for_orientation( self.widget_layout = QGridLayout() if not flipped: if value_position == Qt.LeftEdge: - self.widget_layout.addWidget(self.value_label, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 0, 1) - self.widget_layout.addItem(self.limits_layout, 1, 1) + self.widget_layout.addWidget(self.value_label, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r, 1) + self.widget_layout.addItem(self.limits_layout, r + 1, 1) elif value_position == Qt.RightEdge: - self.widget_layout.addWidget(self.value_label, 0, 1) - self.widget_layout.addWidget(self.scale_indicator, 0, 0) - self.widget_layout.addItem(self.limits_layout, 1, 0) + self.widget_layout.addWidget(self.value_label, r, 1) + self.widget_layout.addWidget(self.scale_indicator, r, 0) + self.widget_layout.addItem(self.limits_layout, r + 1, 0) elif value_position == Qt.TopEdge: - self.widget_layout.addWidget(self.value_label, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 1, 0) - self.widget_layout.addItem(self.limits_layout, 2, 0) + self.widget_layout.addWidget(self.value_label, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r + 1, 0) + self.widget_layout.addItem(self.limits_layout, r + 2, 0) elif value_position == Qt.BottomEdge: - self.widget_layout.addWidget(self.scale_indicator, 0, 0) - self.widget_layout.addItem(self.limits_layout, 1, 0) - self.widget_layout.addWidget(self.value_label, 2, 0) + self.widget_layout.addWidget(self.scale_indicator, r, 0) + self.widget_layout.addItem(self.limits_layout, r + 1, 0) + self.widget_layout.addWidget(self.value_label, r + 2, 0) if not inverted: self.lower_label.setAlignment(Qt.AlignTop | Qt.AlignLeft) @@ -527,21 +528,21 @@ def setup_widgets_for_orientation( self.upper_label.setAlignment(Qt.AlignTop | Qt.AlignLeft) else: if value_position == Qt.LeftEdge: - self.widget_layout.addItem(self.limits_layout, 0, 1) - self.widget_layout.addWidget(self.scale_indicator, 1, 1) - self.widget_layout.addWidget(self.value_label, 1, 0) + self.widget_layout.addItem(self.limits_layout, r, 1) + self.widget_layout.addWidget(self.scale_indicator, r + 1, 1) + self.widget_layout.addWidget(self.value_label, r + 1, 0) elif value_position == Qt.RightEdge: - self.widget_layout.addItem(self.limits_layout, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 1, 0) - self.widget_layout.addWidget(self.value_label, 1, 1) + self.widget_layout.addItem(self.limits_layout, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r + 1, 0) + self.widget_layout.addWidget(self.value_label, r + 1, 1) elif value_position == Qt.TopEdge: - self.widget_layout.addWidget(self.value_label, 0, 0) - self.widget_layout.addItem(self.limits_layout, 1, 0) - self.widget_layout.addWidget(self.scale_indicator, 2, 0) + self.widget_layout.addWidget(self.value_label, r, 0) + self.widget_layout.addItem(self.limits_layout, r + 1, 0) + self.widget_layout.addWidget(self.scale_indicator, r + 2, 0) elif value_position == Qt.BottomEdge: - self.widget_layout.addItem(self.limits_layout, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 1, 0) - self.widget_layout.addWidget(self.value_label, 2, 0) + self.widget_layout.addItem(self.limits_layout, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r + 1, 0) + self.widget_layout.addWidget(self.value_label, r + 2, 0) if not inverted: self.lower_label.setAlignment(Qt.AlignBottom | Qt.AlignLeft) @@ -574,20 +575,20 @@ def setup_widgets_for_orientation( self.widget_layout = QGridLayout() if not flipped: if value_position == Qt.LeftEdge: - self.widget_layout.addWidget(self.value_label, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 0, 1) - self.widget_layout.addItem(self.limits_layout, 0, 2) + self.widget_layout.addWidget(self.value_label, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r, 1) + self.widget_layout.addItem(self.limits_layout, r, 2) elif value_position == Qt.RightEdge: - self.widget_layout.addWidget(self.scale_indicator, 0, 0) - self.widget_layout.addItem(self.limits_layout, 0, 1) + self.widget_layout.addWidget(self.scale_indicator, r, 0) + self.widget_layout.addItem(self.limits_layout, r, 1) elif value_position == Qt.TopEdge: - self.widget_layout.addWidget(self.value_label, 0, 0, 1, 2) - self.widget_layout.addWidget(self.scale_indicator, 1, 0) - self.widget_layout.addItem(self.limits_layout, 1, 1) + self.widget_layout.addWidget(self.value_label, r, 0, 1, 2) + self.widget_layout.addWidget(self.scale_indicator, r + 1, 0) + self.widget_layout.addItem(self.limits_layout, r + 1, 1) elif value_position == Qt.BottomEdge: - self.widget_layout.addWidget(self.scale_indicator, 0, 0) - self.widget_layout.addItem(self.limits_layout, 0, 1) - self.widget_layout.addWidget(self.value_label, 1, 0, 1, 2) + self.widget_layout.addWidget(self.scale_indicator, r, 0) + self.widget_layout.addItem(self.limits_layout, r, 1) + self.widget_layout.addWidget(self.value_label, r + 1, 0, 1, 2) if not inverted: self.lower_label.setAlignment(Qt.AlignLeft | Qt.AlignBottom) @@ -597,20 +598,20 @@ def setup_widgets_for_orientation( self.upper_label.setAlignment(Qt.AlignLeft | Qt.AlignBottom) else: if value_position == Qt.LeftEdge: - self.widget_layout.addItem(self.limits_layout, 0, 1) - self.widget_layout.addWidget(self.scale_indicator, 0, 2) + self.widget_layout.addItem(self.limits_layout, r, 1) + self.widget_layout.addWidget(self.scale_indicator, r, 2) elif value_position == Qt.RightEdge: - self.widget_layout.addItem(self.limits_layout, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 0, 1) - self.widget_layout.addWidget(self.value_label, 0, 2) + self.widget_layout.addItem(self.limits_layout, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r, 1) + self.widget_layout.addWidget(self.value_label, r, 2) elif value_position == Qt.TopEdge: - self.widget_layout.addWidget(self.value_label, 0, 0, 1, 2) - self.widget_layout.addItem(self.limits_layout, 1, 0) - self.widget_layout.addWidget(self.scale_indicator, 1, 1) + self.widget_layout.addWidget(self.value_label, r, 0, 1, 2) + self.widget_layout.addItem(self.limits_layout, r + 1, 0) + self.widget_layout.addWidget(self.scale_indicator, r + 1, 1) elif value_position == Qt.BottomEdge: - self.widget_layout.addItem(self.limits_layout, 0, 0) - self.widget_layout.addWidget(self.scale_indicator, 0, 1) - self.widget_layout.addWidget(self.value_label, 1, 0, 1, 2) + self.widget_layout.addItem(self.limits_layout, r, 0) + self.widget_layout.addWidget(self.scale_indicator, r, 1) + self.widget_layout.addWidget(self.value_label, r + 1, 0, 1, 2) if not inverted: self.lower_label.setAlignment(Qt.AlignRight | Qt.AlignBottom) @@ -627,6 +628,9 @@ def setup_widgets_for_orientation( self.widget_layout.setContentsMargins(1, 1, 1, 1) self.setLayout(self.widget_layout) + def _grid_row_offset(self) -> int: + return 0 + def readShowValue(self) -> bool: """ Whether or not the current value should be displayed on the scale.