Kaynağa Gözat

Merged in marius_stanciu/flatcam_beta/Beta (pull request #206)

Beta - Fixed a lot of Tcl Commands
Marius Stanciu 6 yıl önce
ebeveyn
işleme
279c2d6cc4
37 değiştirilmiş dosya ile 485 ekleme ve 200 silme
  1. 102 58
      FlatCAMApp.py
  2. 49 37
      FlatCAMObj.py
  3. 1 1
      ObjectCollection.py
  4. 16 0
      README.md
  5. 3 2
      flatcamTools/ToolNonCopperClear.py
  6. 35 16
      flatcamTools/ToolPaint.py
  7. 28 30
      tclCommands/TclCommand.py
  8. 13 7
      tclCommands/TclCommandAlignDrill.py
  9. 11 5
      tclCommands/TclCommandAlignDrillGrid.py
  10. 1 1
      tclCommands/TclCommandBbox.py
  11. 3 2
      tclCommands/TclCommandCncjob.py
  12. 2 0
      tclCommands/TclCommandCopperClear.py
  13. 1 1
      tclCommands/TclCommandCutout.py
  14. 1 1
      tclCommands/TclCommandDrillcncjob.py
  15. 1 1
      tclCommands/TclCommandExteriors.py
  16. 2 2
      tclCommands/TclCommandGeoCutout.py
  17. 1 1
      tclCommands/TclCommandImportSvg.py
  18. 1 1
      tclCommands/TclCommandIsolate.py
  19. 1 1
      tclCommands/TclCommandJoinExcellon.py
  20. 1 1
      tclCommands/TclCommandJoinGeometry.py
  21. 1 1
      tclCommands/TclCommandMillDrills.py
  22. 1 1
      tclCommands/TclCommandMillSlots.py
  23. 0 1
      tclCommands/TclCommandMirror.py
  24. 1 1
      tclCommands/TclCommandNew.py
  25. 51 0
      tclCommands/TclCommandNewExcellon.py
  26. 6 4
      tclCommands/TclCommandNewGeometry.py
  27. 68 0
      tclCommands/TclCommandNewGerber.py
  28. 1 1
      tclCommands/TclCommandNregions.py
  29. 2 0
      tclCommands/TclCommandOpenExcellon.py
  30. 4 1
      tclCommands/TclCommandOpenGCode.py
  31. 5 12
      tclCommands/TclCommandOpenGerber.py
  32. 3 1
      tclCommands/TclCommandOpenProject.py
  33. 9 3
      tclCommands/TclCommandPaint.py
  34. 3 3
      tclCommands/TclCommandPanelize.py
  35. 2 2
      tclCommands/TclCommandPlotAll.py
  36. 51 0
      tclCommands/TclCommandPlotObjects.py
  37. 4 1
      tclCommands/__init__.py

+ 102 - 58
FlatCAMApp.py

@@ -844,6 +844,22 @@ class App(QtCore.QObject):
             "global_point_clipboard_format": "(%.4f, %.4f)",
             "global_point_clipboard_format": "(%.4f, %.4f)",
             "global_zdownrate": None,
             "global_zdownrate": None,
 
 
+            # autocomplete keywords
+            "global_autocomplete_keywords":
+                ['all', 'angle_x', 'angle_y', 'axis', 'axisoffset', 'box', 'center_x', 'center_y',
+                 'columns', 'combine', 'connect', 'contour', 'depthperpass', 'dia', 'diatol', 'dist',
+                 'drilled_dias', 'drillz', 'pp',
+                 'gridoffsety', 'gridx', 'gridy', 'has_offset', 'holes', 'margin', 'method',
+                 'milled_dias',
+                 'minoffset', 'multidepth', 'name', 'offset', 'opt_type', 'order', 'outname',
+                 'overlap', 'passes', 'postamble', 'ppname_e', 'ppname_g', 'preamble', 'radius', 'ref',
+                 'rest', 'rows', 'scale_factor', 'spacing_columns', 'spacing_rows', 'spindlespeed',
+                 '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',
+                 'Desktop', 'FlatPrj', 'FlatConfig', 'Users', 'Documents', 'My Documents', 'Marius'
+                 ],
             # General GUI Settings
             # General GUI Settings
             "global_hover": False,
             "global_hover": False,
             "global_selection_shape": True,
             "global_selection_shape": True,
@@ -1898,27 +1914,13 @@ class App(QtCore.QObject):
                                   'mirror', 'ncc',
                                   'mirror', 'ncc',
                                   'ncc_clear', 'ncr', 'new', 'new_geometry', 'non_copper_regions', 'offset',
                                   'ncc_clear', 'ncr', 'new', 'new_geometry', 'non_copper_regions', 'offset',
                                   'open_excellon', 'open_gcode', 'open_gerber', 'open_project', 'options', 'paint',
                                   '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',
                                   'set_active', 'set_sys', 'setsys', 'skew', 'subtract_poly', 'subtract_rectangle',
                                   'version', 'write_gcode'
                                   'version', 'write_gcode'
                                   ]
                                   ]
 
 
