@@ -341,6 +341,10 @@ def setup_actions(self):
341341 qta .icon ("mdi6.table-arrow-down" ), "Save This Table" , self .view
342342 )
343343 actions ["save_single_table" ].triggered .connect (self .save_single_table )
344+ actions ["save_sbml" ] = QAction (
345+ qta .icon ("mdi6.file-code" ), "Export SBML Model" , self .view
346+ )
347+ actions ["save_sbml" ].triggered .connect (self .save_sbml_model )
344348 # Find + Replace
345349 actions ["find" ] = QAction (qta .icon ("mdi6.magnify" ), "Find" , self .view )
346350 actions ["find" ].setShortcut (QKeySequence .Find )
@@ -574,6 +578,7 @@ def sync_visibility_with_actions(self):
574578
575579 # Store action reference in view for context menus
576580 self .view .sbml_viewer .sbml_toggle_action = sbml_action
581+ self .view .sbml_viewer .save_sbml_action = self .actions ["save_sbml" ]
577582
578583 # Connect menu action to widget visibility
579584 sbml_action .toggled .connect (sbml_widget .setVisible )
@@ -655,6 +660,40 @@ def save_single_table(self):
655660 active_controller .save_table (file_name )
656661 return True
657662
663+ def save_sbml_model (self ):
664+ """Export the SBML model to an XML file."""
665+ if not self .model .sbml or not self .model .sbml .sbml_text :
666+ QMessageBox .warning (
667+ self .view ,
668+ "Export SBML Model" ,
669+ "No SBML model to export." ,
670+ )
671+ return False
672+
673+ file_name , _ = QFileDialog .getSaveFileName (
674+ self .view ,
675+ "Export SBML Model" ,
676+ f"{ self .model .sbml .model_id } .xml" ,
677+ "SBML Files (*.xml *.sbml);;All Files (*)" ,
678+ )
679+ if not file_name :
680+ return False
681+
682+ try :
683+ with open (file_name , "w" ) as f :
684+ f .write (self .model .sbml .sbml_text )
685+ self .logger .log_message (
686+ "SBML model exported successfully to file." , color = "green"
687+ )
688+ return True
689+ except Exception as e :
690+ QMessageBox .critical (
691+ self .view ,
692+ "Export SBML Model" ,
693+ f"Failed to export SBML model: { e } " ,
694+ )
695+ return False
696+
658697 def handle_selection_changed (self ):
659698 """Update the plot when selection in the measurement table changes."""
660699 self .update_plot ()
@@ -736,12 +775,18 @@ def open_file(self, file_path=None, mode=None):
736775 return
737776 # handle file appropriately
738777 actionable , sep = process_file (file_path , self .logger )
739- if actionable in ["yaml" , "sbml" , " omex" ] and mode == "append" :
778+ if actionable in ["yaml" , "omex" ] and mode == "append" :
740779 self .logger .log_message (
741780 f"Append mode is not supported for *.{ actionable } files." ,
742781 color = "red" ,
743782 )
744783 return
784+ if actionable in ["sbml" ] and mode == "append" :
785+ self .logger .log_message (
786+ "Append mode is not supported for SBML models." ,
787+ color = "orange" ,
788+ )
789+ return
745790 if not actionable :
746791 return
747792 if mode is None :
0 commit comments