Sfoglia il codice sorgente

- application wide change: introduced the precision parameters in Edit -> Preferences who will control how many decimals to use in the app parameters

Marius Stanciu 6 anni fa
parent
commit
0d0f872244
53 ha cambiato i file con 429 aggiunte e 401 eliminazioni
  1. 22 10
      FlatCAMApp.py
  2. 12 43
      FlatCAMObj.py
  3. 3 3
      FlatCAMTool.py
  4. 1 1
      ObjectCollection.py
  5. 1 0
      README.md
  6. 30 29
      camlib.py
  7. 2 1
      flatcamEditors/FlatCAMExcEditor.py
  8. 1 1
      flatcamEditors/FlatCAMGrbEditor.py
  9. 18 20
      flatcamGUI/FlatCAMGUI.py
  10. 15 9
      flatcamGUI/GUIElements.py
  11. 28 19
      flatcamGUI/ObjectUI.py
  12. 187 142
      flatcamGUI/PreferencesUI.py
  13. 1 0
      flatcamParsers/ParseExcellon.py
  14. 1 0
      flatcamParsers/ParseGerber.py
  15. 1 1
      flatcamTools/ToolCalculators.py
  16. 1 1
      flatcamTools/ToolCalibrateExcellon.py
  17. 1 1
      flatcamTools/ToolCopperThieving.py
  18. 1 1
      flatcamTools/ToolCutOut.py
  19. 1 1
      flatcamTools/ToolDblSided.py
  20. 2 2
      flatcamTools/ToolDistance.py
  21. 1 1
      flatcamTools/ToolDistanceMin.py
  22. 1 1
      flatcamTools/ToolFiducials.py
  23. 1 1
      flatcamTools/ToolFilm.py
  24. 3 0
      flatcamTools/ToolImage.py
  25. 2 0
      flatcamTools/ToolMove.py
  26. 1 1
      flatcamTools/ToolNonCopperClear.py
  27. 1 1
      flatcamTools/ToolOptimal.py
  28. 1 0
      flatcamTools/ToolPDF.py
  29. 1 1
      flatcamTools/ToolPaint.py
  30. 3 2
      flatcamTools/ToolPanelize.py
  31. 1 0
      flatcamTools/ToolPcbWizard.py
  32. 1 1
      flatcamTools/ToolProperties.py
  33. 1 1
      flatcamTools/ToolQRCode.py
  34. 3 3
      flatcamTools/ToolRulesCheck.py
  35. 1 1
      flatcamTools/ToolSolderPaste.py
  36. 1 0
      flatcamTools/ToolSub.py
  37. 1 1
      flatcamTools/ToolTransform.py
  38. 3 5
      postprocessors/Berta_CNC.py
  39. 3 5
      postprocessors/ISEL_CNC.py
  40. 6 5
      postprocessors/Paste_1.py
  41. 3 5
      postprocessors/Repetier.py
  42. 3 5
      postprocessors/Toolchange_Custom.py
  43. 3 5
      postprocessors/Toolchange_Probe_MACH3.py
  44. 3 5
      postprocessors/Toolchange_manual.py
  45. 3 5
      postprocessors/default.py
  46. 3 5
      postprocessors/grbl_11.py
  47. 3 5
      postprocessors/line_xyz.py
  48. 3 5
      postprocessors/marlin.py
  49. 12 12
      tclCommands/TclCommandCopperClear.py
  50. 9 11
      tclCommands/TclCommandDrillcncjob.py
  51. 5 7
      tclCommands/TclCommandMillDrills.py
  52. 5 7
      tclCommands/TclCommandMillSlots.py
  53. 9 9
      tclCommands/TclCommandPaint.py

+ 22 - 10
FlatCAMApp.py