-        self.ordinary_keywords = ['all', 'angle_x', 'angle_y', 'axis', 'axisoffset', 'box', 'center_x', 'center_y',
-                                  'columns', 'combine', 'connect', 'contour', 'depthperpass', 'dia', 'diatol', 'dist',
-                                  'drilled_dias', 'drillz', 'pp',
-                                  'endz', 'extracut', 'factor', 'False', 'false', 'feedrate', 'feedrate_rapid',
-                                  'filename', 'follow', 'gaps', 'gapsize', 'grid', 'gridoffset', 'gridoffsetx',
-                                  'gridoffsety', 'gridx', 'gridy', 'has_offset', 'holes', 'margin', 'method',
-                                  'milled_dias',
-                                  'minoffset', 'multidepth', 'name', 'offset', 'opt_type', 'order', 'outname',
-                                  'overlap', 'passes', 'postamble', 'ppname_e', 'ppname_g', 'preamble', 'radius', 'ref',
-                                  'rest', 'rows', 'scale_factor', 'spacing_columns', 'spacing_rows', 'spindlespeed',
-                                  'toolchange', 'toolchangez', 'tooldia', 'tools', 'travelz', 'True', 'true', 'type',
-                                  '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'
-                                  ]
+        self.ordinary_keywords = self.defaults["global_autocomplete_keywords"]
 
 
         self.tcl_keywords = [
         self.tcl_keywords = [
             'after', 'append', 'apply', 'argc', 'argv', 'argv0', 'array', 'attemptckalloc', 'attemptckrealloc',
             'after', 'append', 'apply', 'argc', 'argv', 'argv0', 'array', 'attemptckalloc', 'attemptckrealloc',
@@ -2253,6 +2255,10 @@ class App(QtCore.QObject):
         # Variable to store the GCODE that was edited
         # Variable to store the GCODE that was edited
         self.gcode_edited = ""
         self.gcode_edited = ""
 
 
+        # reference for the self.ui.code_editor
+        self.reference_code_editor = None
+        self.script_code = ''
+
         # if Preferences are changed in the Edit -> Preferences tab the value will be set to True
         # if Preferences are changed in the Edit -> Preferences tab the value will be set to True
         self.preferences_changed_flag = False
         self.preferences_changed_flag = False
 
 
@@ -3062,8 +3068,8 @@ class App(QtCore.QObject):
         result = self.exec_command_test(text, False)
         result = self.exec_command_test(text, False)
 
 
         # MS: added this method call so the geometry is updated once the TCL command is executed
         # 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
         return result
 
 
@@ -5913,11 +5919,11 @@ class App(QtCore.QObject):
         if self.ui.shell_dock.isHidden():
         if self.ui.shell_dock.isHidden():
             self.ui.shell_dock.show()
             self.ui.shell_dock.show()
 
 
-        script_code = self.ui.code_editor.toPlainText()
+        self.script_code = deepcopy(self.ui.code_editor.toPlainText())
         # self.shell._sysShell.exec_command(script_code)
         # self.shell._sysShell.exec_command(script_code)
 
 
         old_line = ''
         old_line = ''
-        for tcl_command_line in script_code.splitlines():
+        for tcl_command_line in self.script_code.splitlines():
             # do not process lines starting with '#' = comment and empty lines
             # do not process lines starting with '#' = comment and empty lines
             if not tcl_command_line.startswith('#') and tcl_command_line != '':
             if not tcl_command_line.startswith('#') and tcl_command_line != '':
                 # id FlatCAM is run in Windows then replace all the slashes with
                 # id FlatCAM is run in Windows then replace all the slashes with
@@ -5940,17 +5946,16 @@ class App(QtCore.QObject):
                         self.shell.append_output(result + '\n')
                         self.shell.append_output(result + '\n')
 
 
                     old_line = ''
                     old_line = ''
-                except tk.TclError as e:
+                except tk.TclError:
                     old_line = old_line + tcl_command_line + '\n'
                     old_line = old_line + tcl_command_line + '\n'
+                except Exception as e:
+                    log.debug("App.handleRunCode() --> %s" % str(e))
 
 
         if old_line != '':
         if old_line != '':
             # it means that the script finished with an error
             # it means that the script finished with an error
             result = self.tcl.eval("set errorInfo")
             result = self.tcl.eval("set errorInfo")
             self.log.error("Exec command Exception: %s" % (result + '\n'))
             self.log.error("Exec command Exception: %s" % (result + '\n'))
             self.shell.append_error('ERROR: ' + result + '\n')
             self.shell.append_error('ERROR: ' + result + '\n')
-        else:
-            # success! plot all objects
-            self.plot_all()
 
 
         self.shell.close_proccessing()
         self.shell.close_proccessing()
 
 
@@ -7520,7 +7525,7 @@ class App(QtCore.QObject):
         self.inform.emit('[success] %s...' %
         self.inform.emit('[success] %s...' %
                          _("New Project created"))
                          _("New Project created"))
 
 
-    def on_file_new(self):
+    def on_file_new(self, cli=None):
         """
         """
         Callback for menu item File->New. Returns the application to its
         Callback for menu item File->New. Returns the application to its
         startup state. This method is thread-safe.
         startup state. This method is thread-safe.
@@ -7580,15 +7585,16 @@ class App(QtCore.QObject):
         # Init Tools
         # Init Tools
         self.init_tools()
         self.init_tools()
 
 
-        # Close any Tabs opened in the Plot Tab Area section
-        for index in range(self.ui.plot_tab_area.count()):
-            self.ui.plot_tab_area.closeTab(index)
-            # for whatever reason previous command does not close the last tab so I do it manually
-        self.ui.plot_tab_area.closeTab(0)
+        if cli is None:
+            # Close any Tabs opened in the Plot Tab Area section
+            for index in range(self.ui.plot_tab_area.count()):
+                self.ui.plot_tab_area.closeTab(index)
+                # for whatever reason previous command does not close the last tab so I do it manually
+            self.ui.plot_tab_area.closeTab(0)
 
 
-        # # And then add again the Plot Area
-        self.ui.plot_tab_area.addTab(self.ui.plot_tab, "Plot Area")
-        self.ui.plot_tab_area.protectTab(0)
+            # # And then add again the Plot Area
+            self.ui.plot_tab_area.addTab(self.ui.plot_tab, "Plot Area")
+            self.ui.plot_tab_area.protectTab(0)
 
 
         # take the focus of the Notebook on Project Tab.
         # take the focus of the Notebook on Project Tab.
         self.ui.notebook.setCurrentWidget(self.ui.project_tab)
         self.ui.notebook.setCurrentWidget(self.ui.project_tab)
@@ -8199,6 +8205,9 @@ class App(QtCore.QObject):
         self.ui.code_editor.completer_enable = False
         self.ui.code_editor.completer_enable = False
         self.ui.buttonRun.hide()
         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
         # Switch plot_area to CNCJob tab
         self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
         self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
 
 
@@ -8217,20 +8226,34 @@ class App(QtCore.QObject):
 
 
         if obj.kind == 'gerber':
         if obj.kind == 'gerber':
             flt = "Gerber Files (*.GBR);;All Files (*.*)"
             flt = "Gerber Files (*.GBR);;All Files (*.*)"
-        else:
+        elif obj.kind == 'excellon':
             flt = "Excellon Files (*.DRL);;All Files (*.*)"
             flt = "Excellon Files (*.DRL);;All Files (*.*)"
+        elif obj.kind == 'cncjob':
+            "GCode Files (*.NC);;All Files (*.*)"
+        else:
+            flt = "All Files (*.*)"
 
 
         self.init_code_editor(name=_("Source Editor"))
         self.init_code_editor(name=_("Source Editor"))
         self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
         self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
         self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
         self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
 
 
         # then append the text from GCode to the text editor
         # then append the text from GCode to the text editor
-        try:
-            file = StringIO(obj.source_file)
-        except AttributeError:
-            self.inform.emit('[WARNING_NOTCL] %s' %
-                             _("There is no selected object for which to see it's source file code."))
-            return 'fail'
+        if obj.kind == 'cncjob':
+            try:
+                file = obj.export_gcode(preamble='', postamble='', to_file=True)
+                if file == 'fail':
+                    return 'fail'
+            except AttributeError:
+                self.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("There is no selected object for which to see it's source file code."))
+                return 'fail'
+        else:
+            try:
+                file = StringIO(obj.source_file)
+            except AttributeError:
+                self.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("There is no selected object for which to see it's source file code."))
+                return 'fail'
 
 
         self.ui.cncjob_frame.hide()
         self.ui.cncjob_frame.hide()
         try:
         try:
@@ -8287,6 +8310,10 @@ class App(QtCore.QObject):
         self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
         self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
         self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
         self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
         self.ui.buttonRun.show()
         self.ui.buttonRun.show()
+        try:
+            self.ui.buttonRun.clicked.disconnect(self.handleRunCode)
+        except TypeError:
+            pass
         self.ui.buttonRun.clicked.connect(self.handleRunCode)
         self.ui.buttonRun.clicked.connect(self.handleRunCode)
 
 
         self.handleTextChanged()
         self.handleTextChanged()
