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

refactor: toolbar.py migration to native qt QToolBar

This commit is contained in:
wyzula-jan
2023-11-19 15:17:23 +01:00
parent 286e62df92
commit ee3b616ec1
4 changed files with 67 additions and 165 deletions

View File

@ -1,4 +1,4 @@
from .monitor import BECMonitor, ConfigDialog from .monitor import BECMonitor, ConfigDialog
from .scan_control import ScanControl from .scan_control import ScanControl
from .toolbar import ModularToolbar from .toolbar import ModularToolBar
from .editor import BECEditor from .editor import BECEditor

View File

@ -1,25 +1,17 @@
import subprocess import subprocess
import qdarktheme import qdarktheme
from qtpy.Qsci import QsciScintilla, QsciLexerPython
from qtpy.QtCore import QFile, QTextStream, Signal, QThread from qtpy.QtCore import QFile, QTextStream, Signal, QThread
from qtpy.QtGui import QColor, QFont, QAction, QShortcut, QKeySequence from qtpy.QtGui import QColor, QFont
from qtpy.QtWidgets import ( from qtpy.QtWidgets import (
QApplication, QApplication,
QMainWindow,
QFileDialog, QFileDialog,
QPushButton,
QTextEdit, QTextEdit,
QVBoxLayout, QVBoxLayout,
QWidget, QWidget,
) )
# 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): class ScriptRunnerThread(QThread):
outputSignal = Signal(str) outputSignal = Signal(str)
@ -57,20 +49,15 @@ class BECEditor(QWidget):
self.editor = QsciScintilla() self.editor = QsciScintilla()
self.terminal = QTextEdit() self.terminal = QTextEdit()
self.terminal.setReadOnly(True) self.terminal.setReadOnly(True)
# self.runButton = QPushButton("Run Script")
# Layout # Layout
layout = QVBoxLayout() self.layout = QVBoxLayout()
layout.addWidget(self.editor) self.layout.addWidget(self.editor)
# layout.addWidget(self.runButton) self.layout.addWidget(self.terminal)
layout.addWidget(self.terminal) self.setLayout(self.layout)
self.setLayout(layout)
self.setupEditor() self.setupEditor()
# Connect the run button
# self.runButton.clicked.connect(self.runScript)
def setupEditor(self): def setupEditor(self):
# Set the lexer for Python # Set the lexer for Python
self.lexer = QsciLexerPython() self.lexer = QsciLexerPython()
@ -89,8 +76,6 @@ class BECEditor(QWidget):
# Additional UI elements like menu for load/save can be added here # Additional UI elements like menu for load/save can be added here
self.setEditorStyle() self.setEditorStyle()
self.createActions()
self.createMenus()
def setEditorStyle(self): def setEditorStyle(self):
# Dracula Theme Colors # Dracula Theme Colors
@ -137,23 +122,6 @@ class BECEditor(QWidget):
def updateTerminal(self, text): def updateTerminal(self, text):
self.terminal.append(text) self.terminal.append(text)
def createMenus(self):
...
# self.fileMenu = self.menuBar().addMenu("&File")
# self.fileMenu.addAction(self.openAct)
# self.fileMenu.addAction(self.saveAct)
def createActions(self):
self.openAct = QAction("&Open...", self, triggered=self.openFile)
self.saveAct = QAction("&Save", self, triggered=self.saveFile)
# Shortcuts
self.openShortcut = QShortcut(QKeySequence("Ctrl+O"), self)
self.openShortcut.activated.connect(self.openFile)
self.saveShortcut = QShortcut(QKeySequence("Ctrl+S"), self)
self.saveShortcut.activated.connect(self.saveFile)
def openFile(self): def openFile(self):
path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "Python files (*.py)") path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "Python files (*.py)")
if path: if path:
@ -174,28 +142,16 @@ class BECEditor(QWidget):
if __name__ == "__main__": if __name__ == "__main__":
from bec_widgets.widgets.toolbar.toolbar import ModularToolbar from bec_widgets.widgets.toolbar.toolbar import ModularToolBar
# app = QApplication([])
# qdarktheme.setup_theme("auto")
# mainWin = BECEditor()
# mainWin.show()
# app.exec()
app = QApplication([]) app = QApplication([])
qdarktheme.setup_theme("auto") qdarktheme.setup_theme("auto")
window = QWidget()
layout = QVBoxLayout(window)
editor = BECEditor() mainWin = BECEditor()
# toolbar_auto = ModularToolbar()
# Manual initialization toolbar_manual = ModularToolBar()
toolbar_manual = ModularToolbar(auto_init=False) toolbar_manual.set_target_widget(mainWin)
toolbar_manual.set_target_widget(editor)
layout.addWidget(toolbar_manual) mainWin.layout.insertWidget(0, toolbar_manual)
layout.addWidget(editor) mainWin.show()
window.setLayout(layout)
window.show()
app.exec() app.exec()

