Просмотр исходного кода

- cleaned up the Excellon parser and fixed some bugs (old and new); Excellon parser has it's own convert_units() method no longer inheriting from Geometry
- in Excellon UI fixed bug that did not allow editing of the Offset Z parameter from the Tool table

Marius Stanciu 6 лет назад
Родитель
Сommit
13f67786af
3 измененных файлов с 116 добавлено и 105 удалено
  1. 48 51
      FlatCAMObj.py
  2. 2 0
      README.md
  3. 66 54
      flatcamParsers/ParseExcellon.py

+ 48 - 51
FlatCAMObj.py

@@ -267,7 +267,7 @@ class FlatCAMObj(QtCore.QObject):
         self.app.worker_task.emit({'fcn': worker_task, 'params': []})
         self.app.worker_task.emit({'fcn': worker_task, 'params': []})
 
 
     def on_scale_button_click(self):
     def on_scale_button_click(self):
-        self.app.report_usage("obj_on_scale_button")
+        log.debug("FlatCAMObj.on_scale_button_click()")
         self.read_form()
         self.read_form()
         factor = self.ui.scale_entry.get_value()
         factor = self.ui.scale_entry.get_value()
 
 
@@ -2338,11 +2338,13 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
 
         self.units = self.app.defaults['units'].upper()
         self.units = self.app.defaults['units'].upper()
 
 
-        try:
-            # if connected, disconnect the signal from the slot on item_changed as it creates issues
-            self.ui.tools_table.itemChanged.disconnect()
-        except (TypeError, AttributeError):
-            pass
+        for row in range(self.ui.tools_table.rowCount()):
+            try:
+                # if connected, disconnect the signal from the slot on item_changed as it creates issues
+                offset_spin_widget = self.ui.tools_table.cellWidget(row, 4)
+                offset_spin_widget.valueChanged.disconnect()
+            except (TypeError, AttributeError):
+                pass
 
 
         n = len(self.tools)
         n = len(self.tools)
         # we have (n+2) rows because there are 'n' tools, each a row, plus the last 2 rows for totals.
         # we have (n+2) rows because there are 'n' tools, each a row, plus the last 2 rows for totals.
@@ -2378,45 +2380,42 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
 
             self.tot_slot_cnt += slot_cnt
             self.tot_slot_cnt += slot_cnt
 
 
-            exc_id = QtWidgets.QTableWidgetItem('%d' % int(tool_no))
-            exc_id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
-            self.ui.tools_table.setItem(self.tool_row, 0, exc_id)  # Tool name/id
+            exc_id_item = QtWidgets.QTableWidgetItem('%d' % int(tool_no))
+            exc_id_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
 
 
-            # Make sure that the drill diameter when in MM is with no more than 2 decimals
-            # There are no drill bits in MM with more than 3 decimals diameter
-            # For INCH the decimals should be no more than 3. There are no drills under 10mils
-
-            dia = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, self.tools[tool_no]['C']))
-
-            dia.setFlags(QtCore.Qt.ItemIsEnabled)
+            dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, self.tools[tool_no]['C']))
+            dia_item.setFlags(QtCore.Qt.ItemIsEnabled)
 
 
-            drill_count = QtWidgets.QTableWidgetItem('%d' % drill_cnt)
-            drill_count.setFlags(QtCore.Qt.ItemIsEnabled)
+            drill_count_item = QtWidgets.QTableWidgetItem('%d' % drill_cnt)
+            drill_count_item.setFlags(QtCore.Qt.ItemIsEnabled)
 
 
             # if the slot number is zero is better to not clutter the GUI with zero's so we print a space
             # if the slot number is zero is better to not clutter the GUI with zero's so we print a space
-            if slot_cnt > 0:
-                slot_count = QtWidgets.QTableWidgetItem('%d' % slot_cnt)
-            else:
-                slot_count = QtWidgets.QTableWidgetItem('')
-            slot_count.setFlags(QtCore.Qt.ItemIsEnabled)
+            slot_count_str = '%d' % slot_cnt if slot_cnt > 0 else ''
+            slot_count_item = QtWidgets.QTableWidgetItem(slot_count_str)
+            slot_count_item.setFlags(QtCore.Qt.ItemIsEnabled)
 
 
             try:
             try:
                 t_offset = self.tool_offset[float('%.*f' % (self.decimals, float(self.tools[tool_no]['C'])))]
                 t_offset = self.tool_offset[float('%.*f' % (self.decimals, float(self.tools[tool_no]['C'])))]
             except KeyError:
             except KeyError:
                 t_offset = self.app.defaults['excellon_offset']
                 t_offset = self.app.defaults['excellon_offset']
 
 
