From 7aebf1c60abfef4c8d38e41592a91d55fd8c426d Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 16 Sep 2019 02:57:46 +0300 Subject: [PATCH] - added new TclCommands: NewExcellon, NewGerber - fixed the TclCommand open_project --- FlatCAMApp.py | 24 +++++++--- README.md | 2 + tclCommands/TclCommand.py | 6 +-- tclCommands/TclCommandNewExcellon.py | 51 ++++++++++++++++++++ tclCommands/TclCommandNewGeometry.py | 8 ++-- tclCommands/TclCommandNewGerber.py | 68 +++++++++++++++++++++++++++ tclCommands/TclCommandOpenExcellon.py | 1 + tclCommands/TclCommandOpenGCode.py | 5 +- tclCommands/TclCommandOpenGerber.py | 10 +--- tclCommands/TclCommandOpenProject.py | 2 + tclCommands/__init__.py | 2 + 11 files changed, 156 insertions(+), 23 deletions(-) create mode 100644 tclCommands/TclCommandNewExcellon.py create mode 100644 tclCommands/TclCommandNewGerber.py diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 57fec76a..a0f802f4 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -9575,7 +9575,7 @@ class App(QtCore.QObject): 3) Calls on_file_new() 4) Updates options 5) Calls new_object() with the object's from_dict() as init method. - 6) Calls plot_all() + 6) Calls plot_all() if plot=True :param filename: Name of the file from which to load. :type filename: str @@ -9586,6 +9586,8 @@ class App(QtCore.QObject): """ App.log.debug("Opening project: " + filename) + # for some reason, setting ui_title does not work when this method is called from Tcl Shell + # it's because the TclCommand is run in another thread (it inherit TclCommandSignaled) if cli is None: self.set_ui_title(name=_("Loading Project ... Please Wait ...")) @@ -9610,7 +9612,6 @@ class App(QtCore.QObject): with lzma.open(filename) as f: file_content = f.read().decode('utf-8') d = json.loads(file_content, object_hook=dict2obj) - except Exception as e: App.log.error("Failed to open project file: %s with error: %s" % (filename, str(e))) self.inform.emit('[ERROR_NOTCL] %s: %s' % @@ -9619,15 +9620,21 @@ class App(QtCore.QObject): # Clear the current project # # NOT THREAD SAFE # ## - if run_from_arg is True or cli is True: + if run_from_arg is True: pass + elif cli is True: + self.delete_selection_shape() else: self.on_file_new() # Project options self.options.update(d['options']) self.project_filename = filename - self.set_screen_units(self.options["units"]) + + # for some reason, setting ui_title does not work when this method is called from Tcl Shell + # it's because the TclCommand is run in another thread (it inherit TclCommandSignaled) + if cli is None: + self.set_screen_units(self.options["units"]) # Re create objects App.log.debug(" **************** Started PROEJCT loading... **************** ") @@ -9639,6 +9646,8 @@ class App(QtCore.QObject): App.log.debug("Recreating from opened project an %s object: %s" % (obj['kind'].capitalize(), obj['options']['name'])) + # for some reason, setting ui_title does not work when this method is called from Tcl Shell + # it's because the TclCommand is run in another thread (it inherit TclCommandSignaled) if cli is None: self.set_ui_title(name="{} {}: {}".format(_("Loading Project ... restoring"), obj['kind'].upper(), @@ -9648,13 +9657,16 @@ class App(QtCore.QObject): self.new_object(obj['kind'], obj['options']['name'], obj_init, active=False, fit=False, plot=plot) - # self.plot_all() self.inform.emit('[success] %s: %s' % (_("Project loaded from"), filename)) self.should_we_save = False self.file_opened.emit("project", filename) - self.set_ui_title(name=self.project_filename) + + # for some reason, setting ui_title does not work when this method is called from Tcl Shell + # it's because the TclCommand is run in another thread (it inherit TclCommandSignaled) + if cli is None: + self.set_ui_title(name=self.project_filename) App.log.debug(" **************** Finished PROJECT loading... **************** ") diff --git a/README.md b/README.md index e6ddefc3..436185a4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ CAD program, and create G-Code for Isolation routing. - modified the TclCommands so that open files do not plot the opened files automatically - made all TclCommands not to be plotted automatically - made sure that all TclCommands are not threaded +- added new TclCommands: NewExcellon, NewGerber +- fixed the TclCommand open_project 14.09.2019 diff --git a/tclCommands/TclCommand.py b/tclCommands/TclCommand.py index 4f58a006..e279fee2 100644 --- a/tclCommands/TclCommand.py +++ b/tclCommands/TclCommand.py @@ -78,8 +78,7 @@ class TclCommand(object): :return: current command """ - - command_string = [] + command_string = list() command_string.append(self.aliases[0]) if self.original_args is not None: @@ -117,7 +116,7 @@ class TclCommand(object): if help_key in self.arg_names: arg_type = self.arg_names[help_key] type_name = str(arg_type.__name__) - #in_command_name = help_key + "<" + type_name + ">" + # in_command_name = help_key + "<" + type_name + ">" in_command_name = help_key elif help_key in self.option_types: @@ -416,7 +415,6 @@ class TclCommandSignaled(TclCommand): # when operation will be really long is good to set it higher then defqault 30s self.app.worker_task.emit({'fcn': self.execute_call, 'params': [args, unnamed_args]}) - return self.output except Exception as unknown: diff --git a/tclCommands/TclCommandNewExcellon.py b/tclCommands/TclCommandNewExcellon.py new file mode 100644 index 00000000..22f81347 --- /dev/null +++ b/tclCommands/TclCommandNewExcellon.py @@ -0,0 +1,51 @@ +from ObjectCollection import * +from tclCommands.TclCommand import TclCommandSignaled + + +class TclCommandNewExcellon(TclCommandSignaled): + """ + Tcl shell command to subtract polygon from the given Geometry object. + """ + + # array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + aliases = ['new_excellon'] + + # Dictionary of types from Tcl command, needs to be ordered. + # For positional arguments + arg_names = collections.OrderedDict([ + ('name', str) + ]) + + # Dictionary of types from Tcl command, needs to be ordered. + # For options like -optionname value + option_types = collections.OrderedDict([ + + ]) + + # array of mandatory options for current Tcl command: required = {'name','outname'} + required = [] + + # structured help for current command, args needs to be ordered + help = { + 'main': "Creates a new empty Excellon object.", + 'args': collections.OrderedDict([ + ('name', 'New object name.'), + ]), + 'examples': [] + } + + def execute(self, args, unnamed_args): + """ + execute current TCL shell command + + :param args: array of known named arguments and options + :param unnamed_args: array of other values which were passed into command + without -somename and we do not have them in known arg_names + :return: None or exception + """ + + if 'name' in args: + name = args['name'] + else: + name = 'new_exc' + self.app.new_object('excellon', name, lambda x, y: None, plot=False) diff --git a/tclCommands/TclCommandNewGeometry.py b/tclCommands/TclCommandNewGeometry.py index a7c72c40..746a8d85 100644 --- a/tclCommands/TclCommandNewGeometry.py +++ b/tclCommands/TclCommandNewGeometry.py @@ -23,7 +23,7 @@ class TclCommandNewGeometry(TclCommandSignaled): ]) # array of mandatory options for current Tcl command: required = {'name','outname'} - required = ['name'] + required = [] # structured help for current command, args needs to be ordered help = { @@ -43,7 +43,9 @@ class TclCommandNewGeometry(TclCommandSignaled): without -somename and we do not have them in known arg_names :return: None or exception """ - - name = args['name'] + if 'name' in args: + name = args['name'] + else: + name = 'new_geo' self.app.new_object('geometry', str(name), lambda x, y: None, plot=False) diff --git a/tclCommands/TclCommandNewGerber.py b/tclCommands/TclCommandNewGerber.py new file mode 100644 index 00000000..c461d83d --- /dev/null +++ b/tclCommands/TclCommandNewGerber.py @@ -0,0 +1,68 @@ +from ObjectCollection import * +from tclCommands.TclCommand import TclCommandSignaled + + +class TclCommandNewGerber(TclCommandSignaled): + """ + Tcl shell command to subtract polygon from the given Geometry object. + """ + + # array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + aliases = ['new_gerber'] + + # Dictionary of types from Tcl command, needs to be ordered. + # For positional arguments + arg_names = collections.OrderedDict([ + ('name', str) + ]) + + # Dictionary of types from Tcl command, needs to be ordered. + # For options like -optionname value + option_types = collections.OrderedDict([ + + ]) + + # array of mandatory options for current Tcl command: required = {'name','outname'} + required = [] + + # structured help for current command, args needs to be ordered + help = { + 'main': "Creates a new empty Gerber object.", + 'args': collections.OrderedDict([ + ('name', 'New object name.'), + ]), + 'examples': [] + } + + def execute(self, args, unnamed_args): + """ + execute current TCL shell command + + :param args: array of known named arguments and options + :param unnamed_args: array of other values which were passed into command + without -somename and we do not have them in known arg_names + :return: None or exception + """ + + if 'name' in args: + name = args['name'] + else: + name = 'new_grb' + + def initialize(grb_obj, self): + grb_obj.multitool = False + grb_obj.source_file = [] + grb_obj.multigeo = False + grb_obj.follow = False + grb_obj.apertures = {} + grb_obj.solid_geometry = [] + + try: + grb_obj.options['xmin'] = 0 + grb_obj.options['ymin'] = 0 + grb_obj.options['xmax'] = 0 + grb_obj.options['ymax'] = 0 + except KeyError: + pass + + self.app.new_object('gerber', name, initialize, plot=False) diff --git a/tclCommands/TclCommandOpenExcellon.py b/tclCommands/TclCommandOpenExcellon.py index 1733ccc5..253221cd 100644 --- a/tclCommands/TclCommandOpenExcellon.py +++ b/tclCommands/TclCommandOpenExcellon.py @@ -46,6 +46,7 @@ class TclCommandOpenExcellon(TclCommandSignaled): """ filename = args.pop('filename') + filename = filename.replace(' ', '') args['plot'] = False self.app.open_excellon(filename, **args) diff --git a/tclCommands/TclCommandOpenGCode.py b/tclCommands/TclCommandOpenGCode.py index a1643403..08ada089 100644 --- a/tclCommands/TclCommandOpenGCode.py +++ b/tclCommands/TclCommandOpenGCode.py @@ -46,4 +46,7 @@ class TclCommandOpenGCode(TclCommandSignaled): :return: None or exception """ args['plot'] = False - self.app.open_gcode(args['filename'], **args) + filename = args["filename"] + filename = filename.replace(' ', '') + + self.app.open_gcode(filename, **args) diff --git a/tclCommands/TclCommandOpenGerber.py b/tclCommands/TclCommandOpenGerber.py index dbf5e4b9..18eae168 100644 --- a/tclCommands/TclCommandOpenGerber.py +++ b/tclCommands/TclCommandOpenGerber.py @@ -50,25 +50,19 @@ class TclCommandOpenGerber(TclCommandSignaled): self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (outname, type(gerber_obj))) # Opening the file happens here - self.app.progress.emit(30) try: gerber_obj.parse_file(filename) - except IOError: app_obj.inform.emit("[ERROR_NOTCL] Failed to open file: %s " % filename) - app_obj.progress.emit(0) self.raise_tcl_error('Failed to open file: %s' % filename) except ParseError as e: app_obj.inform.emit("[ERROR_NOTCL] Failed to parse file: %s, %s " % (filename, str(e))) - app_obj.progress.emit(0) self.log.error(str(e)) return - # Further parsing - app_obj.progress.emit(70) - filename = args['filename'] + filename = filename.replace(' ', '') if 'outname' in args: outname = args['outname'] @@ -87,7 +81,5 @@ class TclCommandOpenGerber(TclCommandSignaled): # Register recent file self.app.file_opened.emit("gerber", filename) - self.app.progress.emit(100) - # GUI feedback self.app.inform.emit("[success] Opened: " + filename) diff --git a/tclCommands/TclCommandOpenProject.py b/tclCommands/TclCommandOpenProject.py index 02c74bbf..eab891e9 100644 --- a/tclCommands/TclCommandOpenProject.py +++ b/tclCommands/TclCommandOpenProject.py @@ -44,4 +44,6 @@ class TclCommandOpenProject(TclCommandSignaled): :return: None or exception """ filename = args['filename'] + filename = filename.replace(' ', '') + self.app.open_project(filename, cli=True, plot=False) diff --git a/tclCommands/__init__.py b/tclCommands/__init__.py index ae64e146..98603aa5 100644 --- a/tclCommands/__init__.py +++ b/tclCommands/__init__.py @@ -35,7 +35,9 @@ import tclCommands.TclCommandMillSlots import tclCommands.TclCommandMirror import tclCommands.TclCommandNew import tclCommands.TclCommandNregions +import tclCommands.TclCommandNewExcellon import tclCommands.TclCommandNewGeometry +import tclCommands.TclCommandNewGerber import tclCommands.TclCommandOffset import tclCommands.TclCommandOpenExcellon import tclCommands.TclCommandOpenGCode