View File

@ -1 +1 @@
from .toolbar import ModularToolbar from .toolbar import ModularToolBar

View File

@ -1,127 +1,73 @@
from PyQt6.QtCore import QTimer from PyQt6.QtWidgets import QToolBar
from PyQt6.QtWidgets import QPushButton from qtpy.QtCore import QTimer
from qtpy.QtGui import QAction
from qtpy.QtWidgets import QPushButton
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from PyQt6.QtWidgets import QHBoxLayout, QWidget from qtpy.QtWidgets import QHBoxLayout, QWidget
from bec_widgets.widgets.editor.editor import BECEditor from bec_widgets.widgets.editor.editor import BECEditor
class AbstractToolbarButton(QPushButton): # , ABC): #TODO decide if ABC useful for this case.. class ToolBarAction(ABC):
def __init__(self, text, slot_name, parent=None): @abstractmethod
super().__init__(text, parent) def create(self, target: QWidget):
self.slot_name = slot_name
# @abstractmethod
def setup_button(self):
"""
Setup specific properties for the button.
"""
pass pass
def connect_to_widget(self, widget):
slot_function = getattr(widget, self.slot_name, None) class OpenFileAction: # (ToolBarAction):
if slot_function and callable(slot_function): def create(self, target: QWidget):
self.clicked.connect(slot_function) action = QAction("Open File", target)
action.triggered.connect(target.openFile)
return action
class OpenFileButton(AbstractToolbarButton): class SaveFileAction:
def create(self, target):
action = QAction("Save File", target)
action.triggered.connect(target.saveFile)
return action
class RunScriptAction:
def create(self, target):
action = QAction("Run Script", target)
action.triggered.connect(target.runScript)
return action
class ModularToolBar(QToolBar):
def __init__(self, parent=None): 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) super().__init__(parent)
# self.layout = QHBoxLayout() self.handler = {
# self.setLayout(self.layout) BECEditor: [OpenFileAction(), SaveFileAction(), RunScriptAction()],
# self.initialized = False # BECMonitor: [SomeOtherAction(), AnotherAction()], # Example for another widget
self.layout = QHBoxLayout() } # TODO also buggy fox later
self.setLayout(self.layout) QTimer.singleShot(0, self.detect_context_and_update_actions) # TODO buggy disabled for now
self.current_widget = None self.setStyleSheet("QToolBar { background: transparent; }")
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
def detect_context_and_update_actions(self): # TODO buggy disabled for now
parent_widget = self.parent() parent_widget = self.parent()
if parent_widget is None: if parent_widget is None:
return return
for child in parent_widget.children(): for child in parent_widget.children():
if isinstance(child, BECEditor): for widget_type, actions in self.handler.items():
self.set_widget(child) if isinstance(child, widget_type):
print("BECEditor init success!") self.populate_toolbar(child, actions)
break return
else:
print("no supported widget detected")
def set_widget(self, widget): def set_target_widget(self, widget):
self.clear_buttons() self.populate_toolbar(
self.add_buttons([OpenFileButton(), SaveFileButton(), RunScriptButton()]) widget, actions=[OpenFileAction(), SaveFileAction(), RunScriptAction()]
self.connectToWidget(widget) )
# for widget_type, actions in self.handler.items(): #TODO for automatic population
# if isinstance(widget, widget_type):
# self.populate_toolbar(widget, actions)
# break
def update_buttons(self): def populate_toolbar(self, target_widget, actions):
if self.current_widget is None: self.clear()
return for action_creator in actions:
action = action_creator.create(target_widget)
self.clear_buttons() self.addAction(action)
# 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)