mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-10-31 00:31:28 +01:00
feat(dock_area): add QWidget scan queue next to the QML one in the Add Utils toolbar
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F2iSCsSSznEdY4HxoVaqoi
This commit is contained in:
9 files changed
+124
-4
No files matched your search
@@ -30,6 +30,7 @@ _Widgets = {
|
||||
"BECMainWindow": "BECMainWindow",
|
||||
"BECProgressBar": "BECProgressBar",
|
||||
"BECQueue": "BECQueue",
|
||||
"BECQueueQt": "BECQueueQt",
|
||||
"BECShell": "BECShell",
|
||||
"BECStatusBox": "BECStatusBox",
|
||||
"BeamlineStateManager": "BeamlineStateManager",
|
||||
@@ -526,6 +527,30 @@ class BECQueue(RPCBase):
|
||||
"""
|
||||
|
||||
|
||||
class BECQueueQt(RPCBase):
|
||||
"""The BEC queue with a QWidget view instead of QML, for comparing the two toolkits."""
|
||||
|
||||
_IMPORT_MODULE = "bec_widgets.widgets.services.bec_queue.bec_queue_qt"
|
||||
|
||||
@rpc_call
|
||||
def remove(self):
|
||||
"""
|
||||
Cleanup the BECConnector
|
||||
"""
|
||||
|
||||
@rpc_call
|
||||
def attach(self):
|
||||
"""
|
||||
None
|
||||
"""
|
||||
|
||||
@rpc_call
|
||||
def detach(self):
|
||||
"""
|
||||
Detach the widget from its parent dock widget (if widget is in the dock), making it a floating widget.
|
||||
"""
|
||||
|
||||
|
||||
class BECShell(RPCBase):
|
||||
"""A BecConsole pre-configured to run the BEC shell."""
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ designer_plugins = {
|
||||
"BECProgressBar",
|
||||
),
|
||||
"BECQueue": ("bec_widgets.widgets.services.bec_queue.bec_queue", "BECQueue"),
|
||||
"BECQueueQt": ("bec_widgets.widgets.services.bec_queue.bec_queue_qt", "BECQueueQt"),
|
||||
"BECShell": ("bec_widgets.widgets.editors.bec_console.bec_console", "BECShell"),
|
||||
"BECSpinBox": ("bec_widgets.widgets.utility.spinbox.decimal_spinbox", "BECSpinBox"),
|
||||
"BECStatusBox": ("bec_widgets.widgets.services.bec_status_box.bec_status_box", "BECStatusBox"),
|
||||
@@ -127,6 +128,7 @@ widget_icons = {
|
||||
"BECMainWindow": "widgets",
|
||||
"BECProgressBar": "page_control",
|
||||
"BECQueue": "edit_note",
|
||||
"BECQueueQt": "edit_note",
|
||||
"BECShell": "hub",
|
||||
"BECSpinBox": "123",
|
||||
"BECStatusBox": "widgets",
|
||||
|
||||
@@ -376,7 +376,8 @@ class BECDockArea(DockAreaWidget):
|
||||
),
|
||||
}
|
||||
util_actions = {
|
||||
"queue": (widget_icons["BECQueue"], "Scan Queue", "BECQueue"),
|
||||
"queue": (widget_icons["BECQueue"], "Scan Queue (QML)", "BECQueue"),
|
||||
"queue_qt": (widget_icons["BECQueueQt"], "Scan Queue (QWidgets)", "BECQueueQt"),
|
||||
"status": (widget_icons["BECStatusBox"], "BEC Status Box", "BECStatusBox"),
|
||||
"progress_bar": (
|
||||
widget_icons["RingProgressBar"],
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
QWidget rendering of the BEC queue, with the same UX as the QML view.
|
||||
|
||||
This exists to compare the two toolkits on the same data layer (:class:`QueueController`) and the
|
||||
same shell (:class:`BECQueue`); only the view differs. It is not registered for RPC or Designer.
|
||||
same shell (:class:`BECQueue`); only the view differs.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -732,8 +732,7 @@ class BECQueueQt(BECQueue):
|
||||
Same shell, controller and behaviour as :class:`BECQueue`; only the rendering differs.
|
||||
"""
|
||||
|
||||
PLUGIN = False
|
||||
RPC = False
|
||||
PLUGIN = True
|
||||
|
||||
def _create_view(self) -> QWidget:
|
||||
return QueueView(self.controller, self)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{'files': ['bec_queue_qt.py']}
|
||||
@@ -0,0 +1,57 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
||||
from qtpy.QtWidgets import QWidget
|
||||
|
||||
from bec_widgets.utils.bec_designer import designer_material_icon
|
||||
from bec_widgets.widgets.services.bec_queue.bec_queue_qt import BECQueueQt
|
||||
|
||||
DOM_XML = """
|
||||
<ui language='c++'>
|
||||
<widget class='BECQueueQt' name='bec_queue_qt'>
|
||||
</widget>
|
||||
</ui>
|
||||
"""
|
||||
|
||||
|
||||
class BECQueueQtPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._form_editor = None
|
||||
|
||||
def createWidget(self, parent):
|
||||
if parent is None:
|
||||
return QWidget()
|
||||
t = BECQueueQt(parent)
|
||||
return t
|
||||
|
||||
def domXml(self):
|
||||
return DOM_XML
|
||||
|
||||
def group(self):
|
||||
return "BEC Services"
|
||||
|
||||
def icon(self):
|
||||
return designer_material_icon(BECQueueQt.ICON_NAME)
|
||||
|
||||
def includeFile(self):
|
||||
return "bec_queue_qt"
|
||||
|
||||
def initialize(self, form_editor):
|
||||
self._form_editor = form_editor
|
||||
|
||||
def isContainer(self):
|
||||
return False
|
||||
|
||||
def isInitialized(self):
|
||||
return self._form_editor is not None
|
||||
|
||||
def name(self):
|
||||
return "BECQueueQt"
|
||||
|
||||
def toolTip(self):
|
||||
return "BEC queue with a QWidget view, for comparison with the QML view."
|
||||
|
||||
def whatsThis(self):
|
||||
return self.toolTip()
|
||||
@@ -0,0 +1,15 @@
|
||||
def main(): # pragma: no cover
|
||||
from qtpy import PYSIDE6
|
||||
|
||||
if not PYSIDE6:
|
||||
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
|
||||
return
|
||||
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
|
||||
|
||||
from bec_widgets.widgets.services.bec_queue.bec_queue_qt_plugin import BECQueueQtPlugin
|
||||
|
||||
QPyDesignerCustomWidgetCollection.addCustomWidget(BECQueueQtPlugin())
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
main()
|
||||
@@ -52,3 +52,21 @@ def test_qt_view_paused_banner_and_empty_state(qt_queue, busy_queue):
|
||||
qt_queue.update_queue({}, {})
|
||||
assert qt_queue.view._rows == {}
|
||||
assert not qt_queue.view.empty.isHidden()
|
||||
|
||||
|
||||
def test_dock_area_toolbar_adds_both_queue_views(qtbot, mocked_client):
|
||||
"""The Dock Area toolbar offers the QML and the QWidget queue side by side."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from bec_widgets.widgets.containers.dock_area.dock_area import BECDockArea
|
||||
from bec_widgets.widgets.services.bec_queue.bec_queue import BECQueue
|
||||
|
||||
area = BECDockArea(client=mocked_client)
|
||||
qtbot.addWidget(area)
|
||||
qtbot.waitExposed(area)
|
||||
menu = area.toolbar.components.get_action("menu_utils")
|
||||
menu.actions["queue"].action.trigger()
|
||||
menu.actions["queue_qt"].action.trigger()
|
||||
|
||||
widgets = list(area.widget_map().values())
|
||||
assert sum(type(w) is BECQueue for w in widgets) == 1
|
||||
assert sum(type(w) is BECQueueQt for w in widgets) == 1
|
||||
@@ -887,6 +887,7 @@ class TestToolbarFunctionality:
|
||||
"""Test utils toolbar actions trigger widget creation."""
|
||||
utils_actions = [
|
||||
"queue",
|
||||
"queue_qt",
|
||||
"terminal",
|
||||
"status",
|
||||
"progress_bar",
|
||||
@@ -2496,6 +2497,7 @@ class TestFlatToolbarActions:
|
||||
"""Test that flat utils actions are created."""
|
||||
utils_actions = [
|
||||
"flat_queue",
|
||||
"flat_queue_qt",
|
||||
"flat_status",
|
||||
"flat_progress_bar",
|
||||
"flat_scan_progress_bar",
|
||||
|
||||
Reference in new issue
Block a user