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

- fixed the loading of Excellon with slots and the saving of edited Excellon object in regard of slots, in Excellon Editor
- fixed the Delete tool, Select tool in Excellon Editor to work for Slots too

Marius Stanciu 6 лет назад
Родитель
Сommit
c0cd61df3f
2 измененных файлов с 215 добавлено и 75 удалено
  1. 5 0
      README.md
  2. 210 75
      flatcamEditors/FlatCAMExcEditor.py

+ 5 - 0
README.md

@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+14.08.2019
+
+- fixed the loading of Excellon with slots and the saving of edited Excellon object in regard of slots, in Excellon Editor
+- fixed the Delete tool, Select tool in Excellon Editor to work for Slots too
+
 13.08.2019
 13.08.2019
 
 
 - added new option in ToolSub: the ability to close (or not) the resulting paths when using tool on Geometry objects. Added also a new category in the Edit -> Preferences -> Tools, the Substractor Tool Options
 - added new option in ToolSub: the ability to close (or not) the resulting paths when using tool on Geometry objects. Added also a new category in the Edit -> Preferences -> Tools, the Substractor Tool Options

+ 210 - 75
flatcamEditors/FlatCAMExcEditor.py

@@ -484,23 +484,25 @@ class FCSlot(FCShapeTool):
             return Polygon(geo)
             return Polygon(geo)
 
 
     def make(self):
     def make(self):
+
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
         except Exception as e:
         except Exception as e:
             pass
             pass
 
 
-        # add the point to drills if the diameter is a key in the dict, if not, create it add the drill location
+        try:
+            self.geometry = DrawToolShape(self.util_shape(self.points))
+        except Exception as e:
+            log.debug("FCSlot.make() --> %s" % str(e))
+
+        # add the point to drills/slots if the diameter is a key in the dict, if not, create it add the drill location
         # to the value, as a list of itself
         # to the value, as a list of itself
         if self.selected_dia in self.draw_app.slot_points_edit:
         if self.selected_dia in self.draw_app.slot_points_edit:
             self.draw_app.slot_points_edit[self.selected_dia].append(self.points)
             self.draw_app.slot_points_edit[self.selected_dia].append(self.points)
         else:
         else:
             self.draw_app.slot_points_edit[self.selected_dia] = [self.points]
             self.draw_app.slot_points_edit[self.selected_dia] = [self.points]
 
 
-        self.draw_app.current_storage = self.draw_app.slot_storage_dict[self.selected_dia]
-        try:
-            self.geometry = DrawToolShape(self.util_shape(self.points))
-        except Exception as e:
-            log.debug("FCSlot.make() --> %s" % str(e))
+        self.draw_app.current_storage = self.draw_app.storage_dict[self.selected_dia]
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
@@ -1139,7 +1141,6 @@ class FCDrillSelect(DrawTool):
         self.exc_editor_app.slot_frame.hide()
         self.exc_editor_app.slot_frame.hide()
         # self.exc_editor_app.slot_array_frame.hide()
         # self.exc_editor_app.slot_array_frame.hide()
 
 
-
     def click(self, point):
     def click(self, point):
         key_modifier = QtWidgets.QApplication.keyboardModifiers()
         key_modifier = QtWidgets.QApplication.keyboardModifiers()
         if self.exc_editor_app.app.defaults["global_mselect_key"] == 'Control':
         if self.exc_editor_app.app.defaults["global_mselect_key"] == 'Control':
@@ -1155,6 +1156,7 @@ class FCDrillSelect(DrawTool):
 
 
     def click_release(self, pos):
     def click_release(self, pos):
         self.exc_editor_app.tools_table_exc.clearSelection()
         self.exc_editor_app.tools_table_exc.clearSelection()
+        xmin, ymin, xmax, ymax = 0, 0, 0, 0
 
 
         try:
         try:
             for storage in self.exc_editor_app.storage_dict:
             for storage in self.exc_editor_app.storage_dict:
@@ -1163,14 +1165,24 @@ class FCDrillSelect(DrawTool):
 
 
             _, closest_shape = self.sel_storage.nearest(pos)
             _, closest_shape = self.sel_storage.nearest(pos)
 
 
