Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion src/petab_gui/controllers/mother_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,10 @@ def setup_actions(self):
qta.icon("mdi6.table-arrow-down"), "Save This Table", self.view
)
actions["save_single_table"].triggered.connect(self.save_single_table)
actions["save_sbml"] = QAction(
qta.icon("mdi6.file-code"), "Export SBML Model", self.view
)
actions["save_sbml"].triggered.connect(self.save_sbml_model)
# Find + Replace
actions["find"] = QAction(qta.icon("mdi6.magnify"), "Find", self.view)
actions["find"].setShortcut(QKeySequence.Find)
Expand Down Expand Up @@ -574,6 +578,7 @@ def sync_visibility_with_actions(self):

# Store action reference in view for context menus
self.view.sbml_viewer.sbml_toggle_action = sbml_action
self.view.sbml_viewer.save_sbml_action = self.actions["save_sbml"]

# Connect menu action to widget visibility
sbml_action.toggled.connect(sbml_widget.setVisible)
Expand Down Expand Up @@ -655,6 +660,40 @@ def save_single_table(self):
active_controller.save_table(file_name)
return True

def save_sbml_model(self):
"""Export the SBML model to an XML file."""
if not self.model.sbml or not self.model.sbml.sbml_text:
QMessageBox.warning(
self.view,
"Export SBML Model",
"No SBML model to export.",
)
return False

file_name, _ = QFileDialog.getSaveFileName(
self.view,
"Export SBML Model",
f"{self.model.sbml.model_id}.xml",
"SBML Files (*.xml *.sbml);;All Files (*)",
)
if not file_name:
return False

try:
with open(file_name, "w") as f:
f.write(self.model.sbml.sbml_text)
self.logger.log_message(
"SBML model exported successfully to file.", color="green"
)
return True
except Exception as e:
QMessageBox.critical(
self.view,
"Export SBML Model",
f"Failed to export SBML model: {e}",
)
return False

def handle_selection_changed(self):
"""Update the plot when selection in the measurement table changes."""
self.update_plot()
Expand Down Expand Up @@ -736,12 +775,18 @@ def open_file(self, file_path=None, mode=None):
return
# handle file appropriately
actionable, sep = process_file(file_path, self.logger)
if actionable in ["yaml", "sbml", "omex"] and mode == "append":
if actionable in ["yaml", "omex"] and mode == "append":
self.logger.log_message(
f"Append mode is not supported for *.{actionable} files.",
color="red",
)
return
if actionable in ["sbml"] and mode == "append":
self.logger.log_message(
"Append mode is not supported for SBML models.",
color="orange",
)
return
if not actionable:
return
if mode is None:
Expand Down
11 changes: 11 additions & 0 deletions src/petab_gui/views/sbml_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(self, parent=None, logger_view=None):

# Reference to menu action (set by controller)
self.sbml_toggle_action = None
self.save_sbml_action = None

# Main layout for the SBML tab
layout = QVBoxLayout(self)
Expand Down Expand Up @@ -98,6 +99,11 @@ def _show_sbml_context_menu(self, position):
menu = self.sbml_text_edit.createStandardContextMenu()
menu.addSeparator()

# Add export SBML option
if self.save_sbml_action:
menu.addAction(self.save_sbml_action)
menu.addSeparator()

# Add hide SBML option
hide_action = menu.addAction(
qta.icon("mdi6.chevron-left"), "Hide SBML Editor"
Expand All @@ -116,6 +122,11 @@ def _show_antimony_context_menu(self, position):
menu = self.antimony_text_edit.createStandardContextMenu()
menu.addSeparator()

# Add export SBML option
if self.save_sbml_action:
menu.addAction(self.save_sbml_action)
menu.addSeparator()

# Add show/hide SBML option
if self.sbml_widget.isVisible():
action = menu.addAction(
Expand Down