@@ -9373,7 +9400,7 @@ class App(QtCore.QObject):
             self.inform.emit('[success] %s: %s' %
             self.inform.emit('[success] %s: %s' %
                              (_("Opened"), filename))
                              (_("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
         Opens an Excellon file, parses it and creates a new object for
         it in the program. Thread-safe.
         it in the program. Thread-safe.
@@ -9427,7 +9454,7 @@ class App(QtCore.QObject):
 
 
             # Object name
             # Object name
             name = outname or filename.split('/')[-1].split('\\')[-1]
             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':
             if ret_val == 'fail':
                 self.inform.emit('[ERROR_NOTCL] %s' %
                 self.inform.emit('[ERROR_NOTCL] %s' %
                                  _('Open Excellon file failed. Probable not an Excellon file.'))
                                  _('Open Excellon file failed. Probable not an Excellon file.'))
@@ -9440,7 +9467,7 @@ class App(QtCore.QObject):
             self.inform.emit('[success] %s: %s' %
             self.inform.emit('[success] %s: %s' %
                              (_("Opened"), filename))
                              (_("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
         Opens a G-gcode file, parses it and creates a new object for
         it in the program. Thread-safe.
         it in the program. Thread-safe.
@@ -9492,7 +9519,7 @@ class App(QtCore.QObject):
             name = outname or filename.split('/')[-1].split('\\')[-1]
             name = outname or filename.split('/')[-1].split('\\')[-1]
 
 
             # New object creation and file processing
             # 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':
             if ret == 'fail':
                 self.inform.emit('[ERROR_NOTCL] %s' %
                 self.inform.emit('[ERROR_NOTCL] %s' %
                                  _("Failed to create CNCJob Object. Probable not a GCode file.\n "
                                  _("Failed to create CNCJob Object. Probable not a GCode file.\n "
@@ -9540,7 +9567,7 @@ class App(QtCore.QObject):
                              (_("Failed to open config file"), filename))
                              (_("Failed to open config file"), filename))
             return
             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.
         Loads a project from the specified file.
 
 
@@ -9549,16 +9576,21 @@ class App(QtCore.QObject):
         3) Calls on_file_new()
         3) Calls on_file_new()
         4) Updates options
         4) Updates options
         5) Calls new_object() with the object's from_dict() as init method.
         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.
         :param filename:  Name of the file from which to load.
         :type filename: str
         :type filename: str
         :param run_from_arg: True if run for arguments
         :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
         :return: None
         """
         """
         App.log.debug("Opening project: " + filename)
         App.log.debug("Opening project: " + filename)
 
 
-        self.set_ui_title(name=_("Loading Project ... Please Wait ..."))
+        # 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 ..."))
 
 
         # Open and parse an uncompressed Project file
         # Open and parse an uncompressed Project file
         try:
         try:
@@ -9581,7 +9613,6 @@ class App(QtCore.QObject):
                 with lzma.open(filename) as f:
                 with lzma.open(filename) as f:
                     file_content = f.read().decode('utf-8')
                     file_content = f.read().decode('utf-8')
                     d = json.loads(file_content, object_hook=dict2obj)
                     d = json.loads(file_content, object_hook=dict2obj)
-
             except Exception as e:
             except Exception as e:
                 App.log.error("Failed to open project file: %s with error: %s" % (filename, str(e)))
                 App.log.error("Failed to open project file: %s with error: %s" % (filename, str(e)))
                 self.inform.emit('[ERROR_NOTCL] %s: %s' %
                 self.inform.emit('[ERROR_NOTCL] %s: %s' %
@@ -9592,13 +9623,19 @@ class App(QtCore.QObject):
         # # NOT THREAD SAFE # ##
         # # NOT THREAD SAFE # ##
         if run_from_arg is True:
         if run_from_arg is True:
             pass
             pass
+        elif cli is True:
+            self.delete_selection_shape()
         else:
         else:
             self.on_file_new()
             self.on_file_new()
 
 
         # Project options
         # Project options
         self.options.update(d['options'])
         self.options.update(d['options'])
         self.project_filename = filename
         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
         # Re create objects
         App.log.debug(" **************** Started PROEJCT loading... **************** ")
         App.log.debug(" **************** Started PROEJCT loading... **************** ")
@@ -9606,24 +9643,31 @@ class App(QtCore.QObject):
         for obj in d['objs']:
         for obj in d['objs']:
             def obj_init(obj_inst, app_inst):
             def obj_init(obj_inst, app_inst):
                 obj_inst.from_dict(obj)
                 obj_inst.from_dict(obj)
+
             App.log.debug("Recreating from opened project an %s object: %s" %
             App.log.debug("Recreating from opened project an %s object: %s" %
                           (obj['kind'].capitalize(), obj['options']['name']))
                           (obj['kind'].capitalize(), obj['options']['name']))
 
 
-            self.set_ui_title(name="{} {}: {}".format(_("Loading Project ... restoring"),
-                                                      obj['kind'].upper(),
-                                                      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(),
+                                                          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' %
         self.inform.emit('[success] %s: %s' %
                          (_("Project loaded from"), filename))
                          (_("Project loaded from"), filename))
 
 
         self.should_we_save = False
         self.should_we_save = False
         self.file_opened.emit("project", filename)
         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... **************** ")
         App.log.debug(" **************** Finished PROJECT loading... **************** ")
 
 

+ 49 - 37
FlatCAMObj.py

@@ -923,8 +923,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         except Exception as e:
         except Exception as e:
             return "Operation failed: %s" % str(e)
             return "Operation failed: %s" % str(e)
 
 
-    def isolate(self, iso_type=None, dia=None, passes=None, overlap=None,
-                outname=None, combine=None, milling_type=None, follow=None):
+    def isolate(self, iso_type=None, dia=None, passes=None, overlap=None, outname=None, combine=None,
+                milling_type=None, follow=None, plot=True):
         """
         """
         Creates an isolation routing geometry object in the project.
         Creates an isolation routing geometry object in the project.
 
 
@@ -947,13 +947,13 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             combine = bool(combine)
             combine = bool(combine)
         if milling_type is None:
         if milling_type is None:
             milling_type = self.options["milling_type"]
             milling_type = self.options["milling_type"]
+
         if iso_type is None:
         if iso_type is None:
             self.iso_type = 2
             self.iso_type = 2
         else:
         else:
             self.iso_type = iso_type
             self.iso_type = iso_type
 
 
-        base_name = self.options["name"] + "_iso"
-        base_name = outname or base_name
+        base_name = self.options["name"]
 
 
         def generate_envelope(offset, invert, envelope_iso_type=2, follow=None, passes=0):
         def generate_envelope(offset, invert, envelope_iso_type=2, follow=None, passes=0):
             # isolation_geometry produces an envelope that is going on the left of the geometry
             # isolation_geometry produces an envelope that is going on the left of the geometry
@@ -1061,12 +1061,15 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             return new_geometry
             return new_geometry
 
 
         if combine:
         if combine:
-            if self.iso_type == 0:
-                iso_name = self.options["name"] + "_ext_iso"
-            elif self.iso_type == 1:
-                iso_name = self.options["name"] + "_int_iso"
+            if outname is None:
+                if self.iso_type == 0:
+                    iso_name = base_name + "_ext_iso"
+                elif self.iso_type == 1:
+                    iso_name = base_name + "_int_iso"
+                else:
+                    iso_name = base_name + "_iso"
             else:
             else:
-                iso_name = base_name
+                iso_name = outname
 
 
             # TODO: This is ugly. Create way to pass data into init function.
             # TODO: This is ugly. Create way to pass data into init function.
             def iso_init(geo_obj, app_obj):
             def iso_init(geo_obj, app_obj):
@@ -1161,25 +1164,31 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                     geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
                     geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
 
 
             # TODO: Do something if this is None. Offer changing name?
             # TODO: Do something if this is None. Offer changing name?
-            self.app.new_object("geometry", iso_name, iso_init)
+            self.app.new_object("geometry", iso_name, iso_init, plot=plot)
         else:
         else:
             for i in range(passes):
             for i in range(passes):
 
 
                 offset = dia * ((2 * i + 1) / 2.0) - (i * overlap * dia)
                 offset = dia * ((2 * i + 1) / 2.0) - (i * overlap * dia)
                 if passes > 1:
                 if passes > 1:
-                    if self.iso_type == 0:
-                        iso_name = self.options["name"] + "_ext_iso" + str(i + 1)
-                    elif self.iso_type == 1:
-                        iso_name = self.options["name"] + "_int_iso" + str(i + 1)
+                    if outname is None:
+                        if self.iso_type == 0:
+                            iso_name = base_name + "_ext_iso" + str(i + 1)
+                        elif self.iso_type == 1:
+                            iso_name = base_name + "_int_iso" + str(i + 1)
+                        else:
+                            iso_name = base_name + "_iso" + str(i + 1)
                     else:
                     else:
-                        iso_name = base_name + str(i + 1)
+                        iso_name = outname
                 else:
                 else:
-                    if self.iso_type == 0:
-                        iso_name = self.options["name"] + "_ext_iso"
-                    elif self.iso_type == 1:
-                        iso_name = self.options["name"] + "_int_iso"
+                    if outname is None:
+                        if self.iso_type == 0:
+                            iso_name = base_name + "_ext_iso"
+                        elif self.iso_type == 1:
+                            iso_name = base_name + "_int_iso"
+                        else:
+                            iso_name = base_name + "_iso"
                     else:
                     else:
-                        iso_name = base_name
+                        iso_name = outname
 
 
                 # TODO: This is ugly. Create way to pass data into init function.
                 # TODO: This is ugly. Create way to pass data into init function.
                 def iso_init(geo_obj, app_obj):
                 def iso_init(geo_obj, app_obj):
@@ -1230,7 +1239,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                         geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
                         geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
 
 
                 # TODO: Do something if this is None. Offer changing name?
                 # TODO: Do something if this is None. Offer changing name?
-                self.app.new_object("geometry", iso_name, iso_init)
+                self.app.new_object("geometry", iso_name, iso_init, plot=plot)
 
 
     def on_plot_cb_click(self, *args):
     def on_plot_cb_click(self, *args):
         if self.muted_ui:
         if self.muted_ui:
@@ -2595,7 +2604,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
 
         return has_slots, excellon_code
         return has_slots, excellon_code
 
 
-    def generate_milling_drills(self, tools=None, outname=None, tooldia=None, use_thread=False):
+    def generate_milling_drills(self, tools=None, outname=None, tooldia=None, plot=False, use_thread=False):
         """
         """
         Note: This method is a good template for generic operations as
         Note: This method is a good template for generic operations as
         it takes it's options from parameters or otherwise from the
         it takes it's options from parameters or otherwise from the
@@ -2674,7 +2683,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
                             Point(hole['point']).buffer(buffer_value).exterior)
                             Point(hole['point']).buffer(buffer_value).exterior)
         if use_thread:
         if use_thread:
             def geo_thread(app_obj):
             def geo_thread(app_obj):
-                app_obj.new_object("geometry", outname, geo_init)
+                app_obj.new_object("geometry", outname, geo_init, plot=plot)
                 app_obj.progress.emit(100)
                 app_obj.progress.emit(100)
 
 
             # Create a promise with the new name
             # Create a promise with the new name
@@ -2683,11 +2692,11 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
             # Send to worker
             # Send to worker
             self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
             self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
         else:
         else:
-            self.app.new_object("geometry", outname, geo_init)
+            self.app.new_object("geometry", outname, geo_init, plot=plot)
 
 
         return True, ""
         return True, ""
 
 
-    def generate_milling_slots(self, tools=None, outname=None, tooldia=None, use_thread=False):
+    def generate_milling_slots(self, tools=None, outname=None, tooldia=None, plot=True, use_thread=False):
         """
         """
         Note: This method is a good template for generic operations as
         Note: This method is a good template for generic operations as
         it takes it's options from parameters or otherwise from the
         it takes it's options from parameters or otherwise from the
@@ -2781,7 +2790,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
 
         if use_thread:
         if use_thread:
             def geo_thread(app_obj):
             def geo_thread(app_obj):
-                app_obj.new_object("geometry", outname + '_slot', geo_init)
+                app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
                 app_obj.progress.emit(100)
                 app_obj.progress.emit(100)
 
 
             # Create a promise with the new name
             # Create a promise with the new name
@@ -2790,7 +2799,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
             # Send to worker
             # Send to worker
             self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
             self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
         else:
         else:
-            self.app.new_object("geometry", outname + '_slot', geo_init)
+            self.app.new_object("geometry", outname + '_slot', geo_init, plot=plot)
 
 
         return True, ""
         return True, ""
 
 
@@ -4518,7 +4527,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             self.app.inform.emit('[ERROR_NOTCL] %s' %
             self.app.inform.emit('[ERROR_NOTCL] %s' %
                                  _("Failed. No tool selected in the tool table ..."))
                                  _("Failed. No tool selected in the tool table ..."))
 
 
-    def mtool_gen_cncjob(self, outname=None, tools_dict=None, tools_in_use=None, segx=None, segy=None, use_thread=True):
+    def mtool_gen_cncjob(self, outname=None, tools_dict=None, tools_in_use=None, segx=None, segy=None,
+                         plot=True, use_thread=True):
         """
         """
         Creates a multi-tool CNCJob out of this Geometry object.
         Creates a multi-tool CNCJob out of this Geometry object.
         The actual work is done by the target FlatCAMCNCjob object's
         The actual work is done by the target FlatCAMCNCjob object's
@@ -4875,7 +4885,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             def job_thread(app_obj):
             def job_thread(app_obj):
                 if self.solid_geometry:
                 if self.solid_geometry:
                     with self.app.proc_container.new(_("Generating CNC Code")):
                     with self.app.proc_container.new(_("Generating CNC Code")):
-                        if app_obj.new_object("cncjob", outname, job_init_single_geometry) != 'fail':
+                        if app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
                             app_obj.inform.emit('[success] %s: %s' %
                             app_obj.inform.emit('[success] %s: %s' %
                                                 (_("CNCjob created")), outname)
                                                 (_("CNCjob created")), outname)
                             app_obj.progress.emit(100)
                             app_obj.progress.emit(100)
@@ -4892,9 +4902,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
             self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
         else:
         else:
             if self.solid_geometry:
             if self.solid_geometry:
-                self.app.new_object("cncjob", outname, job_init_single_geometry)
+                self.app.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
             else:
             else:
-                self.app.new_object("cncjob", outname, job_init_multi_geometry)
+                self.app.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
 
 
     def generatecncjob(
     def generatecncjob(
             self, outname=None,
             self, outname=None,
@@ -4907,7 +4917,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             extracut=None, startz=None, endz=None,
             extracut=None, startz=None, endz=None,
             ppname_g=None,
             ppname_g=None,
             segx=None, segy=None,
             segx=None, segy=None,
-            use_thread=True):
+            use_thread=True,
+            plot=True):
         """
         """
         Only used for TCL Command.
         Only used for TCL Command.
         Creates a CNCJob out of this Geometry object. The actual
         Creates a CNCJob out of this Geometry object. The actual
@@ -5034,7 +5045,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             # To be run in separate thread
             # To be run in separate thread
             def job_thread(app_obj):
             def job_thread(app_obj):
                 with self.app.proc_container.new(_("Generating CNC Code")):
                 with self.app.proc_container.new(_("Generating CNC Code")):
-                    app_obj.new_object("cncjob", outname, job_init)
+                    app_obj.new_object("cncjob", outname, job_init, plot=plot)
                     app_obj.inform.emit('[success] %s: %s' %
                     app_obj.inform.emit('[success] %s: %s' %
                                         (_("CNCjob created")), outname)
                                         (_("CNCjob created")), outname)
                     app_obj.progress.emit(100)
                     app_obj.progress.emit(100)
@@ -5044,7 +5055,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             # Send to worker
             # Send to worker
             self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
             self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
         else:
         else:
-            self.app.new_object("cncjob", outname, job_init)
+            self.app.new_object("cncjob", outname, job_init, plot=plot)
 
 
     # def on_plot_cb_click(self, *args):  # TODO: args not needed
     # def on_plot_cb_click(self, *args):  # TODO: args not needed
     #     if self.muted_ui:
     #     if self.muted_ui:
@@ -5833,11 +5844,12 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
 
 
         preamble = str(self.ui.prepend_text.get_value())
         preamble = str(self.ui.prepend_text.get_value())
         postamble = str(self.ui.append_text.get_value())
         postamble = str(self.ui.append_text.get_value())
-        gc = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True)
-        if gc == 'fail':
+
+        gco = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True)
+        if gco == 'fail':
             return
             return
         else:
         else:
-            self.app.gcode_edited = gc
+            self.app.gcode_edited = gco
 
 
         self.app.init_code_editor(name=_("Code Editor"))
         self.app.init_code_editor(name=_("Code Editor"))
         self.app.ui.buttonOpen.clicked.connect(self.app.handleOpen)
         self.app.ui.buttonOpen.clicked.connect(self.app.handleOpen)

+ 1 - 1
ObjectCollection.py

@@ -320,7 +320,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
                     self.app.ui.menuprojectgeneratecnc.setVisible(False)
                     self.app.ui.menuprojectgeneratecnc.setVisible(False)
                 if type(obj) != FlatCAMGeometry and type(obj) != FlatCAMExcellon and type(obj) != FlatCAMGerber:
                 if type(obj) != FlatCAMGeometry and type(obj) != FlatCAMExcellon and type(obj) != FlatCAMGerber:
                     self.app.ui.menuprojectedit.setVisible(False)
                     self.app.ui.menuprojectedit.setVisible(False)
-                if type(obj) != FlatCAMGerber and type(obj) != FlatCAMExcellon:
+                if type(obj) != FlatCAMGerber and type(obj) != FlatCAMExcellon and type(obj) != FlatCAMCNCjob:
                     self.app.ui.menuprojectviewsource.setVisible(False)
                     self.app.ui.menuprojectviewsource.setVisible(False)
         else:
         else:
             self.app.ui.menuprojectgeneratecnc.setVisible(False)
             self.app.ui.menuprojectgeneratecnc.setVisible(False)

+ 16 - 0
README.md

@@ -9,6 +9,10 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+16.09.2019
+
+- modified the TclCommand New so it will no longer close all tabs when called (it closed the Code Editor tab which may have been holding the code that run)
+
 15.09.2019
 15.09.2019
 
 
 - refactored FlatCAMGeometry.mtool_gen_cncjob() method
 - refactored FlatCAMGeometry.mtool_gen_cncjob() method
@@ -19,6 +23,18 @@ CAD program, and create G-Code for Isolation routing.
 - finished updating the TclCommand cncjob to work for multi-geo Geometry objects with the parameters from the args
 - finished updating the TclCommand cncjob to work for multi-geo Geometry objects with the parameters from the args
 - fixed the TclCommand cncjob to use the -outname parameter
 - fixed the TclCommand cncjob to use the -outname parameter
 - added some more keywords in the data_model for auto-completer
 - 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 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
+- added the outname parameter (and established an default name when outname not used) for the AlignDrillGrid and AlignDrill TclCommands
+- fixed Scripts repeating multiple time when the Code Editor is used. This repetition was correlated with multiple openings of the Code Editor window (especially after an error)
+- added the autocomplete keywords that can be changed to the defaults dictionary
 
 
 14.09.2019
 14.09.2019
 
 

+ 3 - 2
flatcamTools/ToolNonCopperClear.py

@@ -1292,6 +1292,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                      method=None,
                      method=None,
                      rest=None,
                      rest=None,
                      tools_storage=None,
                      tools_storage=None,
+                     plot=True,
                      run_threaded=True):
                      run_threaded=True):
         """
         """
         Clear the excess copper from the entire object.
         Clear the excess copper from the entire object.
