mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-12-31 19:11:18 +01:00
f - wip
This commit is contained in:
@@ -3,9 +3,14 @@ from typing import List
|
||||
import PySide6QtAds as QtAds
|
||||
from PySide6QtAds import CDockManager, CDockWidget
|
||||
from qtpy.QtCore import Qt, QTimer
|
||||
from qtpy.QtWidgets import QSplitter, QTreeWidget, QVBoxLayout, QWidget
|
||||
from qtpy.QtGui import QKeySequence, QShortcut
|
||||
from qtpy.QtWidgets import QSplitter, QTextEdit, QVBoxLayout, QWidget
|
||||
|
||||
from bec_widgets import BECWidget
|
||||
from bec_widgets.utils.error_popups import SafeSlot
|
||||
from bec_widgets.utils.toolbars.actions import MaterialIconAction
|
||||
from bec_widgets.utils.toolbars.bundles import ToolbarBundle
|
||||
from bec_widgets.utils.toolbars.toolbar import ModularToolBar
|
||||
from bec_widgets.widgets.containers.advanced_dock_area.advanced_dock_area import AdvancedDockArea
|
||||
from bec_widgets.widgets.editors.monaco.monaco_tab import MonacoDock
|
||||
from bec_widgets.widgets.editors.web_console.web_console import WebConsole
|
||||
@@ -48,21 +53,36 @@ def set_splitter_weights(splitter: QSplitter, weights: List[float]) -> None:
|
||||
|
||||
class DeveloperView(BECWidget, QWidget):
|
||||
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
super().__init__(parent, *args, **kwargs)
|
||||
def __init__(self, parent=None, **kwargs):
|
||||
super().__init__(parent=parent, **kwargs)
|
||||
|
||||
# Top-level layout hosting a toolbar and the dock manager
|
||||
self._root_layout = QVBoxLayout(self)
|
||||
self._root_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self._root_layout.setSpacing(0)
|
||||
self.toolbar = ModularToolBar(self)
|
||||
self.init_developer_toolbar()
|
||||
self._root_layout.addWidget(self.toolbar)
|
||||
|
||||
self.dock_manager = CDockManager(self)
|
||||
self._root_layout.addWidget(self.dock_manager)
|
||||
|
||||
# Initialize the widgets
|
||||
self.explorer = IDEExplorer(self) # TODO will be replaced by explorer widget
|
||||
self.explorer = IDEExplorer(self)
|
||||
self.console = WebConsole(self)
|
||||
self.terminal = WebConsole(self, startup_cmd="")
|
||||
self.monaco = MonacoDock(self)
|
||||
self.monaco.save_enabled.connect(self._on_save_enabled_update)
|
||||
self.plotting_ads = AdvancedDockArea(self, mode="plot", default_add_direction="bottom")
|
||||
self.signature_help = QTextEdit(self)
|
||||
self.signature_help.setAcceptRichText(True)
|
||||
self.signature_help.setReadOnly(True)
|
||||
self.signature_help.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
|
||||
opt = self.signature_help.document().defaultTextOption()
|
||||
opt.setWrapMode(opt.WrapMode.WrapAnywhere) # wrap everything, including code
|
||||
self.signature_help.document().setDefaultTextOption(opt)
|
||||
|
||||
self.monaco.signature_help.connect(self.signature_help.setMarkdown)
|
||||
|
||||
# Create the dock widgets
|
||||
self.explorer_dock = QtAds.CDockWidget("Explorer", self)
|
||||
@@ -74,20 +94,22 @@ class DeveloperView(BECWidget, QWidget):
|
||||
self.monaco_dock = QtAds.CDockWidget("Monaco Editor", self)
|
||||
self.monaco_dock.setWidget(self.monaco)
|
||||
|
||||
self.plotting_ads_dock = QtAds.CDockWidget("Plotting Area", self)
|
||||
self.plotting_ads_dock.setWidget(self.plotting_ads)
|
||||
self.terminal_dock = QtAds.CDockWidget("Terminal", self)
|
||||
self.terminal_dock.setWidget(self.terminal)
|
||||
|
||||
# Monaco will be central widget
|
||||
self.dock_manager.setCentralWidget(self.monaco_dock)
|
||||
|
||||
# Add the dock widgets to the dock manager
|
||||
self.dock_manager.addDockWidget(
|
||||
area_bottom = self.dock_manager.addDockWidget(
|
||||
QtAds.DockWidgetArea.BottomDockWidgetArea, self.console_dock
|
||||
)
|
||||
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, self.explorer_dock)
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.DockWidgetArea.RightDockWidgetArea, self.plotting_ads_dock
|
||||
self.dock_manager.addDockWidgetTabToArea(self.terminal_dock, area_bottom)
|
||||
|
||||
area_left = self.dock_manager.addDockWidget(
|
||||
QtAds.DockWidgetArea.LeftDockWidgetArea, self.explorer_dock
|
||||
)
|
||||
area_left.titleBar().setVisible(False)
|
||||
|
||||
for dock in self.dock_manager.dockWidgets():
|
||||
# dock.setFeature(CDockWidget.DockWidgetDeleteOnClose, True)#TODO implement according to MonacoDock or AdvancedDockArea
|
||||
@@ -96,13 +118,71 @@ class DeveloperView(BECWidget, QWidget):
|
||||
dock.setFeature(CDockWidget.DockWidgetFloatable, False)
|
||||
dock.setFeature(CDockWidget.DockWidgetMovable, False)
|
||||
|
||||
# Fetch all dock areas of the dock widgets (on our case always one dock area)
|
||||
for dock in self.dock_manager.dockWidgets():
|
||||
area = dock.dockAreaWidget()
|
||||
area.titleBar().setVisible(False)
|
||||
self.plotting_ads_dock = QtAds.CDockWidget("Plotting Area", self)
|
||||
self.plotting_ads_dock.setWidget(self.plotting_ads)
|
||||
|
||||
self.signature_dock = QtAds.CDockWidget("Signature Help", self)
|
||||
self.signature_dock.setWidget(self.signature_help)
|
||||
|
||||
area_right = self.dock_manager.addDockWidget(
|
||||
QtAds.DockWidgetArea.RightDockWidgetArea, self.plotting_ads_dock
|
||||
)
|
||||
self.dock_manager.addDockWidgetTabToArea(self.signature_dock, area_right)
|
||||
|
||||
# Apply stretch after the layout is done
|
||||
self.set_default_view([2, 5, 3], [5, 5])
|
||||
self.set_default_view([2, 5, 3], [7, 3])
|
||||
|
||||
# Connect editor signals
|
||||
self.explorer.file_open_requested.connect(self._open_new_file)
|
||||
|
||||
self.toolbar.show_bundles(["save", "execution", "settings"])
|
||||
|
||||
def init_developer_toolbar(self):
|
||||
"""Initialize the developer toolbar with necessary actions and widgets."""
|
||||
save_button = MaterialIconAction(icon_name="save", tooltip="Save", parent=self)
|
||||
save_button.action.triggered.connect(self.on_save)
|
||||
self.toolbar.components.add_safe("save", save_button)
|
||||
|
||||
save_as_button = MaterialIconAction(icon_name="save_as", tooltip="Save As", parent=self)
|
||||
self.toolbar.components.add_safe("save_as", save_as_button)
|
||||
|
||||
save_bundle = ToolbarBundle("save", self.toolbar.components)
|
||||
save_bundle.add_action("save")
|
||||
save_bundle.add_action("save_as")
|
||||
self.toolbar.add_bundle(save_bundle)
|
||||
|
||||
self.toolbar.components.add_safe(
|
||||
"run",
|
||||
MaterialIconAction(
|
||||
icon_name="play_arrow", tooltip="Run current file", filled=True, parent=self
|
||||
),
|
||||
)
|
||||
self.toolbar.components.add_safe(
|
||||
"stop",
|
||||
MaterialIconAction(
|
||||
icon_name="stop", tooltip="Stop current execution", filled=True, parent=self
|
||||
),
|
||||
)
|
||||
|
||||
execution_bundle = ToolbarBundle("execution", self.toolbar.components)
|
||||
execution_bundle.add_action("run")
|
||||
execution_bundle.add_action("stop")
|
||||
self.toolbar.add_bundle(execution_bundle)
|
||||
|
||||
vim_action = MaterialIconAction(
|
||||
icon_name="text_ad", tooltip="Vim", filled=True, parent=self, checkable=True
|
||||
)
|
||||
self.toolbar.components.add_safe("vim", vim_action)
|
||||
vim_action.action.triggered.connect(self.on_vim_triggered)
|
||||
|
||||
settings_bundle = ToolbarBundle("settings", self.toolbar.components)
|
||||
settings_bundle.add_action("vim")
|
||||
self.toolbar.add_bundle(settings_bundle)
|
||||
|
||||
save_shortcut = QShortcut(QKeySequence("Ctrl+S"), self)
|
||||
save_shortcut.activated.connect(self.on_save)
|
||||
save_as_shortcut = QShortcut(QKeySequence("Ctrl+Shift+S"), self)
|
||||
save_as_shortcut.activated.connect(self.on_save_as)
|
||||
|
||||
####### Default view has to be done with setting up splitters ########
|
||||
def set_default_view(self, horizontal_weights: list, vertical_weights: list):
|
||||
@@ -166,6 +246,26 @@ class DeveloperView(BECWidget, QWidget):
|
||||
v = [1, 1]
|
||||
self.set_default_view(h, v)
|
||||
|
||||
def _open_new_file(self, file_name: str, scope: str):
|
||||
self.monaco.open_file(file_name)
|
||||
|
||||
@SafeSlot()
|
||||
def on_save(self):
|
||||
self.monaco.save_file()
|
||||
|
||||
@SafeSlot()
|
||||
def on_save_as(self):
|
||||
self.monaco.save_file(force_save_as=True)
|
||||
|
||||
@SafeSlot()
|
||||
def on_vim_triggered(self):
|
||||
self.monaco.set_vim_mode(self.toolbar.components.get_action("vim").action.isChecked())
|
||||
|
||||
@SafeSlot(bool)
|
||||
def _on_save_enabled_update(self, enabled: bool):
|
||||
self.toolbar.components.get_action("save").action.setEnabled(enabled)
|
||||
self.toolbar.components.get_action("save_as").action.setEnabled(enabled)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
@@ -176,6 +276,6 @@ if __name__ == "__main__":
|
||||
developer_view = DeveloperView()
|
||||
developer_view.show()
|
||||
developer_view.setWindowTitle("Developer View")
|
||||
developer_view.resize(1200, 800)
|
||||
developer_view.resize(1920, 1080)
|
||||
# developer_view.set_stretch(horizontal=[1, 3, 2], vertical=[5, 5]) #can be set during runtime
|
||||
sys.exit(app.exec_())
|
||||
|
||||
@@ -4,6 +4,7 @@ import os
|
||||
from typing import Any, cast
|
||||
|
||||
import PySide6QtAds as QtAds
|
||||
from bec_lib.logger import bec_logger
|
||||
from PySide6QtAds import CDockWidget
|
||||
from qtpy.QtCore import QEvent, QTimer, Signal
|
||||
from qtpy.QtWidgets import QFileDialog, QMessageBox, QToolButton, QVBoxLayout, QWidget
|
||||
@@ -11,6 +12,8 @@ from qtpy.QtWidgets import QFileDialog, QMessageBox, QToolButton, QVBoxLayout, Q
|
||||
from bec_widgets import BECWidget
|
||||
from bec_widgets.widgets.editors.monaco.monaco_widget import MonacoWidget
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class MonacoDock(BECWidget, QWidget):
|
||||
"""
|
||||
@@ -74,6 +77,8 @@ class MonacoDock(BECWidget, QWidget):
|
||||
return
|
||||
|
||||
widget = cast(MonacoWidget, editor.widget())
|
||||
if widget.modified:
|
||||
logger.info(f"Editor '{widget.current_file}' has unsaved changes: {widget.get_text()}")
|
||||
self.save_enabled.emit(widget.modified)
|
||||
|
||||
def _on_signature_change(self, signature: dict):
|
||||
@@ -157,6 +162,7 @@ class MonacoDock(BECWidget, QWidget):
|
||||
idx = tb.indexOf(tb.tabBar())
|
||||
tb.insertWidget(idx + 1, plus_btn)
|
||||
plus_btn.clicked.connect(lambda: self.add_editor(area))
|
||||
# pylint: disable=protected-access
|
||||
area._monaco_plus_btn = plus_btn
|
||||
|
||||
def _scan_and_fix_areas(self):
|
||||
@@ -244,8 +250,9 @@ class MonacoDock(BECWidget, QWidget):
|
||||
if not widget:
|
||||
return
|
||||
if widget.current_file and not force_save_as:
|
||||
with open(widget.current_file, "w") as f:
|
||||
with open(widget.current_file, "w", encoding="utf-8") as f:
|
||||
f.write(widget.get_text())
|
||||
# pylint: disable=protected-access
|
||||
widget._original_content = widget.get_text()
|
||||
widget.save_enabled.emit(False)
|
||||
return
|
||||
@@ -268,7 +275,12 @@ class MonacoDock(BECWidget, QWidget):
|
||||
print(f"Save file called, last focused editor: {self.last_focused_editor}")
|
||||
|
||||
def set_vim_mode(self, enabled: bool):
|
||||
# Toggle Vim mode for all editor widgets
|
||||
"""
|
||||
Set Vim mode for all editor widgets.
|
||||
|
||||
Args:
|
||||
enabled (bool): Whether to enable or disable Vim mode.
|
||||
"""
|
||||
for widget in self.dock_manager.dockWidgets():
|
||||
editor_widget = cast(MonacoWidget, widget.widget())
|
||||
editor_widget.set_vim_mode_enabled(enabled)
|
||||
@@ -295,6 +307,6 @@ if __name__ == "__main__":
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
dock = MonacoDock()
|
||||
dock.show()
|
||||
_dock = MonacoDock()
|
||||
_dock.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
@@ -83,8 +83,9 @@ class MonacoWidget(BECWidget, QWidget):
|
||||
text (str): The text to set in the editor.
|
||||
file_name (str): Set the file name
|
||||
"""
|
||||
self.editor.set_text(text, uri=file_name)
|
||||
self._current_file = file_name
|
||||
self._original_content = text
|
||||
self.editor.set_text(text, uri=file_name)
|
||||
|
||||
def get_text(self) -> str:
|
||||
"""
|
||||
@@ -125,7 +126,6 @@ class MonacoWidget(BECWidget, QWidget):
|
||||
|
||||
with open(file_name, "r", encoding="utf-8") as file:
|
||||
content = file.read()
|
||||
self._original_content = content
|
||||
self.set_text(content, file_name=file_name)
|
||||
|
||||
@property
|
||||
@@ -277,7 +277,7 @@ if TYPE_CHECKING:
|
||||
scans: Scans
|
||||
|
||||
#######################################
|
||||
########## User Script #####################
|
||||
########## User Script ################
|
||||
#######################################
|
||||
|
||||
# This is a comment
|
||||
|
||||
Reference in New Issue
Block a user