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

WIP launch window change of inheritance

This commit is contained in:
2025-04-06 18:19:07 +02:00
parent 3fae913888
commit 86b7aec643
2 changed files with 23 additions and 166 deletions

View File

@ -1,133 +1,43 @@
import os import os
from bec_lib.logger import bec_logger from qtpy.QtWidgets import QSizePolicy
from qtpy.QtCore import QSize
from qtpy.QtGui import QAction, QActionGroup
from qtpy.QtWidgets import QApplication, QMainWindow, QSizePolicy, QStyle
import bec_widgets import bec_widgets
from bec_lib.logger import bec_logger
from bec_widgets.cli.rpc.rpc_register import RPCRegister from bec_widgets.cli.rpc.rpc_register import RPCRegister
from bec_widgets.utils import UILoader from bec_widgets.utils import UILoader
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import apply_theme
from bec_widgets.utils.container_utils import WidgetContainerUtils from bec_widgets.utils.container_utils import WidgetContainerUtils
from bec_widgets.widgets.containers.dock.dock_area import BECDockArea from bec_widgets.widgets.containers.dock.dock_area import BECDockArea
from bec_widgets.widgets.containers.main_window.addons.web_links import BECWebLinksMixin from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow
logger = bec_logger.logger logger = bec_logger.logger
MODULE_PATH = os.path.dirname(bec_widgets.__file__) MODULE_PATH = os.path.dirname(bec_widgets.__file__)
class LaunchWindow(BECWidget, QMainWindow): class LaunchWindow(BECMainWindow):
def __init__(self, gui_id: str = None, *args, **kwargs): def __init__(self, gui_id: str = None, *args, **kwargs):
QMainWindow.__init__(self, *args, **kwargs) BECMainWindow.__init__(self, gui_id=gui_id, window_title="BEC Launcher", *args, **kwargs)
BECWidget.__init__(self, gui_id=gui_id, **kwargs)
self.setObjectName("LaunchWindow") self.setObjectName("LaunchWindow")
self.app = QApplication.instance()
self.resize(500, 300) self.resize(500, 300)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.loader = UILoader(self)
self._init_ui() self._init_ui()
def _init_ui(self): def _init_ui(self):
# Set the window title super()._init_ui()
self.setWindowTitle("BEC Launcher")
# Load ui file # Load ui file
ui_file_path = os.path.join(MODULE_PATH, "applications/launch_dialog.ui") ui_file_path = os.path.join(MODULE_PATH, "applications/launch_dialog.ui")
self.load_ui(ui_file_path) self.load_ui(ui_file_path)
# Set Menu and Status bar
self._setup_menu_bar()
# BEC Specific UI
self._init_bec_specific_ui()
# TODO can be implemented for toolbar
def load_ui(self, ui_file): def load_ui(self, ui_file):
loader = UILoader(self) self.ui = self.loader.loader(ui_file)
self.ui = loader.loader(ui_file)
self.setCentralWidget(self.ui) self.setCentralWidget(self.ui)
self.ui.open_dock_area.setText("Open Dock Area") self.ui.open_dock_area.setText("Open Dock Area")
self.ui.open_dock_area.clicked.connect(lambda: self.launch("dock_area")) self.ui.open_dock_area.clicked.connect(lambda: self.launch("dock_area"))
def _init_bec_specific_ui(self):
if getattr(self.app, "gui_id", None):
self.statusBar().showMessage(f"App ID: {self.app.gui_id}")
else:
logger.warning(
"Application is not a BECApplication instance. Status bar will not show App ID. Please initialize the application with BECApplication."
)
# Set the window icon
# FIXME this do not work
def list_app_hierarchy(self):
"""
List the hierarchy of the application.
"""
self.app.list_hierarchy()
def _setup_menu_bar(self):
"""
Setup the menu bar for the main window.
"""
menu_bar = self.menuBar()
########################################
# Theme menu
theme_menu = menu_bar.addMenu("Theme")
theme_group = QActionGroup(self)
light_theme_action = QAction("Light Theme", self, checkable=True)
dark_theme_action = QAction("Dark Theme", self, checkable=True)
theme_group.addAction(light_theme_action)
theme_group.addAction(dark_theme_action)
theme_group.setExclusive(True)
theme_menu.addAction(light_theme_action)
theme_menu.addAction(dark_theme_action)
# Connect theme actions
light_theme_action.triggered.connect(lambda: self.change_theme("light"))
dark_theme_action.triggered.connect(lambda: self.change_theme("dark"))
# Set the default theme
# TODO can be fetched from app
dark_theme_action.setChecked(True)
########################################
# Help menu
help_menu = menu_bar.addMenu("Help")
help_icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxQuestion)
bug_icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxInformation)
bec_docs = QAction("BEC Docs", self)
bec_docs.setIcon(help_icon)
widgets_docs = QAction("BEC Widgets Docs", self)
widgets_docs.setIcon(help_icon)
bug_report = QAction("Bug Report", self)
bug_report.setIcon(bug_icon)
bec_docs.triggered.connect(BECWebLinksMixin.open_bec_docs)
widgets_docs.triggered.connect(BECWebLinksMixin.open_bec_widgets_docs)
bug_report.triggered.connect(BECWebLinksMixin.open_bec_bug_report)
help_menu.addAction(bec_docs)
help_menu.addAction(widgets_docs)
help_menu.addAction(bug_report)
debug_bar = menu_bar.addMenu(f"DEBUG {self.__class__.__name__}")
list_hierarchy = QAction("List App Hierarchy", self)
list_hierarchy.triggered.connect(self.list_app_hierarchy)
debug_bar.addAction(list_hierarchy)
def change_theme(self, theme):
apply_theme(theme)
def launch( def launch(
self, self,
launch_script: str, launch_script: str,
@ -163,9 +73,16 @@ class LaunchWindow(BECWidget, QMainWindow):
if geometry is not None: if geometry is not None:
dock_area.setGeometry(*geometry) dock_area.setGeometry(*geometry)
# TODO somehow we need to encapsulate this into BECMainWindow and keep dock area as top widget
# window = BECMainWindow()
# window.setCentralWidget(dock_area)
# window.show()
# dock_area.parent_id = None
dock_area.show() dock_area.show()
return dock_area return dock_area
def custom_ui_launcher(self): ...
def show_launcher(self): def show_launcher(self):
self.show() self.show()

View File

@ -1,13 +1,11 @@
import os import os
from typing import TYPE_CHECKING
from bec_lib.logger import bec_logger
from qtpy.QtCore import QSize from qtpy.QtCore import QSize
from qtpy.QtGui import QAction, QActionGroup, QIcon from qtpy.QtGui import QAction, QActionGroup, QIcon
from qtpy.QtWidgets import QApplication, QMainWindow, QStyle from qtpy.QtWidgets import QApplication, QMainWindow, QStyle
import bec_widgets import bec_widgets
from bec_widgets.cli.rpc.rpc_register import RPCRegister from bec_lib.logger import bec_logger
from bec_widgets.utils import UILoader from bec_widgets.utils import UILoader
from bec_widgets.utils.bec_widget import BECWidget from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import apply_theme from bec_widgets.utils.colors import apply_theme
@ -16,9 +14,6 @@ from bec_widgets.utils.error_popups import SafeSlot
from bec_widgets.utils.widget_io import WidgetHierarchy from bec_widgets.utils.widget_io import WidgetHierarchy
from bec_widgets.widgets.containers.main_window.addons.web_links import BECWebLinksMixin from bec_widgets.widgets.containers.main_window.addons.web_links import BECWebLinksMixin
if TYPE_CHECKING:
from bec_widgets.widgets.containers.dock.dock_area import BECDockArea
logger = bec_logger.logger logger = bec_logger.logger
MODULE_PATH = os.path.dirname(bec_widgets.__file__) MODULE_PATH = os.path.dirname(bec_widgets.__file__)
@ -35,21 +30,25 @@ class BECMainWindow(BECWidget, QMainWindow):
def _init_ui(self): def _init_ui(self):
# Set the icon
self._init_bec_icon()
# Set Menu and Status bar # Set Menu and Status bar
self._setup_menu_bar() self._setup_menu_bar()
# BEC Specific UI # BEC Specific UI
self.display_app_it() self.display_app_id()
def _init_bec_icon(self): def _init_bec_icon(self):
icon = self.app.windowIcon() icon = self.app.windowIcon()
if icon.isNull(): if icon.isNull():
print("No icon is set, setting default icon")
icon = QIcon() icon = QIcon()
icon.addFile( icon.addFile(
os.path.join(MODULE_PATH, "assets", "app_icons", "bec_widgets_icon.png"), os.path.join(MODULE_PATH, "assets", "app_icons", "bec_widgets_icon.png"),
size=QSize(48, 48), size=QSize(48, 48),
) )
self.setWindowIcon(icon) self.app.setWindowIcon(icon)
else: else:
print("An icon is set") print("An icon is set")
@ -58,7 +57,7 @@ class BECMainWindow(BECWidget, QMainWindow):
self.ui = loader.loader(ui_file) self.ui = loader.loader(ui_file)
self.setCentralWidget(self.ui) self.setCentralWidget(self.ui)
def display_app_it(self): def display_app_id(self):
server_id = self.bec_dispatcher.cli_server.gui_id server_id = self.bec_dispatcher.cli_server.gui_id
self.statusBar().showMessage(f"App ID: {server_id}") self.statusBar().showMessage(f"App ID: {server_id}")
@ -122,65 +121,6 @@ class BECMainWindow(BECWidget, QMainWindow):
def change_theme(self, theme: str): def change_theme(self, theme: str):
apply_theme(theme) apply_theme(theme)
# #FIXME I have zero idea what this is good for...
# def _dump(self):
# """Return a dictionary with informations about the application state, for use in tests"""
# # TODO: ModularToolBar and something else leak top-level widgets (3 or 4 QMenu + 2 QWidget);
# # so, a filtering based on title is applied here, but the solution is to not have those widgets
# # as top-level (so for now, a window with no title does not appear in _dump() result)
#
# # NOTE: the main window itself is excluded, since we want to dump dock areas
# info = {
# tlw.gui_id: {
# "title": tlw.windowTitle(),
# "visible": tlw.isVisible(),
# "class": str(type(tlw)),
# }
# for tlw in QApplication.instance().topLevelWidgets()
# if tlw is not self and tlw.windowTitle()
# }
# # Add the main window dock area
# info[self.centralWidget().gui_id] = {
# "title": self.windowTitle(),
# "visible": self.isVisible(),
# "class": str(type(self.centralWidget())),
# }
# return info
#
def new_dock_area(
self, name: str | None = None, geometry: tuple[int, int, int, int] | None = None
) -> "BECDockArea":
"""Create a new dock area.
Args:
name(str): The name of the dock area.
geometry(tuple): The geometry parameters to be passed to the dock area.
Returns:
BECDockArea: The newly created dock area.
"""
from bec_widgets.widgets.containers.dock.dock_area import BECDockArea
with RPCRegister.delayed_broadcast() as rpc_register:
existing_dock_areas = rpc_register.get_names_of_rpc_by_class_type(BECDockArea)
if name is not None:
if name in existing_dock_areas:
raise ValueError(
f"Name {name} must be unique for dock areas, but already exists: {existing_dock_areas}."
)
else:
name = "dock_area"
name = WidgetContainerUtils.generate_unique_name(name, existing_dock_areas)
dock_area = WindowWithUi() # BECDockArea(name=name)
dock_area.resize(dock_area.minimumSizeHint())
# TODO Should we simply use the specified name as title here?
dock_area.window().setWindowTitle(f"BEC - {name}")
logger.info(f"Created new dock area: {name}")
logger.info(f"Existing dock areas: {geometry}")
if geometry is not None:
dock_area.setGeometry(*geometry)
dock_area.show()
return dock_area
def cleanup(self): def cleanup(self):
super().close() super().close()