@@ -2189,9 +2190,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
         def job_thread(app_obj):
         def job_thread(app_obj):
             try:
             try:
                 if rest_machining_choice is True:
                 if rest_machining_choice is True:
-                    app_obj.new_object("geometry", name, gen_clear_area_rest)
+                    app_obj.new_object("geometry", name, gen_clear_area_rest, plot=plot)
                 else:
                 else:
-                    app_obj.new_object("geometry", name, gen_clear_area)
+                    app_obj.new_object("geometry", name, gen_clear_area, plot=plot)
             except FlatCAMApp.GracefulException:
             except FlatCAMApp.GracefulException:
                 proc.done()
                 proc.done()
                 return
                 return

+ 35 - 16
flatcamTools/ToolPaint.py

@@ -1168,7 +1168,9 @@ class ToolPaint(FlatCAMTool, Gerber):
                    outname=None,
                    outname=None,
                    connect=None,
                    connect=None,
                    contour=None,
                    contour=None,
-                   tools_storage=None):
+                   tools_storage=None,
+                   plot=True,
+                   run_threaded=True):
         """
         """
         Paints a polygon selected by clicking on its interior or by having a point coordinates given
         Paints a polygon selected by clicking on its interior or by having a point coordinates given
 
 
@@ -1432,7 +1434,7 @@ class ToolPaint(FlatCAMTool, Gerber):
 
 
         def job_thread(app_obj):
         def job_thread(app_obj):
             try:
             try:
