diff --git a/src/petab_gui/controllers/mother_controller.py b/src/petab_gui/controllers/mother_controller.py
index fc2ea85..a56efd1 100644
--- a/src/petab_gui/controllers/mother_controller.py
+++ b/src/petab_gui/controllers/mother_controller.py
@@ -444,6 +444,9 @@ def setup_actions(self):
actions["show_plot"] = QAction("Data Plot", self.view)
actions["show_plot"].setCheckable(True)
actions["show_plot"].setChecked(True)
+ actions["show_sbml_editor"] = QAction("SBML Editor", self.view)
+ actions["show_sbml_editor"].setCheckable(True)
+ actions["show_sbml_editor"].setChecked(True)
# What's This action
actions["whats_this"] = QAction(
@@ -536,6 +539,16 @@ def sync_visibility_with_actions(self):
action.toggled.connect(dock.setVisible)
dock.visibilityChanged.connect(action.setChecked)
+ # Connect SBML editor visibility toggle
+ sbml_action = self.actions["show_sbml_editor"]
+ sbml_widget = self.view.sbml_viewer.sbml_widget
+
+ # Store action reference in view for context menus
+ self.view.sbml_viewer.sbml_toggle_action = sbml_action
+
+ # Connect menu action to widget visibility
+ sbml_action.toggled.connect(sbml_widget.setVisible)
+
def save_model(self):
options = QFileDialog.Options()
file_name, filtering = QFileDialog.getSaveFileName(
diff --git a/src/petab_gui/models/tooltips.py b/src/petab_gui/models/tooltips.py
index 396b3ea..3cb2ff6 100644
--- a/src/petab_gui/models/tooltips.py
+++ b/src/petab_gui/models/tooltips.py
@@ -177,7 +177,8 @@ def cell_tip(table: str, column: str) -> str:
"SBML (XML) view
"
"• Edit or paste valid SBML.
"
"• Use Forward → Antimony to sync.
"
- "• Some constructs may not round-trip."
+ "• Some constructs may not round-trip.
"
+ "• Hide/show via View → SBML Editor menu."
)
ANTIMONY_VIEW_TOOLTIP = (
diff --git a/src/petab_gui/views/sbml_view.py b/src/petab_gui/views/sbml_view.py
index 4363f4f..1b1bc62 100644
--- a/src/petab_gui/views/sbml_view.py
+++ b/src/petab_gui/views/sbml_view.py
@@ -1,5 +1,6 @@
"""Widget for viewing the SBML model."""
+import qtawesome as qta
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QLabel,
@@ -20,6 +21,9 @@ class SbmlViewer(QWidget):
def __init__(self, parent=None, logger_view=None):
super().__init__(parent)
+ # Reference to menu action (set by controller)
+ self.sbml_toggle_action = None
+
# Main layout for the SBML tab
layout = QVBoxLayout(self)
vertical_splitter = QSplitter(Qt.Vertical)
@@ -36,6 +40,11 @@ def __init__(self, parent=None, logger_view=None):
self.sbml_text_edit.setWhatsThis(
WHATS_THIS["sbml_view"]["sbml_editor"]
)
+ # Enable custom context menu
+ self.sbml_text_edit.setContextMenuPolicy(Qt.CustomContextMenu)
+ self.sbml_text_edit.customContextMenuRequested.connect(
+ self._show_sbml_context_menu
+ )
sbml_layout.addWidget(self.sbml_text_edit)
# Add forward changes button for SBML
@@ -51,6 +60,11 @@ def __init__(self, parent=None, logger_view=None):
self.sbml_text_edit.setWhatsThis(
WHATS_THIS["sbml_view"]["antimony_editor"]
)
+ # Enable custom context menu
+ self.antimony_text_edit.setContextMenuPolicy(Qt.CustomContextMenu)
+ self.antimony_text_edit.customContextMenuRequested.connect(
+ self._show_antimony_context_menu
+ )
antimony_layout.addWidget(self.antimony_text_edit)
# Add forward changes button for Antimony
@@ -58,14 +72,14 @@ def __init__(self, parent=None, logger_view=None):
antimony_layout.addWidget(self.forward_antimony_button)
# Create widgets to hold SBML and Antimony sections
- sbml_widget = QWidget()
- sbml_widget.setLayout(sbml_layout)
+ self.sbml_widget = QWidget()
+ self.sbml_widget.setLayout(sbml_layout)
antimony_widget = QWidget()
antimony_widget.setLayout(antimony_layout)
# Add widgets to the splitter
- splitter.addWidget(sbml_widget)
+ splitter.addWidget(self.sbml_widget)
splitter.addWidget(antimony_widget)
# Add the splitter to the main layout
@@ -75,3 +89,47 @@ def __init__(self, parent=None, logger_view=None):
layout.addWidget(vertical_splitter)
vertical_splitter.setStretchFactor(0, 7)
vertical_splitter.setStretchFactor(1, 3)
+
+ def _show_sbml_context_menu(self, position):
+ """Show context menu for SBML text edit."""
+ if not self.sbml_toggle_action:
+ return
+
+ menu = self.sbml_text_edit.createStandardContextMenu()
+ menu.addSeparator()
+
+ # Add hide SBML option
+ hide_action = menu.addAction(
+ qta.icon("mdi6.chevron-left"), "Hide SBML Editor"
+ )
+ hide_action.triggered.connect(
+ lambda: self.sbml_toggle_action.setChecked(False)
+ )
+
+ menu.exec(self.sbml_text_edit.mapToGlobal(position))
+
+ def _show_antimony_context_menu(self, position):
+ """Show context menu for Antimony text edit."""
+ if not self.sbml_toggle_action:
+ return
+
+ menu = self.antimony_text_edit.createStandardContextMenu()
+ menu.addSeparator()
+
+ # Add show/hide SBML option
+ if self.sbml_widget.isVisible():
+ action = menu.addAction(
+ qta.icon("mdi6.chevron-left"), "Hide SBML Editor"
+ )
+ action.triggered.connect(
+ lambda: self.sbml_toggle_action.setChecked(False)
+ )
+ else:
+ action = menu.addAction(
+ qta.icon("mdi6.chevron-right"), "Show SBML Editor"
+ )
+ action.triggered.connect(
+ lambda: self.sbml_toggle_action.setChecked(True)
+ )
+
+ menu.exec(self.antimony_text_edit.mapToGlobal(position))
diff --git a/src/petab_gui/views/task_bar.py b/src/petab_gui/views/task_bar.py
index 408221c..99e528b 100644
--- a/src/petab_gui/views/task_bar.py
+++ b/src/petab_gui/views/task_bar.py
@@ -120,6 +120,7 @@ def __init__(self, parent, actions):
self.menu.addAction(actions["show_plot"])
self.menu.addAction(actions["show_visualization"])
self.menu.addAction(actions["show_simulation"])
+ self.menu.addAction(actions["show_sbml_editor"])
self.menu.addSeparator()
self.menu.addAction(actions["reset_view"])
self.menu.addAction(actions["clear_log"])