-            tool_offset_item = QtWidgets.QTableWidgetItem('%s' % str(t_offset))
-            tool_offset_item.setFlags(QtCore.Qt.ItemIsEnabled)
+            tool_offset_item = FCDoubleSpinner()
+            tool_offset_item.set_precision(self.decimals)
+            tool_offset_item.set_range(-9999.9999, 9999.9999)
+            tool_offset_item.setWrapping(True)
+            tool_offset_item.setSingleStep(0.1) if self.units == 'MM' else tool_offset_item.setSingleStep(0.01)
+            tool_offset_item.set_value(t_offset)
 
 
             plot_item = FCCheckBox()
             plot_item = FCCheckBox()
             plot_item.setLayoutDirection(QtCore.Qt.RightToLeft)
             plot_item.setLayoutDirection(QtCore.Qt.RightToLeft)
             if self.ui.plot_cb.isChecked():
             if self.ui.plot_cb.isChecked():
                 plot_item.setChecked(True)
                 plot_item.setChecked(True)
 
 
-            self.ui.tools_table.setItem(self.tool_row, 1, dia)  # Diameter
-            self.ui.tools_table.setItem(self.tool_row, 2, drill_count)  # Number of drills per tool
-            self.ui.tools_table.setItem(self.tool_row, 3, slot_count)  # Number of drills per tool
-            self.ui.tools_table.setItem(self.tool_row, 4, tool_offset_item)  # Tool offset
+            self.ui.tools_table.setItem(self.tool_row, 0, exc_id_item)  # Tool name/id
+            self.ui.tools_table.setItem(self.tool_row, 1, dia_item)  # Diameter
+            self.ui.tools_table.setItem(self.tool_row, 2, drill_count_item)  # Number of drills per tool
+            self.ui.tools_table.setItem(self.tool_row, 3, slot_count_item)  # Number of drills per tool
+            self.ui.tools_table.setCellWidget(self.tool_row, 4, tool_offset_item)  # Tool offset
             empty_plot_item = QtWidgets.QTableWidgetItem('')
             empty_plot_item = QtWidgets.QTableWidgetItem('')
             empty_plot_item.setFlags(~QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
             empty_plot_item.setFlags(~QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
             self.ui.tools_table.setItem(self.tool_row, 5, empty_plot_item)
             self.ui.tools_table.setItem(self.tool_row, 5, empty_plot_item)
@@ -2538,7 +2537,12 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
             self.ui.generate_milling_slots_button.show()
             self.ui.generate_milling_slots_button.show()
 
 
         # we reactivate the signals after the after the tool adding as we don't need to see the tool been populated
         # we reactivate the signals after the after the tool adding as we don't need to see the tool been populated
-        self.ui.tools_table.itemChanged.connect(self.on_tool_offset_edit)
+        for row in range(self.ui.tools_table.rowCount()):
+            try:
+                offset_spin_widget = self.ui.tools_table.cellWidget(row, 4)
+                offset_spin_widget.valueChanged.connect(self.on_tool_offset_edit)
+            except (TypeError, AttributeError):
+                pass
 
 
         self.ui_connect()
         self.ui_connect()
 
 
@@ -2647,36 +2651,29 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
 
     def on_tool_offset_edit(self):
     def on_tool_offset_edit(self):
         # if connected, disconnect the signal from the slot on item_changed as it creates issues
         # if connected, disconnect the signal from the slot on item_changed as it creates issues
-        self.ui.tools_table.itemChanged.disconnect()
-        # self.tools_table_exc.selectionModel().currentChanged.disconnect()
+        for row in range(self.ui.tools_table.rowCount()):
+            try:
+                # if connected, disconnect the signal from the slot on item_changed as it creates issues
+                offset_spin_widget = self.ui.tools_table.cellWidget(row, 4)
+                offset_spin_widget.valueChanged.disconnect()
+            except (TypeError, AttributeError):
+                pass
 
 
         self.units = self.app.defaults['units'].upper()
         self.units = self.app.defaults['units'].upper()
-
         self.is_modified = True
         self.is_modified = True
 
 
         row_of_item_changed = self.ui.tools_table.currentRow()
         row_of_item_changed = self.ui.tools_table.currentRow()
         dia = float('%.*f' % (self.decimals, float(self.ui.tools_table.item(row_of_item_changed, 1).text())))
         dia = float('%.*f' % (self.decimals, float(self.ui.tools_table.item(row_of_item_changed, 1).text())))
 
 
-        current_table_offset_edited = None
-        if self.ui.tools_table.currentItem() is not None:
-            try:
-                current_table_offset_edited = float(self.ui.tools_table.currentItem().text())
-            except ValueError:
-                # try to convert comma to decimal point. if it's still not working error message and return
-                try:
-                    current_table_offset_edited = float(self.ui.tools_table.currentItem().text().replace(',', '.'))
-                    self.ui.tools_table.currentItem().setText(
-                        self.ui.tools_table.currentItem().text().replace(',', '.'))
-                except ValueError:
-                    self.app.inform.emit('[ERROR_NOTCL] %s' %
-                                         _("Wrong value format entered, use a number."))
-                    self.ui.tools_table.currentItem().setText(str(self.tool_offset[dia]))
-                    return
-
-        self.tool_offset[dia] = current_table_offset_edited
+        self.tool_offset[dia] = self.sender().get_value()
 
 
         # we reactivate the signals after the after the tool editing
         # we reactivate the signals after the after the tool editing
-        self.ui.tools_table.itemChanged.connect(self.on_tool_offset_edit)
+        for row in range(self.ui.tools_table.rowCount()):
+            try:
+                offset_spin_widget = self.ui.tools_table.cellWidget(row, 4)
+                offset_spin_widget.valueChanged.connect(self.on_tool_offset_edit)
+            except (TypeError, AttributeError):
+                pass
 
 
     def get_selected_tools_list(self):
     def get_selected_tools_list(self):
         """
         """

+ 2 - 0
README.md

@@ -12,6 +12,8 @@ CAD program, and create G-Code for Isolation routing.
 6.12.2019
 6.12.2019
 
 
 - fixed the toggle_units() method so now the grid values are accurate to the decimal
 - fixed the toggle_units() method so now the grid values are accurate to the decimal
+- cleaned up the Excellon parser and fixed some bugs (old and new); Excellon parser has it's own convert_units() method no longer inheriting from Geometry
+- in Excellon UI fixed bug that did not allow editing of the Offset Z parameter from the Tool table
 
 
 5.12.2019 
 5.12.2019 
 
 

+ 66 - 54
flatcamParsers/ParseExcellon.py

@@ -90,7 +90,6 @@ class Excellon(Geometry):
         self.tools = {}
         self.tools = {}
         # list to store the drills, see above for description
         # list to store the drills, see above for description
         self.drills = []
         self.drills = []
-
         # self.slots (list) to store the slots; each is a dictionary
         # self.slots (list) to store the slots; each is a dictionary
         self.slots = []
         self.slots = []
 
 
@@ -107,7 +106,7 @@ class Excellon(Geometry):
         self.index_per_tool = {}  # Dictionary to store the indexed points for each tool
         self.index_per_tool = {}  # Dictionary to store the indexed points for each tool
 
 
         # ## IN|MM -> Units are inherited from Geometry
         # ## IN|MM -> Units are inherited from Geometry
-        # self.units = units
+        self.units = self.app.defaults['units']
 
 
         # Trailing "T" or leading "L" (default)
         # Trailing "T" or leading "L" (default)
         # self.zeros = "T"
         # self.zeros = "T"
@@ -305,8 +304,7 @@ class Excellon(Geometry):
                 # and we need to exit from here
                 # and we need to exit from here
                 if self.detect_gcode_re.search(eline):
                 if self.detect_gcode_re.search(eline):
                     log.warning("This is GCODE mark: %s" % eline)
                     log.warning("This is GCODE mark: %s" % eline)
-                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
-                                         (_('This is GCODE mark'), eline))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_('This is GCODE mark'), eline))
                     return
                     return
 
 
                 # Header Begin (M48) #
                 # Header Begin (M48) #