-                app_obj.new_object("geometry", name, gen_paintarea)
+                app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
             except FlatCAMApp.GracefulException:
             except FlatCAMApp.GracefulException:
                 proc.done()
                 proc.done()
                 return
                 return
@@ -1451,8 +1453,11 @@ class ToolPaint(FlatCAMTool, Gerber):
         # Promise object with the new name
         # Promise object with the new name
         self.app.collection.promise(name)
         self.app.collection.promise(name)
 
 
-        # Background
-        self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
+        if run_threaded:
+            # Background
+            self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
+        else:
+            job_thread(app_obj=self.app)
 
 
     def paint_poly_all(self, obj,
     def paint_poly_all(self, obj,
                        tooldia=None,
                        tooldia=None,
@@ -1463,7 +1468,9 @@ class ToolPaint(FlatCAMTool, Gerber):
                        outname=None,
                        outname=None,
                        connect=None,
                        connect=None,
                        contour=None,
                        contour=None,
-                       tools_storage=None):
+                       tools_storage=None,
+                       plot=True,
+                       run_threaded=True):
         """
         """
         Paints all polygons in this object.
         Paints all polygons in this object.
 
 
@@ -1901,9 +1908,9 @@ class ToolPaint(FlatCAMTool, Gerber):
         def job_thread(app_obj):
         def job_thread(app_obj):
             try:
             try:
                 if self.rest_cb.isChecked():
                 if self.rest_cb.isChecked():
-                    app_obj.new_object("geometry", name, gen_paintarea_rest_machining)
+                    app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
                 else:
                 else:
-                    app_obj.new_object("geometry", name, gen_paintarea)
+                    app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
             except FlatCAMApp.GracefulException:
             except FlatCAMApp.GracefulException:
                 proc.done()
                 proc.done()
                 return
                 return
@@ -1920,8 +1927,11 @@ class ToolPaint(FlatCAMTool, Gerber):
         # Promise object with the new name
         # Promise object with the new name
         self.app.collection.promise(name)
         self.app.collection.promise(name)
 
 
-        # Background
-        self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
+        if run_threaded:
+            # Background
+            self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
+        else:
+            job_thread(app_obj=self.app)
 
 
     def paint_poly_area(self, obj, sel_obj,
     def paint_poly_area(self, obj, sel_obj,
                         tooldia=None,
                         tooldia=None,
@@ -1932,7 +1942,9 @@ class ToolPaint(FlatCAMTool, Gerber):
                         outname=None,
                         outname=None,
                         connect=None,
                         connect=None,
                         contour=None,
                         contour=None,
-                        tools_storage=None):
+                        tools_storage=None,
+                        plot=True,
+                        run_threaded=True):
         """
         """
         Paints all polygons in this object that are within the sel_obj object
         Paints all polygons in this object that are within the sel_obj object
 
 
@@ -2366,9 +2378,9 @@ class ToolPaint(FlatCAMTool, Gerber):
         def job_thread(app_obj):
         def job_thread(app_obj):
             try:
             try:
                 if self.rest_cb.isChecked():
                 if self.rest_cb.isChecked():
-                    app_obj.new_object("geometry", name, gen_paintarea_rest_machining)
+                    app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
                 else:
                 else:
-                    app_obj.new_object("geometry", name, gen_paintarea)
+                    app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
             except FlatCAMApp.GracefulException:
             except FlatCAMApp.GracefulException:
                 proc.done()
                 proc.done()
                 return
                 return
@@ -2385,8 +2397,11 @@ class ToolPaint(FlatCAMTool, Gerber):
         # Promise object with the new name
         # Promise object with the new name
         self.app.collection.promise(name)
         self.app.collection.promise(name)
 
 
-        # Background
-        self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
+        if run_threaded:
+            # Background
+            self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
+        else:
+            job_thread(app_obj=self.app)
 
 
     def paint_poly_ref(self, obj, sel_obj,
     def paint_poly_ref(self, obj, sel_obj,
                        tooldia=None,
                        tooldia=None,
@@ -2397,7 +2412,9 @@ class ToolPaint(FlatCAMTool, Gerber):
                        outname=None,
                        outname=None,
                        connect=None,
                        connect=None,
                        contour=None,
                        contour=None,
-                       tools_storage=None):
+                       tools_storage=None,
+                       plot=True,
+                       run_threaded=True):
         """
         """
         Paints all polygons in this object that are within the sel_obj object
         Paints all polygons in this object that are within the sel_obj object
 
 
@@ -2441,7 +2458,9 @@ class ToolPaint(FlatCAMTool, Gerber):
                              outname=outname,
                              outname=outname,
                              connect=connect,
                              connect=connect,
                              contour=contour,
                              contour=contour,
-                             tools_storage=tools_storage)
+                             tools_storage=tools_storage,
+                             plot=plot,
+                             run_threaded=run_threaded)
 
 
     @staticmethod
     @staticmethod
     def paint_bounds(geometry):
     def paint_bounds(geometry):

+ 28 - 30
tclCommands/TclCommand.py

@@ -78,8 +78,7 @@ class TclCommand(object):
 
 
         :return: current command
         :return: current command
         """
         """
-
-        command_string = []
+        command_string = list()
         command_string.append(self.aliases[0])
         command_string.append(self.aliases[0])
 
 
         if self.original_args is not None:
         if self.original_args is not None:
@@ -117,7 +116,7 @@ class TclCommand(object):
             if help_key in self.arg_names:
             if help_key in self.arg_names:
                 arg_type = self.arg_names[help_key]
                 arg_type = self.arg_names[help_key]
                 type_name = str(arg_type.__name__)
                 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
                 in_command_name = help_key
 
 
             elif help_key in self.option_types:
             elif help_key in self.option_types:
@@ -163,35 +162,36 @@ class TclCommand(object):
 
 
     @staticmethod
     @staticmethod
     def parse_arguments(args):
     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
-
-                if name is None:
-                    arguments.append(args[i])
-                else:
-                    options[name] = args[i]
-                    name = None
+        options = {}
+        arguments = []
+        n = len(args)
 
 
-            return arguments, options
+        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
+
+            if name is None:
+                arguments.append(args[i])
+            else:
+                options[name] = args[i]
+                name = None
+
+        return arguments, options
 
 
     def check_args(self, args):
     def check_args(self, args):
         """
         """
@@ -274,7 +274,6 @@ class TclCommand(object):
         """
         """
 
 
         # self.worker_task.emit({'fcn': self.exec_command_test, 'params': [text, False]})
         # self.worker_task.emit({'fcn': self.exec_command_test, 'params': [text, False]})
-
         try:
         try:
             self.log.debug("TCL command '%s' executed." % str(self.__class__))
             self.log.debug("TCL command '%s' executed." % str(self.__class__))
             self.original_args = args
             self.original_args = args
@@ -416,7 +415,6 @@ class TclCommandSignaled(TclCommand):
                 # when operation  will be  really long is good  to set it higher then defqault 30s
                 # 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]})
                 self.app.worker_task.emit({'fcn': self.execute_call, 'params': [args, unnamed_args]})
 
 
-
             return self.output
             return self.output
 
 
         except Exception as unknown:
         except Exception as unknown:

+ 13 - 7
tclCommands/TclCommandAlignDrill.py

@@ -29,6 +29,7 @@ class TclCommandAlignDrill(TclCommandSignaled):
         ('axisoffset', float),
         ('axisoffset', float),
         ('dia', float),
         ('dia', float),
         ('dist', float),
         ('dist', float),
+        ('outname', str),
     ])
     ])
 
 
     # array of mandatory options for current Tcl command: required = {'name','outname'}
     # array of mandatory options for current Tcl command: required = {'name','outname'}