@@ -396,6 +396,8 @@ class App(QtCore.QObject):
         self.defaults = LoudDict()
         self.defaults.update({
             # Global APP Preferences
+            "decimals_inch": 4,
+            "decimals_metric": 4,
             "version": self.version,
             "first_run": True,
             "units": "MM",
@@ -937,6 +939,11 @@ class App(QtCore.QObject):
         if user_defaults:
             self.load_defaults(filename='current_defaults')
 
+        if self.defaults['units'] == 'MM':
+            self.decimals = int(self.defaults['decimals_metric'])
+        else:
+            self.decimals = int(self.defaults['decimals_inch'])
+
         # #############################################################################
         # ##################### CREATE MULTIPROCESSING POOL ###########################
         # #############################################################################
@@ -987,7 +994,7 @@ class App(QtCore.QObject):
 
         QtCore.QObject.__init__(self)
 
-        self.ui = FlatCAMGUI(self.version, self.beta, self)
+        self.ui = FlatCAMGUI(self)
 
         theme_settings = QtCore.QSettings("Open Source", "FlatCAM")
         if theme_settings.contains("theme"):
@@ -1020,6 +1027,8 @@ class App(QtCore.QObject):
         # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
         self.defaults_form_fields = {
             # General App
+            "decimals_inch": self.ui.general_defaults_form.general_app_group.precision_inch_entry,
+            "decimals_metric": self.ui.general_defaults_form.general_app_group.precision_metric_entry,
             "units": self.ui.general_defaults_form.general_app_group.units_radio,
             "global_graphic_engine": self.ui.general_defaults_form.general_app_group.ge_radio,
             "global_app_level": self.ui.general_defaults_form.general_app_group.app_level_radio,
@@ -3354,7 +3363,7 @@ class App(QtCore.QObject):
                         self.inform.emit('[WARNING_NOTCL] %s' %
                                          _("Select a Gerber, Geometry or Excellon Object to update."))
                         return
-                    edited_obj.set_ui(edited_obj.ui_type())
+                    edited_obj.set_ui(edited_obj.ui_type(decimals=self.decimals))
                     self.ui.notebook.setCurrentWidget(self.ui.selected_tab)
                 elif response == bt_cancel:
                     return
@@ -5670,13 +5679,15 @@ class App(QtCore.QObject):
                     coords_xy = [float(eval(a)) for a in coordinates if a != '']
                     coords_xy[0] *= sfactor
                     coords_xy[1] *= sfactor
-                    self.defaults['excellon_toolchangexy'] = "%.4f, %.4f" % (coords_xy[0], coords_xy[1])
+                    self.defaults['excellon_toolchangexy'] = "%.*f, %.*f" % (self.decimals, coords_xy[0],
+                                                                             self.decimals, coords_xy[1])
                 elif dim == 'geometry_toolchangexy':
                     coordinates = self.defaults["geometry_toolchangexy"].split(",")
                     coords_xy = [float(eval(a)) for a in coordinates if a != '']
                     coords_xy[0] *= sfactor
                     coords_xy[1] *= sfactor
-                    self.defaults['geometry_toolchangexy'] = "%.4f, %.4f" % (coords_xy[0], coords_xy[1])
+                    self.defaults['geometry_toolchangexy'] = "%.*f, %.*f" % (self.decimals, coords_xy[0],
+                                                                             self.decimals, coords_xy[1])
                 elif dim == 'geometry_cnctooldia':
                     tools_diameters = []
                     try:
@@ -5688,7 +5699,7 @@ class App(QtCore.QObject):
                     self.defaults['geometry_cnctooldia'] = ''
                     for t in range(len(tools_diameters)):
                         tools_diameters[t] *= sfactor
-                        self.defaults['geometry_cnctooldia'] += "%.4f," % tools_diameters[t]
+                        self.defaults['geometry_cnctooldia'] += "%.*f," % (self.decimals, tools_diameters[t])
                 elif dim == 'tools_ncctools':
                     ncctools = []
                     try:
@@ -5700,7 +5711,7 @@ class App(QtCore.QObject):
                     self.defaults['tools_ncctools'] = ''
                     for t in range(len(ncctools)):
                         ncctools[t] *= sfactor
-                        self.defaults['tools_ncctools'] += "%.4f," % ncctools[t]
+                        self.defaults['tools_ncctools'] += "%.*f," % (self.decimals, ncctools[t])
                 elif dim == 'tools_solderpaste_tools':
                     sptools = []
                     try:
@@ -5712,13 +5723,14 @@ class App(QtCore.QObject):
                     self.defaults['tools_solderpaste_tools'] = ""
                     for t in range(len(sptools)):
                         sptools[t] *= sfactor
-                        self.defaults['tools_solderpaste_tools'] += "%.4f," % sptools[t]
+                        self.defaults['tools_solderpaste_tools'] += "%.*f," % (self.decimals, sptools[t])
                 elif dim == 'tools_solderpaste_xy_toolchange':
                     coordinates = self.defaults["tools_solderpaste_xy_toolchange"].split(",")
                     sp_coords = [float(eval(a)) for a in coordinates if a != '']
                     sp_coords[0] *= sfactor
                     sp_coords[1] *= sfactor
-                    self.defaults['tools_solderpaste_xy_toolchange'] = "%.4f, %.4f" % (sp_coords[0], sp_coords[1])
+                    self.defaults['tools_solderpaste_xy_toolchange'] = "%.*f, %.*f" % (self.decimals, sp_coords[0],
+                                                                                       self.decimals, sp_coords[1])
                 elif dim == 'global_gridx' or dim == 'global_gridy':
                     if new_units == 'IN':
                         val = 0.1
@@ -5727,7 +5739,7 @@ class App(QtCore.QObject):
                         except Exception as e:
                             log.debug('App.on_toggle_units().scale_defaults() --> %s' % str(e))
 
-                        self.defaults[dim] = float('%.6f' % val)
+                        self.defaults[dim] = float('%.*f' % (self.decimals, val))
                     else:
                         val = 0.1
                         try:
@@ -5735,7 +5747,7 @@ class App(QtCore.QObject):
                         except Exception as e:
                             log.debug('App.on_toggle_units().scale_defaults() --> %s' % str(e))
 
-                        self.defaults[dim] = float('%.4f' % val)
+                        self.defaults[dim] = float('%.*f' % (self.decimals, val))
                 else:
                     val = 0.1
                     if self.defaults[dim]:

+ 12 - 43
FlatCAMObj.py

@@ -83,6 +83,7 @@ class FlatCAMObj(QtCore.QObject):
         :param name: Name of the object given by the user.
         :return: FlatCAMObj
         """
+
         QtCore.QObject.__init__(self)
 
         # View
@@ -572,6 +573,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         grb_final.follow_geometry = MultiPolygon(grb_final.follow_geometry)
 
     def __init__(self, name):
+        self.decimals = self.app.decimals
+
         Gerber.__init__(self, steps_per_circle=int(self.app.defaults["gerber_circle_steps"]))
         FlatCAMObj.__init__(self, name)
 
@@ -617,9 +620,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         # list of rows with apertures plotted
         self.marked_rows = []
 
-        # Number of decimals to be used by tools in this class
-        self.decimals = 4
-
         # Mouse events
         self.mr = None
 
@@ -648,11 +648,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
 
         self.units = self.app.defaults['units'].upper()
 
-        if self.units == 'MM':
-            self.decimals = 2
-        else:
-            self.decimals = 4
-
         self.replotApertures.connect(self.on_mark_cb_click_table)
 
         self.form_fields.update({
@@ -2095,6 +2090,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
     optionChanged = QtCore.pyqtSignal(str)
 
     def __init__(self, name):
+        self.decimals = self.app.decimals
+
         Excellon.__init__(self, geo_steps_per_circle=int(self.app.defaults["geometry_circle_steps"]))
         FlatCAMObj.__init__(self, name)
 
@@ -2146,9 +2143,6 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
         self.multigeo = False
 
-        # Number fo decimals to be used for tools in this class
-        self.decimals = 4
-
         # Attributes to be included in serialization
         # Always append to it because it carries contents
         # from predecessors.
@@ -2559,11 +2553,6 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
         self.units = self.app.defaults['units'].upper()
 
-        if self.units == 'MM':
-            self.decimals = 2
-        else:
-            self.decimals = 4
-
         self.form_fields.update({
             "plot": self.ui.plot_cb,
             "solid": self.ui.solid_cb,
@@ -3430,6 +3419,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
     ui_type = GeometryObjectUI
 
     def __init__(self, name):
+        self.decimals = self.app.decimals
         FlatCAMObj.__init__(self, name)
         Geometry.__init__(self, geo_steps_per_circle=int(self.app.defaults["geometry_circle_steps"]))
 
@@ -3507,9 +3497,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         self.old_pp_state = self.app.defaults["geometry_multidepth"]
         self.old_toolchangeg_state = self.app.defaults["geometry_toolchange"]
 
-        # Number of decimals to be used for tools in this class
-        self.decimals = 4
-
         # Attributes to be included in serialization
         # Always append to it because it carries contents
         # from predecessors.
@@ -3668,11 +3655,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
         self.units = self.app.defaults['units'].upper()
 
-        if self.units == 'MM':
-            self.decimals = 2
-        else:
-            self.decimals = 4
-
         # populate postprocessor names in the combobox
         for name in list(self.app.postprocessors.keys()):
             self.ui.pp_geometry_name_cb.addItem(name)
@@ -5588,10 +5570,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         if tooldia:
             tooldia *= factor
             # limit the decimals to 2 for METRIC and 3 for INCH
-            if units.lower() == 'in':
-                tooldia = float('%.4f' % tooldia)
-            else:
-                tooldia = float('%.2f' % tooldia)
+            tooldia = float('%.*f' % (self.decimals, tooldia))
 
             self.ui.addtool_entry.set_value(tooldia)
 
@@ -5810,7 +5789,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
 
         FlatCAMApp.App.log.debug("Creating CNCJob object...")
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         CNCjob.__init__(self, units=units, kind=kind, z_move=z_move,
                         feedrate=feedrate, feedrate_rapid=feedrate_rapid, z_cut=z_cut, tooldia=tooldia,
@@ -6033,11 +6012,6 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
 
         self.units = self.app.defaults['units'].upper()
 
-        if self.units == "IN":
-            self.decimals = 4
-        else:
-            self.decimals = 2
-
         # this signal has to be connected to it's slot before the defaults are populated
         # the decision done in the slot has to override the default value set bellow
         self.ui.toolchange_cb.toggled.connect(self.on_toolchange_custom_clicked)
@@ -6709,6 +6683,8 @@ class FlatCAMScript(FlatCAMObj):
     ui_type = ScriptObjectUI
 
     def __init__(self, name):
+        self.decimals = self.app.decimals
+
         FlatCAMApp.App.log.debug("Creating a FlatCAMScript object...")
         FlatCAMObj.__init__(self, name)
 
@@ -6721,7 +6697,6 @@ class FlatCAMScript(FlatCAMObj):
         })
 
         self.units = ''
-        self.decimals = 4
 
         self.ser_attrs = ['options', 'kind', 'source_file']
         self.source_file = ''
@@ -6738,7 +6713,6 @@ class FlatCAMScript(FlatCAMObj):
             "Expected a ScriptObjectUI, got %s" % type(self.ui)
 
         self.units = self.app.defaults['units'].upper()
-        self.decimals = 4 if self.units == "IN" else 2
 
         # Fill form fields only on object create
         self.to_form()
@@ -6905,13 +6879,13 @@ class FlatCAMDocument(FlatCAMObj):
     ui_type = DocumentObjectUI
 
     def __init__(self, name):
+        self.decimals = self.app.decimals
+
         FlatCAMApp.App.log.debug("Creating a Document object...")
         FlatCAMObj.__init__(self, name)
 
         self.kind = "document"
-
         self.units = ''
-        self.decimals = 4
 
         self.ser_attrs = ['options', 'kind', 'source_file']
         self.source_file = ''
@@ -6934,11 +6908,6 @@ class FlatCAMDocument(FlatCAMObj):
 
         self.units = self.app.defaults['units'].upper()
 
-        if self.units == "IN":
-            self.decimals = 4
-        else:
-            self.decimals = 2
-
         # Fill form fields only on object create
         self.to_form()
 

+ 3 - 3
FlatCAMTool.py

@@ -24,15 +24,15 @@ class FlatCAMTool(QtWidgets.QWidget):
         :param parent: Qt Parent
         :return: FlatCAMTool
         """
-        QtWidgets.QWidget.__init__(self, parent)
+        self.app = app
+        self.decimals = app.decimals
 
+        QtWidgets.QWidget.__init__(self, parent)
         # self.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
 
         self.layout = QtWidgets.QVBoxLayout()
         self.setLayout(self.layout)
 
-        self.app = app
-
         self.menuAction = None
 
     def install(self, icon=None, separator=None, shortcut=None, **kwargs):

+ 1 - 1
ObjectCollection.py

@@ -498,7 +498,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
                 name += "_1"
         obj.options["name"] = name
 
-        obj.set_ui(obj.ui_type())
+        obj.set_ui(obj.ui_type(decimals=self.app.decimals))
 
         # Required before appending (Qt MVC)
         group = self.group_items[obj.kind]

+ 1 - 0
README.md

@@ -15,6 +15,7 @@ CAD program, and create G-Code for Isolation routing.
 - Copper Thieving Tool - added units label for the pattern plated area
 - Properties Tool - added a new parameter, the copper area which show the area of the copper features for the Gerber objects
 - Copper Thieving Tool - added a default value for the mask clearance when generating pattern plating mask
+- application wide change: introduced the precision parameters in Edit -> Preferences who will control how many decimals to use in the app parameters
 
 4.12.2019 
 

+ 30 - 29
camlib.py

@@ -465,7 +465,8 @@ class Geometry(object):
     def __init__(self, geo_steps_per_circle=None):
         # Units (in or mm)
         self.units = self.app.defaults["units"]
-        
+        self.decimals = self.app.decimals
+
         # Final geometry: MultiPolygon or list (of geometry constructs)
         self.solid_geometry = None
 
@@ -2144,6 +2145,8 @@ class CNCjob(Geometry):
                  segy=None,
                  steps_per_circle=None):
 
+        self.decimals = self.app.decimals
+
         # Used when parsing G-code arcs
         self.steps_per_circle = int(self.app.defaults['cncjob_steps_per_circle'])
 
@@ -2592,10 +2595,7 @@ class CNCjob(Geometry):
                                 if self.dwell is True:
                                     gcode += self.doformat(p.dwell_code)  # Dwell time
 
-                            if self.units == 'MM':
-                                current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
-                            else:
-                                current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
+                            current_tooldia = float('%.*f' % (self.decimals, float(exobj.tools[tool]["C"])))
 
                             self.app.inform.emit(
                                 '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
@@ -2738,10 +2738,7 @@ class CNCjob(Geometry):
                                 if self.dwell is True:
                                     gcode += self.doformat(p.dwell_code)  # Dwell time
 
-                            if self.units == 'MM':
-                                current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
-                            else:
-                                current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
+                            current_tooldia = float('%.*f' % (self.decimals, float(exobj.tools[tool]["C"])))
 
                             self.app.inform.emit(
                                 '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
@@ -2842,10 +2839,7 @@ class CNCjob(Geometry):
                             if self.dwell is True:
                                 gcode += self.doformat(p.dwell_code)  # Dwell time
 
-                        if self.units == 'MM':
-                            current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
-                        else:
-                            current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
+                        current_tooldia = float('%.*f' % (self.decimals, float(exobj.tools[tool]["C"])))
 
                         self.app.inform.emit(
                             '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
@@ -3164,10 +3158,7 @@ class CNCjob(Geometry):
         old_disp_number = 0
         log.warning("Number of paths for which to generate GCode: %s" % str(geo_len))
 
-        if self.units == 'MM':
-            current_tooldia = float('%.2f' % float(self.tooldia))
-        else:
-            current_tooldia = float('%.4f' % float(self.tooldia))
+        current_tooldia = float('%.*f' % (self.decimals, float(self.tooldia)))
 
         self.app.inform.emit( '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
                                              str(current_tooldia),
@@ -3511,10 +3502,7 @@ class CNCjob(Geometry):
         old_disp_number = 0
         log.warning("Number of paths for which to generate GCode: %s" % str(geo_len))
 
-        if self.units == 'MM':
-            current_tooldia = float('%.2f' % float(self.tooldia))
-        else:
-            current_tooldia = float('%.4f' % float(self.tooldia))
+        current_tooldia = float('%.*f' % (self.decimals, float(self.tooldia)))
 
         self.app.inform.emit(
             '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
@@ -3997,18 +3985,27 @@ class CNCjob(Geometry):
                 # create the geometry for the holes created when drilling Excellon drills
                 if self.origin_kind == 'excellon':
                     if current['Z'] < 0:
-                        current_drill_point_coords = (float('%.4f' % current['X']), float('%.4f' % current['Y']))
+                        current_drill_point_coords = (
+                            float('%.*f' % (self.decimals, current['X'])),
+                            float('%.*f' % (self.decimals, current['Y']))
+                        )
+
                         # find the drill diameter knowing the drill coordinates
                         for pt_dict in self.exc_drills:
-                            point_in_dict_coords = (float('%.4f' % pt_dict['point'].x),
-                                                   float('%.4f' % pt_dict['point'].y))
+                            point_in_dict_coords = (
+                                float('%.*f' % (self.decimals, pt_dict['point'].x)),
+                                float('%.*f' % (self.decimals, pt_dict['point'].y))
+                            )
                             if point_in_dict_coords == current_drill_point_coords:
                                 tool = pt_dict['tool']
                                 dia = self.exc_tools[tool]['C']
                                 kind = ['C', 'F']
-                                geometry.append({"geom": Point(current_drill_point_coords).
-                                                buffer(dia/2).exterior,
-                                                 "kind": kind})
+                                geometry.append(
+                                    {
+                                        "geom": Point(current_drill_point_coords).buffer(dia/2).exterior,
+                                        "kind": kind
+                                    }
+                                )
                                 break
 
             if 'G' in gobj:
@@ -4053,8 +4050,12 @@ class CNCjob(Geometry):
         # end, therefore, see here too if there is
         # a final path.
         if len(path) > 1:
-            geometry.append({"geom": LineString(path),
-                             "kind": kind})
+            geometry.append(
+                {
+                    "geom": LineString(path),
+                    "kind": kind
+                }
+            )
 
         self.gcode_parsed = geometry
         return geometry

+ 2 - 1
flatcamEditors/FlatCAMExcEditor.py

@@ -3009,7 +3009,8 @@ class FlatCAMExcEditor(QtCore.QObject):
 
         # add a first tool in the Tool Table but only if the Excellon Object is empty
         if not self.tool2tooldia:
-            self.on_tool_add(tooldia=float('%.2f' % float(self.app.defaults['excellon_editor_newdia'])))
+            self.on_tool_add(tooldia=float('%.*f' % (self.decimals,
+                                                     float(self.app.defaults['excellon_editor_newdia']))))
 
     def update_fcexcellon(self, exc_obj):
         """

+ 1 - 1
flatcamEditors/FlatCAMGrbEditor.py

@@ -4959,7 +4959,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
 
                         if float(upper_threshold_val) > area > float(lower_threshold_val):
                             current_pos = geo_el.geo['solid'].exterior.coords[-1]
-                            text_elem = '%.4f' % area
+                            text_elem = '%.*f' % (self.decimals, area)
                             text.append(text_elem)
                             position.append(current_pos)
                             self.geo_to_delete.append(geo_el)

+ 18 - 20
flatcamGUI/FlatCAMGUI.py

@@ -32,10 +32,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
     geom_update = QtCore.pyqtSignal(int, int, int, int, int, name='geomUpdate')
     final_save = QtCore.pyqtSignal(name='saveBeforeExit')
 
-    def __init__(self, version, beta, app):
+    def __init__(self, app):
         super(FlatCAMGUI, self).__init__()
 
         self.app = app
+        self.decimals = self.app.decimals
+
         # Divine icon pack by Ipapun @ finicons.com
 
         # ################################## ##
@@ -2002,8 +2004,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
         self.setGeometry(100, 100, 1024, 650)
         self.setWindowTitle('FlatCAM %s %s - %s' %
-                            (version,
-                             ('BETA' if beta else ''),
+                            (self.app.version,
+                             ('BETA' if self.app.beta else ''),
                              platform.architecture()[0])
                             )
 
@@ -2024,14 +2026,14 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.grb_editor_cmenu.menuAction().setVisible(False)
         self.e_editor_cmenu.menuAction().setVisible(False)
 
-        self.general_defaults_form = GeneralPreferencesUI()
-        self.gerber_defaults_form = GerberPreferencesUI()
-        self.excellon_defaults_form = ExcellonPreferencesUI()
-        self.geometry_defaults_form = GeometryPreferencesUI()
-        self.cncjob_defaults_form = CNCJobPreferencesUI()
-        self.tools_defaults_form = ToolsPreferencesUI()
-        self.tools2_defaults_form = Tools2PreferencesUI()
-        self.util_defaults_form = UtilPreferencesUI()
+        self.general_defaults_form = GeneralPreferencesUI(decimals=self.decimals)
+        self.gerber_defaults_form = GerberPreferencesUI(decimals=self.decimals)
+        self.excellon_defaults_form = ExcellonPreferencesUI(decimals=self.decimals)
+        self.geometry_defaults_form = GeometryPreferencesUI(decimals=self.decimals)
+        self.cncjob_defaults_form = CNCJobPreferencesUI(decimals=self.decimals)
+        self.tools_defaults_form = ToolsPreferencesUI(decimals=self.decimals)
+        self.tools2_defaults_form = Tools2PreferencesUI(decimals=self.decimals)
+        self.util_defaults_form = UtilPreferencesUI(decimals=self.decimals)
 
         QtWidgets.qApp.installEventFilter(self)
 
@@ -3471,16 +3473,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                     val, ok = tool_add_popup.get_value()
                     if ok:
                         self.app.exc_editor.on_tool_add(tooldia=val)
-                        formated_val = '%.4f' % float(val)
-                        self.app.inform.emit('[success] %s: %s %s' %
-                                             (_("Added new tool with dia"),
-                                              formated_val,
-                                              str(self.units)
-                                              )
-                                             )
-                    else:
+                        formated_val = '%.*f' % (self.decimals, float(val))
                         self.app.inform.emit(
-                            '[WARNING_NOTCL] %s' % _("Adding Tool cancelled ..."))
+                            '[success] %s: %s %s' % (_("Added new tool with dia"), formated_val, str(self.units))
+                        )
+                    else:
+                        self.app.inform.emit('[WARNING_NOTCL] %s' % _("Adding Tool cancelled ..."))
                     return
 
                 # Zoom Fit

+ 15 - 9
flatcamGUI/GUIElements.py

@@ -145,7 +145,7 @@ class RadioSet(QtWidgets.QWidget):
 
 
 class LengthEntry(QtWidgets.QLineEdit):
-    def __init__(self, output_units='IN', parent=None):
+    def __init__(self, output_units='IN', decimals=None, parent=None):
         super(LengthEntry, self).__init__(parent)
 
         self.output_units = output_units
@@ -160,6 +160,7 @@ class LengthEntry(QtWidgets.QLineEdit):
         }
         self.readyToEdit = True
         self.editingFinished.connect(self.on_edit_finished)
+        self.decimals = decimals if decimals is not None else 4
 
     def on_edit_finished(self):
         self.clearFocus()
@@ -203,8 +204,9 @@ class LengthEntry(QtWidgets.QLineEdit):
             log.warning("Could not parse value in entry: %s" % str(raw))
             return None
 
-    def set_value(self, val):
-        self.setText(str('%.4f' % val))
+    def set_value(self, val, decimals=None):
+        dec_digits = decimals if decimals is not None else self.decimals
+        self.setText(str('%.*f' % (dec_digits, val)))
 
     def sizeHint(self):
         default_hint_size = super(LengthEntry, self).sizeHint()
@@ -212,10 +214,11 @@ class LengthEntry(QtWidgets.QLineEdit):
 
 
 class FloatEntry(QtWidgets.QLineEdit):
-    def __init__(self, parent=None):
+    def __init__(self, decimals=None, parent=None):
         super(FloatEntry, self).__init__(parent)
         self.readyToEdit = True
         self.editingFinished.connect(self.on_edit_finished)
+        self.decimals = decimals if decimals is not None else 4
 
     def on_edit_finished(self):
         self.clearFocus()
@@ -251,9 +254,10 @@ class FloatEntry(QtWidgets.QLineEdit):
                 log.error("Could not evaluate val: %s, error: %s" % (str(raw), str(e)))
             return None
 
-    def set_value(self, val):
+    def set_value(self, val, decimals=None):
+        dig_digits = decimals if decimals is not None else self.decimals
         if val is not None:
-            self.setText("%.4f" % float(val))
+            self.setText("%.*f" % (dig_digits, float(val)))
         else:
             self.setText("")
 
@@ -263,10 +267,11 @@ class FloatEntry(QtWidgets.QLineEdit):
 
 
 class FloatEntry2(QtWidgets.QLineEdit):
-    def __init__(self, parent=None):
+    def __init__(self, decimals=None, parent=None):
         super(FloatEntry2, self).__init__(parent)
         self.readyToEdit = True
         self.editingFinished.connect(self.on_edit_finished)
+        self.decimals = decimals if decimals is not None else 4
 
     def on_edit_finished(self):
         self.clearFocus()
@@ -295,8 +300,9 @@ class FloatEntry2(QtWidgets.QLineEdit):
                 log.error("Could not evaluate val: %s, error: %s" % (str(raw), str(e)))
             return None
 
-    def set_value(self, val):
-        self.setText("%.4f" % val)
+    def set_value(self, val, decimals=None):
+        dig_digits = decimals if decimals is not None else self.decimals
+        self.setText("%.*f" % (dig_digits, val))
 
     def sizeHint(self):
         default_hint_size = super(FloatEntry2, self).sizeHint()

+ 28 - 19
flatcamGUI/ObjectUI.py

@@ -35,10 +35,11 @@ class ObjectUI(QtWidgets.QWidget):
     put UI elements in ObjectUI.custom_box (QtWidgets.QLayout).
     """
 
-    def __init__(self, icon_file='share/flatcam_icon32.png', title=_('FlatCAM Object'), parent=None, common=True):
+    def __init__(self, icon_file='share/flatcam_icon32.png', title=_('FlatCAM Object'), parent=None, common=True, 
+                 decimals=4):
         QtWidgets.QWidget.__init__(self, parent=parent)
 
-        self.decimals = 4
+        self.decimals = decimals
 
         layout = QtWidgets.QVBoxLayout()
         self.setLayout(layout)
@@ -153,9 +154,9 @@ class GerberObjectUI(ObjectUI):
     User interface for Gerber objects.
     """
 
-    def __init__(self, parent=None):
-        ObjectUI.__init__(self, title=_('Gerber Object'), parent=parent)
-        self.decimals = 4
+    def __init__(self, decimals, parent=None):
+        ObjectUI.__init__(self, title=_('Gerber Object'), parent=parent, decimals=decimals)
+        self.decimals = decimals
 
         # Plot options
         grid0 = QtWidgets.QGridLayout()
@@ -669,12 +670,13 @@ class ExcellonObjectUI(ObjectUI):
     User interface for Excellon objects.
     """
 
-    def __init__(self, parent=None):
+    def __init__(self, decimals, parent=None):
         ObjectUI.__init__(self, title=_('Excellon Object'),
                           icon_file='share/drill32.png',
-                          parent=parent)
+                          parent=parent,
+                          decimals=decimals)
 
-        self.decimals = 4
+        self.decimals = decimals
 
         # ### Plot options ####
         hlay_plot = QtWidgets.QHBoxLayout()
@@ -1072,10 +1074,10 @@ class GeometryObjectUI(ObjectUI):
     User interface for Geometry objects.
     """
 
-    def __init__(self, parent=None):
+    def __init__(self, decimals, parent=None):
         super(GeometryObjectUI, self).__init__(title=_('Geometry Object'),
-                                               icon_file='share/geometry32.png', parent=parent)
-        self.decimals = 4
+                                               icon_file='share/geometry32.png', parent=parent, decimals=decimals)
+        self.decimals = decimals
 
         # Plot options
         self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options"))
@@ -1623,14 +1625,15 @@ class CNCObjectUI(ObjectUI):
     User interface for CNCJob objects.
     """
 
-    def __init__(self, parent=None):
+    def __init__(self, decimals, parent=None):
         """
         Creates the user interface for CNCJob objects. GUI elements should
         be placed in ``self.custom_box`` to preserve the layout.
         """
-
-        ObjectUI.__init__(self, title=_('CNC Job Object'), icon_file='share/cnc32.png', parent=parent)
-        self.decimals = 4
+        
+        ObjectUI.__init__(self, title=_('CNC Job Object'), icon_file='share/cnc32.png', parent=parent, 
+                          decimals=decimals)
+        self.decimals = decimals
 
         for i in range(0, self.common_grid.count()):
             self.common_grid.itemAt(i).widget().hide()
@@ -1932,7 +1935,7 @@ class ScriptObjectUI(ObjectUI):
     User interface for Script  objects.
     """
 
-    def __init__(self, parent=None):
+    def __init__(self, decimals, parent=None):
         """
         Creates the user interface for Script objects. GUI elements should
         be placed in ``self.custom_box`` to preserve the layout.
@@ -1941,7 +1944,10 @@ class ScriptObjectUI(ObjectUI):
         ObjectUI.__init__(self, title=_('Script Object'),
                           icon_file='share/script_new24.png',
                           parent=parent,
-                          common=False)
+                          common=False,
+                          decimals=decimals)
+
+        self.decimals = decimals
 
         # ## Object name
         self.name_hlay = QtWidgets.QHBoxLayout()
@@ -1984,7 +1990,7 @@ class DocumentObjectUI(ObjectUI):
     User interface for Notes objects.
     """
 
-    def __init__(self, parent=None):
+    def __init__(self, decimals, parent=None):
         """
         Creates the user interface for Notes objects. GUI elements should
         be placed in ``self.custom_box`` to preserve the layout.
@@ -1993,7 +1999,10 @@ class DocumentObjectUI(ObjectUI):
         ObjectUI.__init__(self, title=_('Document Object'),
                           icon_file='share/notes16_1.png',
                           parent=parent,
-                          common=False)
+                          common=False,
+                          decimals=decimals)
+
+        self.decimals = decimals
 
         # ## Object name
         self.name_hlay = QtWidgets.QHBoxLayout()

File diff suppressed because it is too large
+ 187 - 142
flatcamGUI/PreferencesUI.py


+ 1 - 0
flatcamParsers/ParseExcellon.py

@@ -77,6 +77,7 @@ class Excellon(Geometry):
         :return: Excellon object.
         :rtype: Excellon
         """
+        self.decimals = self.app.decimals
 
         if geo_steps_per_circle is None:
             geo_steps_per_circle = int(Excellon.defaults['geo_steps_per_circle'])

+ 1 - 0
flatcamParsers/ParseGerber.py

@@ -83,6 +83,7 @@ class Gerber(Geometry):
 
         # How to approximate a circle with lines.
         self.steps_per_circle = int(self.app.defaults["gerber_circle_steps"])
+        self.decimals = self.app.decimals
 
         # Initialize parent
         Geometry.__init__(self, geo_steps_per_circle=self.steps_per_circle)

+ 1 - 1
flatcamTools/ToolCalculators.py

@@ -30,7 +30,7 @@ class ToolCalculator(FlatCAMTool):
         FlatCAMTool.__init__(self, app)
 
         self.app = app
-        self.decimals = 6
+        self.decimals = self.app.decimals
 
         # ## Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 1 - 1
flatcamTools/ToolCalibrateExcellon.py

@@ -38,7 +38,7 @@ class ToolCalibrateExcellon(FlatCAMTool):
         self.app = app
         self.canvas = self.app.plotcanvas
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # ## Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 1 - 1
flatcamTools/ToolCopperThieving.py

@@ -45,7 +45,7 @@ class ToolCopperThieving(FlatCAMTool):
         self.app = app
         self.canvas = self.app.plotcanvas
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
         self.units = self.app.defaults['units']
 
         # ## Title

+ 1 - 1
flatcamTools/ToolCutOut.py

@@ -46,7 +46,7 @@ class CutOut(FlatCAMTool):
 
         self.app = app
         self.canvas = app.plotcanvas
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 1 - 1
flatcamTools/ToolDblSided.py

@@ -26,7 +26,7 @@ class DblSidedTool(FlatCAMTool):
 
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # ## Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 2 - 2
flatcamTools/ToolDistance.py

@@ -33,6 +33,8 @@ class Distance(FlatCAMTool):
         FlatCAMTool.__init__(self, app)
 
         self.app = app
+        self.decimals = self.app.decimals
+
         self.canvas = self.app.plotcanvas
         self.units = self.app.defaults['units'].lower()
 
@@ -135,8 +137,6 @@ class Distance(FlatCAMTool):
         self.mm = None
         self.mr = None
 
-        self.decimals = 4
-
         # VisPy visuals
         if self.app.is_legacy is False:
             self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)

+ 1 - 1
flatcamTools/ToolDistanceMin.py

@@ -36,6 +36,7 @@ class DistanceMin(FlatCAMTool):
         self.app = app
         self.canvas = self.app.plotcanvas
         self.units = self.app.defaults['units'].lower()
+        self.decimals = self.app.decimals
 
         # ## Title
         title_label = QtWidgets.QLabel("<font size=4><b>%s</b></font><br>" % self.toolName)
@@ -137,7 +138,6 @@ class DistanceMin(FlatCAMTool):
 
         self.layout.addStretch()
 
-        self.decimals = 4
         self.h_point = (0, 0)
 
         self.measure_btn.clicked.connect(self.activate_measure_tool)

+ 1 - 1
flatcamTools/ToolFiducials.py

@@ -38,7 +38,7 @@ class ToolFiducials(FlatCAMTool):
         self.app = app
         self.canvas = self.app.plotcanvas
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
         self.units = ''
 
         # ## Title

+ 1 - 1
flatcamTools/ToolFilm.py

@@ -44,7 +44,7 @@ class Film(FlatCAMTool):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 3 - 0
flatcamTools/ToolImage.py

@@ -26,6 +26,9 @@ class ToolImage(FlatCAMTool):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
 
+        self.app = app
+        self.decimals = self.app.decimals
+
         # Title
         title_label = QtWidgets.QLabel("%s" % _('Image to PCB'))
         title_label.setStyleSheet("""

+ 2 - 0
flatcamTools/ToolMove.py

@@ -30,6 +30,8 @@ class ToolMove(FlatCAMTool):
 
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
+        self.app = app
+        self.decimals = self.app.decimals
 
         self.layout.setContentsMargins(0, 0, 3, 0)
         self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Maximum)

+ 1 - 1
flatcamTools/ToolNonCopperClear.py

@@ -39,7 +39,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
 
     def __init__(self, app):
         self.app = app
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         FlatCAMTool.__init__(self, app)
         Gerber.__init__(self, steps_per_circle=self.app.defaults["gerber_circle_steps"])

+ 1 - 1
flatcamTools/ToolOptimal.py

@@ -40,7 +40,7 @@ class ToolOptimal(FlatCAMTool):
         FlatCAMTool.__init__(self, app)
 
         self.units = self.app.defaults['units'].upper()
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # ############################################################################
         # ############################ GUI creation ##################################

+ 1 - 0
flatcamTools/ToolPDF.py

@@ -44,6 +44,7 @@ class ToolPDF(FlatCAMTool):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
         self.app = app
+        self.decimals = self.app.decimals
         self.step_per_circles = self.app.defaults["gerber_circle_steps"]
 
         self.stream_re = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)

+ 1 - 1
flatcamTools/ToolPaint.py

@@ -42,7 +42,7 @@ class ToolPaint(FlatCAMTool, Gerber):
 
     def __init__(self, app):
         self.app = app
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         FlatCAMTool.__init__(self, app)
         Geometry.__init__(self, geo_steps_per_circle=self.app.defaults["geometry_circle_steps"])

+ 3 - 2
flatcamTools/ToolPanelize.py

@@ -34,8 +34,9 @@ class Panelize(FlatCAMTool):
     toolName = _("Panelize PCB")
 
     def __init__(self, app):
-        super(Panelize, self).__init__(self)
-        self.app = app
+        self.decimals = app.decimals
+
+        FlatCAMTool.__init__(self, app)
 
         # ## Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 1 - 0
flatcamTools/ToolPcbWizard.py

@@ -34,6 +34,7 @@ class PcbWizard(FlatCAMTool):
         FlatCAMTool.__init__(self, app)
 
         self.app = app
+        self.decimals = self.app.decimals
 
         # Title
         title_label = QtWidgets.QLabel("%s" % _('Import 2-file Excellon'))

+ 1 - 1
flatcamTools/ToolProperties.py

@@ -34,7 +34,7 @@ class Properties(FlatCAMTool):
 
         self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # this way I can hide/show the frame
         self.properties_frame = QtWidgets.QFrame()

+ 1 - 1
flatcamTools/ToolQRCode.py

@@ -48,7 +48,7 @@ class QRCode(FlatCAMTool):
         self.app = app
         self.canvas = self.app.plotcanvas
 
-        self.decimals = 4
+        self.decimals = self.app.decimals
         self.units = ''
 
         # ## Title

+ 3 - 3
flatcamTools/ToolRulesCheck.py

@@ -35,9 +35,9 @@ class RulesCheck(FlatCAMTool):
     tool_finished = QtCore.pyqtSignal(list)
 
     def __init__(self, app):
-        super(RulesCheck, self).__init__(self)
-        self.app = app
-        self.decimals = 4
+        self.decimals = app.decimals
+
+        FlatCAMTool.__init__(self, app)
 
         # ## Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 1 - 1
flatcamTools/ToolSolderPaste.py

@@ -40,7 +40,7 @@ class SolderPaste(FlatCAMTool):
         FlatCAMTool.__init__(self, app)
 
         # Number of decimals to be used for tools/nozzles in this FlatCAM Tool
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         # ## Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)

+ 1 - 0
flatcamTools/ToolSub.py

@@ -36,6 +36,7 @@ class ToolSub(FlatCAMTool):
 
     def __init__(self, app):
         self.app = app
+        self.decimals = self.app.decimals
 
         FlatCAMTool.__init__(self, app)
 

+ 1 - 1
flatcamTools/ToolTransform.py

@@ -30,7 +30,7 @@ class ToolTransform(FlatCAMTool):
 
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
-        self.decimals = 4
+        self.decimals = self.app.decimals
 
         self.transform_lay = QtWidgets.QVBoxLayout()
         self.layout.addLayout(self.transform_lay)

+ 3 - 5
postprocessors/Berta_CNC.py

@@ -47,7 +47,8 @@ class Berta_CNC(FlatCAMPostProc):
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
 
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
 
@@ -110,10 +111,7 @@ class Berta_CNC(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/ISEL_CNC.py

@@ -44,7 +44,8 @@ class ISEL_CNC(FlatCAMPostProc):
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
 
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
 
@@ -84,10 +85,7 @@ class ISEL_CNC(FlatCAMPostProc):
         f_plunge = p.f_plunge
         no_drills = 1
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 6 - 5
postprocessors/Paste_1.py

@@ -36,7 +36,8 @@ class Paste_1(FlatCAMPostProc_Tools):
         gcode += '(Z_Travel: ' + str(p['z_travel']) + units + ')\n'
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
 
-        gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+        gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                       p.decimals, coords_xy[1]) + units + ')\n'
 
         if 'Paste' in p.pp_solderpaste_name:
             gcode += '(Postprocessor SolderPaste Dispensing Geometry: ' + str(p.pp_solderpaste_name) + ')\n' + '\n'
@@ -74,11 +75,11 @@ class Paste_1(FlatCAMPostProc_Tools):
         if toolchangexy is not None:
             x_toolchange = toolchangexy[0]
             y_toolchange = toolchangexy[1]
-
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(float(p['toolC']), '.2f')
         else:
-            toolC_formatted = format(float(p['toolC']), '.4f')
+            x_toolchange = 0.0
+            y_toolchange = 0.0
+
+        toolC_formatted = '%.*f' % (p.decimals, float(p['toolC']))
 
         if toolchangexy is not None:
             gcode = """

+ 3 - 5
postprocessors/Repetier.py

@@ -45,7 +45,8 @@ class Repetier(FlatCAMPostProc):
         gcode += ';Z Toolchange: ' + str(p['z_toolchange']) + units + '\n'
 
         if coords_xy is not None:
-            gcode += ';X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + '\n'
+            gcode += ';X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + '\n'
         else:
             gcode += ';X,Y Toolchange: ' + "None" + units + '\n'
 
@@ -95,10 +96,7 @@ class Repetier(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/Toolchange_Custom.py

@@ -44,7 +44,8 @@ class Toolchange_Custom(FlatCAMPostProc):
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
 
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
 
@@ -93,10 +94,7 @@ class Toolchange_Custom(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/Toolchange_Probe_MACH3.py

@@ -45,7 +45,8 @@ class Toolchange_Probe_MACH3(FlatCAMPostProc):
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
 
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
 
@@ -99,10 +100,7 @@ class Toolchange_Probe_MACH3(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/Toolchange_manual.py

@@ -43,7 +43,8 @@ class Toolchange_manual(FlatCAMPostProc):
         gcode += '(Z_Move: ' + str(p['z_move']) + units + ')\n'
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
         gcode += '(Z Start: ' + str(p['startz']) + units + ')\n'
@@ -97,10 +98,7 @@ class Toolchange_manual(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/default.py

@@ -44,7 +44,8 @@ class default(FlatCAMPostProc):
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
 
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
 
@@ -95,10 +96,7 @@ class default(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/grbl_11.py

@@ -43,7 +43,8 @@ class grbl_11(FlatCAMPostProc):
         gcode += '(Z_Move: ' + str(p['z_move']) + units + ')\n'
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
         gcode += '(Z Start: ' + str(p['startz']) + units + ')\n'
@@ -94,10 +95,7 @@ class grbl_11(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/line_xyz.py

@@ -43,7 +43,8 @@ class line_xyz(FlatCAMPostProc):
         gcode += '(Z_Move: ' + str(p['z_move']) + units + ')\n'
         gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
         if coords_xy is not None:
-            gcode += '(X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + ')\n'
+            gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + ')\n'
         else:
             gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
         gcode += '(Z Start: ' + str(p['startz']) + units + ')\n'
@@ -109,10 +110,7 @@ class line_xyz(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 3 - 5
postprocessors/marlin.py

@@ -45,7 +45,8 @@ class marlin(FlatCAMPostProc):
         gcode += ';Z Toolchange: ' + str(p['z_toolchange']) + units + '\n'
 
         if coords_xy is not None:
-            gcode += ';X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + '\n'
+            gcode += ';X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+                                                           p.decimals, coords_xy[1]) + units + '\n'
         else:
             gcode += ';X,Y Toolchange: ' + "None" + units + '\n'
 
@@ -95,10 +96,7 @@ class marlin(FlatCAMPostProc):
         if int(p.tool) == 1 and p.startz is not None:
             z_toolchange = p.startz
 
-        if p.units.upper() == 'MM':
-            toolC_formatted = format(p.toolC, '.2f')
-        else:
-            toolC_formatted = format(p.toolC, '.4f')
+        toolC_formatted = '%.*f' % (p.decimals, p.toolC)
 
         if str(p['options']['type']) == 'Excellon':
             for i in p['options']['Tools_in_use']:

+ 12 - 12
tclCommands/TclCommandCopperClear.py

@@ -89,6 +89,17 @@ class TclCommandCopperClear(TclCommand):
 
         name = args['name']
 
+        # Get source object.
+        try:
+            obj = self.app.collection.get_by_name(str(name))
+        except Exception as e:
+            log.debug("TclCommandCopperClear.execute() --> %s" % str(e))
+            self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
+            return "Could not retrieve object: %s" % name
+
+        if obj is None:
+            return "Object not found: %s" % name
+
         if 'tooldia' in args:
             tooldia = str(args['tooldia'])
         else:
@@ -181,7 +192,7 @@ class TclCommandCopperClear(TclCommand):
             tooluid += 1
             ncc_tools.update({
                 int(tooluid): {
-                    'tooldia': float('%.4f' % tool),
+                    'tooldia': float('%.*f' % (obj.decimals, tool)),
                     'offset': 'Path',
                     'offset_value': 0.0,
                     'type': 'Iso',
@@ -204,17 +215,6 @@ class TclCommandCopperClear(TclCommand):
             else:
                 outname = name + "_ncc_rm"
 
-        # Get source object.
-        try:
-            obj = self.app.collection.get_by_name(str(name))
-        except Exception as e:
-            log.debug("TclCommandCopperClear.execute() --> %s" % str(e))
-            self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
-            return "Could not retrieve object: %s" % name
-
-        if obj is None:
-            return "Object not found: %s" % name
-
         # Non-Copper clear all polygons in the non-copper clear object
         if 'all' in args and args['all'] == 1:
             self.app.ncclear_tool.clear_copper(ncc_obj=obj,

+ 9 - 11
tclCommands/TclCommandDrillcncjob.py

@@ -89,6 +89,13 @@ class TclCommandDrillcncjob(TclCommandSignaled):
 
         name = args['name']
 
+        obj = self.app.collection.get_by_name(name)
+        if obj is None:
+            if muted == 0:
+                self.raise_tcl_error("Object not found: %s" % name)
+            else:
+                return "fail"
+
         if 'outname' not in args:
             args['outname'] = name + "_cnc"
 
@@ -97,13 +104,6 @@ class TclCommandDrillcncjob(TclCommandSignaled):
         else:
             muted = 0
 
-        obj = self.app.collection.get_by_name(name)
-        if obj is None:
-            if muted == 0:
-                self.raise_tcl_error("Object not found: %s" % name)
-            else:
-                return "fail"
-
         if not isinstance(obj, FlatCAMExcellon):
             if muted == 0:
                 self.raise_tcl_error('Expected FlatCAMExcellon, got %s %s.' % (name, type(obj)))
@@ -127,10 +127,8 @@ class TclCommandDrillcncjob(TclCommandSignaled):
                     req_tools = set()
                     for tool in obj.tools:
                         for req_dia in diameters:
-                            obj_dia_form = float('%.2f' % float(obj.tools[tool]["C"])) if units == 'MM' else \
-                                float('%.4f' % float(obj.tools[tool]["C"]))
-                            req_dia_form = float('%.2f' % float(req_dia)) if units == 'MM' else \
-                                float('%.4f' % float(req_dia))
+                            obj_dia_form = float('%.*f' % (obj.decimals, float(obj.tools[tool]["C"])))
+                            req_dia_form = float('%.*f' % (obj.decimals, float(req_dia)))
 
                             if 'diatol' in args:
                                 tolerance = args['diatol'] / 100

+ 5 - 7
tclCommands/TclCommandMillDrills.py

@@ -70,15 +70,15 @@ class TclCommandMillDrills(TclCommandSignaled):
 
         name = args['name']
 
-        if 'outname' not in args:
-            args['outname'] = name + "_mill_drills"
-
         try:
             obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
             obj = None
             self.raise_tcl_error("Could not retrieve object: %s" % name)
 
+        if 'outname' not in args:
+            args['outname'] = name + "_mill_drills"
+
         if not obj.drills:
             self.raise_tcl_error("The Excellon object has no drills: %s" % name)
 
@@ -92,10 +92,8 @@ class TclCommandMillDrills(TclCommandSignaled):
                 req_tools = set()
                 for tool in obj.tools:
                     for req_dia in diameters:
-                        obj_dia_form = float('%.2f' % float(obj.tools[tool]["C"])) if units == 'MM' else \
-                            float('%.4f' % float(obj.tools[tool]["C"]))
-                        req_dia_form = float('%.2f' % float(req_dia)) if units == 'MM' else \
-                            float('%.4f' % float(req_dia))
+                        obj_dia_form = float('%.*f' % (obj.decimals, float(obj.tools[tool]["C"])))
+                        req_dia_form = float('%.*f' % (obj.decimals, float(req_dia)))
 
                         if 'diatol' in args:
                             tolerance = args['diatol'] / 100

+ 5 - 7
tclCommands/TclCommandMillSlots.py

@@ -70,15 +70,15 @@ class TclCommandMillSlots(TclCommandSignaled):
 
         name = args['name']
 
-        if 'outname' not in args:
-            args['outname'] = name + "_mill_slots"
-
         try:
             obj = self.app.collection.get_by_name(str(name))
         except Exception:
             obj = None
             self.raise_tcl_error("Could not retrieve object: %s" % name)
 
+        if 'outname' not in args:
+            args['outname'] = name + "_mill_slots"
+
         if not obj.slots:
             self.raise_tcl_error("The Excellon object has no slots: %s" % name)
 
@@ -91,10 +91,8 @@ class TclCommandMillSlots(TclCommandSignaled):
                 req_tools = set()
                 for tool in obj.tools:
                     for req_dia in diameters:
-                        obj_dia_form = float('%.2f' % float(obj.tools[tool]["C"])) if units == 'MM' else \
-                            float('%.4f' % float(obj.tools[tool]["C"]))
-                        req_dia_form = float('%.2f' % float(req_dia)) if units == 'MM' else \
-                            float('%.4f' % float(req_dia))
+                        obj_dia_form = float('%.*f' % (obj.decimals, float(obj.tools[tool]["C"])))
+                        req_dia_form = float('%.*f' % (obj.decimals, float(req_dia)))
 
                         if 'diatol' in args:
                             tolerance = args['diatol'] / 100

+ 9 - 9
tclCommands/TclCommandPaint.py

@@ -89,6 +89,14 @@ class TclCommandPaint(TclCommand):
 
         name = args['name']
 
+        # Get source object.
+        try:
+            obj = self.app.collection.get_by_name(str(name))
+        except Exception as e:
+            log.debug("TclCommandPaint.execute() --> %s" % str(e))
+            self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
+            return "Could not retrieve object: %s" % name
+
         if 'tooldia' in args:
             tooldia = str(args['tooldia'])
         else:
@@ -129,14 +137,6 @@ class TclCommandPaint(TclCommand):
         else:
             outname = name + "_paint"
 
-        # Get source object.
-        try:
-            obj = self.app.collection.get_by_name(str(name))
-        except Exception as e:
-            log.debug("TclCommandPaint.execute() --> %s" % str(e))
-            self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
-            return "Could not retrieve object: %s" % name
-
         try:
             tools = [float(eval(dia)) for dia in tooldia.split(",") if dia != '']
         except AttributeError:
@@ -181,7 +181,7 @@ class TclCommandPaint(TclCommand):
             tooluid += 1
             paint_tools.update({
                 int(tooluid): {
-                    'tooldia': float('%.4f' % tool),
+                    'tooldia': float('%.*f' % (obj.decimals, tool)),
                     'offset': 'Path',
                     'offset_value': 0.0,
                     'type': 'Iso',

Some files were not shown because too many files changed in this diff