@@ -341,11 +339,11 @@ class Excellon(Geometry):
                             if line_units == 'MILS':
                             if line_units == 'MILS':
                                 spec = {"C": (float(match.group(2)) / 1000)}
                                 spec = {"C": (float(match.group(2)) / 1000)}
                                 self.tools[str(name_tool)] = spec
                                 self.tools[str(name_tool)] = spec
-                                log.debug("  Tool definition: %s %s" % (name_tool, spec))
+                                log.debug("Tool definition: %s %s" % (name_tool, spec))
                             else:
                             else:
                                 spec = {"C": float(match.group(2))}
                                 spec = {"C": float(match.group(2))}
                                 self.tools[str(name_tool)] = spec
                                 self.tools[str(name_tool)] = spec
-                                log.debug("  Tool definition: %s %s" % (name_tool, spec))
+                                log.debug("Tool definition: %s %s" % (name_tool, spec))
                             spec['solid_geometry'] = []
                             spec['solid_geometry'] = []
                             continue
                             continue
                     # search for Altium Excellon Format / Sprint Layout who is included as a comment
                     # search for Altium Excellon Format / Sprint Layout who is included as a comment
@@ -387,17 +385,18 @@ class Excellon(Geometry):
                 # object's units.
                 # object's units.
                 match = self.meas_re.match(eline)
                 match = self.meas_re.match(eline)
                 if match:
                 if match:
-                    # self.units = {"1": "MM", "2": "IN"}[match.group(1)]
+                    self.units = {"1": "MM", "2": "IN"}[match.group(1)]
 
 
                     # Modified for issue #80
                     # Modified for issue #80
-                    self.convert_units({"1": "MM", "2": "IN"}[match.group(1)])
-                    log.debug("  Units: %s" % self.units)
+                    log.debug("ALternative M71/M72 units found, before conversion: %s" % self.units)
+                    self.convert_units(self.units)
+                    log.debug("ALternative M71/M72 units found, after conversion: %s" % self.units)
                     if self.units == 'MM':
                     if self.units == 'MM':
-                        log.warning("Excellon format preset is: %s" % self.excellon_format_upper_mm + \
-                                    ':' + str(self.excellon_format_lower_mm))
+                        log.warning("Excellon format preset is: %s:%s" %
+                                    (str(self.excellon_format_upper_mm), str(self.excellon_format_lower_mm)))
                     else:
                     else:
-                        log.warning("Excellon format preset is: %s" % self.excellon_format_upper_in + \
-                                    ':' + str(self.excellon_format_lower_in))
+                        log.warning("Excellon format preset is: %s:%s" %
+                                    (str(self.excellon_format_upper_in), str(self.excellon_format_lower_in)))
                     continue
                     continue
 
 
                 # ### Body ####
                 # ### Body ####
@@ -784,13 +783,13 @@ class Excellon(Geometry):
                     # ## Units and number format # ##
                     # ## Units and number format # ##
                     match = self.units_re.match(eline)
                     match = self.units_re.match(eline)
                     if match:
                     if match:
-                        self.units = match.group(1)
+                        self.units = self.units = {"METRIC": "MM", "INCH": "IN"}[match.group(1)]
                         self.zeros = match.group(2)  # "T" or "L". Might be empty
                         self.zeros = match.group(2)  # "T" or "L". Might be empty
                         self.excellon_format = match.group(3)
                         self.excellon_format = match.group(3)
                         if self.excellon_format:
                         if self.excellon_format:
                             upper = len(self.excellon_format.partition('.')[0])
                             upper = len(self.excellon_format.partition('.')[0])
                             lower = len(self.excellon_format.partition('.')[2])
                             lower = len(self.excellon_format.partition('.')[2])
-                            if self.units == 'METRIC':
+                            if self.units == 'MM':
                                 self.excellon_format_upper_mm = upper
                                 self.excellon_format_upper_mm = upper
                                 self.excellon_format_lower_mm = lower
                                 self.excellon_format_lower_mm = lower
                             else:
                             else:
@@ -798,57 +797,55 @@ class Excellon(Geometry):
                                 self.excellon_format_lower_in = lower
                                 self.excellon_format_lower_in = lower
 
 
                         # Modified for issue #80
                         # Modified for issue #80
-                        self.convert_units({"INCH": "IN", "METRIC": "MM"}[self.units])
-                        # log.warning("  Units/Format: %s %s" % (self.units, self.zeros))
-                        log.warning("Units: %s" % self.units)
+                        log.warning("UNITS found inline before conversion: %s" % self.units)
+                        self.convert_units(self.units)
+                        log.warning("UNITS found inline after conversion: %s" % self.units)
                         if self.units == 'MM':
                         if self.units == 'MM':
-                            log.warning("Excellon format preset is: %s" % str(self.excellon_format_upper_mm) +
-                                        ':' + str(self.excellon_format_lower_mm))
+                            log.warning("Excellon format preset is: %s:%s" %
+                                        (str(self.excellon_format_upper_mm), str(self.excellon_format_lower_mm)))
                         else:
                         else:
-                            log.warning("Excellon format preset is: %s" % str(self.excellon_format_upper_in) +
-                                        ':' + str(self.excellon_format_lower_in))
-                        log.warning("Type of zeros found inline: %s" % self.zeros)
+                            log.warning("Excellon format preset is: %s:%s" %
+                                        (str(self.excellon_format_upper_in), str(self.excellon_format_lower_in)))
+                        log.warning("Type of ZEROS found inline, in header: %s" % self.zeros)
                         continue
                         continue
 
 
                     # Search for units type again it might be alone on the line
                     # Search for units type again it might be alone on the line
                     if "INCH" in eline:
                     if "INCH" in eline:
-                        line_units = "INCH"
+                        line_units = "IN"
                         # Modified for issue #80
                         # Modified for issue #80
-                        self.convert_units({"INCH": "IN", "METRIC": "MM"}[line_units])
-                        log.warning("Type of UNITS found inline: %s" % line_units)
-                        log.warning("Excellon format preset is: %s" % str(self.excellon_format_upper_in) +
-                                    ':' + str(self.excellon_format_lower_in))
-                        # TODO: not working
-                        # FlatCAMApp.App.inform.emit("Detected INLINE: %s" % str(eline))
+                        log.warning("Type of UNITS found inline, in header, before conversion: %s" % line_units)
+                        self.convert_units(line_units)
+                        log.warning("Type of UNITS found inline, in header, after conversion: %s" % self.units)
+                        log.warning("Excellon format preset is: %s:%s" %
+                                    (str(self.excellon_format_upper_in), str(self.excellon_format_lower_in)))
                         continue
                         continue
                     elif "METRIC" in eline:
                     elif "METRIC" in eline:
-                        line_units = "METRIC"
+                        line_units = "MM"
                         # Modified for issue #80
                         # Modified for issue #80
-                        self.convert_units({"INCH": "IN", "METRIC": "MM"}[line_units])
-                        log.warning("Type of UNITS found inline: %s" % line_units)
-                        log.warning("Excellon format preset is: %s" % str(self.excellon_format_upper_mm) +
-                                    ':' + str(self.excellon_format_lower_mm))
-                        # TODO: not working
-                        # FlatCAMApp.App.inform.emit("Detected INLINE: %s" % str(eline))
+                        log.warning("Type of UNITS found inline, in header, before conversion: %s" % line_units)
+                        self.convert_units(line_units)
+                        log.warning("Type of UNITS found inline, in header, after conversion: %s" % self.units)
+                        log.warning("Excellon format preset is: %s:%s" %
+                                    (str(self.excellon_format_upper_mm), str(self.excellon_format_lower_mm)))
                         continue
                         continue
 
 
                     # Search for zeros type again because it might be alone on the line
                     # Search for zeros type again because it might be alone on the line
                     match = re.search(r'[LT]Z', eline)
                     match = re.search(r'[LT]Z', eline)
                     if match:
                     if match:
                         self.zeros = match.group()
                         self.zeros = match.group()
-                        log.warning("Type of zeros found: %s" % self.zeros)
+                        log.warning("Type of ZEROS found: %s" % self.zeros)
                         continue
                         continue
 
 
                 # ## Units and number format outside header# ##
                 # ## Units and number format outside header# ##
                 match = self.units_re.match(eline)
                 match = self.units_re.match(eline)
                 if match:
                 if match:
-                    self.units = match.group(1)
+                    self.units = self.units = {"METRIC": "MM", "INCH": "IN"}[match.group(1)]
                     self.zeros = match.group(2)  # "T" or "L". Might be empty
                     self.zeros = match.group(2)  # "T" or "L". Might be empty
                     self.excellon_format = match.group(3)
                     self.excellon_format = match.group(3)
                     if self.excellon_format:
                     if self.excellon_format:
                         upper = len(self.excellon_format.partition('.')[0])
                         upper = len(self.excellon_format.partition('.')[0])
                         lower = len(self.excellon_format.partition('.')[2])
                         lower = len(self.excellon_format.partition('.')[2])
-                        if self.units == 'METRIC':
+                        if self.units == 'MM':
                             self.excellon_format_upper_mm = upper
                             self.excellon_format_upper_mm = upper
                             self.excellon_format_lower_mm = lower
                             self.excellon_format_lower_mm = lower
                         else:
                         else:
@@ -856,18 +853,17 @@ class Excellon(Geometry):
                             self.excellon_format_lower_in = lower
                             self.excellon_format_lower_in = lower
 
 
                     # Modified for issue #80
                     # Modified for issue #80
-                    self.convert_units({"INCH": "IN", "METRIC": "MM"}[self.units])
-                    # log.warning("  Units/Format: %s %s" % (self.units, self.zeros))
-                    log.warning("Units: %s" % self.units)
+                    log.warning("Type of UNITS found outside header, inline before conversion: %s" % self.units)
+                    self.convert_units(self.units)
+                    log.warning("Type of UNITS found outside header, inline after conversion: %s" % self.units)
+
                     if self.units == 'MM':
                     if self.units == 'MM':
-                        log.warning("Excellon format preset is: %s" % str(self.excellon_format_upper_mm) +
-                                    ':' + str(self.excellon_format_lower_mm))
+                        log.warning("Excellon format preset is: %s:%s" %
+                                    (str(self.excellon_format_upper_mm), str(self.excellon_format_lower_mm)))
                     else:
                     else:
-                        log.warning("Excellon format preset is: %s" % str(self.excellon_format_upper_in) +
-                                    ':' + str(self.excellon_format_lower_in))
-                    log.warning("Type of zeros found outside header, inline: %s" % self.zeros)
-
-                    log.warning("UNITS found outside header")
+                        log.warning("Excellon format preset is: %s:%s" %
+                                    (str(self.excellon_format_upper_in), str(self.excellon_format_lower_in)))
+                    log.warning("Type of ZEROS found outside header, inline: %s" % self.zeros)
                     continue
                     continue
 
 
                 log.warning("Line ignored: %s" % eline)
                 log.warning("Line ignored: %s" % eline)
@@ -875,6 +871,7 @@ class Excellon(Geometry):
             # make sure that since we are in headerless mode, we convert the tools only after the file parsing
             # make sure that since we are in headerless mode, we convert the tools only after the file parsing
             # is finished since the tools definitions are spread in the Excellon body. We use as units the value
             # is finished since the tools definitions are spread in the Excellon body. We use as units the value
             # from self.defaults['excellon_units']
             # from self.defaults['excellon_units']
+
             log.info("Zeros: %s, Units %s." % (self.zeros, self.units))
             log.info("Zeros: %s, Units %s." % (self.zeros, self.units))
         except Exception:
         except Exception:
             log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline))
             log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline))
@@ -950,6 +947,8 @@ class Excellon(Geometry):
 
 
         :return: None
         :return: None
         """
         """
+
+        log.debug("flatcamParsers.ParseExcellon.Excellon.create_geometry()")
         self.solid_geometry = []
         self.solid_geometry = []
         try:
         try:
             # clear the solid_geometry in self.tools
             # clear the solid_geometry in self.tools
@@ -1084,16 +1083,29 @@ class Excellon(Geometry):
         :type str: IN or MM
         :type str: IN or MM
         :return:
         :return:
         """
         """
-        log.debug("camlib.Excellon.convert_units()")
 
 
-        factor = Geometry.convert_units(self, units)
+        # factor = Geometry.convert_units(self, units)
+        obj_units = units
+        if obj_units.upper() == self.units.upper():
+            factor = 1.0
+        elif obj_units.upper() == "MM":
+            factor = 25.4
+        elif obj_units.upper() == "IN":
+            factor = 1 / 25.4
+        else:
+            log.error("Unsupported units: %s" % str(obj_units))
+            factor = 1.0
+        log.debug("flatcamParsers.ParseExcellon.Excellon.convert_units() --> Factor: %s" % str(factor))
+
+        self.units = obj_units
+        self.scale(factor, factor)
+        self.file_units_factor = factor
 
 
         # Tools
         # Tools
         for tname in self.tools:
         for tname in self.tools:
             self.tools[tname]["C"] *= factor
             self.tools[tname]["C"] *= factor
 
 
         self.create_geometry()
         self.create_geometry()
-
         return factor
         return factor
 
 
     def scale(self, xfactor, yfactor=None, point=None):
     def scale(self, xfactor, yfactor=None, point=None):
@@ -1108,7 +1120,7 @@ class Excellon(Geometry):
         :return: None
         :return: None
         :rtype: NOne
         :rtype: NOne
         """
         """
-        log.debug("camlib.Excellon.scale()")
+        log.debug("flatcamParsers.ParseExcellon.Excellon..scale()")
 
 
         if yfactor is None:
         if yfactor is None:
             yfactor = xfactor
             yfactor = xfactor