@@ -47,9 +48,11 @@ class TclCommandAlignDrill(TclCommandSignaled):
             ('minoffset', 'min and max distance between align hole and pcb.'),
             ('minoffset', 'min and max distance between align hole and pcb.'),
             ('axisoffset', 'Offset on second axis before aligment holes'),
             ('axisoffset', 'Offset on second axis before aligment holes'),
             ('axis', 'Mirror axis parallel to the X or Y axis.'),
             ('axis', 'Mirror axis parallel to the X or Y axis.'),
-            ('dist', 'Distance of the mirror axis to the X or Y axis.')
+            ('dist', 'Distance of the mirror axis to the X or Y axis.'),
+            ('outname', 'Name of the resulting Excellon object.'),
         ]),
         ]),
-        'examples': []
+        'examples': ['aligndrill my_object -axis X -box my_object -dia 3.125 -grid 1 '
+                     '-gridoffset 0 -minoffset 2 -axisoffset 2']
     }
     }
 
 
     def execute(self, args, unnamed_args):
     def execute(self, args, unnamed_args):
@@ -64,6 +67,11 @@ class TclCommandAlignDrill(TclCommandSignaled):
 
 
         name = args['name']
         name = args['name']
 
 
+        if 'outname' in args:
+            outname = args['outname']
+        else:
+            outname = name + "_aligndrill"
+
         # Get source object.
         # Get source object.
         try:
         try:
             obj = self.app.collection.get_by_name(str(name))
             obj = self.app.collection.get_by_name(str(name))
@@ -176,9 +184,7 @@ class TclCommandAlignDrill(TclCommandSignaled):
                 px = 0.5 * (xmin + xmax)
                 px = 0.5 * (xmin + xmax)
                 py = 0.5 * (ymin + ymax)
                 py = 0.5 * (ymin + ymax)
 
 
-                obj.app.new_object("excellon",
-                                   name + "_aligndrill",
-                                   alligndrill_init_me)
+                obj.app.new_object("excellon", outname, alligndrill_init_me, plot=False)
 
 
             except Exception as e:
             except Exception as e:
                 return "Operation failed: %s" % str(e)
                 return "Operation failed: %s" % str(e)
@@ -194,8 +200,8 @@ class TclCommandAlignDrill(TclCommandSignaled):
             try:
             try:
                 px = dist
                 px = dist
                 py = dist
                 py = dist
-                obj.app.new_object("excellon", name + "_alligndrill", alligndrill_init_me)
+                obj.app.new_object("excellon", outname, alligndrill_init_me, plot=False)
             except Exception as e:
             except Exception as e:
                 return "Operation failed: %s" % str(e)
                 return "Operation failed: %s" % str(e)
 
 
-        return 'Ok'
+        return 'Ok. Align Drills Excellon object created'

+ 11 - 5
tclCommands/TclCommandAlignDrillGrid.py

@@ -17,7 +17,7 @@ class TclCommandAlignDrillGrid(TclCommandSignaled):
     # Dictionary of types from Tcl command, needs to be ordered.
     # Dictionary of types from Tcl command, needs to be ordered.
     # For positional arguments
     # For positional arguments
     arg_names = collections.OrderedDict([
     arg_names = collections.OrderedDict([
-        ('outname', str)
+
     ])
     ])
 
 
     # Dictionary of types from Tcl command, needs to be ordered.
     # Dictionary of types from Tcl command, needs to be ordered.
@@ -29,11 +29,12 @@ class TclCommandAlignDrillGrid(TclCommandSignaled):
         ('gridy', float),
         ('gridy', float),
         ('gridoffsety', float),
         ('gridoffsety', float),
         ('columns', int),
         ('columns', int),
-        ('rows', int)
+        ('rows', int),
+        ('outname', str)
     ])
     ])
 
 
     # array of mandatory options for current Tcl command: required = {'name','outname'}
     # array of mandatory options for current Tcl command: required = {'name','outname'}
-    required = ['outname', 'gridx', 'gridy', 'columns', 'rows']
+    required = ['gridx', 'gridy', 'columns', 'rows']
 
 
     # structured help for current command, args needs to be ordered
     # structured help for current command, args needs to be ordered
     help = {
     help = {
@@ -48,7 +49,7 @@ class TclCommandAlignDrillGrid(TclCommandSignaled):
             ('colums', 'Number of grid holes on X axis.'),
             ('colums', 'Number of grid holes on X axis.'),
             ('rows', 'Number of grid holes on Y axis.'),
             ('rows', 'Number of grid holes on Y axis.'),
         ]),
         ]),
-        'examples': []
+        'examples': ['aligndrillgrid -rows 2 -columns 2 -gridoffsetx 10 -gridoffsety 10 -gridx 2.54 -gridy 5.08']
     }
     }
 
 
     def execute(self, args, unnamed_args):
     def execute(self, args, unnamed_args):
@@ -61,6 +62,11 @@ class TclCommandAlignDrillGrid(TclCommandSignaled):
         :return: None or exception
         :return: None or exception
         """
         """
 
 
+        if 'outname' in args:
+            outname = args['outname']
+        else:
+            outname = "new_aligndrill_grid"
+
         if 'gridoffsetx' not in args:
         if 'gridoffsetx' not in args:
             gridoffsetx = 0
             gridoffsetx = 0
         else:
         else:
@@ -102,4 +108,4 @@ class TclCommandAlignDrillGrid(TclCommandSignaled):
             init_obj.create_geometry()
             init_obj.create_geometry()
 
 
         # Create the new object
         # Create the new object
-        self.app.new_object("excellon", args['outname'], aligndrillgrid_init_me)
+        self.app.new_object("excellon", outname, aligndrillgrid_init_me, plot=False)

+ 1 - 1
tclCommands/TclCommandBbox.py

@@ -90,6 +90,6 @@ class TclCommandBbox(TclCommand):
                     bounding_box = bounding_box.envelope
                     bounding_box = bounding_box.envelope
                 geo_obj.solid_geometry = bounding_box
                 geo_obj.solid_geometry = bounding_box
 
 
-            self.app.new_object("geometry", args['outname'], geo_init)
+            self.app.new_object("geometry", args['outname'], geo_init, plot=False)
         except Exception as e:
         except Exception as e:
             return "Operation failed: %s" % str(e)
             return "Operation failed: %s" % str(e)

+ 3 - 2
tclCommands/TclCommandCncjob.py

@@ -143,7 +143,7 @@ class TclCommandCncjob(TclCommandSignaled):
         obj.options['multidepth'] = False
         obj.options['multidepth'] = False
 
 
         if not obj.multigeo:
         if not obj.multigeo:
-            obj.generatecncjob(use_thread=False, **args)
+            obj.generatecncjob(use_thread=False, plot=False, **args)
         else:
         else:
             # Update the local_tools_dict values with the args value
             # Update the local_tools_dict values with the args value
             local_tools_dict = deepcopy(obj.tools)
             local_tools_dict = deepcopy(obj.tools)
@@ -171,5 +171,6 @@ class TclCommandCncjob(TclCommandSignaled):
                 outname=args['outname'],
                 outname=args['outname'],
                 tools_dict=local_tools_dict,
                 tools_dict=local_tools_dict,
                 tools_in_use=[],
                 tools_in_use=[],
-                use_thread=False)
+                use_thread=False,
+                plot=False)
             # self.raise_tcl_error('The object is a multi-geo geometry which is not supported in cncjob Tcl Command')
             # self.raise_tcl_error('The object is a multi-geo geometry which is not supported in cncjob Tcl Command')

+ 2 - 0
tclCommands/TclCommandCopperClear.py

@@ -226,6 +226,7 @@ class TclCommandCopperClear(TclCommand):
                                                contour=contour,
                                                contour=contour,
                                                rest=rest,
                                                rest=rest,
                                                tools_storage=ncc_tools,
                                                tools_storage=ncc_tools,
+                                               plot=False,
                                                run_threaded=False)
                                                run_threaded=False)
             return
             return
 
 
@@ -259,6 +260,7 @@ class TclCommandCopperClear(TclCommand):
                                                    contour=contour,
                                                    contour=contour,
                                                    rest=rest,
                                                    rest=rest,
                                                    tools_storage=ncc_tools,
                                                    tools_storage=ncc_tools,
+                                                   plot=False,
                                                    run_threaded=False)
                                                    run_threaded=False)
             return
             return
         else:
         else:

+ 1 - 1
tclCommands/TclCommandCutout.py

@@ -123,7 +123,7 @@ class TclCommandCutout(TclCommand):
             geo_obj.solid_geometry = cascaded_union([LineString(segment) for segment in cuts])
             geo_obj.solid_geometry = cascaded_union([LineString(segment) for segment in cuts])
 
 
         try:
         try:
-            self.app.new_object("geometry", name + "_cutout", geo_init_me)
+            self.app.new_object("geometry", name + "_cutout", geo_init_me, plot=False)
             self.app.inform.emit("[success] Rectangular-form Cutout operation finished.")
             self.app.inform.emit("[success] Rectangular-form Cutout operation finished.")
         except Exception as e:
         except Exception as e:
             return "Operation failed: %s" % str(e)
             return "Operation failed: %s" % str(e)

+ 1 - 1
tclCommands/TclCommandDrillcncjob.py

@@ -181,4 +181,4 @@ class TclCommandDrillcncjob(TclCommandSignaled):
             job_obj.gcode_parse()
             job_obj.gcode_parse()
             job_obj.create_geometry()
             job_obj.create_geometry()
 
 
-        self.app.new_object("cncjob", args['outname'], job_init)
+        self.app.new_object("cncjob", args['outname'], job_init, plot=False)

+ 1 - 1
tclCommands/TclCommandExteriors.py

@@ -61,4 +61,4 @@ class TclCommandExteriors(TclCommandSignaled):
             geo_obj.solid_geometry = obj_exteriors
             geo_obj.solid_geometry = obj_exteriors
 
 
         obj_exteriors = obj.get_exteriors()
         obj_exteriors = obj.get_exteriors()
-        self.app.new_object('geometry', outname, geo_init)
+        self.app.new_object('geometry', outname, geo_init, plot=False)

+ 2 - 2
tclCommands/TclCommandGeoCutout.py

@@ -279,7 +279,7 @@ class TclCommandGeoCutout(TclCommandSignaled):
                 app_obj.inform.emit("[success] Any-form Cutout operation finished.")
                 app_obj.inform.emit("[success] Any-form Cutout operation finished.")
 
 
             outname = cutout_obj.options["name"] + "_cutout"
             outname = cutout_obj.options["name"] + "_cutout"
-            self.app.new_object('geometry', outname, geo_init)
+            self.app.new_object('geometry', outname, geo_init, plot=False)
 
 
             # cutout_obj.plot()
             # cutout_obj.plot()
             # self.app.inform.emit("[success] Any-form Cutout operation finished.")
             # self.app.inform.emit("[success] Any-form Cutout operation finished.")
@@ -338,7 +338,7 @@ class TclCommandGeoCutout(TclCommandSignaled):
                 app_obj.inform.emit("[success] Any-form Cutout operation finished.")
                 app_obj.inform.emit("[success] Any-form Cutout operation finished.")
 
 
             outname = cutout_obj.options["name"] + "_cutout"
             outname = cutout_obj.options["name"] + "_cutout"
-            self.app.new_object('geometry', outname, geo_init)
+            self.app.new_object('geometry', outname, geo_init, plot=False)
 
 
             cutout_obj = self.app.collection.get_by_name(outname)
             cutout_obj = self.app.collection.get_by_name(outname)
         else:
         else:

+ 1 - 1
tclCommands/TclCommandImportSvg.py

@@ -71,7 +71,7 @@ class TclCommandImportSvg(TclCommandSignaled):
         with self.app.proc_container.new("Import SVG"):
         with self.app.proc_container.new("Import SVG"):
 
 
             # Object creation
             # Object creation
-            self.app.new_object(obj_type, outname, obj_init)
+            self.app.new_object(obj_type, outname, obj_init, plot=False)
 
 
             # Register recent file
             # Register recent file
             self.app.file_opened.emit("svg", filename)
             self.app.file_opened.emit("svg", filename)

+ 1 - 1
tclCommands/TclCommandIsolate.py

@@ -85,4 +85,4 @@ class TclCommandIsolate(TclCommandSignaled):
             self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (name, type(obj)))
             self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (name, type(obj)))
 
 
         del args['name']
         del args['name']
-        obj.isolate(**args)
+        obj.isolate(plot=False, **args)

+ 1 - 1
tclCommands/TclCommandJoinExcellon.py

@@ -61,4 +61,4 @@ class TclCommandJoinExcellon(TclCommand):
             FlatCAMExcellon.merge(objs, obj_)
             FlatCAMExcellon.merge(objs, obj_)
 
 
         if objs is not None:
         if objs is not None:
-            self.app.new_object("excellon", outname, initialize)
+            self.app.new_object("excellon", outname, initialize, plot=False)

+ 1 - 1
tclCommands/TclCommandJoinGeometry.py

@@ -61,4 +61,4 @@ class TclCommandJoinGeometry(TclCommand):
             FlatCAMGeometry.merge(objs, obj_)
             FlatCAMGeometry.merge(objs, obj_)
 
 
         if objs is not None:
         if objs is not None:
-            self.app.new_object("geometry", outname, initialize)
+            self.app.new_object("geometry", outname, initialize, plot=False)

+ 1 - 1
tclCommands/TclCommandMillDrills.py

@@ -128,7 +128,7 @@ class TclCommandMillDrills(TclCommandSignaled):
             del args['name']
             del args['name']
 
 
             # This runs in the background... Is blocking handled?
             # This runs in the background... Is blocking handled?
-            success, msg = obj.generate_milling_drills(**args)
+            success, msg = obj.generate_milling_drills(plot=False, **args)
         except Exception as e:
         except Exception as e:
             success = None
             success = None
             msg = None
             msg = None

+ 1 - 1
tclCommands/TclCommandMillSlots.py

@@ -127,7 +127,7 @@ class TclCommandMillSlots(TclCommandSignaled):
             del args['name']
             del args['name']
 
 
             # This runs in the background... Is blocking handled?
             # This runs in the background... Is blocking handled?
-            success, msg = obj.generate_milling_slots(**args)
+            success, msg = obj.generate_milling_slots(plot=False, **args)
 
 
         except Exception as e:
         except Exception as e:
             success = None
             success = None

+ 0 - 1
tclCommands/TclCommandMirror.py

@@ -103,6 +103,5 @@ class TclCommandMirror(TclCommandSignaled):
 
 
             try:
             try:
                 obj.mirror(axis, [dist, dist])
                 obj.mirror(axis, [dist, dist])
-                obj.plot()
             except Exception as e:
             except Exception as e:
                 return "Operation failed: %s" % str(e)
                 return "Operation failed: %s" % str(e)

+ 1 - 1
tclCommands/TclCommandNew.py

@@ -36,4 +36,4 @@ class TclCommandNew(TclCommand):
         :return: None or exception
         :return: None or exception
         """
         """
 
 
-        self.app.on_file_new()
+        self.app.on_file_new(cli=True)

+ 51 - 0
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)

+ 6 - 4
tclCommands/TclCommandNewGeometry.py

@@ -23,7 +23,7 @@ class TclCommandNewGeometry(TclCommandSignaled):
     ])
     ])
 
 
     # array of mandatory options for current Tcl command: required = {'name','outname'}
     # array of mandatory options for current Tcl command: required = {'name','outname'}
-    required = ['name']
+    required = []
 
 
     # structured help for current command, args needs to be ordered
     # structured help for current command, args needs to be ordered
     help = {
     help = {
@@ -43,7 +43,9 @@ class TclCommandNewGeometry(TclCommandSignaled):
             without -somename and  we do not have them in known arg_names
             without -somename and  we do not have them in known arg_names
         :return: None or exception
         :return: None or exception
         """
         """
+        if 'name' in args:
+            name = args['name']
+        else:
+            name = 'new_geo'
 
 
-        name = args['name']
-
-        self.app.new_object('geometry', str(name), lambda x, y: None)
+        self.app.new_object('geometry', str(name), lambda x, y: None, plot=False)

+ 68 - 0
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)

+ 1 - 1
tclCommands/TclCommandNregions.py

@@ -89,7 +89,7 @@ class TclCommandNregions(TclCommand):
                 non_copper = bounding_box.difference(geo)
                 non_copper = bounding_box.difference(geo)
                 geo_obj.solid_geometry = non_copper
                 geo_obj.solid_geometry = non_copper
 
 
-            self.app.new_object("geometry", args['outname'], geo_init)
+            self.app.new_object("geometry", args['outname'], geo_init, plot=False)
         except Exception as e:
         except Exception as e:
             return "Operation failed: %s" % str(e)
             return "Operation failed: %s" % str(e)
 
 

+ 2 - 0
tclCommands/TclCommandOpenExcellon.py

@@ -46,5 +46,7 @@ class TclCommandOpenExcellon(TclCommandSignaled):
         """
         """
 
 
         filename = args.pop('filename')
         filename = args.pop('filename')
+        filename = filename.replace(' ', '')
 
 
+        args['plot'] = False
         self.app.open_excellon(filename, **args)
         self.app.open_excellon(filename, **args)

+ 4 - 1
tclCommands/TclCommandOpenGCode.py

@@ -45,5 +45,8 @@ class TclCommandOpenGCode(TclCommandSignaled):
             without -somename and  we do not have them in known arg_names
             without -somename and  we do not have them in known arg_names
         :return: None or exception
         :return: None or exception
         """
         """
+        args['plot'] = False
+        filename = args["filename"]
+        filename = filename.replace(' ', '')
 
 
-        self.app.open_gcode(args['filename'], **args)
+        self.app.open_gcode(filename, **args)

+ 5 - 12
tclCommands/TclCommandOpenGerber.py

@@ -30,7 +30,7 @@ class TclCommandOpenGerber(TclCommandSignaled):
             ('filename', 'Path to file to open.'),
             ('filename', 'Path to file to open.'),
             ('outname', 'Name of the resulting Gerber object.')
             ('outname', 'Name of the resulting Gerber object.')
         ]),
         ]),
