diff --git a/src/main/Simulator/Databases/__pycache__/Databases.cpython-36.pyc b/src/main/Simulator/Databases/__pycache__/Databases.cpython-36.pyc deleted file mode 100644 index fd10705..0000000 Binary files a/src/main/Simulator/Databases/__pycache__/Databases.cpython-36.pyc and /dev/null differ diff --git a/src/main/Simulator/Databases/__pycache__/Databases.cpython-37.pyc b/src/main/Simulator/Databases/__pycache__/Databases.cpython-37.pyc deleted file mode 100644 index 861284c..0000000 Binary files a/src/main/Simulator/Databases/__pycache__/Databases.cpython-37.pyc and /dev/null differ diff --git a/src/main/Simulator/Generated/data.mo b/src/main/Simulator/Generated/data.mo new file mode 100644 index 0000000..f32a706 --- /dev/null +++ b/src/main/Simulator/Generated/data.mo @@ -0,0 +1,64 @@ +within Simulator.Generated; + +package data + + record GeneralProperties "Record to declare the variables for thermophysical properties of the compounds in the database" + extends Modelica.Icons.Record; + parameter Integer SN "Serial Number"; + parameter String name "Compound Name"; + parameter String CAS "CAS Number"; + parameter Real Tc (unit="K") "Critical Temperature"; + parameter Real Pc (unit="Pa") "Critical Pressure"; + parameter Real Vc (unit="m3/kmol") "Critical Volume"; + parameter Real Cc (unit="-") "Critical Compressibility Factor"; + parameter Real Tb (unit="K") "Boiling Point Temperature"; + parameter Real Tm (unit="K") "Melting Point Temperature"; + parameter Real TT (unit="K") "Triple Point Temperature"; + parameter Real TP (unit="Pa") "Triple Point Pressure"; + parameter Real MW (unit="-") "Molecular Weight"; + parameter Real LVB (unit="m3/kmol") "Liquid Molar Volume at Normal Boiling Point"; + parameter Real AF (unit="-") "Acentric Factor"; + parameter Real SP (unit="J0.5/m1.5") "Solubility Parameter"; + parameter Real DM (unit="Coulomb.m") "Dipole Moment"; + parameter Real SH (unit="J/kmol") "Absolute Enthalpy"; + parameter Real IGHF (unit="J/kmol") "Standard Heat of Formation"; + parameter Real GEF (unit="J/kmol") "Gibbs Energy of Formation"; + parameter Real AS (unit="J/kmol/K") "Absolute Entropy"; + parameter Real HFMP (unit="J/kmol") "Heat of Fusion at Melting Point"; + parameter Real HOC (unit="J/kmol") "Heat of Combustion"; + parameter Real UniquacR (unit="-") "UNIQUAC r"; + parameter Real UniquacQ (unit="-") "UNIQUAC q"; + parameter Real LiqDen[6] (each unit="kmol/m3") "Liquid Density Coefficients"; + parameter Real VP[6] (each unit="Pa") "Vapor Pressure Coefficients"; + parameter Real LiqCp[6] (each unit="J/kmol/K") "Liquid Heat Capacity Coefficients"; + parameter Real HOV[6] (each unit="J/kmol") "Heat of Vaporization Coefficients"; + parameter Real VapCp[6] (each unit="J/kmol/K") "Ideal Gas Heat Capacity Coefficients"; + parameter Real LiqVis[6] (each unit="Pa s") "Liquid Viscosity Coefficients"; + parameter Real VapVis[6] (each unit="Pa s") "Vapor Viscosity Coefficients"; + parameter Real LiqK[6] (each unit="W/m/K") "Liquid Thermal Conductivity Coefficients"; + parameter Real VapK[6] (each unit="W/m/K") "Vapor Thermal Conductivity Coefficients"; + parameter Real Racketparam (unit="-") "Racket Parameter"; + parameter Real ChaoSeadAF (unit="-") "Chao-Seader Accentric Factor"; + parameter Real ChaoSeadSP (unit="J0.5/m1.5") "Shao-Seader Solubility Parameter"; + parameter Real ChaoSeadLV (unit="m3/kmol") "Chao-Seader Liquid Volume"; + end GeneralProperties; + + + record Air + extends Modelica.Icons.Record; + extends GeneralProperties(SN = 1, name = "Air", CAS = "132259-10-0", Tc = 132.45, Pc = 3774000, Vc = 0.09147, Cc = 0.313, Tb = 78.67, Tm = 59.15, TT = 59.15, TP = 5642.15, MW = 28.96, LVB = 0.0329147, AF = 0, SP = 12750, DM = 0, SH = 0.0, IGHF = 0, GEF = 0, AS = 199000, HFMP = 0, HOC = 0, LiqDen = {105, 2.6731, 0.25637, 132.51, 0.26788, 0}, VP = {101, 14.794, -599.85, 1.0009, -3.9938E-07, 2}, LiqCp = {16, 53628, 4511.1, -143.29, 1.582, -0.0051332}, HOV = {106, 7385651, 0.276676, 0.211253, -0.836764, 0.722737}, VapCp = {100, 29562.29, -7.164949, 0.0216294, -0.0000139748, 2.89195E-09}, LiqVis = {101, -72.336, 813.48, 12.687, -0.00033062, 2}, VapVis = {102, 0.000001592, 0.48975, 123.45, -829.58, 0}, LiqK = {16, -0.21199, -16.311, -0.23057, -0.0076197, 0.0000025018}, VapK = {102, 0.0003511, 0.76492, 16.071, 1084.4, 0}, Racketparam = 0.29056, UniquacR = 0, UniquacQ = 0, ChaoSeadAF = -0.00787976, ChaoSeadSP = 12749.8, ChaoSeadLV = 0.0329147); + end Air; + + + record Argon + extends Modelica.Icons.Record; + extends GeneralProperties(SN = 2, name = "Argon", CAS = "7440-37-1", Tc = 150.86, Pc = 4898000, Vc = 0.07457, Cc = 0.291, Tb = 87.27, Tm = 83.8039, TT = 83.8, TP = 68906.1, MW = 39.948, LVB = 0.0291, AF = -0.002, SP = 14138.3, DM = 0, SH = 0.0, IGHF = 0, GEF = 0, AS = 154732, HFMP = 1184900, HOC = 0, LiqDen = {105, 3.803, 0.286, 150.86, 0.2984, 0}, VP = {101, 44.369, -1126.1, -4.5688, 0.000062339, 2}, LiqCp = {16, 46085, -1304.5, 21.195, -0.015382, 0.000033063}, HOV = {106, 7981000, 0.099752, 0.32009, -0.11898, 0.031141}, VapCp = {16, 20786, 0, 0, 0, 0}, LiqVis = {101, -99.903, 1347.5, 17.615, -0.00032893, 2}, VapVis = {102, 0.0000010023, 0.5922, 85.563, 238.26, 0}, LiqK = {16, -0.30397, -0.82999, -0.71462, -0.00039294, -0.000012209}, VapK = {102, 0.00013095, 0.81923, -122.33, 13993, 0}, Racketparam = 0, UniquacR = 1.1074, UniquacQ = 1.068, ChaoSeadAF = -0.002, ChaoSeadSP = 14138.3, ChaoSeadLV = 0.0285865); + end Argon; + + + record Bromine + extends Modelica.Icons.Record; + extends GeneralProperties(SN = 3, name = "Bromine", CAS = "7726-95-6", Tc = 584.15, Pc = 1.03E+07, Vc = 0.135, Cc = 0.286, Tb = 331.9, Tm = 265.9, TT = 265.85, TP = 5853.37, MW = 159.808, LVB = 0.0514795, AF = 0.128997, SP = 23590, DM = 0, SH = 0.0, IGHF = 3.091E+07, GEF = 3140000, AS = 245350, HFMP = 1.057E+07, HOC = 0, LiqDen = {105, 2.0603, 0.28982, 584.15, 0.28948, 0}, VP = {101, 63.657, -5321.6, -6.3199, 0.0000054412, 2}, LiqCp = {16, 75351, -4.87E+07, 54033, 102.73, 0.43775}, HOV = {106, 3.8419E+07, -0.26282, 2.1808, -2.7529, 1.1823}, VapCp = {16, 35000, -410, 8.5, -0.00016, -0.00000001}, LiqVis = {101, -5.9813, 410.55, -0.30036, -0.000006936, 2}, VapVis = {102, 1.1438E-07, 0.88111, 59.595, -6723.3, 0}, LiqK = {16, -0.69183, 27.775, -0.38966, 0.00057103, -8.8462E-07}, VapK = {102, 0.0000065648, 1.4785, 4505.6, -870500, 0}, Racketparam = 0.279241, UniquacR = 1.8985, UniquacQ = 1.672, ChaoSeadAF = 0.108, ChaoSeadSP = 23591.8, ChaoSeadLV = 0.0514795); + end Bromine; + +end data; diff --git a/src/main/Simulator/Generated/package.mo b/src/main/Simulator/Generated/package.mo new file mode 100644 index 0000000..fc8684a --- /dev/null +++ b/src/main/Simulator/Generated/package.mo @@ -0,0 +1,5 @@ +within Simulator; + +package Generated + extends Modelica.Icons.Package; +end Generated; diff --git a/src/main/python/DockWidgets/__pycache__/DistillationColumnStagewiseResults.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DistillationColumnStagewiseResults.cpython-36.pyc deleted file mode 100644 index 0feb70b..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DistillationColumnStagewiseResults.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DistillationColumnStagewiseResults.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DistillationColumnStagewiseResults.cpython-37.pyc deleted file mode 100644 index d8c43f1..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DistillationColumnStagewiseResults.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidget.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidget.cpython-36.pyc deleted file mode 100644 index 853e89a..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidget.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidget.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidget.cpython-37.pyc deleted file mode 100644 index 90c3ef9..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidget.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetCompoundSeparator.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetCompoundSeparator.cpython-36.pyc deleted file mode 100644 index 355cf3a..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetCompoundSeparator.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetCompoundSeparator.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetCompoundSeparator.cpython-37.pyc deleted file mode 100644 index eed70e1..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetCompoundSeparator.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetCompressorExpander.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetCompressorExpander.cpython-36.pyc deleted file mode 100644 index 88102aa..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetCompressorExpander.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetCompressorExpander.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetCompressorExpander.cpython-37.pyc deleted file mode 100644 index 05d0157..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetCompressorExpander.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetDistillationColumn.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetDistillationColumn.cpython-36.pyc deleted file mode 100644 index f5eccbb..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetDistillationColumn.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetDistillationColumn.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetDistillationColumn.cpython-37.pyc deleted file mode 100644 index a3cba32..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetDistillationColumn.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetFlash.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetFlash.cpython-36.pyc deleted file mode 100644 index 34d90b2..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetFlash.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetFlash.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetFlash.cpython-37.pyc deleted file mode 100644 index 08f6dae..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetFlash.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetMaterialStream.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetMaterialStream.cpython-36.pyc deleted file mode 100644 index 1181e13..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetMaterialStream.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetMaterialStream.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetMaterialStream.cpython-37.pyc deleted file mode 100644 index abc5f50..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetMaterialStream.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetMixer.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetMixer.cpython-36.pyc deleted file mode 100644 index 1fc6df4..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetMixer.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetMixer.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetMixer.cpython-37.pyc deleted file mode 100644 index 2974d48..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetMixer.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetShortcutColumn.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetShortcutColumn.cpython-36.pyc deleted file mode 100644 index 99d84d1..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetShortcutColumn.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetShortcutColumn.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetShortcutColumn.cpython-37.pyc deleted file mode 100644 index 46cd536..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetShortcutColumn.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetSplitter.cpython-36.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetSplitter.cpython-36.pyc deleted file mode 100644 index 6c8bb16..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetSplitter.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/DockWidgetSplitter.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/DockWidgetSplitter.cpython-37.pyc deleted file mode 100644 index d23e668..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/DockWidgetSplitter.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/DockWidgets/__pycache__/__init__.cpython-37.pyc b/src/main/python/DockWidgets/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 9a9342e..0000000 Binary files a/src/main/python/DockWidgets/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/Landing_page.py b/src/main/python/Landing_page.py index 7c0d735..f91693b 100644 --- a/src/main/python/Landing_page.py +++ b/src/main/python/Landing_page.py @@ -22,6 +22,20 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))) from src.main.ui.utils.LandingPageUI import IconPanel, GlassButton +# Import the module-level globals that Graphics.py uses so we can +# purge them before stashing the old MainApp window. +try: + from python.utils.Graphics import dock_widget_lst as _dock_widget_lst, lst as _node_lst +except Exception: + _dock_widget_lst = None + _node_lst = None + +# Keep old MainApp instances alive (hidden) so their C++ objects are never +# destroyed while something might still reference them. This prevents the +# "wrapped C/C++ object has been deleted" crashes and the "Not responding" +# freezes caused by asynchronous deleteLater() destruction. +_stashed_windows = [] + class LandingPage(QWidget): def __init__(self): super().__init__() @@ -41,7 +55,7 @@ def __init__(self): self.main_window = None self.init_ui() - # πŸ”₯ Start background preload once the window is ready + # Start background preload once the window is ready QTimer.singleShot(500, self.preload_main_window) def paintEvent(self, event): @@ -157,13 +171,33 @@ def start_simulation(self): def _cleanup_main_window(self): - """Safely schedule the old main window for deletion.""" + """Hide the old main window and stash it so it stays alive. + + We intentionally do NOT call deleteLater(). Destroying a QMainWindow + with dozens of child widgets, dock widgets, QThreads, and scene items + triggers asynchronous C++ object destruction that races with the Qt + event loop and causes 'Not responding' freezes or outright segfaults. + Keeping the old window alive but hidden is safe and costs very little + memory (users won't create hundreds of sessions). + """ if self.main_window is not None: + # Clear the module-level global Graphics lists so the new + # MainApp starts with clean state. + try: + if _dock_widget_lst is not None: + _dock_widget_lst.clear() + if _node_lst is not None: + _node_lst.clear() + except Exception: + pass + try: self.main_window.hide() - self.main_window.deleteLater() except Exception: pass + + # Stash β€” prevent Python GC from collecting (and destroying) it + _stashed_windows.append(self.main_window) self.main_window = None def open_existing_project(self): @@ -184,18 +218,8 @@ def open_existing_project(self): self._cleanup_main_window() self.main_window = MainApp() - # Preserve original closeEvent - orig_close = getattr(self.main_window, "closeEvent", None) - def _wrapped_close(event): - try: - if orig_close is not None: - orig_close(event) - except Exception: - pass - if event.isAccepted(): - # Defer restoration so closeEvent finishes before we touch self.main_window - QTimer.singleShot(0, self.restore_landing_page) - self.main_window.closeEvent = _wrapped_close + # Connect to closed signal to restore landing page + self.main_window.closed.connect(lambda: QTimer.singleShot(0, self.restore_landing_page)) # Open project file self.main_window.open(file_path) @@ -241,18 +265,8 @@ def launch_main_window(self): self.main_window = MainApp() self.main_window.new_project() # reset all components for new project - # Wrap closeEvent to restore landing page - orig_close = getattr(self.main_window, "closeEvent", None) - def _wrapped_close(event): - if orig_close: - try: - orig_close(event) - except Exception: - pass - if event.isAccepted(): - # Defer restoration so closeEvent finishes before we touch self.main_window - QTimer.singleShot(0, self.restore_landing_page) - self.main_window.closeEvent = _wrapped_close + # Connect to closed signal to restore landing page + self.main_window.closed.connect(lambda: QTimer.singleShot(0, self.restore_landing_page)) # Show main window maximized self.main_window.showMaximized() @@ -324,20 +338,26 @@ def fit_canvas(self): gv.centerOn(self.main_window.scene.itemsBoundingRect().center()) self.reset_cursor() + def closeEvent(self, event): + # Explicitly quit the entire application when the landing page is closed + QApplication.quit() + event.accept() + def restore_landing_page(self): + # Drain the entire override cursor stack left by MainApp/Graphics/Container + # before showing the landing page, to prevent corrupted mouse events. + while QApplication.overrideCursor() is not None: + QApplication.restoreOverrideCursor() + # Safely clean up old main window using Qt event loop self._cleanup_main_window() - # Show landing page in full screen - # self.showFullScreen() - # Show landing page (windowed) self.show() # Make sure it is active self.activateWindow() self.raise_() - # QApplication.processEvents() def resizeEvent(self, event): # """Make sure gradient background fills screen on resize.""" @@ -391,6 +411,7 @@ def reset_cursor(self): def run(): app = QApplication(sys.argv) + app.setQuitOnLastWindowClosed(False) window = LandingPage() window.show() sys.exit(app.exec_()) diff --git a/src/main/python/OMChem/__pycache__/EngStm.cpython-36.pyc b/src/main/python/OMChem/__pycache__/EngStm.cpython-36.pyc deleted file mode 100644 index a5f5a78..0000000 Binary files a/src/main/python/OMChem/__pycache__/EngStm.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/OMChem/__pycache__/EngStm.cpython-37.pyc b/src/main/python/OMChem/__pycache__/EngStm.cpython-37.pyc deleted file mode 100644 index d065cdb..0000000 Binary files a/src/main/python/OMChem/__pycache__/EngStm.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/OMChem/__pycache__/Flowsheet.cpython-36.pyc b/src/main/python/OMChem/__pycache__/Flowsheet.cpython-36.pyc deleted file mode 100644 index 4039084..0000000 Binary files a/src/main/python/OMChem/__pycache__/Flowsheet.cpython-36.pyc and /dev/null differ diff --git a/src/main/python/OMChem/__pycache__/Flowsheet.cpython-37.pyc b/src/main/python/OMChem/__pycache__/Flowsheet.cpython-37.pyc deleted file mode 100644 index 1a76d03..0000000 Binary files a/src/main/python/OMChem/__pycache__/Flowsheet.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/OMChem/__pycache__/__init__.cpython-37.pyc b/src/main/python/OMChem/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index ee871fe..0000000 Binary files a/src/main/python/OMChem/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/mainApp.py b/src/main/python/mainApp.py index 943dee3..5ffc177 100644 --- a/src/main/python/mainApp.py +++ b/src/main/python/mainApp.py @@ -88,6 +88,7 @@ def eventFilter(self, obj, event): MainApp class is responsible for all the main App Ui operations ''' class MainApp(QMainWindow,ui): + closed = pyqtSignal() global compound_selected ''' Initializing the application @@ -446,20 +447,27 @@ def simulate(self, mode): Terminate the current running simulation ''' def terminate(self): - os.chdir(self.container.flowsheet.root_dir) - if self.thrd: + try: + os.chdir(self.container.flowsheet.root_dir) + except Exception: + pass + + if self.thrd and self.thrd.is_alive(): thread_id = self.thrd.ident - # print('____________________Going to terminate simulation thread with Thread ID:',thread_id,'____________________') - # print('____________________Going to terminate the new process created for omc____________________') - self.container.flowsheet.process.terminate() - print('____________________New process created for omc is terminated.____________________') - res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit)) + if hasattr(self.container, 'flowsheet') and hasattr(self.container.flowsheet, 'process') and self.container.flowsheet.process: + try: + self.container.flowsheet.process.terminate() + print('____________________New process created for omc is terminated.____________________') + except Exception: + pass + + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), ctypes.py_object(SystemExit)) self.textBrowser.append("["+str(self.current_time())+"]Simulation Terminated.") self.container.disableInterfaceforSimulation(False) - # print('____________________Simulation thread terminated____________________') if res > 1: - ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0) - # print('Exception raise (Thread termination) failure') + ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), 0) + + self.thrd = None ''' Resets the zoom level to default scaling @@ -626,10 +634,13 @@ def new(self): if hasattr(cls, "counter"): cls.counter = 1 - # Clear old dock widgets + # Clear old dock widgets β€” guard against already-deleted C++ objects for dw in dock_widget_lst: - dw.hide() - dw.setParent(None) + try: + dw.hide() + dw.setParent(None) + except RuntimeError: + pass # C++ object already deleted β€” safe to skip dock_widget_lst.clear() # Reset compound selection @@ -893,6 +904,21 @@ def _clear_selected_compounds_panel(self): self.selectedElementsList.clear() self._sel_status_label.setText("No compounds selected") + def closeEvent(self, event): + # Stop simulation thread if still running + try: + if self.thrd and self.thrd.is_alive(): + self.terminate() + except Exception: + pass + + # Drain any override cursors this window left on the stack + while QApplication.overrideCursor() is not None: + QApplication.restoreOverrideCursor() + + event.accept() + self.closed.emit() + from python.utils.ComponentSelectorWindow import ComponentSelectorWindow def select_compounds(self): diff --git a/src/main/python/utils/Container.py b/src/main/python/utils/Container.py index 8d9e51c..c8c7f02 100644 --- a/src/main/python/utils/Container.py +++ b/src/main/python/utils/Container.py @@ -44,7 +44,7 @@ def __init__(self, msgbrowser, graphicsView): self.result = [] self.graphics = Graphics(self, self.graphicsView) self.scene = self.graphics.get_scene() - print(f"[DEBUG] Scene check β†’ container.scene id={id(self.scene)}, graphics.scene id={id(self.graphics.scene)}") + print(f"[DEBUG] Scene check -> container.scene id={id(self.scene)}, graphics.scene id={id(self.graphics.scene)}") # ----------------- Utility ----------------- diff --git a/src/main/python/utils/__pycache__/Bin_Phase_env.cpython-37.pyc b/src/main/python/utils/__pycache__/Bin_Phase_env.cpython-37.pyc deleted file mode 100644 index 35c4753..0000000 Binary files a/src/main/python/utils/__pycache__/Bin_Phase_env.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/__pycache__/ComponentSelector.cpython-37.pyc b/src/main/python/utils/__pycache__/ComponentSelector.cpython-37.pyc deleted file mode 100644 index b6bceec..0000000 Binary files a/src/main/python/utils/__pycache__/ComponentSelector.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/__pycache__/Container.cpython-37.pyc b/src/main/python/utils/__pycache__/Container.cpython-37.pyc deleted file mode 100644 index 98797d2..0000000 Binary files a/src/main/python/utils/__pycache__/Container.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/__pycache__/Graphics.cpython-37.pyc b/src/main/python/utils/__pycache__/Graphics.cpython-37.pyc deleted file mode 100644 index 7426c2f..0000000 Binary files a/src/main/python/utils/__pycache__/Graphics.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/__pycache__/Streams.cpython-37.pyc b/src/main/python/utils/__pycache__/Streams.cpython-37.pyc deleted file mode 100644 index 18287f2..0000000 Binary files a/src/main/python/utils/__pycache__/Streams.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/__pycache__/UnitOperations.cpython-37.pyc b/src/main/python/utils/__pycache__/UnitOperations.cpython-37.pyc deleted file mode 100644 index ac4d056..0000000 Binary files a/src/main/python/utils/__pycache__/UnitOperations.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/__pycache__/__init__.cpython-37.pyc b/src/main/python/utils/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index a687f51..0000000 Binary files a/src/main/python/utils/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/src/main/python/utils/undo_manager.py b/src/main/python/utils/undo_manager.py index ace2a8d..9becf75 100644 --- a/src/main/python/utils/undo_manager.py +++ b/src/main/python/utils/undo_manager.py @@ -1,4 +1,4 @@ -ο»Ώimport os +import os import pickle import copy @@ -17,11 +17,11 @@ def _load_stack(file_name): with open(file_path, "rb") as f: stack = pickle.load(f) if not isinstance(stack, list): - print(f"[DEBUG] UndoManager._load_stack β†’ invalid format (not list)") + print(f"[DEBUG] UndoManager._load_stack -> invalid format (not list)") return [] return stack except Exception as e: - print(f"[DEBUG] UndoManager._load_stack failed β†’ {e}") + print(f"[DEBUG] UndoManager._load_stack failed -> {e}") return [] @@ -37,32 +37,32 @@ def _save_stack(file_name, stack): pickle.dump(stack, f) os.replace(tmp_path, file_path) except Exception as e: - print(f"[DEBUG] UndoManager._save_stack failed β†’ {e}") + print(f"[DEBUG] UndoManager._save_stack failed -> {e}") # -------------------- Public Interface -------------------- # def push(file_name, data): """Push snapshot to Undo/Redo stack (file-based).""" if data is None: - print(f"[DEBUG] UndoManager.push β†’ skipped (None data)") + print(f"[DEBUG] UndoManager.push -> skipped (None data)") return stack = _load_stack(file_name) stack.append(copy.deepcopy(data)) _save_stack(file_name, stack) - print(f"[DEBUG] UndoManager.push β†’ file='{file_name}', stack_size={len(stack)}") + print(f"[DEBUG] UndoManager.push -> file='{file_name}', stack_size={len(stack)}") def pop(file_name): """Pop last snapshot from stack and return it.""" stack = _load_stack(file_name) if not stack: - print(f"[DEBUG] UndoManager.pop β†’ file='{file_name}', stack empty") + print(f"[DEBUG] UndoManager.pop -> file='{file_name}', stack empty") return None data = stack.pop() _save_stack(file_name, stack) - print(f"[DEBUG] UndoManager.pop β†’ file='{file_name}', remaining={len(stack)}") + print(f"[DEBUG] UndoManager.pop -> file='{file_name}', remaining={len(stack)}") return data @@ -70,7 +70,7 @@ def get_last_list(file_name): """Return top snapshot from the stack (without popping).""" stack = _load_stack(file_name) if not stack: - print(f"[DEBUG] UndoManager.get_last_list β†’ {file_name} empty") + print(f"[DEBUG] UndoManager.get_last_list -> {file_name} empty") return None return copy.deepcopy(stack[-1]) @@ -86,9 +86,9 @@ def clean_file(file_name): try: if os.path.exists(file_path): os.remove(file_path) - print(f"[DEBUG] UndoManager.clean_file β†’ cleared {file_name}") + print(f"[DEBUG] UndoManager.clean_file -> cleared {file_name}") except Exception as e: - print(f"[DEBUG] UndoManager.clean_file failed β†’ {e}") + print(f"[DEBUG] UndoManager.clean_file failed -> {e}") # -------------------- Optional Convenience -------------------- # @@ -100,11 +100,11 @@ def reset_all(): def swap_to_redo(): """ - Utility: move current snapshot from Undo β†’ Redo. + Utility: move current snapshot from Undo -> Redo. Used automatically during Undo operations. """ last = get_last_list("Undo") if last: push("Redo", last) pop("Undo") - print("[DEBUG] UndoManager.swap_to_redo β†’ moved top from Undo β†’ Redo") + print("[DEBUG] UndoManager.swap_to_redo -> moved top from Undo -> Redo")