-            # constrain selection to happen only within a certain bounding box
-            x_coord, y_coord = closest_shape.geo[0].xy
-            delta = (x_coord[1] - x_coord[0])
-            # closest_shape_coords = (((x_coord[0] + delta / 2)), y_coord[0])
-            xmin = x_coord[0] - (0.7 * delta)
-            xmax = x_coord[0] + (1.7 * delta)
-            ymin = y_coord[0] - (0.7 * delta)
-            ymax = y_coord[0] + (1.7 * delta)
+            # constrain selection to happen only within a certain bounding box; it works only for MultiLineStrings
+            if isinstance(closest_shape.geo, MultiLineString):
+                x_coord, y_coord = closest_shape.geo[0].xy
+                delta = (x_coord[1] - x_coord[0])
+                # closest_shape_coords = (((x_coord[0] + delta / 2)), y_coord[0])
+                xmin = x_coord[0] - (0.7 * delta)
+                xmax = x_coord[0] + (1.7 * delta)
+                ymin = y_coord[0] - (0.7 * delta)
+                ymax = y_coord[0] + (1.7 * delta)
+            elif isinstance(closest_shape.geo, Polygon):
+                xmin, ymin, xmax, ymax = closest_shape.geo.bounds
+                dx = xmax - xmin
+                dy = ymax - ymin
+                delta = dx if dx > dy else dy
+                xmin -= 0.7 * delta
+                xmax += 0.7 * delta
+                ymin -= 0.7 * delta
+                ymax += 0.7 * delta
         except StopIteration:
         except StopIteration:
             return ""
             return ""
 
 
@@ -1417,7 +1429,7 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         res_entry_lbl = QtWidgets.QLabel(_('Resize Dia:'))
         res_entry_lbl = QtWidgets.QLabel(_('Resize Dia:'))
         res_entry_lbl.setToolTip(
         res_entry_lbl.setToolTip(
-           _( "Diameter to resize to.")
+           _("Diameter to resize to.")
         )
         )
         grid3.addWidget(res_entry_lbl, 0, 0)
         grid3.addWidget(res_entry_lbl, 0, 0)
 
 
@@ -1457,8 +1469,8 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         self.array_type_combo = FCComboBox()
         self.array_type_combo = FCComboBox()
         self.array_type_combo.setToolTip(
         self.array_type_combo.setToolTip(
-           _( "Select the type of drills array to create.\n"
-              "It can be Linear X(Y) or Circular")
+           _("Select the type of drills array to create.\n"
+             "It can be Linear X(Y) or Circular")
         )
         )
         self.array_type_combo.addItem(_("Linear"))
         self.array_type_combo.addItem(_("Linear"))
         self.array_type_combo.addItem(_("Circular"))
         self.array_type_combo.addItem(_("Circular"))
@@ -1470,10 +1482,8 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         # Set the number of drill holes in the drill array
         # Set the number of drill holes in the drill array
         self.drill_array_size_label = QtWidgets.QLabel(_('Nr of drills:'))
         self.drill_array_size_label = QtWidgets.QLabel(_('Nr of drills:'))
-        self.drill_array_size_label.setToolTip(
-            _("Specify how many drills to be in the array.")
-        )
-        self.drill_array_size_label.setFixedWidth(100)
+        self.drill_array_size_label.setToolTip(_("Specify how many drills to be in the array."))
+        self.drill_array_size_label.setMinimumWidth(100)
 
 
         self.drill_array_size_entry = LengthEntry()
         self.drill_array_size_entry = LengthEntry()
         self.array_form.addRow(self.drill_array_size_label, self.drill_array_size_entry)
         self.array_form.addRow(self.drill_array_size_label, self.drill_array_size_entry)
@@ -1516,10 +1526,10 @@ class FlatCAMExcEditor(QtCore.QObject):
         # Linear Drill Array angle
         # Linear Drill Array angle
         self.linear_angle_label = QtWidgets.QLabel(_('Angle:'))
         self.linear_angle_label = QtWidgets.QLabel(_('Angle:'))
         self.linear_angle_label.setToolTip(
         self.linear_angle_label.setToolTip(
-           _( "Angle at which the linear array is placed.\n"
-              "The precision is of max 2 decimals.\n"
-              "Min value is: -359.99 degrees.\n"
-              "Max value is:  360.00 degrees.")
+           _("Angle at which the linear array is placed.\n"
+             "The precision is of max 2 decimals.\n"
+             "Min value is: -359.99 degrees.\n"
+             "Max value is:  360.00 degrees.")
         )
         )
         self.linear_angle_label.setFixedWidth(100)
         self.linear_angle_label.setFixedWidth(100)
 
 
