|
4 | 4 | This file can be safely edited to change the runtime behavior of the widget. |
5 | 5 | """ |
6 | 6 |
|
| 7 | +from pydm.utilities import ACTIVE_QT_WRAPPER, QtWrapperTypes |
| 8 | +from qtpy.QtWidgets import QWidget |
| 9 | + |
7 | 10 | from pcdswidgets.builder.designer_options import DesignerOptions |
8 | 11 | from pcdswidgets.builder.icon_options import IconOptions |
9 | 12 | from pcdswidgets.generated.motion.common.motor_classic_full_base import MotorClassicFullBase |
10 | 13 |
|
| 14 | +try: |
| 15 | + from qtpy.QtCore import pyqtProperty |
| 16 | +except ImportError: |
| 17 | + from qtpy.QtCore import Property as pyqtProperty # type: ignore |
| 18 | + |
| 19 | +# Note: for forward compat, setting up enum properties is completely different |
| 20 | +# depending on if we use pyqt5 or pyside6. |
| 21 | +# I'm following the examples in PyDM here. |
| 22 | +if ACTIVE_QT_WRAPPER == QtWrapperTypes.PYSIDE6: |
| 23 | + from enum import Enum |
| 24 | + |
| 25 | + from PySide6.QtCore import QEnum # type: ignore |
| 26 | + |
| 27 | + @QEnum |
| 28 | + class MotorTypes(Enum): # type: ignore |
| 29 | + """Options for motor type to select error reset PV.""" |
| 30 | + |
| 31 | + GENERIC = 0 |
| 32 | + IMS = 1 |
| 33 | + BECKHOFF = 2 |
| 34 | + BECKHOFF_LEGACY = 3 |
| 35 | + |
| 36 | +else: |
| 37 | + # pyqt5 can't use real python enums for this, unfortunately |
| 38 | + class MotorTypes: # type: ignore |
| 39 | + """Options for motor type to select error reset PV.""" |
| 40 | + |
| 41 | + GENERIC = 0 |
| 42 | + IMS = 1 |
| 43 | + BECKHOFF = 2 |
| 44 | + BECKHOFF_LEGACY = 3 |
| 45 | + |
11 | 46 |
|
12 | 47 | class MotorClassicFull(MotorClassicFullBase): |
| 48 | + """ |
| 49 | + Generic motor widget at full size. |
| 50 | +
|
| 51 | + This class is extended to allow us to support multiple |
| 52 | + types of motor IOCs with the same ui layout. |
| 53 | +
|
| 54 | + The user can set the `motor_type` enum to change the |
| 55 | + following behavior: |
| 56 | +
|
| 57 | + - Error reset PV and value |
| 58 | +
|
| 59 | + There are four options: |
| 60 | +
|
| 61 | + - GENERIC: default, no error reset. |
| 62 | + - IMS: standard IMS IOC (not motor record). |
| 63 | + - BECKHOFF: Motor that uses the 2026+ version of our TwinCAT motion libraries. |
| 64 | + - BECKHOFF_LEGACY: uses the pre-2026 version of the above. |
| 65 | + """ |
| 66 | + |
13 | 67 | designer_options = DesignerOptions( |
14 | 68 | group="ECS Motion Common", |
15 | 69 | is_container=False, |
16 | 70 | icon=IconOptions.NONE, |
17 | 71 | ) |
| 72 | + # Boilerplate to make the enum property work |
| 73 | + if ACTIVE_QT_WRAPPER == QtWrapperTypes.PYQT5: |
| 74 | + from PyQt5.QtCore import Q_ENUM |
| 75 | + |
| 76 | + Q_ENUM(MotorTypes) |
| 77 | + MotorTypes = MotorTypes |
| 78 | + GENERIC = MotorTypes.GENERIC |
| 79 | + IMS = MotorTypes.IMS |
| 80 | + BECKHOFF = MotorTypes.BECKHOFF |
| 81 | + BECKHOFF_LEGACY = MotorTypes.BECKHOFF_LEGACY |
| 82 | + |
| 83 | + def __init__(self, parent: QWidget | None = None): |
| 84 | + super().__init__(parent) |
| 85 | + self._motor_type = MotorTypes.GENERIC |
| 86 | + self._clear_error_suffix = "" |
| 87 | + self.PyDMPushButton_clear_error.hide() |
| 88 | + |
| 89 | + def after_set_macro(self, macro_name: str, value: str): |
| 90 | + """Puts motor prefix into error reset PV.""" |
| 91 | + if macro_name == "MOTOR": |
| 92 | + self.new_clear_error_motor(value) |
| 93 | + |
| 94 | + def get_motor_type(self) -> MotorTypes | int: |
| 95 | + return self._motor_type |
| 96 | + |
| 97 | + def set_motor_type(self, value: MotorTypes | int) -> None: |
| 98 | + self._motor_type = value |
| 99 | + match value: |
| 100 | + case MotorTypes.IMS: |
| 101 | + self.new_clear_error_suffix(":SEQ_SELN") |
| 102 | + self.PyDMPushButton_clear_error.setPressValue(48) |
| 103 | + self.PyDMPushButton_clear_error.show() |
| 104 | + case MotorTypes.BECKHOFF: |
| 105 | + self.new_clear_error_suffix(":bReset") |
| 106 | + self.PyDMPushButton_clear_error.setPressValue(1) |
| 107 | + self.PyDMPushButton_clear_error.show() |
| 108 | + case MotorTypes.BECKHOFF_LEGACY: |
| 109 | + self.new_clear_error_suffix(":PLC:bReset") |
| 110 | + self.PyDMPushButton_clear_error.setPressValue(1) |
| 111 | + self.PyDMPushButton_clear_error.show() |
| 112 | + case _: |
| 113 | + self.PyDMPushButton_clear_error.hide() |
| 114 | + |
| 115 | + motor_type = pyqtProperty(MotorTypes, get_motor_type, set_motor_type) |
| 116 | + |
| 117 | + def new_clear_error_suffix(self, suffix: str): |
| 118 | + self._clear_error_suffix = suffix |
| 119 | + if motor := self.get_macro("MOTOR"): |
| 120 | + self.new_clear_error_motor(motor) |
| 121 | + |
| 122 | + def new_clear_error_motor(self, motor: str): |
| 123 | + if self._clear_error_suffix: |
| 124 | + self.PyDMPushButton_clear_error.set_channel(f"ca://{motor}{self._clear_error_suffix}") |
0 commit comments