-        'examples': []
+        'examples': ["open_gerber gerber_object_path -outname bla"]
     }
     }
 
 
     def execute(self, args, unnamed_args):
     def execute(self, args, unnamed_args):
@@ -50,25 +50,19 @@ class TclCommandOpenGerber(TclCommandSignaled):
                 self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (outname, type(gerber_obj)))
                 self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (outname, type(gerber_obj)))
 
 
             # Opening the file happens here
             # Opening the file happens here
-            self.app.progress.emit(30)
             try:
             try:
                 gerber_obj.parse_file(filename)
                 gerber_obj.parse_file(filename)
-
             except IOError:
             except IOError:
                 app_obj.inform.emit("[ERROR_NOTCL] Failed to open file: %s " % filename)
                 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)
                 self.raise_tcl_error('Failed to open file: %s' % filename)
 
 
             except ParseError as e:
             except ParseError as e:
                 app_obj.inform.emit("[ERROR_NOTCL] Failed to parse file: %s, %s " % (filename, str(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))
                 self.log.error(str(e))
                 return
                 return
 
 
-            # Further parsing
-            app_obj.progress.emit(70)
-
         filename = args['filename']
         filename = args['filename']
+        filename = filename.replace(' ', '')
 
 
         if 'outname' in args:
         if 'outname' in args:
             outname = args['outname']
             outname = args['outname']
@@ -76,17 +70,16 @@ class TclCommandOpenGerber(TclCommandSignaled):
             outname = filename.split('/')[-1].split('\\')[-1]
             outname = filename.split('/')[-1].split('\\')[-1]
 
 
         if 'follow' in args:
         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"):
         with self.app.proc_container.new("Opening Gerber"):
 
 
             # Object creation
             # Object creation
-            self.app.new_object("gerber", outname, obj_init)
+            self.app.new_object("gerber", outname, obj_init, plot=False)
 
 
             # Register recent file
             # Register recent file
             self.app.file_opened.emit("gerber", filename)
             self.app.file_opened.emit("gerber", filename)
 
 
-            self.app.progress.emit(100)
-
             # GUI feedback
             # GUI feedback
             self.app.inform.emit("[success] Opened: " + filename)
             self.app.inform.emit("[success] Opened: " + filename)

+ 3 - 1
tclCommands/TclCommandOpenProject.py

@@ -43,5 +43,7 @@ class TclCommandOpenProject(TclCommandSignaled):
             without -somename and  we do not have them in known arg_names
             without -somename and  we do not have them in known arg_names
         :return: None or exception
         :return: None or exception
         """
         """
+        filename = args['filename']
+        filename = filename.replace(' ', '')
 
 
-        self.app.open_project(args['filename'])
+        self.app.open_project(filename, cli=True, plot=False)

+ 9 - 3
tclCommands/TclCommandPaint.py

@@ -201,7 +201,9 @@ class TclCommandPaint(TclCommand):
                                                outname=outname,
                                                outname=outname,
                                                connect=connect,
                                                connect=connect,
                                                contour=contour,
                                                contour=contour,
-                                               tools_storage=paint_tools)
+                                               tools_storage=paint_tools,
+                                               plot=False,
+                                               run_threaded=False)
             return
             return
 
 
         # Paint single polygon in the painted object
         # Paint single polygon in the painted object
@@ -222,7 +224,9 @@ class TclCommandPaint(TclCommand):
                                                outname=outname,
                                                outname=outname,
                                                connect=connect,
                                                connect=connect,
                                                contour=contour,
                                                contour=contour,
-                                               tools_storage=paint_tools)
+                                               tools_storage=paint_tools,
+                                               plot=False,
+                                               run_threaded=False)
             return
             return
 
 
         # Paint all polygons found within the box object from the the painted object
         # Paint all polygons found within the box object from the the painted object
@@ -250,7 +254,9 @@ class TclCommandPaint(TclCommand):
                                                    outname=outname,
                                                    outname=outname,
                                                    connect=connect,
                                                    connect=connect,
                                                    contour=contour,
                                                    contour=contour,
-                                                   tools_storage=paint_tools)
+                                                   tools_storage=paint_tools,
+                                                   plot=False,
+                                                   run_threaded=False)
             return
             return
 
 
         else:
         else:

+ 3 - 3
tclCommands/TclCommandPanelize.py

@@ -90,7 +90,7 @@ class TclCommandPanelize(TclCommand):
         if 'threaded' in args:
         if 'threaded' in args:
             threaded = args['threaded']
             threaded = args['threaded']
         else:
         else:
-            threaded = 1
+            threaded = 0
 
 
         if 'spacing_columns' in args:
         if 'spacing_columns' in args:
             spacing_columns = args['spacing_columns']
             spacing_columns = args['spacing_columns']
@@ -265,10 +265,10 @@ class TclCommandPanelize(TclCommand):
 
 
                 if isinstance(obj, FlatCAMExcellon):
                 if isinstance(obj, FlatCAMExcellon):
                     self.app.progress.emit(50)
                     self.app.progress.emit(50)
-                    self.app.new_object("excellon", outname, job_init_excellon, plot=True, autoselected=True)
+                    self.app.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True)
                 else:
                 else:
                     self.app.progress.emit(50)
                     self.app.progress.emit(50)
-                    self.app.new_object("geometry", outname, job_init_geometry, plot=True, autoselected=True)
+                    self.app.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True)
 
 
         if threaded == 1:
         if threaded == 1:
             proc = self.app.proc_container.new("Generating panel ... Please wait.")
             proc = self.app.proc_container.new("Generating panel ... Please wait.")

+ 2 - 2
tclCommands/TclCommandPlot.py → tclCommands/TclCommandPlotAll.py

@@ -2,7 +2,7 @@ from ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 from tclCommands.TclCommand import TclCommand
 
 
 
 
-class TclCommandPlot(TclCommand):
+class TclCommandPlotAll(TclCommand):
     """
     """
     Tcl shell command to update the plot on the user interface.
     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)
     # 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
     # Dictionary of types from Tcl command, needs to be ordered
     arg_names = collections.OrderedDict([
     arg_names = collections.OrderedDict([

+ 51 - 0
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()

+ 4 - 1
tclCommands/__init__.py

@@ -35,7 +35,9 @@ import tclCommands.TclCommandMillSlots
 import tclCommands.TclCommandMirror
 import tclCommands.TclCommandMirror
 import tclCommands.TclCommandNew
 import tclCommands.TclCommandNew
 import tclCommands.TclCommandNregions
 import tclCommands.TclCommandNregions
+import tclCommands.TclCommandNewExcellon
 import tclCommands.TclCommandNewGeometry
 import tclCommands.TclCommandNewGeometry
+import tclCommands.TclCommandNewGerber
 import tclCommands.TclCommandOffset
 import tclCommands.TclCommandOffset
 import tclCommands.TclCommandOpenExcellon
 import tclCommands.TclCommandOpenExcellon
 import tclCommands.TclCommandOpenGCode
 import tclCommands.TclCommandOpenGCode
@@ -44,7 +46,8 @@ import tclCommands.TclCommandOpenProject
 import tclCommands.TclCommandOptions
 import tclCommands.TclCommandOptions
 import tclCommands.TclCommandPaint
 import tclCommands.TclCommandPaint
 import tclCommands.TclCommandPanelize
 import tclCommands.TclCommandPanelize
-import tclCommands.TclCommandPlot
+import tclCommands.TclCommandPlotAll
+import tclCommands.TclCommandPlotObjects
 import tclCommands.TclCommandSaveProject
 import tclCommands.TclCommandSaveProject
 import tclCommands.TclCommandSaveSys
 import tclCommands.TclCommandSaveSys
 import tclCommands.TclCommandScale
 import tclCommands.TclCommandScale