@@ -1537,10 +1547,8 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.array_circular_frame.setLayout(self.circular_box)
         self.array_circular_frame.setLayout(self.circular_box)
 
 
         self.drill_direction_label = QtWidgets.QLabel(_('Direction:'))
         self.drill_direction_label = QtWidgets.QLabel(_('Direction:'))
-        self.drill_direction_label.setToolTip(
-           _( "Direction for circular array."
-              "Can be CW = clockwise or CCW = counter clockwise.")
-        )
+        self.drill_direction_label.setToolTip(_("Direction for circular array."
+                                                "Can be CW = clockwise or CCW = counter clockwise."))
         self.drill_direction_label.setFixedWidth(100)
         self.drill_direction_label.setFixedWidth(100)
 
 
         self.circular_form = QtWidgets.QFormLayout()
         self.circular_form = QtWidgets.QFormLayout()
@@ -1551,9 +1559,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.circular_form.addRow(self.drill_direction_label, self.drill_direction_radio)
         self.circular_form.addRow(self.drill_direction_label, self.drill_direction_radio)
 
 
         self.drill_angle_label = QtWidgets.QLabel(_('Angle:'))
         self.drill_angle_label = QtWidgets.QLabel(_('Angle:'))
-        self.drill_angle_label.setToolTip(
-            _("Angle at which each element in circular array is placed.")
-        )
+        self.drill_angle_label.setToolTip(_("Angle at which each element in circular array is placed."))
         self.drill_angle_label.setMinimumWidth(100)
         self.drill_angle_label.setMinimumWidth(100)
 
 
         self.drill_angle_entry = LengthEntry()
         self.drill_angle_entry = LengthEntry()
@@ -1620,10 +1626,10 @@ class FlatCAMExcEditor(QtCore.QObject):
         # Slot custom angle
         # Slot custom angle
         self.slot_angle_label = QtWidgets.QLabel(_('Angle:'))
         self.slot_angle_label = QtWidgets.QLabel(_('Angle:'))
         self.slot_angle_label.setToolTip(
         self.slot_angle_label.setToolTip(
-           _( "Angle at which the slot is placed.\n"
-              "The precision is of max 2 decimals.\n"
-              "Min value is: -359.99 degrees.\n"
-              "Max value is:  360.00 degrees.")
+           _("Angle at which the slot is placed.\n"
+             "The precision is of max 2 decimals.\n"
+             "Min value is: -359.99 degrees.\n"
+             "Max value is:  360.00 degrees.")
         )
         )
         self.slot_angle_label.setMinimumWidth(100)
         self.slot_angle_label.setMinimumWidth(100)
 
 
