From f6aa2649e4253d895486cdd6b6d5dd60bc3c53f5 Mon Sep 17 00:00:00 2001 From: Ronald Pandolfi Date: Wed, 10 Feb 2021 23:46:43 -0800 Subject: [PATCH 1/2] Use ophyd name kwarg when present, otherwise defer to attr name. --- typhos/panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typhos/panel.py b/typhos/panel.py index 2aeb2845e..2d93a57e9 100644 --- a/typhos/panel.py +++ b/typhos/panel.py @@ -616,7 +616,7 @@ def _maybe_add_signal(self, device, attr, dotted_name, component): dotted_name, device.name, ex, exc_info=True) return - return self.add_signal(signal, name=attr, tooltip=component.doc) + return self.add_signal(signal, name=component.kwargs.get('name', attr), tooltip=component.doc) return self._add_component(device, attr, dotted_name, component) From 4b708a77950d6fee739743c94d1190a8e6674ec0 Mon Sep 17 00:00:00 2001 From: Ronald Pandolfi Date: Wed, 3 Dec 2025 15:58:14 -0800 Subject: [PATCH 2/2] fixes for pyside6 --- requirements.txt | 1 - typhos/alarm.py | 23 ++++--- typhos/display.py | 20 +++--- typhos/notes.py | 21 ++++-- typhos/panel.py | 7 +- typhos/positioner.py | 17 +++-- typhos/related_display.py | 5 +- typhos/suite.py | 4 +- typhos/ui/core/detailed_screen.ui | 6 +- typhos/ui/core/embedded_screen.ui | 2 +- typhos/ui/core/engineering_screen.ui | 6 +- typhos/ui/devices/PositionerBase.detailed.ui | 6 +- typhos/ui/widgets/positioner.ui | 69 +++++++++----------- typhos/ui/widgets/positioner_row.ui | 2 +- typhos/ui/widgets/tweakable.ui | 2 +- typhos/utils.py | 39 +++++++++-- typhos/widgets.py | 2 +- 17 files changed, 139 insertions(+), 93 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3fb04fd0d..5778afbce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,6 @@ numpydoc ophyd pcdsutils platformdirs -PyQt5 pydm>=1.19.1 pyqtgraph pyyaml diff --git a/typhos/alarm.py b/typhos/alarm.py index b48cd93a4..82e3a734d 100644 --- a/typhos/alarm.py +++ b/typhos/alarm.py @@ -103,8 +103,8 @@ class TyphosAlarm(TyphosObject, PyDMDrawing, _KindLevel, _AlarmLevel): We will consider a subset of the signals that is of KindLevel and above and summarize state based on the "worst" alarm we see as defined by AlarmLevel. """ - QtCore.Q_ENUMS(_KindLevel) - QtCore.Q_ENUMS(_AlarmLevel) + QtCore.Q_ENUMS(KindLevel) + QtCore.Q_ENUMS(AlarmLevel) KindLevel = KindLevel AlarmLevel = AlarmLevel @@ -119,11 +119,14 @@ class TyphosAlarm(TyphosObject, PyDMDrawing, _KindLevel, _AlarmLevel): def __init__(self, *args, **kwargs): self._kind_level = KindLevel.HINTED super().__init__(*args, **kwargs) + QtCore.QTimer.singleShot(0, self._finish_init) + self.reset_alarm_state() + + def _finish_init(self): # Default drawing properties, can override if needed self.penWidth = 2 self.penColor = QtGui.QColor('black') self.penStyle = Qt.SolidLine - self.reset_alarm_state() self.alarm_changed.connect(self.set_alarm_color) @QtCore.Property(_KindLevel) @@ -210,13 +213,13 @@ def reset_alarm_state(self): self.signal_info = {} self.device_info = defaultdict(list) self.alarm_summary = AlarmLevel.DISCONNECTED - self.set_alarm_color(AlarmLevel.DISCONNECTED) + QtCore.QTimer.singleShot(0, partial(self.set_alarm_color, AlarmLevel.DISCONNECTED)) def channels(self): """ Let pydm know about our pydm channels. """ - ch = list(self._channels) + ch = list(getattr(self, '_channels', [])) for info in self.signal_info.values(): ch.append(info.channel) return ch @@ -395,27 +398,27 @@ def show_alarm_tooltip(self, event): # Each of these must be included for these to work in designer class TyphosAlarmCircle(TyphosAlarm, PyDMDrawingCircle): - QtCore.Q_ENUMS(_KindLevel) + QtCore.Q_ENUMS(KindLevel) kindLevel = TyphosAlarm.kindLevel class TyphosAlarmRectangle(TyphosAlarm, PyDMDrawingRectangle): - QtCore.Q_ENUMS(_KindLevel) + QtCore.Q_ENUMS(KindLevel) kindLevel = TyphosAlarm.kindLevel class TyphosAlarmTriangle(TyphosAlarm, PyDMDrawingTriangle): - QtCore.Q_ENUMS(_KindLevel) + QtCore.Q_ENUMS(KindLevel) kindLevel = TyphosAlarm.kindLevel class TyphosAlarmEllipse(TyphosAlarm, PyDMDrawingEllipse): - QtCore.Q_ENUMS(_KindLevel) + QtCore.Q_ENUMS(KindLevel) kindLevel = TyphosAlarm.kindLevel class TyphosAlarmPolygon(TyphosAlarm, PyDMDrawingPolygon): - QtCore.Q_ENUMS(_KindLevel) + QtCore.Q_ENUMS(KindLevel) kindLevel = TyphosAlarm.kindLevel numberOfPoints = PyDMDrawingPolygon.numberOfPoints diff --git a/typhos/display.py b/typhos/display.py index 8150958ad..e5ce7b2f4 100644 --- a/typhos/display.py +++ b/typhos/display.py @@ -221,7 +221,7 @@ class TyphosDisplayConfigButton(TyphosToolButton): def __init__(self, icon=None, *, parent=None): super().__init__(icon=icon, parent=parent) - self.setPopupMode(self.InstantPopup) + self.setPopupMode(self.ToolButtonPopupMode.InstantPopup) self.setArrowType(Qt.NoArrow) self.templates = None self.device_display = None @@ -838,8 +838,8 @@ def __init__(self, title='${name}', *, show_switcher=True, self.switcher = TyphosDisplaySwitcher() self.underline = QtWidgets.QFrame() - self.underline.setFrameShape(self.underline.HLine) - self.underline.setFrameShadow(self.underline.Plain) + self.underline.setFrameShape(self.underline.Shape.HLine) + self.underline.setFrameShadow(self.underline.Shadow.Plain) self.underline.setLineWidth(10) self.notes_edit = TyphosNotesEdit() @@ -877,7 +877,7 @@ def __init__(self, title='${name}', *, show_switcher=True, self.grid_layout.addWidget(self.help, 2, 0, 1, 2) - self.grid_layout.setSizeConstraint(self.grid_layout.SetMinimumSize) + self.grid_layout.setSizeConstraint(self.grid_layout.SizeConstraint.SetMinimumSize) self.setLayout(self.grid_layout) # Set the property: @@ -945,7 +945,7 @@ def toggle(): self.label.toggle_requested.connect(toggle) # Make designable properties from the title label available here as well - label_alignment = forward_property('label', QtWidgets.QLabel, 'alignment') + # label_alignment = forward_property('label', QtWidgets.QLabel, 'alignment') label_font = forward_property('label', QtWidgets.QLabel, 'font') label_indent = forward_property('label', QtWidgets.QLabel, 'indent') label_margin = forward_property('label', QtWidgets.QLabel, 'margin') @@ -955,13 +955,13 @@ def toggle(): label_text = forward_property('label', QtWidgets.QLabel, 'text') label_textFormat = forward_property('label', QtWidgets.QLabel, 'textFormat') - label_textInteractionFlags = forward_property('label', QtWidgets.QLabel, - 'textInteractionFlags') + # label_textInteractionFlags = forward_property('label', QtWidgets.QLabel, + # 'textInteractionFlags') label_wordWrap = forward_property('label', QtWidgets.QLabel, 'wordWrap') # Make designable properties from the grid_layout - layout_margin = forward_property('grid_layout', QtWidgets.QHBoxLayout, - 'margin') + # layout_margin = forward_property('grid_layout', QtWidgets.QHBoxLayout, + # 'margin') layout_spacing = forward_property('grid_layout', QtWidgets.QHBoxLayout, 'spacing') @@ -1019,7 +1019,7 @@ class TyphosDeviceDisplay(utils.TyphosBase, widgets.TyphosDesignerMixin, """ # Template types and defaults - Q_ENUMS(_DisplayTypes) + Q_ENUMS(DisplayTypes) TemplateEnum = DisplayTypes # For convenience template_changed = QtCore.Signal(object) templates_loaded = QtCore.Signal(object) diff --git a/typhos/notes.py b/typhos/notes.py index f9d515edd..badb9d3e0 100644 --- a/typhos/notes.py +++ b/typhos/notes.py @@ -178,14 +178,10 @@ class TyphosNotesEdit( } def __init__(self, *args, refresh_time: float = 5.0, **kwargs): - super().__init__(*args, **kwargs) - self.editingFinished.connect(self.save_note) - self.setPlaceholderText('no notes...') - self.edit_filter = utils.FrameOnEditFilter(parent=self) - self.setFrame(False) - self.installEventFilter(self.edit_filter) - self._last_updated: Optional[float] = None + QtWidgets.QLineEdit.__init__(self, *args, **kwargs) # This will call both parent __init__ methods + utils.TyphosBase.__init__(self) self._refresh_time: float = refresh_time + # to be initialized later self.device_name: Optional[str] = None self.notes_source: Optional[NotesSource] = None @@ -195,6 +191,17 @@ def __init__(self, *args, refresh_time: float = 5.0, **kwargs): QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred ) + self._last_updated: Optional[float] = None + + QtCore.QTimer.singleShot(0, self._finish_init) + + def _finish_init(self): + self.editingFinished.connect(self.save_note) + self.setPlaceholderText('no notes...') + self.edit_filter = utils.FrameOnEditFilter(parent=self) + self.setFrame(False) + self.installEventFilter(self.edit_filter) + def update_tooltip(self) -> None: if self.data['note'] and self.notes_source is not None: diff --git a/typhos/panel.py b/typhos/panel.py index e5b687252..86a94d715 100644 --- a/typhos/panel.py +++ b/typhos/panel.py @@ -14,6 +14,7 @@ import functools import logging +from enum import Enum from functools import partial from typing import Dict, List, Optional @@ -31,7 +32,7 @@ logger = logging.getLogger(__name__) -class SignalOrder: +class SignalOrder(Enum): """ Options for sorting signals. @@ -667,7 +668,7 @@ def add_device(self, device): self._maybe_add_signal(device, walk.item.attr, walk.dotted_name, walk.item) - self.setSizeConstraint(self.SetMinimumSize) + self.setSizeConstraint(self.SizeConstraint.SetMinimumSize) def _maybe_add_signal(self, device, attr, dotted_name, component): """ @@ -727,7 +728,7 @@ def clear(self): self.signal_name_to_info.clear() -class TyphosSignalPanel(TyphosBase, TyphosDesignerMixin, SignalOrder): +class TyphosSignalPanel(TyphosBase, TyphosDesignerMixin): """ Panel of Signals for a given device, using :class:`SignalPanel`. diff --git a/typhos/positioner.py b/typhos/positioner.py index 7e92c8478..eca38afc7 100644 --- a/typhos/positioner.py +++ b/typhos/positioner.py @@ -137,7 +137,7 @@ class TyphosPositionerWidget( ``hinted`` signals. ============== =========================================================== """ - QtCore.Q_ENUMS(_KindLevel) + QtCore.Q_ENUMS(KindLevel) KindLevel = KindLevel ui: _TyphosPositionerUI @@ -179,6 +179,12 @@ def __init__(self, parent=None): super().__init__(parent=parent) self.ui = typing.cast(_TyphosPositionerUI, uic.loadUi(self.ui_template, self)) + + QtCore.QTimer.singleShot(0, self._finish_init) + + def _finish_init(self): + + self.ui.tweak_positive.clicked.connect(self.positive_tweak) self.ui.tweak_negative.clicked.connect(self.negative_tweak) self.ui.stop_button.clicked.connect(self.stop) @@ -198,7 +204,7 @@ def _clear_status_thread(self): return logger.debug("Clearing current active status") - self._status_thread.disconnect() + self._status_thread.disconnect(self) self._status_thread = None def _start_status_thread( @@ -732,7 +738,7 @@ def show_expert_button(self): inside of an unrelated screen. This will default to False. """ - return self._show_expert_button + return getattr(self, '_show_expert_button', False) @show_expert_button.setter def show_expert_button(self, show): @@ -939,6 +945,9 @@ def __init__(self, *args, **kwargs): self._alarm_level = AlarmLevel.DISCONNECTED super().__init__(*args, **kwargs) + + def _finish_init(self): + super()._finish_init() dynamic_font.patch_widget(self.ui.low_limit, pad_percent=0.01, max_size=12, min_size=4) dynamic_font.patch_widget(self.ui.high_limit, pad_percent=0.01, max_size=12, min_size=4) dynamic_font.patch_widget(self.ui.device_name_label, pad_percent=0.01, min_size=4) @@ -1024,7 +1033,7 @@ def _create_signal_panel(self) -> Optional[TyphosSignalPanel]: if self.device is None: return None - return RowDetails(row=self, parent=self, flags=QtCore.Qt.Window) + return RowDetails(row=self, parent=self, f=QtCore.Qt.Window) def _expand_layout(self) -> None: """Toggle the expansion of the signal panel.""" diff --git a/typhos/related_display.py b/typhos/related_display.py index 896718b25..da6769466 100644 --- a/typhos/related_display.py +++ b/typhos/related_display.py @@ -30,7 +30,7 @@ def happi_check(): return happi_loaded -class TyphosRelatedSuiteButton(TyphosObject, QtWidgets.QPushButton): +class TyphosRelatedSuiteButton(QtWidgets.QPushButton, TyphosObject): """ Button to open a typhos suite with happi-loaded devices. """ @@ -46,6 +46,9 @@ def __init__(self, *args, **kwargs): self._happi_cfg = '' self._preload = False self._suite = None + QtCore.QTimer.singleShot(0, self._finish_init) + + def _finish_init(self): self.clicked.connect(self.show_suite) @QtCore.Property('QStringList') diff --git a/typhos/suite.py b/typhos/suite.py index 2fb29e74d..d3eb2f2f9 100644 --- a/typhos/suite.py +++ b/typhos/suite.py @@ -872,7 +872,9 @@ def _get_sidebar(self, widget): items = {} for group in self.top_level_groups.values(): for item in flatten_tree(group): - items[item.value()] = item + value = item.opts.get('value', None) + if value: + items[value] = item return items.get(widget) def _show_sidebar(self, widget, dock): diff --git a/typhos/ui/core/detailed_screen.ui b/typhos/ui/core/detailed_screen.ui index 87a669e58..95066492c 100644 --- a/typhos/ui/core/detailed_screen.ui +++ b/typhos/ui/core/detailed_screen.ui @@ -178,7 +178,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -279,7 +279,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -300,7 +300,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/typhos/ui/core/embedded_screen.ui b/typhos/ui/core/embedded_screen.ui index 74637b4bf..04117949d 100644 --- a/typhos/ui/core/embedded_screen.ui +++ b/typhos/ui/core/embedded_screen.ui @@ -93,7 +93,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/typhos/ui/core/engineering_screen.ui b/typhos/ui/core/engineering_screen.ui index 023ff43c8..504047be6 100644 --- a/typhos/ui/core/engineering_screen.ui +++ b/typhos/ui/core/engineering_screen.ui @@ -87,7 +87,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -158,7 +158,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -175,7 +175,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/typhos/ui/devices/PositionerBase.detailed.ui b/typhos/ui/devices/PositionerBase.detailed.ui index aeeb11276..7c7a71372 100644 --- a/typhos/ui/devices/PositionerBase.detailed.ui +++ b/typhos/ui/devices/PositionerBase.detailed.ui @@ -176,7 +176,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -277,7 +277,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -298,7 +298,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/typhos/ui/widgets/positioner.ui b/typhos/ui/widgets/positioner.ui index 1a081cfb1..c612a6bb3 100644 --- a/typhos/ui/widgets/positioner.ui +++ b/typhos/ui/widgets/positioner.ui @@ -6,8 +6,8 @@ 0 0 - 369 - 277 + 543 + 327 @@ -44,7 +44,7 @@ 5 - + @@ -65,7 +65,7 @@ - QFrame::Box + QFrame::Shape::Box 0 @@ -90,8 +90,8 @@ 0 - - + + 0 @@ -148,7 +148,7 @@ - + @@ -171,7 +171,7 @@ low_limit - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter false @@ -185,8 +185,8 @@ 0 - - + + 0 @@ -249,7 +249,7 @@ - + @@ -261,7 +261,7 @@ motion - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -270,7 +270,7 @@ - + @@ -286,7 +286,6 @@ - 75 true @@ -305,7 +304,7 @@ Screen - Qt::Vertical + Qt::Orientation::Vertical @@ -355,7 +354,7 @@ Screen user_readback - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -365,7 +364,7 @@ Screen - + @@ -389,7 +388,7 @@ Screen - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter false @@ -449,7 +448,7 @@ Screen - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -485,7 +484,6 @@ Screen - 75 true @@ -526,9 +524,6 @@ Screen false - - PyDMLabel::String - @@ -550,7 +545,7 @@ Screen - Qt::Vertical + Qt::Orientation::Vertical @@ -575,8 +570,8 @@ Screen 0 - - + + 25 @@ -622,9 +617,6 @@ Screen 50 - - Qt::Vertical - false @@ -659,7 +651,7 @@ Screen high_limit - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter false @@ -673,8 +665,8 @@ Screen 0 - - + + 25 @@ -695,7 +687,7 @@ Screen - + @@ -707,7 +699,7 @@ Screen alarm - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -716,7 +708,7 @@ Screen - + @@ -732,7 +724,6 @@ Screen - 75 true @@ -751,12 +742,12 @@ Error - Qt::Vertical + Qt::Orientation::Vertical - 20 - 40 + 40 + 20 diff --git a/typhos/ui/widgets/positioner_row.ui b/typhos/ui/widgets/positioner_row.ui index 2747c2ac4..c0b8d6138 100644 --- a/typhos/ui/widgets/positioner_row.ui +++ b/typhos/ui/widgets/positioner_row.ui @@ -932,7 +932,7 @@ - Qt::Vertical + Qt::Orientation::Vertical false diff --git a/typhos/ui/widgets/tweakable.ui b/typhos/ui/widgets/tweakable.ui index e07a548fb..e6b660ee7 100644 --- a/typhos/ui/widgets/tweakable.ui +++ b/typhos/ui/widgets/tweakable.ui @@ -174,7 +174,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/typhos/utils.py b/typhos/utils.py index 3175cde28..7e4d07c06 100644 --- a/typhos/utils.py +++ b/typhos/utils.py @@ -464,10 +464,24 @@ def iconSize(self, size): self._animation.setScaledSize(self._icon_size) -class TyphosObject: +class TyphosObject(): def __init__(self, *args, **kwargs): self.devices = list() - super().__init__(*args, **kwargs) + self._weak_partials_ = [] + + # Check if a QWidget is already initialized (multiple inheritance case) + mro = type(self).__mro__ + typhos_object_index = mro.index(TyphosObject) + has_other_qwidget = any( + 'QtWidgets' in cls.__module__ or cls is TyphosBase + for cls in mro[:typhos_object_index] + ) + + if not has_other_qwidget: + # Normal case: initialize the full chain + super().__init__(*args, **kwargs) + else: + pass def add_device(self, device): """ @@ -606,7 +620,24 @@ class TyphosBase(TyphosObject, QWidget): def __init__(self, *args, **kwargs): self._weak_partials_ = [] - super().__init__(*args, **kwargs) + # Check if a QWidget is already initialized (multiple inheritance case) + mro = type(self).__mro__ + typhos_base_index = mro.index(TyphosBase) + has_other_qwidget = any( + 'QtWidgets' in cls.__module__ + for cls in mro[:typhos_base_index] + ) + + if not has_other_qwidget: + # Normal case: initialize the full chain + try: + QWidget.__init__(self, kwargs.get('parent', None)) + except TypeError: + print('blah') + super().__init__(*args, **kwargs) + else: + # Multiple inheritance case: just initialize TyphosObject + TyphosObject.__init__(self) def _connect_partial_weakly( self, @@ -679,7 +710,7 @@ def reload_widget_stylesheet(widget, cascade=False): """Reload the stylesheet of the provided widget""" widget.style().unpolish(widget) widget.style().polish(widget) - widget.update() + QWidget.update(widget) if cascade: for child in widget.children(): if isinstance(child, QWidget): diff --git a/typhos/widgets.py b/typhos/widgets.py index 9ae27b076..fb6e09553 100644 --- a/typhos/widgets.py +++ b/typhos/widgets.py @@ -499,8 +499,8 @@ class HappiChannel(pydm.widgets.channel.PyDMChannel, QObject): """ def __init__(self, *, tx_slot, **kwargs): - super().__init__(**kwargs) QObject.__init__(self) + super().__init__(**kwargs) self._tx_slot = tx_slot self._last_md = None