diff --git a/CHANGELOG.md b/CHANGELOG.md index fe49541e..ad31f61b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ CHANGELOG for FlatCAM beta - most of the logging (except in the Editors) is now done by the AppLogging class - made sure that for laser preprocessors, the laser is always turned off completely at the end of a job - added a new script example +- improved the quit application process; now the `quit_flatcam` Tcl command works properly 30.01.2022 diff --git a/app_Main.py b/app_Main.py index 6c619510..47aa0560 100644 --- a/app_Main.py +++ b/app_Main.py @@ -7,6 +7,7 @@ # Modified by Marius Stanciu (2019) # # ########################################################### import os.path +import sys import urllib.request import urllib.parse import urllib.error @@ -641,7 +642,7 @@ class App(QtCore.QObject): 'offset', 'open_dxf', 'open_excellon', 'open_gcode', 'open_gerber', 'open_project', 'open_svg', 'options', 'origin', - 'paint', 'panelize', 'plot_all', 'plot_objects', 'plot_status', 'quit_flatcam', + 'paint', 'panelize', 'plot_all', 'plot_objects', 'plot_status', 'quit_app', 'save', 'save_project', 'save_sys', 'scale', 'set_active', 'set_origin', 'set_path', 'set_sys', 'skew', 'subtract_poly', 'subtract_rectangle', @@ -4059,7 +4060,8 @@ class App(QtCore.QObject): self.geo_editor.disconnect() except TypeError: pass - self.log.debug("App.quit_application() --> Geo Editor deactivated.") + if silent is False: + self.log.debug("App.quit_application() --> Geo Editor deactivated.") if self.call_source == 'exc_editor': self.exc_editor.deactivate() @@ -4067,7 +4069,8 @@ class App(QtCore.QObject): self.grb_editor.disconnect() except TypeError: pass - self.log.debug("App.quit_application() --> Excellon Editor deactivated.") + if silent is False: + self.log.debug("App.quit_application() --> Excellon Editor deactivated.") if self.call_source == 'grb_editor': self.grb_editor.deactivate_grb_editor() @@ -4075,7 +4078,8 @@ class App(QtCore.QObject): self.exc_editor.disconnect() except TypeError: pass - self.log.debug("App.quit_application() --> Gerber Editor deactivated.") + if silent is False: + self.log.debug("App.quit_application() --> Gerber Editor deactivated.") # disconnect the mouse events if self.use_3d_engine: @@ -4093,7 +4097,8 @@ class App(QtCore.QObject): self.plotcanvas.graph_event_disconnect(self.kp) self.preferencesUiManager.save_defaults(silent=True) - self.log.debug("App.quit_application() --> App Defaults saved.") + if silent is False: + self.log.debug("App.quit_application() --> App Defaults saved.") if self.cmd_line_headless != 1: # save app state to file @@ -4126,17 +4131,18 @@ class App(QtCore.QObject): # This will write the setting to the platform specific storage. del stgs - self.log.debug("App.quit_application() --> App UI state saved.") + if silent is False: + self.log.debug("App.quit_application() --> App UI state saved.") # try to quit the Socket opened by ArgsThread class - try: - # self.new_launch.thread_exit = True - # self.new_launch.listener.close() - if sys.platform == 'win32' or sys.platform == 'linux': - self.new_launch.close_listener() - # self.new_launch.stop.emit() - except Exception as err: - self.log.error("App.quit_application() --> %s" % str(err)) + # try: + # # self.new_launch.thread_exit = True + # # self.new_launch.listener.close() + # if sys.platform == 'win32' or sys.platform == 'linux': + # self.new_launch.close_listener() + # # self.new_launch.stop.emit() + # except Exception as err: + # self.log.error("App.quit_application() --> %s" % str(err)) # try to quit the QThread that run ArgsThread class try: @@ -4144,7 +4150,8 @@ class App(QtCore.QObject): if sys.platform == 'win32' or sys.platform == 'linux': self.listen_th.quit() except Exception as e: - self.log.error("App.quit_application() --> %s" % str(e)) + if silent is False: + self.log.error("App.quit_application() --> %s" % str(e)) # terminate workers # self.workers.__del__() @@ -4153,11 +4160,8 @@ class App(QtCore.QObject): # quit app by signalling for self.kill_app() method # self.close_app_signal.emit() # sys.exit(0) - - if silent: - os._exit(0) - else: - QtWidgets.QApplication.quit() + QtWidgets.QApplication.quit() + self.new_launch.close_command() @staticmethod def kill_app(): @@ -9337,8 +9341,9 @@ class App(QtCore.QObject): if old_line != '': # it means that the script finished with an error result = self.shell.tcl.eval("set errorInfo") - self.log.error("Exec command Exception: %s\n" % result) - self.shell.append_error('ERROR: %s\n' % result) + if "quit_app" not in result: + self.log.error("Exec command Exception: %s\n" % result) + self.shell.append_error('ERROR: %s\n' % result) # self.ui.fcinfo.lock_pmaps = False self.shell.close_processing() @@ -9417,7 +9422,18 @@ class ArgsThread(QtCore.QObject): @pyqtSlot() def close_listener(self): self.thread_exit = True - self.listener.close() + try: + self.listener.close() + except Exception: + pass + + def close_command(self): + conn = Client(*self.address) + conn.send(['quit']) + try: + self.listener.close() + except Exception: + pass class MenuFileHandlers(QtCore.QObject): diff --git a/assets/examples/copper_clear_gerber.FlatScript b/assets/examples/copper_clear_gerber.FlatScript index 30ed45cd..b9bc260b 100644 --- a/assets/examples/copper_clear_gerber.FlatScript +++ b/assets/examples/copper_clear_gerber.FlatScript @@ -26,9 +26,12 @@ ncc gerber_file -overlap 10 -tooldia 0.254 -method seed -connect 1 -margin 2 -al cncjob gerber_ncc -dia 0.254 -z_cut -0.05 -z_move 3 -feedrate 100 -outname gerber_ncc_cnc # plot the objects so we can see them; not required for the script but in this script we want to see the results -plot_all +# plot_all # write the GCode to a file -# write_gcode gerber_ncc_cnc ${ROOT_FOLDER}/assets/examples/copper_clear.gcode +write_gcode gerber_ncc_cnc ${ROOT_FOLDER}/assets/examples/copper_clear.gcode + +# in the end, the script is executed so we exit the application +quit_app diff --git a/tclCommands/TclCommandQuit.py b/tclCommands/TclCommandQuit.py index d1124222..64e09064 100644 --- a/tclCommands/TclCommandQuit.py +++ b/tclCommands/TclCommandQuit.py @@ -4,6 +4,7 @@ # Date: 8/17/2019 # # MIT Licence # # ########################################################## +import sys from tclCommands.TclCommand import TclCommand @@ -19,7 +20,7 @@ class TclCommandQuit(TclCommand): """ # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) - aliases = ['quit_flatcam'] + aliases = ['quit_app'] description = '%s %s' % ("--", "Tcl shell command to quit FlatCAM from Tcl shell.") @@ -42,7 +43,7 @@ class TclCommandQuit(TclCommand): 'args': collections.OrderedDict([ ]), - 'examples': ['quit_flatcam'] + 'examples': ['quit_app'] } def execute(self, args, unnamed_args): @@ -53,4 +54,8 @@ class TclCommandQuit(TclCommand): :return: """ - self.app.quit_application(silent=True) + try: + self.app.quit_application(silent=True) + except Exception: + import os + os._exit(0)