@@ -1647,9 +1653,9 @@ class FlatCAMExcEditor(QtCore.QObject):
             "drill_array": {"button": self.app.ui.add_drill_array_btn,
             "drill_array": {"button": self.app.ui.add_drill_array_btn,
                             "constructor": FCDrillArray},
                             "constructor": FCDrillArray},
             "drill_slot": {"button": self.app.ui.add_slot_btn,
             "drill_slot": {"button": self.app.ui.add_slot_btn,
-                          "constructor": FCSlot},
+                           "constructor": FCSlot},
             "drill_slotarray": {"button": self.app.ui.add_slot_array_btn,
             "drill_slotarray": {"button": self.app.ui.add_slot_array_btn,
-                            "constructor": FCSlotArray},
+                                "constructor": FCSlotArray},
             "drill_resize": {"button": self.app.ui.resize_drill_btn,
             "drill_resize": {"button": self.app.ui.resize_drill_btn,
                              "constructor": FCDrillResize},
                              "constructor": FCDrillResize},
             "drill_copy": {"button": self.app.ui.copy_drill_btn,
             "drill_copy": {"button": self.app.ui.copy_drill_btn,
@@ -1664,7 +1670,6 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.in_action = False
         self.in_action = False
 
 
         self.storage_dict = {}
         self.storage_dict = {}
-        self.slot_storage_dict = {}
 
 
         self.current_storage = []
         self.current_storage = []
 
 
@@ -1673,11 +1678,11 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.points_edit = {}
         self.points_edit = {}
         self.slot_points_edit = {}
         self.slot_points_edit = {}
 
 
-        self.sorted_diameters =[]
+        self.sorted_diameters = []
 
 
         self.new_drills = []
         self.new_drills = []
         self.new_tools = {}
         self.new_tools = {}
-        self.new_slots = {}
+        self.new_slots = []
         self.new_tool_offset = {}
         self.new_tool_offset = {}
 
 
         # dictionary to store the tool_row and diameters in Tool_table
         # dictionary to store the tool_row and diameters in Tool_table
@@ -1827,10 +1832,33 @@ class FlatCAMExcEditor(QtCore.QObject):
                 except KeyError:
                 except KeyError:
                     self.points_edit[tool_dia] = [drill['point']]
                     self.points_edit[tool_dia] = [drill['point']]
 
 
+        # build the self.slot_points_edit dict {dimaters: {"start": Point, "stop": Point}}
+        for slot in self.exc_obj.slots:
+            if slot['tool'] in self.exc_obj.tools:
+                if self.units == 'IN':
+                    tool_dia = float('%.4f' % self.exc_obj.tools[slot['tool']]['C'])
+                else:
+                    tool_dia = float('%.2f' % self.exc_obj.tools[slot['tool']]['C'])
+
+                try:
+                    self.slot_points_edit[tool_dia].append({
+                        "start": slot["start"],
+                        "stop": slot["stop"]
+                    })
+                except KeyError:
+                    self.slot_points_edit[tool_dia] = [{
+                        "start": slot["start"],
+                        "stop": slot["stop"]
+                    }]
+
         # update the olddia_newdia dict to make sure we have an updated state of the tool_table
         # update the olddia_newdia dict to make sure we have an updated state of the tool_table
         for key in self.points_edit:
         for key in self.points_edit:
             self.olddia_newdia[key] = key
             self.olddia_newdia[key] = key
 
 
+        for key in self.slot_points_edit:
+            if key not in self.olddia_newdia:
+                self.olddia_newdia[key] = key
+
         sort_temp = []
         sort_temp = []
         for diam in self.olddia_newdia:
         for diam in self.olddia_newdia:
             sort_temp.append(float(diam))
             sort_temp.append(float(diam))
@@ -1924,8 +1952,12 @@ class FlatCAMExcEditor(QtCore.QObject):
                 self.tot_slot_cnt += slot_cnt
                 self.tot_slot_cnt += slot_cnt
             except AttributeError:
             except AttributeError:
                 # log.debug("No slots in the Excellon file")
                 # log.debug("No slots in the Excellon file")
-                # slot editing not implemented
-                pass
+                # Find no of slots for the current tool
+                for tool_dia in self.slot_points_edit:
+                    if float(tool_dia) == tool_no:
+                        slot_cnt = len(self.slot_points_edit[tool_dia])
+
+                self.tot_slot_cnt += slot_cnt
 
 
             idd = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
             idd = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
             idd.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
             idd.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
@@ -2137,7 +2169,7 @@ class FlatCAMExcEditor(QtCore.QObject):
                         deleted_tool_dia_list.append(float('%.4f' % dd))
                         deleted_tool_dia_list.append(float('%.4f' % dd))
                 else:
                 else:
                     deleted_tool_dia_list.append(float('%.4f' % dia))
                     deleted_tool_dia_list.append(float('%.4f' % dia))
-        except:
+        except Exception as e:
             self.app.inform.emit(_("[WARNING_NOTCL] Select a tool in Tool Table"))
             self.app.inform.emit(_("[WARNING_NOTCL] Select a tool in Tool Table"))
             return
             return
 
 
@@ -2274,7 +2306,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.sorted_diameters = []
         self.sorted_diameters = []
         self.new_drills = []
         self.new_drills = []
         self.new_tools = {}
         self.new_tools = {}
-        self.new_slots = {}
+        self.new_slots = []
         self.new_tool_offset = {}
         self.new_tool_offset = {}
         self.olddia_newdia = {}
         self.olddia_newdia = {}
 
 
@@ -2524,6 +2556,21 @@ class FlatCAMExcEditor(QtCore.QObject):
                     self.add_exc_shape(DrawToolShape(shape_geo), storage_elem)
                     self.add_exc_shape(DrawToolShape(shape_geo), storage_elem)
             self.storage_dict[tool_dia] = storage_elem
             self.storage_dict[tool_dia] = storage_elem
 
 
+        # slots
+        for tool_dia in self.slot_points_edit:
+            buf_value = float(tool_dia) / 2
+            for elem_dict in self.slot_points_edit[tool_dia]:
+
+                line_geo = LineString([elem_dict['start'], elem_dict['stop']])
+                shape_geo = line_geo.buffer(buf_value)
+
+                if tool_dia not in self.storage_dict:
+                    storage_elem = FlatCAMGeoEditor.make_storage()
+                    self.storage_dict[tool_dia] = storage_elem
+
+                if shape_geo is not None:
+                    self.add_exc_shape(DrawToolShape(shape_geo), self.storage_dict[tool_dia])
+
         self.replot()
         self.replot()
 
 
         # add a first tool in the Tool Table but only if the Excellon Object is empty
         # add a first tool in the Tool Table but only if the Excellon Object is empty
@@ -2541,36 +2588,85 @@ class FlatCAMExcEditor(QtCore.QObject):
         # this dictionary will contain tooldia's as keys and a list of coordinates tuple as values
         # this dictionary will contain tooldia's as keys and a list of coordinates tuple as values
         # the values of this dict are coordinates of the holes (drills)
         # the values of this dict are coordinates of the holes (drills)
         edited_points = {}
         edited_points = {}
+
+        """
+         - this dictionary will contain tooldia's as keys and a list of another dicts as values
+         - the dict element of the list has the structure
+         ================  ====================================
+        Key               Value
+        ================  ====================================
+        start             (Shapely.Point) Start point of the slot
+        stop              (Shapely.Point) Stop point of the slot
+        ================  ====================================
+        """
+        edited_slot_points = {}
+
         for storage_tooldia in self.storage_dict:
         for storage_tooldia in self.storage_dict:
             for x in self.storage_dict[storage_tooldia].get_objects():
             for x in self.storage_dict[storage_tooldia].get_objects():
+                if isinstance(x.geo, MultiLineString):
+                    # all x.geo in self.storage_dict[storage] are MultiLinestring objects for drills
+                    # each MultiLineString is made out of Linestrings
+                    # select first Linestring object in the current MultiLineString
+                    first_linestring = x.geo[0]
+                    # get it's coordinates
+                    first_linestring_coords = first_linestring.coords
+                    x_coord = first_linestring_coords[0][0] + (float(first_linestring.length / 2))
+                    y_coord = first_linestring_coords[0][1]
+
+                    # create a tuple with the coordinates (x, y) and add it to the list that is the value of the
+                    # edited_points dictionary
+                    point = (x_coord, y_coord)
+                    if storage_tooldia not in edited_points:
+                        edited_points[storage_tooldia] = [point]
+                    else:
+                        edited_points[storage_tooldia].append(point)
+                elif isinstance(x.geo, Polygon):
+                    # create a tuple with the points (start, stop) and add it to the list that is the value of the
+                    # edited_points dictionary
+
+                    # first determine the start and stop coordinates for the slot knowing the geometry and the tool
+                    # diameter
+                    radius = float(storage_tooldia) / 2
+                    radius = radius - 0.0000001
+
+                    poly = x.geo
+                    poly = poly.buffer(-radius)
+
+                    xmin, ymin, xmax, ymax = poly.bounds
+                    line_one = LineString([(xmin, ymin), (xmax, ymax)]).intersection(poly).length
+                    line_two = LineString([(xmin, ymax), (xmax, ymin)]).intersection(poly).length
+
+                    if line_one < line_two:
+                        point = {
+                            "start": (xmin, ymax),
+                            "stop": (xmax, ymin)
+                        }
+                    else:
+                        point = {
+                            "start": (xmin, ymin),
+                            "stop": (xmax, ymax)
+                        }
 
 
-                # all x.geo in self.storage_dict[storage] are MultiLinestring objects
-                # each MultiLineString is made out of Linestrings
-                # select first Linestring object in the current MultiLineString
-                first_linestring = x.geo[0]
-                # get it's coordinates
-                first_linestring_coords = first_linestring.coords
-                x_coord = first_linestring_coords[0][0] + (float(first_linestring.length / 2))
-                y_coord = first_linestring_coords[0][1]
-
-                # create a tuple with the coordinates (x, y) and add it to the list that is the value of the
-                # edited_points dictionary
-                point = (x_coord, y_coord)
-                if storage_tooldia not in edited_points:
-                    edited_points[storage_tooldia] = [point]
-                else:
-                    edited_points[storage_tooldia].append(point)
+                    if storage_tooldia not in edited_slot_points:
+                        edited_slot_points[storage_tooldia] = [point]
+                    else:
+                        edited_slot_points[storage_tooldia].append(point)
 
 
         # recreate the drills and tools to be added to the new Excellon edited object
         # recreate the drills and tools to be added to the new Excellon edited object
         # first, we look in the tool table if one of the tool diameters was changed then
         # first, we look in the tool table if one of the tool diameters was changed then
         # append that a tuple formed by (old_dia, edited_dia) to a list
         # append that a tuple formed by (old_dia, edited_dia) to a list
-        changed_key = []
+        changed_key = set()
         for initial_dia in self.olddia_newdia:
         for initial_dia in self.olddia_newdia:
             edited_dia = self.olddia_newdia[initial_dia]
             edited_dia = self.olddia_newdia[initial_dia]
             if edited_dia != initial_dia:
             if edited_dia != initial_dia:
+                # for drills
                 for old_dia in edited_points:
                 for old_dia in edited_points:
                     if old_dia == initial_dia:
                     if old_dia == initial_dia:
-                        changed_key.append((old_dia, edited_dia))
+                        changed_key.add((old_dia, edited_dia))
+                # for slots
+                for old_dia in edited_slot_points:
+                    if old_dia == initial_dia:
+                        changed_key.add((old_dia, edited_dia))
             # if the initial_dia is not in edited_points it means it is a new tool with no drill points
             # if the initial_dia is not in edited_points it means it is a new tool with no drill points
             # (and we have to add it)
             # (and we have to add it)
             # because in case we have drill points it will have to be already added in edited_points
             # because in case we have drill points it will have to be already added in edited_points
@@ -2579,6 +2675,7 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         for el in changed_key:
         for el in changed_key:
             edited_points[el[1]] = edited_points.pop(el[0])
             edited_points[el[1]] = edited_points.pop(el[0])
+            edited_slot_points[el[1]] = edited_slot_points.pop(el[0])
 
 
         # Let's sort the edited_points dictionary by keys (diameters) and store the result in a zipped list
         # Let's sort the edited_points dictionary by keys (diameters) and store the result in a zipped list
         # ordered_edited_points is a ordered list of tuples;
         # ordered_edited_points is a ordered list of tuples;
@@ -2610,6 +2707,41 @@ class FlatCAMExcEditor(QtCore.QObject):
                 poly = Point(point).buffer(float(tool_dia[0]) / 2.0, int(int(exc_obj.geo_steps_per_circle) / 4))
                 poly = Point(point).buffer(float(tool_dia[0]) / 2.0, int(int(exc_obj.geo_steps_per_circle) / 4))
                 self.new_tools[name]['solid_geometry'].append(poly)
                 self.new_tools[name]['solid_geometry'].append(poly)
 
 
+        ordered_edited_slot_points = sorted(zip(edited_slot_points.keys(), edited_slot_points.values()))
+        for tool_dia in ordered_edited_slot_points:
+
+            tool_exist_flag = False
+            for tool in self.new_tools:
+                if tool_dia[0] == self.new_tools[tool]["C"]:
+                    current_tool = tool
+                    tool_exist_flag = True
+                    break
+
+            if tool_exist_flag is False:
+                current_tool += 1
+                # create the self.tools for the new Excellon object (the one with edited content)
+                name = str(current_tool)
+                spec = {"C": float(tool_dia[0])}
+                self.new_tools[name] = spec
+
+                # add in self.tools the 'solid_geometry' key, the value (a list) is populated bellow
+                self.new_tools[name]['solid_geometry'] = []
+
+            # create the self.slots for the new Excellon object (the one with edited content)
+            for coord_dict in tool_dia[1]:
+                self.new_slots.append(
+                    {
+                        'start': Point(coord_dict['start']),
+                        'stop': Point(coord_dict['stop']),
+                        'tool': str(current_tool)
+                    }
+                )
+                # repopulate the 'solid_geometry' for each tool
+                poly = LineString([coord_dict['start'], coord_dict['stop']]).buffer(
+                    float(tool_dia[0]) / 2.0, int(int(exc_obj.geo_steps_per_circle) / 4)
+                )
+                self.new_tools[str(current_tool)]['solid_geometry'].append(poly)
+
         if self.is_modified is True:
         if self.is_modified is True:
             if "_edit" in self.edited_obj_name:
             if "_edit" in self.edited_obj_name:
                 try:
                 try:
@@ -2623,8 +2755,6 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.app.worker_task.emit({'fcn': self.new_edited_excellon,
         self.app.worker_task.emit({'fcn': self.new_edited_excellon,
                                    'params': [self.edited_obj_name]})
                                    'params': [self.edited_obj_name]})
 
 
-        if self.exc_obj.slots:
-            self.new_slots = self.exc_obj.slots
 
 
         self.new_tool_offset = self.exc_obj.tool_offset
         self.new_tool_offset = self.exc_obj.tool_offset
 
 
@@ -2807,6 +2937,7 @@ class FlatCAMExcEditor(QtCore.QObject):
                     if self.current_storage is not None:
                     if self.current_storage is not None:
                         self.on_exc_shape_complete(self.current_storage)
                         self.on_exc_shape_complete(self.current_storage)
                         self.build_ui()
                         self.build_ui()
+
                     # MS: always return to the Select Tool if modifier key is not pressed
                     # MS: always return to the Select Tool if modifier key is not pressed
                     # else return to the current tool
                     # else return to the current tool
                     key_modifier = QtWidgets.QApplication.keyboardModifiers()
                     key_modifier = QtWidgets.QApplication.keyboardModifiers()
@@ -2819,8 +2950,8 @@ class FlatCAMExcEditor(QtCore.QObject):
                     if key_modifier == modifier_to_use:
                     if key_modifier == modifier_to_use:
                         self.select_tool(self.active_tool.name)
                         self.select_tool(self.active_tool.name)
                     else:
                     else:
-                        # return to Select tool but not for FCPad
-                        if isinstance(self.active_tool, FCDrillAdd):
+                        # return to Select tool but not for FCDrillAdd or FCSlot
+                        if isinstance(self.active_tool, FCDrillAdd) or isinstance(self.active_tool, FCSlot):
                             self.select_tool(self.active_tool.name)
                             self.select_tool(self.active_tool.name)
                         else:
                         else:
                             self.select_tool("drill_select")
                             self.select_tool("drill_select")
@@ -3262,13 +3393,17 @@ class FlatCAMExcEditor(QtCore.QObject):
             # except:
             # except:
             #     pass
             #     pass
             if del_shape in self.storage_dict[storage].get_objects():
             if del_shape in self.storage_dict[storage].get_objects():
-                self.storage_dict[storage].remove(del_shape)
-                # a hack to make the tool_table display less drills per diameter
-                # self.points_edit it's only useful first time when we load the data into the storage
-                # but is still used as referecen when building tool_table in self.build_ui()
-                # the number of drills displayed in column 2 is just a len(self.points_edit) therefore
-                # deleting self.points_edit elements (doesn't matter who but just the number) solved the display issue.
-                del self.points_edit[storage][0]
+                if isinstance(del_shape.geo, MultiLineString):
+                    self.storage_dict[storage].remove(del_shape)
+                    # a hack to make the tool_table display less drills per diameter
+                    # self.points_edit it's only useful first time when we load the data into the storage
+                    # but is still used as referecen when building tool_table in self.build_ui()
+                    # the number of drills displayed in column 2 is just a len(self.points_edit) therefore
+                    # deleting self.points_edit elements (doesn't matter who but just the number) solved the display issue.
+                    del self.points_edit[storage][0]
+                else:
+                    self.storage_dict[storage].remove(del_shape)
+                    del self.slot_points_edit[storage][0]
 
 
         if del_shape in self.selected:
         if del_shape in self.selected:
             self.selected.remove(del_shape)  # TODO: Check performance
             self.selected.remove(del_shape)  # TODO: Check performance