mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 03:31:50 +02:00
WIP hierarchy on app level
This commit is contained in:
@ -1,5 +1,8 @@
|
||||
# pylint: disable=no-name-in-module
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
import pyqtgraph as pg
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
@ -331,17 +334,77 @@ class WidgetHierarchy:
|
||||
if only_bec_widgets and not isinstance(child, BECConnector):
|
||||
continue
|
||||
|
||||
if WidgetHierarchy._get_becwidget_ancestor(child) == widget:
|
||||
child_prefix = prefix + " └─ "
|
||||
WidgetHierarchy.print_widget_hierarchy(
|
||||
child,
|
||||
indent=indent + 1,
|
||||
grab_values=grab_values,
|
||||
prefix=child_prefix,
|
||||
exclude_internal_widgets=exclude_internal_widgets,
|
||||
only_bec_widgets=only_bec_widgets,
|
||||
show_parent=show_parent,
|
||||
)
|
||||
# if WidgetHierarchy._get_becwidget_ancestor(child) == widget:
|
||||
child_prefix = prefix + " └─ "
|
||||
WidgetHierarchy.print_widget_hierarchy(
|
||||
child,
|
||||
indent=indent + 1,
|
||||
grab_values=grab_values,
|
||||
prefix=child_prefix,
|
||||
exclude_internal_widgets=exclude_internal_widgets,
|
||||
only_bec_widgets=only_bec_widgets,
|
||||
show_parent=show_parent,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def print_becconnector_hierarchy_from_app():
|
||||
"""
|
||||
Enumerate ALL widgets in the QApplication, pick only BECConnector objects,
|
||||
then build a parent->child graph where each child's 'parent' is the closest
|
||||
BECConnector ancestor. Finally, print the entire hierarchy from the root(s).
|
||||
|
||||
The result is a single, consolidated hierarchy for your entire running GUI.
|
||||
"""
|
||||
# 1. Gather ALL widgets from the running QApplication
|
||||
all_widgets = QApplication.allWidgets()
|
||||
|
||||
# 2. Filter out those which are BECConnector
|
||||
bec_widgets = [w for w in all_widgets if isinstance(w, BECConnector)]
|
||||
|
||||
# 3. Build a mapping parent -> list of children,
|
||||
# where 'parent' is the nearest BECConnector ancestor
|
||||
parent_map = defaultdict(list)
|
||||
|
||||
for w in bec_widgets:
|
||||
parent_bec = WidgetHierarchy._get_becwidget_ancestor(w)
|
||||
parent_map[parent_bec].append(w)
|
||||
|
||||
# 4. Recursively print the hierarchy (DFS or BFS).
|
||||
# Start from items whose nearest BECConnector parent is None.
|
||||
def print_tree(parent, prefix=""):
|
||||
children = parent_map[parent]
|
||||
for i, child in enumerate(children):
|
||||
# Figure out indentation/prefix
|
||||
# We'll do a "└─" for the last child at that level, "├─" otherwise
|
||||
connector_class = child.__class__.__name__
|
||||
connector_name = child.objectName() or connector_class
|
||||
# The parent label
|
||||
if parent is None:
|
||||
parent_label = "None"
|
||||
else:
|
||||
parent_label = parent.objectName() or parent.__class__.__name__
|
||||
|
||||
# Print the line for this child
|
||||
line = f"{connector_class} ({connector_name}) parent={parent_label}"
|
||||
if i == len(children) - 1:
|
||||
print(prefix + "└─ " + line)
|
||||
next_prefix = prefix + " "
|
||||
else:
|
||||
print(prefix + "├─ " + line)
|
||||
next_prefix = prefix + "│ "
|
||||
|
||||
# Recurse
|
||||
print_tree(child, prefix=next_prefix)
|
||||
|
||||
# 5. Print top-level roots (those whose parent is None)
|
||||
# Each top-level root is printed without indentation/prefix.
|
||||
for root in parent_map[None]:
|
||||
root_class = root.__class__.__name__
|
||||
root_name = root.objectName() or root_class
|
||||
print(f"{root_class} ({root_name}) parent=None")
|
||||
|
||||
# Recurse into its children
|
||||
print_tree(root, prefix=" ")
|
||||
|
||||
@staticmethod
|
||||
def _get_becwidget_ancestor(widget):
|
||||
@ -356,6 +419,19 @@ class WidgetHierarchy:
|
||||
parent = parent.parent()
|
||||
return None
|
||||
|
||||
# @staticmethod
|
||||
# def _get_becwidget_ancestor(widget):
|
||||
# """
|
||||
# Traverse up the parent chain to find the nearest BECConnector.
|
||||
# Returns None if none is found.
|
||||
# """
|
||||
# parent = widget.parent()
|
||||
# while parent is not None:
|
||||
# if isinstance(parent, BECConnector):
|
||||
# return parent
|
||||
# parent = parent.parent()
|
||||
# return None
|
||||
|
||||
@staticmethod
|
||||
def export_config_to_dict(
|
||||
widget: QWidget,
|
||||
|
@ -6,6 +6,8 @@ from typing import Literal
|
||||
import lmfit
|
||||
import numpy as np
|
||||
import pyqtgraph as pg
|
||||
from PySide6.QtWidgets import QApplication, QPushButton
|
||||
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from pydantic import Field, ValidationError, field_validator
|
||||
@ -18,6 +20,7 @@ from bec_widgets.utils.colors import Colors, set_theme
|
||||
from bec_widgets.utils.error_popups import SafeProperty, SafeSlot
|
||||
from bec_widgets.utils.settings_dialog import SettingsDialog
|
||||
from bec_widgets.utils.toolbar import MaterialIconAction
|
||||
from bec_widgets.utils.widget_io import WidgetHierarchy
|
||||
from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow
|
||||
from bec_widgets.widgets.dap.lmfit_dialog.lmfit_dialog import LMFitDialog
|
||||
from bec_widgets.widgets.plots.plot_base import PlotBase
|
||||
@ -1592,32 +1595,45 @@ class Waveform(PlotBase):
|
||||
super().cleanup()
|
||||
|
||||
|
||||
class DemoApp(BECMainWindow): # pragma: no cover
|
||||
class DemoApp(QMainWindow): # pragma: no cover
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Waveform Demo")
|
||||
self.resize(800, 600)
|
||||
self.main_widget = QWidget()
|
||||
self.main_widget = QWidget(self)
|
||||
self.layout = QHBoxLayout(self.main_widget)
|
||||
self.setCentralWidget(self.main_widget)
|
||||
|
||||
self.waveform_popup = Waveform(popups=True)
|
||||
self.waveform_popup.plot(y_name="monitor_async")
|
||||
|
||||
self.waveform_side = Waveform(popups=False)
|
||||
self.waveform_side = Waveform(popups=False, parent=self.main_widget)
|
||||
self.waveform_side.plot(y_name="bpm4i", y_entry="bpm4i", dap="GaussianModel")
|
||||
self.waveform_side.plot(y_name="bpm3a", y_entry="bpm3a")
|
||||
|
||||
self.hierarchy_button = QPushButton()
|
||||
self.hierarchy_button.setText("Hierarchy")
|
||||
self.hierarchy_button.clicked.connect(self.hierarchy)
|
||||
|
||||
self.layout.addWidget(self.waveform_side)
|
||||
self.layout.addWidget(self.waveform_popup)
|
||||
self.layout.addWidget(self.hierarchy_button)
|
||||
|
||||
def hierarchy(self):
|
||||
print("getting app")
|
||||
WidgetHierarchy.print_becconnector_hierarchy_from_app() # , only_bec_widgets=True)
|
||||
|
||||
print("getting of side waveform")
|
||||
WidgetHierarchy.print_widget_hierarchy(self.waveform_side, only_bec_widgets=True)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
import sys
|
||||
|
||||
from bec_widgets.utils.bec_qapp import BECApplication
|
||||
|
||||
app = BECApplication(sys.argv)
|
||||
# from bec_widgets.utils.bec_qapp import BECApplication
|
||||
#
|
||||
# app = BECApplication(sys.argv)
|
||||
app = QApplication(sys.argv)
|
||||
set_theme("dark")
|
||||
widget = DemoApp()
|
||||
widget.show()
|
||||
|
Reference in New Issue
Block a user