diff --git a/CHANGELOG.md b/CHANGELOG.md index 95777037..69e062d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta ================================================= +2.01.2022 + +- improved the running of scripts when loading from GUI a script as a FlatCAM script + 21.01.2022 - added a new Tcl command: `buffer` which will buffer the geometry of an object or will scale individually each geometry sub element @@ -17,7 +21,7 @@ CHANGELOG for FlatCAM beta 19.01.2022 -- updated the header of the postprocessos with 'laser' to show essential informations like some of them do not move on the Z axis +- updated the header of the preprocessors with 'laser' to show essential information's like some of them do not move on the Z axis - make sure that the laser postprocessor that do move on the Z axis (like 'GRBL_laser_Z') accept negative values for the Z focus - fixed issue in highlighter such that the keywords that have an underscore included are highlighted - rearranged the default keywords diff --git a/appObjects/FlatCAMScript.py b/appObjects/FlatCAMScript.py index b4c1ddd1..29064ff8 100644 --- a/appObjects/FlatCAMScript.py +++ b/appObjects/FlatCAMScript.py @@ -14,9 +14,6 @@ from appEditors.AppTextEditor import AppTextEditor from appObjects.FlatCAMObj import * from appGUI.ObjectUI import * -import tkinter as tk -import sys - import gettext import appTranslation as fcTranslate import builtins @@ -209,81 +206,8 @@ class ScriptObject(FlatCAMObj): self.script_filename = filename def handle_run_code(self): - # trying to run a Tcl command without having the Shell open will create some warnings because the Tcl Shell - # tries to print on a hidden widget, therefore show the dock if hidden - if self.app.ui.shell_dock.isHidden(): - self.app.ui.shell_dock.show() - - self.app.shell.open_processing() # Disables input box. - - # make sure that the pixmaps are not updated when running this as they will crash - # TODO find why the pixmaps for the whole app load crash when run from this object (perhaps another thread?) - self.app.ui.fcinfo.lock_pmaps = True - self.script_code = self.script_editor_tab.code_editor.toPlainText() - - old_line = '' - # set tcl info script to actual scriptfile - - set_tcl_script_name = '''proc procExists p {{ - return uplevel 1 [expr {{[llength [info command $p]] > 0}}] - }} - - if {{[procExists "info_original"]==0}} {{ - rename info info_original - }} - - proc info args {{ - switch [lindex $args 0] {{ - script {{ - return "{0}" - }} - default {{ - return [uplevel info_original $args] - }} - }} - }}'''.format(self.script_filename) - - for tcl_command_line in set_tcl_script_name.splitlines()+self.script_code.splitlines(): - # do not process lines starting with '#' = comment and empty lines - if not tcl_command_line.startswith('#') and tcl_command_line != '': - # if FlatCAM is run in Windows then replace all the slashes with - # the UNIX style slash that TCL understands - if sys.platform == 'win32': - tcl_command_line_lowered = tcl_command_line.lower() - if "open" in tcl_command_line_lowered or "path" in tcl_command_line_lowered: - tcl_command_line = tcl_command_line.replace('\\', '/') - - if old_line != '': - new_command = old_line + tcl_command_line + '\n' - else: - new_command = tcl_command_line - - # execute the actual Tcl command - try: - result = self.app.shell.tcl.eval(str(new_command)) - if result != 'None': - self.app.shell.append_output(result + '\n') - if result == 'fail': - self.app.ui.fcinfo.lock_pmaps = False - self.app.shell.close_processing() - self.app.inform.emit("[ERROR] %s: %s" % (_("Tcl Command failed"), str(new_command))) - self.app.inform.emit("[ERROR] %s" % _("Aborting.")) - return - old_line = '' - except tk.TclError: - old_line = old_line + tcl_command_line + '\n' - except Exception as e: - log.error("ScriptObject.handleRunCode() --> %s" % str(e)) - - if old_line != '': - # it means that the script finished with an error - result = self.app.shell.tcl.eval("set errorInfo") - log.error("Exec command Exception: %s\n" % result) - self.app.shell.append_error('ERROR: %s\n' % result) - - self.app.ui.fcinfo.lock_pmaps = False - self.app.shell.close_processing() + self.app.run_script.emit(self.script_code) def on_autocomplete_changed(self, state): if state: diff --git a/appPlugins/ToolMilling.py b/appPlugins/ToolMilling.py index 9f254be2..4dc0491d 100644 --- a/appPlugins/ToolMilling.py +++ b/appPlugins/ToolMilling.py @@ -3412,7 +3412,6 @@ class ToolMilling(AppTool, Excellon): is_last = True if tooluid_key == tool_lst[-1] else False last_pt = tools_dict[tooluid_key]['data']['tools_mill_endxy'] - print(tools_dict[tooluid_key]['data']['tools_mill_ppname_g']) res, start_gcode = new_cncjob_obj.geometry_tool_gcode_gen(tooluid_key, tools_dict, first_pt=first_pt, last_pt=last_pt, tolerance=tol, diff --git a/appPlugins/ToolShell.py b/appPlugins/ToolShell.py index e350644d..02dd6bbe 100644 --- a/appPlugins/ToolShell.py +++ b/appPlugins/ToolShell.py @@ -462,9 +462,6 @@ class FCShell(TermWidget): will create crashes of the _Expandable_Edit widget :return: output if there was any """ - - self.app.defaults.report_usage('exec_command') - return self.exec_command_test(text, False, no_echo=no_echo) def exec_command_test(self, text, reraise=True, no_echo=False): diff --git a/app_Main.py b/app_Main.py index c9cafb96..76324b61 100644 --- a/app_Main.py +++ b/app_Main.py @@ -39,15 +39,18 @@ from multiprocessing.connection import Listener, Client from multiprocessing import Pool import socket +import tkinter as tk + import qdarktheme import qdarktheme.themes.dark.stylesheet as qdarksheet -from appGUI import style_sheet # #################################################################################################################### # ################################### Imports part of FlatCAM ############################################# # #################################################################################################################### # Various +from appGUI import style_sheet + from appCommon.Common import LoudDict from appCommon.Common import color_variant from appCommon.Common import ExclusionAreas @@ -268,6 +271,9 @@ class App(QtCore.QObject): proj_selection_changed = pyqtSignal(object, object) + # used by the FlatCAMScript object to process a script + run_script = pyqtSignal(str) + def __init__(self, qapp, user_defaults=True): """ Starts the application. @@ -1555,6 +1561,9 @@ class App(QtCore.QObject): # signal to close the application self.close_app_signal.connect(self.kill_app) + + # signal to process the body of a script + self.run_script.connect(self.script_processing) # ################################# FINISHED CONNECTING SIGNALS ############################################# # ########################################################################################################### # ########################################################################################################### @@ -9247,6 +9256,79 @@ class App(QtCore.QObject): except AttributeError: self.log.debug("shell_message() is called before Shell Class is instantiated. The message is: %s", str(msg)) + def script_processing(self, script_code): + # trying to run a Tcl command without having the Shell open will create some warnings because the Tcl Shell + # tries to print on a hidden widget, therefore show the dock if hidden + if self.ui.shell_dock.isHidden(): + self.ui.shell_dock.show() + + self.shell.open_processing() # Disables input box. + + # make sure that the pixmaps are not updated when running this as they will crash + # TODO find why the pixmaps for the whole app load crash when run from this object (perhaps another thread?) + # self.ui.fcinfo.lock_pmaps = True + + old_line = '' + # set tcl info script to actual scriptfile + + set_tcl_script_name = '''proc procExists p {{ + return uplevel 1 [expr {{[llength [info command $p]] > 0}}] + }} + + if {{[procExists "info_original"]==0}} {{ + rename info info_original + }} + + proc info args {{ + switch [lindex $args 0] {{ + script {{ + return "{0}" + }} + default {{ + return [uplevel info_original $args] + }} + }} + }}'''.format(script_code) + + for tcl_command_line in set_tcl_script_name.splitlines() + script_code.splitlines(): + # do not process lines starting with '#' = comment and empty lines + if not tcl_command_line.startswith('#') and tcl_command_line != '': + # if FlatCAM is run in Windows then replace all the slashes with + # the UNIX style slash that TCL understands + if sys.platform == 'win32': + tcl_command_line_lowered = tcl_command_line.lower() + if "open" in tcl_command_line_lowered or "path" in tcl_command_line_lowered: + tcl_command_line = tcl_command_line.replace('\\', '/') + + new_command = '%s%s\n' % (old_line, tcl_command_line) if old_line != '' else tcl_command_line + + # execute the actual Tcl command + try: + result = self.shell.tcl.eval(str(new_command)) + if result != 'None': + self.shell.append_output(result + '\n') + if result == 'fail': + # self.ui.fcinfo.lock_pmaps = False + self.shell.append_output(result.capitalize() + '\n') + self.shell.close_processing() + self.log.error("%s: %s" % ("Tcl Command failed", str(new_command))) + self.inform.emit("[ERROR] %s" % _("Aborting.")) + return + old_line = '' + except tk.TclError: + old_line = old_line + tcl_command_line + '\n' + except Exception as e: + self.log.error("App.script_processing() --> %s" % str(e)) + + 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) + + # self.ui.fcinfo.lock_pmaps = False + self.shell.close_processing() + def dec_format(self, val, dec=None): """ Returns a formatted float value with a certain number of decimals