0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 11:41:49 +02:00

fix: changed inheritance to adress qt designer bug in rendering

This commit is contained in:
2024-07-03 18:43:10 +02:00
parent 1586ce2d6c
commit e403870874
3 changed files with 40 additions and 46 deletions

View File

@ -12,7 +12,7 @@ from typing import TYPE_CHECKING
import qdarktheme
from bec_lib.utils.import_utils import lazy_import_from
from qtpy.QtCore import QObject, QTimer, Signal, Slot
from qtpy.QtWidgets import QTreeWidget, QTreeWidgetItem
from qtpy.QtWidgets import QHBoxLayout, QTreeWidget, QTreeWidgetItem, QWidget
from bec_widgets.utils.bec_connector import BECConnector
from bec_widgets.widgets.bec_status_box.status_item import StatusItem
@ -43,8 +43,8 @@ class BECServiceStatusMixin(QObject):
services_update = Signal(dict, dict)
def __init__(self, client: BECClient):
super().__init__()
def __init__(self, parent, client: BECClient):
super().__init__(parent)
self.client = client
self._service_update_timer = QTimer()
self._service_update_timer.timeout.connect(self._get_service_status)
@ -57,7 +57,7 @@ class BECServiceStatusMixin(QObject):
self.services_update.emit(self.client._services_info, self.client._services_metric)
class BECStatusBox(BECConnector, QTreeWidget):
class BECStatusBox(BECConnector, QWidget):
"""An autonomous widget to display the status of BEC services.
Args:
@ -73,9 +73,6 @@ class BECStatusBox(BECConnector, QTreeWidget):
service_update = Signal(BECServiceInfoContainer)
bec_core_state = Signal(str)
_initialized = False
_bec_status_box = None
def __init__(
self,
parent=None,
@ -84,34 +81,23 @@ class BECStatusBox(BECConnector, QTreeWidget):
bec_service_status_mixin: BECServiceStatusMixin = None,
gui_id: str = None,
):
if self._initialized == True:
return
super().__init__(client=client, gui_id=gui_id)
QTreeWidget.__init__(self, parent=parent)
QWidget.__init__(self, parent=parent)
self.tree = QTreeWidget(self)
self.layout = QHBoxLayout(self)
self.box_name = box_name
self.status_container = defaultdict(lambda: {"info": None, "item": None, "widget": None})
self._initialized = False
if not bec_service_status_mixin:
bec_service_status_mixin = BECServiceStatusMixin(client=self.client)
bec_service_status_mixin = BECServiceStatusMixin(self, client=self.client)
self.bec_service_status = bec_service_status_mixin
if not self._initialized:
self.init_ui()
self.bec_service_status.services_update.connect(self.update_service_status)
self.bec_core_state.connect(self.update_top_item_status)
self.itemDoubleClicked.connect(self.on_tree_item_double_clicked)
def __new__(cls, *args, forced: bool = False, **kwargs):
if forced:
cls._initialized = False
cls._bec_status_box = super(BECStatusBox, cls).__new__(cls)
return cls._bec_status_box
if cls._bec_status_box is not None and cls._initialized is True:
return cls._bec_status_box
cls._bec_status_box = super(BECStatusBox, cls).__new__(cls)
return cls._bec_status_box
self.init_ui()
self.bec_service_status.services_update.connect(self.update_service_status)
self.bec_core_state.connect(self.update_top_item_status)
self.tree.itemDoubleClicked.connect(self.on_tree_item_double_clicked)
self.layout.addWidget(self.tree)
def init_ui(self) -> None:
"""Init the UI for the BECStatusBox widget, should only take place once."""
@ -121,15 +107,16 @@ class BECStatusBox(BECConnector, QTreeWidget):
tree_item.setExpanded(True)
tree_item.setDisabled(True)
self.status_container[self.box_name].update({"item": tree_item, "widget": top_label})
self.addTopLevelItem(tree_item)
self.setItemWidget(tree_item, 0, top_label)
self.tree.addTopLevelItem(tree_item)
self.tree.setItemWidget(tree_item, 0, top_label)
self.service_update.connect(top_label.update_config)
self._initialized = True
def init_ui_tree_widget(self) -> None:
"""Initialise the tree widget for the status box."""
self.setHeaderHidden(True)
self.setStyleSheet(
self.tree.setHeaderHidden(True)
# TODO probably here is a problem still with setting the stylesheet
self.tree.setStyleSheet(
"QTreeWidget::item:!selected "
"{ "
"border: 1px solid gainsboro; "
@ -191,7 +178,10 @@ class BECStatusBox(BECConnector, QTreeWidget):
container.metrics = metrics
return
service_info_item = BECServiceInfoContainer(
service_name=service_name, status=status.name, info=info, metrics=metrics
service_name=service_name,
status=status.name if isinstance(status, BECStatus) else status,
info=info,
metrics=metrics,
)
self.status_container[service_name].update({"info": service_info_item})
@ -213,6 +203,9 @@ class BECStatusBox(BECConnector, QTreeWidget):
metric_msg = services_metric.get(service_name, None)
metrics = metric_msg.metrics if metric_msg else None
if service_name in self.status_container:
if not msg:
self.add_tree_item(service_name, "NOTCONNECTED", {}, metrics)
continue
self._update_status_container(service_name, msg.status, msg.info, metrics)
self.service_update.emit(self.status_container[service_name]["info"])
continue
@ -236,6 +229,9 @@ class BECStatusBox(BECConnector, QTreeWidget):
metrics = metric_msg.metrics if metric_msg else None
msg = services_info.pop(service_name, None)
if service_name not in self.status_container:
if not msg:
self.add_tree_item(service_name, "NOTCONNECTED", {}, metrics)
continue
self.add_tree_item(service_name, msg.status, msg.info, metrics)
continue
if not msg:
@ -248,8 +244,6 @@ class BECStatusBox(BECConnector, QTreeWidget):
self.service_update.emit(self.status_container[service_name]["info"])
# self.add_tree_item(service_name, msg.status, msg.info, metrics)
self.bec_core_state.emit(core_state.name if core_state else "NOTCONNECTED")
return services_info
@ -278,10 +272,10 @@ class BECStatusBox(BECConnector, QTreeWidget):
metrics (dict): The metrics of the service.
"""
item_widget = self._create_status_widget(service_name, status, info, metrics)
item = QTreeWidgetItem() # setDisabled=True
item = QTreeWidgetItem()
self.service_update.connect(item_widget.update_config)
self.status_container[self.box_name]["item"].addChild(item)
self.setItemWidget(item, 0, item_widget)
self.tree.setItemWidget(item, 0, item_widget)
self.status_container[service_name].update({"item": item, "widget": item_widget})
@Slot(QTreeWidgetItem, int)
@ -297,13 +291,13 @@ class BECStatusBox(BECConnector, QTreeWidget):
objects["widget"].show_popup()
def closeEvent(self, event):
"""Upon closing the widget, clean up the BECStatusBox and the QTreeWidget.
"""Upon closing the widget, clean up the BECStatusBox and the QWidget.
Args:
event: The close event.
"""
super().cleanup()
return QTreeWidget.closeEvent(self, event)
super().closeEvent(event)
def main():

View File

@ -48,7 +48,7 @@ class BECStatusBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
return "BECStatusBox"
def toolTip(self):
return "Widget to display the BECStatus from all active services."
return "An autonomous widget to display the status of BEC services."
def whatsThis(self):
return self.toolTip()

View File

@ -23,11 +23,11 @@ def status_box(qtbot, mocked_client, service_status_fixture):
def test_update_top_item(status_box):
assert status_box.children()[0].children()[0].config.status == "IDLE"
assert status_box.tree.children()[0].children()[0].config.status == "IDLE"
name = status_box.box_name
status_box.update_top_item_status(status="RUNNING")
assert status_box.status_container[name]["info"].status == "RUNNING"
assert status_box.children()[0].children()[0].config.status == "RUNNING"
assert status_box.tree.children()[0].children()[0].config.status == "RUNNING"
def test_create_status_widget(status_box):
@ -62,9 +62,9 @@ def test_add_tree_item(status_box):
status = BECStatus.IDLE
info = {"test": "test"}
metrics = {"metric": "test_metric"}
assert len(status_box.children()[0].children()) == 1
assert len(status_box.tree.children()[0].children()) == 1
status_box.add_tree_item(name, status, info, metrics)
assert len(status_box.children()[0].children()) == 2
assert len(status_box.tree.children()[0].children()) == 2
assert name in status_box.status_container
@ -98,14 +98,14 @@ def test_update_core_services(status_box):
services_metrics = {name: ServiceMetricMessage(name=name, metrics=metrics)}
status_box.update_core_services(services_status, services_metrics)
assert status_box.children()[0].children()[0].config.status == "RUNNING"
assert status_box.tree.children()[0].children()[0].config.status == "RUNNING"
assert status_box.status_container[name]["widget"].config.metrics == metrics
status = BECStatus.IDLE
services_status = {name: StatusMessage(name=name, status=status, info=info)}
services_metrics = {name: ServiceMetricMessage(name=name, metrics=metrics)}
status_box.update_core_services(services_status, services_metrics)
assert status_box.children()[0].children()[0].config.status == status.name
assert status_box.tree.children()[0].children()[0].config.status == status.name
assert status_box.status_container[name]["widget"].config.metrics == metrics
@ -119,5 +119,5 @@ def test_double_click_item(status_box):
item = container["item"]
status_item = container["widget"]
with mock.patch.object(status_item, "show_popup") as mock_show_popup:
status_box.itemDoubleClicked.emit(item, 0)
status_box.tree.itemDoubleClicked.emit(item, 0)
assert mock_show_popup.call_count == 1