From 286e62df92927d2efe0b4ab07995f7b5e36a0435 Mon Sep 17 00:00:00 2001 From: wyzula-jan <133381102+wyzula-jan@users.noreply.github.com> Date: Sat, 18 Nov 2023 15:53:24 +0100 Subject: [PATCH] feat: toolbar.py proof-of-concept --- bec_widgets/widgets/__init__.py | 2 + bec_widgets/widgets/editor/__init__.py | 1 + bec_widgets/widgets/editor/editor.py | 34 ++++++- bec_widgets/widgets/toolbar/__init__.py | 1 + bec_widgets/widgets/toolbar/toolbar.py | 127 ++++++++++++++++++++++++ 5 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 bec_widgets/widgets/editor/__init__.py create mode 100644 bec_widgets/widgets/toolbar/__init__.py create mode 100644 bec_widgets/widgets/toolbar/toolbar.py diff --git a/bec_widgets/widgets/__init__.py b/bec_widgets/widgets/__init__.py index ea74ba33..ecbd45b7 100644 --- a/bec_widgets/widgets/__init__.py +++ b/bec_widgets/widgets/__init__.py @@ -1,2 +1,4 @@ from .monitor import BECMonitor, ConfigDialog from .scan_control import ScanControl +from .toolbar import ModularToolbar +from .editor import BECEditor diff --git a/bec_widgets/widgets/editor/__init__.py b/bec_widgets/widgets/editor/__init__.py new file mode 100644 index 00000000..e3b91ff2 --- /dev/null +++ b/bec_widgets/widgets/editor/__init__.py @@ -0,0 +1 @@ +from .editor import BECEditor diff --git a/bec_widgets/widgets/editor/editor.py b/bec_widgets/widgets/editor/editor.py index 0f72a415..b6b6da9e 100644 --- a/bec_widgets/widgets/editor/editor.py +++ b/bec_widgets/widgets/editor/editor.py @@ -16,6 +16,10 @@ from qtpy.QtWidgets import ( # from PyQt6.Qsci import QsciScintilla, QsciLexerPython from qtpy.Qsci import QsciScintilla, QsciLexerPython +# from bec_widgets.widgets.toolbar.toolbar import ModularToolbar + +# from bec_widgets.widgets import ModularToolbar + class ScriptRunnerThread(QThread): outputSignal = Signal(str) @@ -53,19 +57,19 @@ class BECEditor(QWidget): self.editor = QsciScintilla() self.terminal = QTextEdit() self.terminal.setReadOnly(True) - self.runButton = QPushButton("Run Script") + # self.runButton = QPushButton("Run Script") # Layout layout = QVBoxLayout() layout.addWidget(self.editor) - layout.addWidget(self.runButton) + # layout.addWidget(self.runButton) layout.addWidget(self.terminal) self.setLayout(layout) self.setupEditor() # Connect the run button - self.runButton.clicked.connect(self.runScript) + # self.runButton.clicked.connect(self.runScript) def setupEditor(self): # Set the lexer for Python @@ -170,8 +174,28 @@ class BECEditor(QWidget): if __name__ == "__main__": + from bec_widgets.widgets.toolbar.toolbar import ModularToolbar + + # app = QApplication([]) + # qdarktheme.setup_theme("auto") + # mainWin = BECEditor() + # mainWin.show() + # app.exec() app = QApplication([]) qdarktheme.setup_theme("auto") - mainWin = BECEditor() - mainWin.show() + window = QWidget() + layout = QVBoxLayout(window) + + editor = BECEditor() + # toolbar_auto = ModularToolbar() + + # Manual initialization + toolbar_manual = ModularToolbar(auto_init=False) + toolbar_manual.set_target_widget(editor) + + layout.addWidget(toolbar_manual) + layout.addWidget(editor) + + window.setLayout(layout) + window.show() app.exec() diff --git a/bec_widgets/widgets/toolbar/__init__.py b/bec_widgets/widgets/toolbar/__init__.py new file mode 100644 index 00000000..de994213 --- /dev/null +++ b/bec_widgets/widgets/toolbar/__init__.py @@ -0,0 +1 @@ +from .toolbar import ModularToolbar diff --git a/bec_widgets/widgets/toolbar/toolbar.py b/bec_widgets/widgets/toolbar/toolbar.py new file mode 100644 index 00000000..0bdf194f --- /dev/null +++ b/bec_widgets/widgets/toolbar/toolbar.py @@ -0,0 +1,127 @@ +from PyQt6.QtCore import QTimer +from PyQt6.QtWidgets import QPushButton +from abc import ABC, abstractmethod + +from PyQt6.QtWidgets import QHBoxLayout, QWidget + +from bec_widgets.widgets.editor.editor import BECEditor + + +class AbstractToolbarButton(QPushButton): # , ABC): #TODO decide if ABC useful for this case.. + def __init__(self, text, slot_name, parent=None): + super().__init__(text, parent) + self.slot_name = slot_name + + # @abstractmethod + def setup_button(self): + """ + Setup specific properties for the button. + """ + pass + + def connect_to_widget(self, widget): + slot_function = getattr(widget, self.slot_name, None) + if slot_function and callable(slot_function): + self.clicked.connect(slot_function) + + +class OpenFileButton(AbstractToolbarButton): + def __init__(self, parent=None): + super().__init__("Open File", "openFile", parent) + self.setup_button() + + def setup_button(self): + self.setText("Open File") + # Add specific setup for Open File Button + # pass + + +class SaveFileButton(AbstractToolbarButton): + def __init__(self, parent=None): + super().__init__("Save File", "saveFile", parent) + self.setup_button() + + def setup_button(self): + self.setText("Save File") + # Add specific setup for Save File Button + # pass + + +class RunScriptButton(AbstractToolbarButton): + def __init__(self, parent=None): + super().__init__("Run Script", "runScript", parent) + self.setup_button() + + def setup_button(self): + # Add specific setup for Run Script Button + self.setText("Run Script") + # pass + + +class ModularToolbar(QWidget): + def __init__(self, parent=None, auto_init=False): + super().__init__(parent) + # self.layout = QHBoxLayout() + # self.setLayout(self.layout) + # self.initialized = False + self.layout = QHBoxLayout() + self.setLayout(self.layout) + self.current_widget = None + self.auto_init = auto_init + self.initialized = False + if self.auto_init: + QTimer.singleShot(0, self.detect_context_and_update_buttons) + + def set_target_widget(self, widget): + self.current_widget = widget + self.update_buttons() + + def showEvent(self, event): + super().showEvent(event) + if not self.initialized: + self.detect_context_and_update_buttons() + self.initialized = True + + def detect_context_and_update_buttons(self): + if not self.auto_init or self.initialized: + return + + parent_widget = self.parent() + if parent_widget is None: + return + + for child in parent_widget.children(): + if isinstance(child, BECEditor): + self.set_widget(child) + print("BECEditor init success!") + break + else: + print("no supported widget detected") + + def set_widget(self, widget): + self.clear_buttons() + self.add_buttons([OpenFileButton(), SaveFileButton(), RunScriptButton()]) + self.connectToWidget(widget) + + def update_buttons(self): + if self.current_widget is None: + return + + self.clear_buttons() + # if isinstance(self.current_widget, BECEditor): + self.add_buttons([OpenFileButton(), SaveFileButton(), RunScriptButton()]) + # Additional conditions for other widget types can be added here + + def clear_buttons(self): + for button in self.findChildren(AbstractToolbarButton): + self.layout.removeWidget(button) + button.deleteLater() + + def add_buttons(self, buttons): + for button in buttons: + self.layout.addWidget(button) + button.connect_to_widget(self.current_widget) + + def connectToWidget(self, target_widget): + for button in self.findChildren(AbstractToolbarButton): + button.connect_to_widget(target_widget)