From 2f553c900500206f00bb512498bc24f731958751 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 16 Sep 2019 00:47:15 +0300 Subject: [PATCH] - added a new TclCommand named PlotObjects which will plot a list of FlatCAM objects - made that after opening an object in FlatCAM it is not automatically plotted. If the user wants to plot it can use the TclCommands PlotAll or PlotObjects - modified the TclCommands that open files to not plot the opened files automatically --- FlatCAMApp.py | 48 ++++++++++------- README.md | 3 ++ tclCommands/TclCommand.py | 50 +++++++++--------- tclCommands/TclCommandOpenExcellon.py | 1 + tclCommands/TclCommandOpenGCode.py | 2 +- tclCommands/TclCommandOpenGerber.py | 7 +-- tclCommands/TclCommandOpenProject.py | 4 +- ...TclCommandPlot.py => TclCommandPlotAll.py} | 4 +- tclCommands/TclCommandPlotObjects.py | 51 +++++++++++++++++++ tclCommands/__init__.py | 3 +- 10 files changed, 122 insertions(+), 51 deletions(-) rename tclCommands/{TclCommandPlot.py => TclCommandPlotAll.py} (94%) create mode 100644 tclCommands/TclCommandPlotObjects.py diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 0d820b21..72f3b36c 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -1898,7 +1898,8 @@ class App(QtCore.QObject): 'mirror', 'ncc', 'ncc_clear', 'ncr', 'new', 'new_geometry', 'non_copper_regions', 'offset', 'open_excellon', 'open_gcode', 'open_gerber', 'open_project', 'options', 'paint', - 'pan', 'panel', 'panelize', 'plot', 'save', 'save_project', 'save_sys', 'scale', + 'pan', 'panel', 'panelize', 'plot_all', 'plot_objects', 'save', 'save_project', + 'save_sys', 'scale', 'set_active', 'set_sys', 'setsys', 'skew', 'subtract_poly', 'subtract_rectangle', 'version', 'write_gcode' ] @@ -1917,7 +1918,8 @@ class App(QtCore.QObject): 'use_threads', 'value', 'x', 'x0', 'x1', 'y', 'y0', 'y1', 'z_cut', 'z_move', 'default', 'feedrate_z', 'grbl_11', 'grbl_laser', 'hpgl', 'line_xyz', 'marlin', 'Paste_1', 'Repetier', 'Toolchange_Custom', 'Roland_MDX_20', 'Toolchange_manual', - 'Toolchange_Probe_MACH3', 'dwell', 'dwelltime', 'toolchange_xy', 'iso_type' + 'Toolchange_Probe_MACH3', 'dwell', 'dwelltime', 'toolchange_xy', 'iso_type', + 'Desktop', 'FlatPrj', 'FlatConfig', 'Users', 'Documents', 'My Documents', 'Marius' ] self.tcl_keywords = [ @@ -2253,6 +2255,9 @@ class App(QtCore.QObject): # Variable to store the GCODE that was edited self.gcode_edited = "" + # reference for the self.ui.code_editor + self.reference_code_editor = None + # if Preferences are changed in the Edit -> Preferences tab the value will be set to True self.preferences_changed_flag = False @@ -3062,8 +3067,8 @@ class App(QtCore.QObject): result = self.exec_command_test(text, False) # MS: added this method call so the geometry is updated once the TCL command is executed - if no_plot is None: - self.plot_all() + # if no_plot is None: + # self.plot_all() return result @@ -5941,6 +5946,7 @@ class App(QtCore.QObject): old_line = '' except tk.TclError as e: + log.debug("App.handleRunCode() --> %s" % str(e)) old_line = old_line + tcl_command_line + '\n' if old_line != '': @@ -8199,6 +8205,9 @@ class App(QtCore.QObject): self.ui.code_editor.completer_enable = False self.ui.buttonRun.hide() + # make sure to keep a reference to the code editor + self.reference_code_editor = self.ui.code_editor + # Switch plot_area to CNCJob tab self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab) @@ -9387,7 +9396,7 @@ class App(QtCore.QObject): self.inform.emit('[success] %s: %s' % (_("Opened"), filename)) - def open_excellon(self, filename, outname=None): + def open_excellon(self, filename, outname=None, plot=True): """ Opens an Excellon file, parses it and creates a new object for it in the program. Thread-safe. @@ -9441,7 +9450,7 @@ class App(QtCore.QObject): # Object name name = outname or filename.split('/')[-1].split('\\')[-1] - ret_val = self.new_object("excellon", name, obj_init, autoselected=False) + ret_val = self.new_object("excellon", name, obj_init, autoselected=False, plot=plot) if ret_val == 'fail': self.inform.emit('[ERROR_NOTCL] %s' % _('Open Excellon file failed. Probable not an Excellon file.')) @@ -9454,7 +9463,7 @@ class App(QtCore.QObject): self.inform.emit('[success] %s: %s' % (_("Opened"), filename)) - def open_gcode(self, filename, outname=None): + def open_gcode(self, filename, outname=None, plot=True): """ Opens a G-gcode file, parses it and creates a new object for it in the program. Thread-safe. @@ -9506,7 +9515,7 @@ class App(QtCore.QObject): name = outname or filename.split('/')[-1].split('\\')[-1] # New object creation and file processing - ret = self.new_object("cncjob", name, obj_init, autoselected=False) + ret = self.new_object("cncjob", name, obj_init, autoselected=False, plot=plot) if ret == 'fail': self.inform.emit('[ERROR_NOTCL] %s' % _("Failed to create CNCJob Object. Probable not a GCode file.\n " @@ -9554,7 +9563,7 @@ class App(QtCore.QObject): (_("Failed to open config file"), filename)) return - def open_project(self, filename, run_from_arg=None): + def open_project(self, filename, run_from_arg=None, plot=True, cli=None): """ Loads a project from the specified file. @@ -9568,11 +9577,14 @@ class App(QtCore.QObject): :param filename: Name of the file from which to load. :type filename: str :param run_from_arg: True if run for arguments + :param plot: If True plot all objects in the project + :param cli: run from command line :return: None """ App.log.debug("Opening project: " + filename) - self.set_ui_title(name=_("Loading Project ... Please Wait ...")) + if cli is None: + self.set_ui_title(name=_("Loading Project ... Please Wait ...")) # Open and parse an uncompressed Project file try: @@ -9604,7 +9616,7 @@ class App(QtCore.QObject): # Clear the current project # # NOT THREAD SAFE # ## - if run_from_arg is True: + if run_from_arg is True or cli is True: pass else: self.on_file_new() @@ -9620,16 +9632,18 @@ class App(QtCore.QObject): for obj in d['objs']: def obj_init(obj_inst, app_inst): obj_inst.from_dict(obj) + App.log.debug("Recreating from opened project an %s object: %s" % (obj['kind'].capitalize(), obj['options']['name'])) - self.set_ui_title(name="{} {}: {}".format(_("Loading Project ... restoring"), - obj['kind'].upper(), - obj['options']['name'] - ) - ) + if cli is None: + self.set_ui_title(name="{} {}: {}".format(_("Loading Project ... restoring"), + obj['kind'].upper(), + obj['options']['name'] + ) + ) - self.new_object(obj['kind'], obj['options']['name'], obj_init, active=False, fit=False, plot=True) + 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' % diff --git a/README.md b/README.md index cf4c0e3d..224fa336 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ CAD program, and create G-Code for Isolation routing. - added some more keywords in the data_model for auto-completer - fixed isolate TclCommand to use correctly the -outname parameter - added possibility to see the GCode when right clicking on the Project tab on a CNCJob object and then clicking View Source +- added a new TclCommand named PlotObjects which will plot a list of FlatCAM objects +- made that after opening an object in FlatCAM it is not automatically plotted. If the user wants to plot it can use the TclCommands PlotAll or PlotObjects +- modified the TclCommands that open files to not plot the opened files automatically 14.09.2019 diff --git a/tclCommands/TclCommand.py b/tclCommands/TclCommand.py index b50b380c..4f58a006 100644 --- a/tclCommands/TclCommand.py +++ b/tclCommands/TclCommand.py @@ -163,35 +163,36 @@ class TclCommand(object): @staticmethod def parse_arguments(args): - """ - Pre-processes arguments to detect '-keyword value' pairs into dictionary - and standalone parameters into list. + """ + Pre-processes arguments to detect '-keyword value' pairs into dictionary + and standalone parameters into list. - This is copy from FlatCAMApp.setup_shell().h() just for accessibility, - original should be removed after all commands will be converted + This is copy from FlatCAMApp.setup_shell().h() just for accessibility, + original should be removed after all commands will be converted - :param args: arguments from tcl to parse - :return: arguments, options - """ + :param args: arguments from tcl to parse + :return: arguments, options + """ - options = {} - arguments = [] - n = len(args) - name = None - for i in range(n): - match = re.search(r'^-([a-zA-Z].*)', args[i]) - if match: - assert name is None - name = match.group(1) - continue + options = {} + arguments = [] + n = len(args) - if name is None: - arguments.append(args[i]) - else: - options[name] = args[i] - name = None + name = None + for i in range(n): + match = re.search(r'^-([a-zA-Z].*)', args[i]) + if match: + assert name is None + name = match.group(1) + continue - return arguments, options + if name is None: + arguments.append(args[i]) + else: + options[name] = args[i] + name = None + + return arguments, options def check_args(self, args): """ @@ -274,7 +275,6 @@ class TclCommand(object): """ # self.worker_task.emit({'fcn': self.exec_command_test, 'params': [text, False]}) - try: self.log.debug("TCL command '%s' executed." % str(self.__class__)) self.original_args = args diff --git a/tclCommands/TclCommandOpenExcellon.py b/tclCommands/TclCommandOpenExcellon.py index 69f8ce70..1733ccc5 100644 --- a/tclCommands/TclCommandOpenExcellon.py +++ b/tclCommands/TclCommandOpenExcellon.py @@ -47,4 +47,5 @@ class TclCommandOpenExcellon(TclCommandSignaled): filename = args.pop('filename') + args['plot'] = False self.app.open_excellon(filename, **args) diff --git a/tclCommands/TclCommandOpenGCode.py b/tclCommands/TclCommandOpenGCode.py index 99314365..a1643403 100644 --- a/tclCommands/TclCommandOpenGCode.py +++ b/tclCommands/TclCommandOpenGCode.py @@ -45,5 +45,5 @@ class TclCommandOpenGCode(TclCommandSignaled): without -somename and we do not have them in known arg_names :return: None or exception """ - + args['plot'] = False self.app.open_gcode(args['filename'], **args) diff --git a/tclCommands/TclCommandOpenGerber.py b/tclCommands/TclCommandOpenGerber.py index 16e82b2a..dbf5e4b9 100644 --- a/tclCommands/TclCommandOpenGerber.py +++ b/tclCommands/TclCommandOpenGerber.py @@ -30,7 +30,7 @@ class TclCommandOpenGerber(TclCommandSignaled): ('filename', 'Path to file to open.'), ('outname', 'Name of the resulting Gerber object.') ]), - 'examples': [] + 'examples': ["open_gerber gerber_object_path -outname bla"] } def execute(self, args, unnamed_args): @@ -76,12 +76,13 @@ class TclCommandOpenGerber(TclCommandSignaled): outname = filename.split('/')[-1].split('\\')[-1] if 'follow' in args: - self.raise_tcl_error("The 'follow' parameter is obsolete. To create 'follow' geometry use the 'follow' parameter for the Tcl Command isolate()") + self.raise_tcl_error("The 'follow' parameter is obsolete. To create 'follow' geometry use the 'follow' " + "parameter for the Tcl Command isolate()") with self.app.proc_container.new("Opening Gerber"): # Object creation - self.app.new_object("gerber", outname, obj_init) + self.app.new_object("gerber", outname, obj_init, plot=False) # Register recent file self.app.file_opened.emit("gerber", filename) diff --git a/tclCommands/TclCommandOpenProject.py b/tclCommands/TclCommandOpenProject.py index 97d39ad6..02c74bbf 100644 --- a/tclCommands/TclCommandOpenProject.py +++ b/tclCommands/TclCommandOpenProject.py @@ -43,5 +43,5 @@ class TclCommandOpenProject(TclCommandSignaled): without -somename and we do not have them in known arg_names :return: None or exception """ - - self.app.open_project(args['filename']) + filename = args['filename'] + self.app.open_project(filename, cli=True, plot=False) diff --git a/tclCommands/TclCommandPlot.py b/tclCommands/TclCommandPlotAll.py similarity index 94% rename from tclCommands/TclCommandPlot.py rename to tclCommands/TclCommandPlotAll.py index d9d045b0..349eeb2f 100644 --- a/tclCommands/TclCommandPlot.py +++ b/tclCommands/TclCommandPlotAll.py @@ -2,7 +2,7 @@ from ObjectCollection import * from tclCommands.TclCommand import TclCommand -class TclCommandPlot(TclCommand): +class TclCommandPlotAll(TclCommand): """ Tcl shell command to update the plot on the user interface. @@ -11,7 +11,7 @@ class TclCommandPlot(TclCommand): """ # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) - aliases = ['plot'] + aliases = ['plot_all'] # Dictionary of types from Tcl command, needs to be ordered arg_names = collections.OrderedDict([ diff --git a/tclCommands/TclCommandPlotObjects.py b/tclCommands/TclCommandPlotObjects.py new file mode 100644 index 00000000..f7a418d7 --- /dev/null +++ b/tclCommands/TclCommandPlotObjects.py @@ -0,0 +1,51 @@ +from ObjectCollection import * +from tclCommands.TclCommand import TclCommand + + +class TclCommandPlotObjects(TclCommand): + """ + Tcl shell command to update the plot on the user interface. + + example: + plot + """ + + # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + aliases = ['plot_objects'] + + # Dictionary of types from Tcl command, needs to be ordered + arg_names = collections.OrderedDict([ + ('names', str) + ]) + + # Dictionary of types from Tcl command, needs to be ordered , this is 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': "Plot a list of objects.", + 'args': collections.OrderedDict([ + ('names', "UA list of object names to be plotted.") + ]), + 'examples': ["plot_objects"] + } + + def execute(self, args, unnamed_args): + """ + + :param args: + :param unnamed_args: + :return: + """ + names = [x.strip() for x in args['names'].split(",")] + objs = [] + for name in names: + objs.append(self.app.collection.get_by_name(name)) + + for obj in objs: + obj.plot() diff --git a/tclCommands/__init__.py b/tclCommands/__init__.py index 26f5c2e3..ae64e146 100644 --- a/tclCommands/__init__.py +++ b/tclCommands/__init__.py @@ -44,7 +44,8 @@ import tclCommands.TclCommandOpenProject import tclCommands.TclCommandOptions import tclCommands.TclCommandPaint import tclCommands.TclCommandPanelize -import tclCommands.TclCommandPlot +import tclCommands.TclCommandPlotAll +import tclCommands.TclCommandPlotObjects import tclCommands.TclCommandSaveProject import tclCommands.TclCommandSaveSys import tclCommands.TclCommandScale