diff --git a/docs/source/widgets/absolute_geometry.rst b/docs/source/widgets/absolute_geometry.rst new file mode 100644 index 000000000..670acd589 --- /dev/null +++ b/docs/source/widgets/absolute_geometry.rst @@ -0,0 +1,8 @@ +####################### +PyDMAbsoluteGeometry +####################### + +.. autoclass:: pydm.widgets.absolute_geometry.PyDMAbsoluteGeometry + :members: + :inherited-members: + :show-inheritance: diff --git a/docs/source/widgets/index.rst b/docs/source/widgets/index.rst index 1c1ccdd69..453f9ae89 100644 --- a/docs/source/widgets/index.rst +++ b/docs/source/widgets/index.rst @@ -50,6 +50,7 @@ Container Widgets .. toctree:: :maxdepth: 1 + absolute_geometry.rst embedded_display.rst frame.rst tab_widget.rst diff --git a/motorxU.ui b/motorxU.ui new file mode 100644 index 000000000..16c556c59 --- /dev/null +++ b/motorxU.ui @@ -0,0 +1,1511 @@ + + + Dialog + + + + 550 + 29 + 176 + 282 + + + + PyDMAbsoluteGeometry#screen { + color: rgb(0, 0, 0); + background-color: rgb(200, 200, 200); + } + + + motorxU + + + + + 4 + 130 + 165 + 40 + + + + + + 0 + 0 + 0 + + + + + Qt::SolidLine + + + + 0 + 0 + 0 + + + + 3 + + + Qt::FlatCap + + + rectangle + + + + + + 5 + 257 + 170 + 24 + + + + STOP + + + + 10 + + + + ${P}${M}.STOP + + + ca://${P}${M}.STOP + + + 1 + + + PyDMPushButton#message_button { + color: rgb(249, 218, 60); + background-color: rgb(253, 0, 0); + } + + + + + + 4 + 236 + 55 + 18 + + + + more + + + more + + + false + + + + 10 + + + + PyDMRelatedDisplayButton#related_display { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + } + + + + ${M} {Tiny} + ${M} {Help} + ${M} {Medium} + ${M} {Setup} + Scan Parameters + ${M} {Debug} + + + + + motorx_tiny.ui + motorx_help.ui + motorx_more.ui + motorx_setup.ui + scanParms.ui + motorx_all.ui + + + + + P=${P},M=${M} + P=${P},M=${M} + P=${P},M=${M} + P=${P},M=${M} + P=${P},Q=${M},PV=${M} + P=${P},M=${M} + + + + true + + + + + + 62 + 236 + 55 + 18 + + + + redefine + + + + 10 + + + + ${P}${M}.SSET + + + ca://${P}${M}.SSET + + + 1 + + + PyDMPushButton#message_button_1 { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + } + + + + + + 118 + 236 + 55 + 18 + + + + operate + + + + 10 + + + + ${P}${M}.SUSE + + + ca://${P}${M}.SUSE + + + 1 + + + PyDMPushButton#message_button_2 { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + } + + + + + + 60 + 234 + 115 + 22 + + + + + + 251 + 243 + 74 + + + + + Qt::SolidLine + + + + 251 + 243 + 74 + + + + 2.0 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.SET", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_1 + + + + + + 0 + 198 + 174 + 34 + + + + + + 97 + 10 + 117 + + + + + Qt::SolidLine + + + + 97 + 10 + 117 + + + + 0 + + + Qt::FlatCap + + + rectangle_2 + + + + + + 4 + 202 + 64 + 9 + + + + PV: ${P}${M}.VELO + + + ca://${P}${M}.VELO + + + + 4 + + + + Qt::AlignCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update { + color: rgb(236, 236, 236); + background-color: rgb(97, 10, 117); + } + + + + + + 148 + 202 + 20 + 9 + + + + /s + + + + 4 + + + + + + 236 + 236 + 236 + + + + + text + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + QLabel#text { + color: rgb(236, 236, 236); + } + + + + + + 3 + 215 + 80 + 14 + + + + speed x0.1 + + + + 8 + + + + ${P}${M}_vCh.A + + + ca://${P}${M}_vCh.A + + + 0.1 + + + PyDMPushButton#message_button_3 { + color: rgb(236, 236, 236); + background-color: rgb(139, 26, 150); + } + + + + + + 90 + 215 + 80 + 14 + + + + speed x10 + + + + 8 + + + + ${P}${M}_vCh.A + + + ca://${P}${M}_vCh.A + + + 10 + + + PyDMPushButton#message_button_4 { + color: rgb(236, 236, 236); + background-color: rgb(139, 26, 150); + } + + + + + + 83 + 202 + 64 + 9 + + + + PV: ${P}${M}.EGU + + + ca://${P}${M}.EGU + + + + 4 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update_1 { + color: rgb(236, 236, 236); + background-color: rgb(97, 10, 117); + } + + + + + + 0 + 126 + 174 + 70 + + + + + + 183 + 157 + 92 + + + + + Qt::SolidLine + + + + 183 + 157 + 92 + + + + 0 + + + Qt::FlatCap + + + rectangle_3 + + + + + + 3 + 174 + 80 + 20 + + + + x0.1 + + + + 10 + + + + ${P}${M}_twCh.A + + + ca://${P}${M}_twCh.A + + + 0.1 + + + PyDMPushButton#message_button_5 { + color: rgb(0, 0, 0); + background-color: rgb(199, 187, 109); + } + + + + + + 90 + 174 + 80 + 20 + + + + x10 + + + + 10 + + + + ${P}${M}_twCh.A + + + ca://${P}${M}_twCh.A + + + 10 + + + PyDMPushButton#message_button_6 { + color: rgb(0, 0, 0); + background-color: rgb(199, 187, 109); + } + + + + + + 6 + 132 + 25 + 36 + + + + - + + + + 10 + + + + ${P}${M}.TWR + + + ca://${P}${M}.TWR + + + 1 + + + PyDMPushButton#message_button_7 { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + } + + + + + + 141 + 132 + 25 + 36 + + + + + + + + + 10 + + + + ${P}${M}.TWF + + + ca://${P}${M}.TWF + + + 1 + + + PyDMPushButton#message_button_8 { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + } + + + + + + 43 + 154 + 84 + 15 + + + + Moving + + + + 9 + + + + + + 115 + 255 + 107 + + + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.DMOV", "trigger": true}], "expression": "ch[0]==0"}] + + + text_1 + + + Qt::AlignCenter + + + PyDMLabel#text_1 { + color: rgb(115, 255, 107); + } + + + + + + 43 + 160 + 84 + 10 + + + + redefine + + + + 4 + + + + + + 251 + 243 + 74 + + + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.SET", "trigger": true}], "expression": "ch[0]!=0"}] + + + text_2 + + + Qt::AlignCenter + + + PyDMLabel#text_2 { + color: rgb(251, 243, 74); + } + + + + + + 36 + 132 + 100 + 20 + + + + ca://${P}${M}.TWV + + + ${P}${M}.TWV + + + + 10 + + + + PyDMLineEdit#text_entry { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + border: 1px solid black; + margin: 0px; + padding: 0px; + spacing: 0px; + } + + + + + + 43 + 152 + 84 + 10 + + + + Soft limit + + + + 4 + + + + + + 251 + 243 + 74 + + + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.LVIO", "trigger": true}], "expression": "ch[0]!=0"}] + + + text_3 + + + Qt::AlignCenter + + + PyDMLabel#text_3 { + color: rgb(251, 243, 74); + } + + + + + + 5 + 0 + 170 + 20 + + + + PV: ${P}${M}.DESC + + + ca://${P}${M}.DESC + + + + 10 + + + + Qt::AlignCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update_2 { + color: rgb(10, 0, 184); + background-color: rgb(255, 255, 255); + } + + + + + + 5 + 32 + 170 + 12 + + + + PV: ${P}${M}.EGU + + + ca://${P}${M}.EGU + + + + 6 + + + + Qt::AlignCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update_3 { + color: rgb(10, 0, 184); + background-color: rgb(200, 200, 200); + } + + + + + + 5 + 20 + 170 + 12 + + + + + + 10 + 0 + 184 + + + + + Qt::SolidLine + + + + 10 + 0 + 184 + + + + 2 + + + Qt::FlatCap + + + rectangle_4 + + + + + + 5 + 21 + 170 + 10 + + + + {${P}${M}} + + + + 4 + + + + + + 255 + 255 + 255 + + + + + text_4 + + + Qt::AlignCenter + + + QLabel#text_4 { + color: rgb(255, 255, 255); + } + + + + + + 164 + 44 + 6 + 78 + + + + + + 253 + 0 + 0 + + + + + Qt::SolidLine + + + + 253 + 0 + 0 + + + + 0 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.HLS", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_5 + + + + + + 5 + 44 + 6 + 78 + + + + + + 253 + 0 + 0 + + + + + Qt::SolidLine + + + + 253 + 0 + 0 + + + + 0 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.LLS", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_6 + + + + + + 11 + 81 + 154 + 31 + + + + + + 115 + 255 + 107 + + + + + Qt::SolidLine + + + + 115 + 255 + 107 + + + + 2 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.DMOV", "trigger": true}], "expression": "ch[0]==0"}] + + + rectangle_7 + + + + + + 11 + 81 + 154 + 31 + + + + + + 251 + 243 + 74 + + + + + Qt::SolidLine + + + + 251 + 243 + 74 + + + + 2 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.LVIO", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_8 + + + + + + 11 + 81 + 154 + 31 + + + + + + 0 + 0 + 0 + + + + + Qt::SolidLine + + + + 0 + 0 + 0 + + + + 2 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}_able.VAL", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_9 + + + + + + 16 + 84 + 145 + 25 + + + + ca://${P}${M}.VAL + + + ${P}${M}.VAL + + + + 10 + + + + PyDMLineEdit#text_entry_1 { + color: rgb(0, 0, 0); + background-color: rgb(115, 223, 255); + border: 1px solid black; + margin: 0px; + padding: 0px; + spacing: 0px; + } + + + + + + 13 + 56 + 151 + 26 + + + + + + 0 + 0 + 0 + + + + + Qt::SolidLine + + + + 0 + 0 + 0 + + + + 2.0 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.SET", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_10 + + + + + + 17 + 58 + 142 + 22 + + + + + + 251 + 243 + 74 + + + + + Qt::SolidLine + + + + 251 + 243 + 74 + + + + 2.0 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.SET", "trigger": true}, {"channel": "ca://${P}${M}.STAT", "trigger": true}], "expression": "ch[0]!=0 or ch[1]==7"}] + + + rectangle_11 + + + + + + 19 + 60 + 139 + 18 + + + + PV: ${P}${M}.RBV + + + ca://${P}${M}.RBV + + + + 10 + + + + Qt::AlignCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update_4 { + color: rgb(10, 0, 184); + background-color: rgb(236, 236, 236); + } + + + + + + 11 + 81 + 154 + 31 + + + + + + 253 + 0 + 0 + + + + + Qt::DashLine + + + + 253 + 0 + 0 + + + + 2.0 + + + Qt::FlatCap + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}_able.VAL", "trigger": true}], "expression": "ch[0]!=0"}] + + + rectangle_12 + + + + + + 13 + 44 + 149 + 12 + + + + PV: ${P}${M}.HLM + + + ca://${P}${M}.HLM + + + + 6 + + + + Qt::AlignCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update_5 { + color: rgb(187, 187, 187); + background-color: rgb(10, 0, 184); + } + + + + + + 13 + 112 + 149 + 12 + + + + PV: ${P}${M}.LLM + + + ca://${P}${M}.LLM + + + + 6 + + + + Qt::AlignCenter + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + PyDMLabel#text_update_6 { + color: rgb(187, 187, 187); + background-color: rgb(10, 0, 184); + } + + + + + + 43 + 152 + 84 + 10 + + + + Controller + + + + 4 + + + + + + 251 + 243 + 74 + + + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.STAT", "trigger": true}], "expression": "ch[0]==7"}] + + + text_5 + + + Qt::AlignCenter + + + PyDMLabel#text_5 { + color: rgb(251, 243, 74); + } + + + + + + 43 + 160 + 84 + 10 + + + + Error + + + + 4 + + + + + + 251 + 243 + 74 + + + + + [{"name": "visibility", "property": "Visible", "channels": [{"channel": "ca://${P}${M}.STAT", "trigger": true}], "expression": "ch[0]==7"}] + + + text_6 + + + Qt::AlignCenter + + + PyDMLabel#text_6 { + color: rgb(251, 243, 74); + } + + + + + + PyDMDrawingRectangle + QWidget +
pydm.widgets.drawing
+
+ + PyDMPushButton + QPushButton +
pydm.widgets.pushbutton
+
+ + PyDMRelatedDisplayButton + QPushButton +
pydm.widgets.related_display_button
+
+ + PyDMLabel + QLabel +
pydm.widgets.label
+
+ + PyDMLineEdit + QLineEdit +
pydm.widgets.line_edit
+
+ + PyDMAbsoluteGeometry + QWidget +
pydm.widgets.absolute_geometry
+ 1 +
+
+
diff --git a/pydm/layouts/__init__.py b/pydm/layouts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pydm/layouts/absolute_geometry_layout.py b/pydm/layouts/absolute_geometry_layout.py new file mode 100644 index 000000000..44f80caa0 --- /dev/null +++ b/pydm/layouts/absolute_geometry_layout.py @@ -0,0 +1,126 @@ +""" +Layout Manager for MEDM widgets. + +Widgets are placed on this layout in absolute coordinates. +When the layout is resized, the manager will resize each of the +widgets in the layout. +""" + +import logging + +from qtpy.QtCore import QPoint, QRect, QSize +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QLayout, QSizePolicy, QStyle + +logger = logging.getLogger(__name__) + + +class AbsoluteGeometryLayout(QLayout): + """ + Layout Manager for widgets laid out by absolute geometry (such as MEDM). + + Widgets are added to this layout with absolute geometry (x,y,height,width). + When the layout is resized, the manager will resize each of the + widgets in the layout. + """ + + def __init__(self, parent=None, margin=-1, h_spacing=-1, v_spacing=-1): + QLayout.__init__(self, parent) + self.setContentsMargins(margin, margin, margin, margin) + self.m_h_space = h_spacing + self.m_v_space = v_spacing + self.item_list = [] + + def addItem(self, item): + print(f"DIAGNOSTIC ({__class__}.addItem) {item=}") + self.item_list.append(item) + + def horizontalSpacing(self): + if self.m_h_space >= 0: + return self.m_h_space + else: + return self.smart_spacing(QStyle.PM_LayoutHorizontalSpacing) + + def verticalSpacing(self): + if self.m_v_space >= 0: + return self.m_v_space + else: + return self.smart_spacing(QStyle.PM_LayoutVerticalSpacing) + + def count(self): + print(f"DIAGNOSTIC ({__class__}.count) {self.item_list=}") + return len(self.item_list) + + def itemAt(self, index): + if index >= 0 and index < len(self.item_list): + return self.item_list[index] + else: + return None + + def takeAt(self, index): + if index >= 0 and index < len(self.item_list): + return self.item_list.pop(index) + else: + return None + + def expandingDirections(self): + # return Qt.Orientations(0) + return Qt.Horizontal | Qt.Vertical + + def hasHeightForWidth(self): + return False + + def heightForWidth(self, width): + return self.do_layout(QRect(0,0, width, 0), True) + + def setGeometry(self, rect): + print(f"DIAGNOSTIC ({__class__}.setGeometry) {rect=}") + super(AbsoluteGeometryLayout, self).setGeometry(rect) + self.do_layout(rect, False) + print(f"DIAGNOSTIC ({__class__}.setGeometry) {self.item_list=}") + + def sizeHint(self): + return self.minimumSize() + + def minimumSize(self): + size = QSize() + for item in self.item_list: + size = size.expandedTo(item.minimumSize()) + #size += QSize(2*self.margin(), 2*self.margin()) + size += QSize(2*8, 2*8) + return size + + def do_layout(self, rect, test_only): + (left, top, right, bottom) = self.getContentsMargins() + effective_rect = rect.adjusted(left, top, -right, -bottom) + x = effective_rect.x() + y = effective_rect.y() + line_height = 0 + for item in self.item_list: + wid = item.widget() + space_x = self.horizontalSpacing() + if space_x == -1: + space_x = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal) + space_y = self.verticalSpacing() + if space_y == -1: + space_y = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical) + next_x = x + item.sizeHint().width() + space_x + if next_x - space_x > effective_rect.right() and line_height > 0: + x = effective_rect.x() + y = y + line_height + space_y + next_x = x + item.sizeHint().width() + space_x + line_height = 0 + if not test_only: + item.setGeometry(QRect(QPoint(x, y), item.sizeHint())) + x = next_x + line_height = max(line_height, item.sizeHint().height()) + return y + line_height - rect.y() + bottom + + def smart_spacing(self, pm): + parent = self.parent() + if not parent: + return -1 + elif parent.isWidgetType(): + return parent.style().pixelMetric(pm, None, parent) + else: + return parent.spacing() diff --git a/pydm/widgets/__init__.py b/pydm/widgets/__init__.py index 1f6721017..2063cc30c 100644 --- a/pydm/widgets/__init__.py +++ b/pydm/widgets/__init__.py @@ -1,3 +1,5 @@ +from .absolute_geometry import PyDMAbsoluteGeometry + from .channel import PyDMChannel from .byte import PyDMByteIndicator diff --git a/pydm/widgets/absolute_geometry.py b/pydm/widgets/absolute_geometry.py new file mode 100644 index 000000000..aa96b9ca2 --- /dev/null +++ b/pydm/widgets/absolute_geometry.py @@ -0,0 +1,107 @@ +import logging +from qtpy.QtCore import QChildEvent, QEvent +from qtpy.QtWidgets import QWidget + +from ..layouts.absolute_geometry_layout import AbsoluteGeometryLayout +from ..utilities import is_qt_designer +from .base import PyDMPrimitiveWidget + +logger = logging.getLogger(__name__) + + +class PyDMAbsoluteGeometry(QWidget, PyDMPrimitiveWidget): + """ + A QWidget with child widgets scaled when the window is stretched. + + Parameters + ---------- + parent : QWidget + The parent widget for the Label + + Notes + ----- + + 1. Having trouble with use of custom layout, skipping it for now. + 2. QWidget can have widget children. + 3. With is_container=True, then can add children in Qt designer. + """ + + def __init__(self, parent=None): + super().__init__(parent) + + # layout = AbsoluteGeometryLayout(self, margin=0, h_spacing=0, v_spacing=0) + # self.setLayout(layout) + + self.original_size = None + self.original_geometries = {} + self.x_scale = None + self.y_scale = None + + def computeScaleFactors(self, new_size): + if self.original_size is None: + raise ValueError("Must set 'original_sizes' first.") + self.x_scale = new_size.width() / self.original_size.width() + self.y_scale = new_size.height() / self.original_size.height() + + def setChildGeometry(self, child): + original_geometry = self.original_geometries.get(child) + if original_geometry is None: + raise KeyError( + f"No original geometry available for widget {child.__class__.__name__} ." + ) + x = int(self.x_scale * original_geometry.x()) + y = int(self.y_scale * original_geometry.y()) + width = int(self.x_scale * original_geometry.width()) + height = int(self.y_scale * original_geometry.height()) + child.setGeometry(x, y, width, height) + + def childEvent(self, event): + if isinstance(event, QChildEvent): + child = event.child() + # print(f"DIAGNOSTIC ({__class__.__name__}.childEvent) {child.__class__=} {child.geometry()=}") + if ( + event.type() in (QEvent.ChildAdded, QEvent.ChildPolished) + and child not in self.original_geometries + ): + if hasattr(child, "geometry"): + self.original_geometries[child] = child.geometry() + else: + print(f"DIAGNOSTIC ({__class__.__name__}.childEvent) {child.__class__=} {child.geometry()=}") + logger.info("Widget %s has no geometry() method: %s", child.__class__) + pass + elif ( + event.type() == QEvent.ChildRemoved + and child in self.original_geometries + ): + self.original_geometries.pop(child) + + def resizeEvent(self, event): + if is_qt_designer(): + return + old_size = event.oldSize() + new_size = event.size() + + # print(f"DIAGNOSTIC ({__class__.__name__}.resizeEvent) {new_size=} {event.oldSize()=}") + # print(f"DIAGNOSTIC ({__class__.__name__}.resizeEvent) {len(self.children())=}") + # for i, child in enumerate(self.children(), start=1): + # print(f"DIAGNOSTIC ({__class__.__name__}.resizeEvent) {i} {child.__class__=} {child.geometry()}") + # print(f"DIAGNOSTIC ({__class__.__name__}.resizeEvent) {len(self.children())=}") + + # fragile algorithm to discover when to set self.original_size & self.original_geometries + if ( + self.original_size is None + and (old_size.width(), old_size.height()) == (-1, -1) + and (new_size != old_size) + ): + print("*" * 20, "first time", "*" * 20) + self.original_size = new_size + for child in self.children(): + if child not in self.original_geometries: + self.original_geometries[child] = child.geometry() + + self.computeScaleFactors(new_size) + # print(f"DIAGNOSTIC ({__class__.__name__}.resizeEvent) {self.x_scale=} {self.y_scale=}") + + for i, child in enumerate(self.children(), start=1): + # print(f"DIAGNOSTIC ({__class__.__name__}.resizeEvent) {i} {child.__class__=} {child.geometry()}") + self.setChildGeometry(child) diff --git a/pydm/widgets/qtplugins.py b/pydm/widgets/qtplugins.py index e96dd8c71..e3eba5af9 100644 --- a/pydm/widgets/qtplugins.py +++ b/pydm/widgets/qtplugins.py @@ -1,6 +1,18 @@ import logging import os +from .qtplugin_base import qtplugin_factory, WidgetCategory +from .qtplugin_extensions import ( + ArchiveTimeCurveEditorExtension, + BasicSettingsExtension, + RulesExtension, + ScatterCurveEditorExtension, + SymbolExtension, + TimeCurveEditorExtension, + WaveformCurveEditorExtension, +) +from .tab_bar_qtplugin import TabWidgetPlugin +from .absolute_geometry import PyDMAbsoluteGeometry from ..utilities.iconfont import IconFont from .archiver_time_plot import PyDMArchiverTimePlot from .byte import PyDMByteIndicator @@ -262,6 +274,12 @@ group=WidgetCategory.MISC, extensions=BASE_EXTENSIONS) +# Absolute Geometry widget plugin +PyDMAbsoluteGeometryPlugin = qtplugin_factory(PyDMAbsoluteGeometry, + group=WidgetCategory.CONTAINER, + is_container=True, + extensions=BASE_EXTENSIONS) + # ********************************************** # NOTE: Add in new PyDM widgets above this line. # **********************************************