- Gerber Editor: added Add Pad Array tool
- Gerber Editor: in Add Pad Array tool, if the pad is not circular type, for circular array the pad will be rotated to match the array angle
This commit is contained in:
parent
036e886af4
commit
cc6ff98529
@ -15,6 +15,8 @@ CAD program, and create G-Code for Isolation routing.
|
||||
- Gerber Editor: added Transformation Tool and Rotation key shortcut
|
||||
- in all Editors, manually deactivating a button in the editor toolbar will automatically select the 'Select' button
|
||||
- fixed Excellon Editor selection: when a tool is selected in Tools Table, all the drills belonging to that tool are selected. When a drill is selected on canvas, the associated tool will be selected without automatically selecting all other drills with same tool
|
||||
- Gerber Editor: added Add Pad Array tool
|
||||
- Gerber Editor: in Add Pad Array tool, if the pad is not circular type, for circular array the pad will be rotated to match the array angle
|
||||
|
||||
10.04.2019
|
||||
|
||||
|
@ -109,42 +109,223 @@ class FCPad(FCShapeTool):
|
||||
|
||||
class FCPadArray(FCShapeTool):
|
||||
"""
|
||||
Resulting type: Polygon
|
||||
Resulting type: MultiPolygon
|
||||
"""
|
||||
|
||||
def __init__(self, draw_app):
|
||||
DrawTool.__init__(self, draw_app)
|
||||
self.name = 'pad_array'
|
||||
self.name = 'array'
|
||||
self.draw_app = draw_app
|
||||
|
||||
self.start_msg = _("Click on 1st corner ...")
|
||||
self.storage_obj = self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['solid_geometry']
|
||||
self.radius = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size']) / 2
|
||||
|
||||
# if those cause KeyError exception it means that the aperture type is not 'R'. Only 'R' type has those keys
|
||||
try:
|
||||
self.half_width = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['width']) / 2
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
self.half_height = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['height']) / 2
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.draw_app.array_frame.show()
|
||||
|
||||
self.selected_size = None
|
||||
self.pad_axis = 'X'
|
||||
self.pad_array = 'linear'
|
||||
self.pad_array_size = None
|
||||
self.pad_pitch = None
|
||||
self.pad_linear_angle = None
|
||||
|
||||
self.pad_angle = None
|
||||
self.pad_direction = None
|
||||
self.pad_radius = None
|
||||
|
||||
self.origin = None
|
||||
self.destination = None
|
||||
self.flag_for_circ_array = None
|
||||
|
||||
self.last_dx = 0
|
||||
self.last_dy = 0
|
||||
|
||||
self.pt = []
|
||||
|
||||
self.draw_app.app.inform.emit(self.start_msg)
|
||||
|
||||
try:
|
||||
self.selected_size = self.draw_app.tool2tooldia[self.draw_app.last_aperture_selected]
|
||||
except KeyError:
|
||||
self.draw_app.app.inform.emit(_("[WARNING_NOTCL] To add an Pad Array first select a tool in Tool Table"))
|
||||
return
|
||||
|
||||
geo = self.utility_geometry(data=(self.draw_app.snap_x, self.draw_app.snap_y), static=True)
|
||||
|
||||
if isinstance(geo, DrawToolShape) and geo.geo is not None:
|
||||
self.draw_app.draw_utility_geometry(geo=geo)
|
||||
|
||||
self.draw_app.app.inform.emit(_("Click on target location ..."))
|
||||
|
||||
# Switch notebook to Selected page
|
||||
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
|
||||
|
||||
def click(self, point):
|
||||
self.points.append(point)
|
||||
|
||||
if len(self.points) == 1:
|
||||
return "Click on opposite corner to complete ..."
|
||||
|
||||
if len(self.points) == 2:
|
||||
if self.pad_array == 'Linear':
|
||||
self.make()
|
||||
return "Done."
|
||||
return
|
||||
else:
|
||||
if self.flag_for_circ_array is None:
|
||||
self.draw_app.in_action = True
|
||||
self.pt.append(point)
|
||||
|
||||
return ""
|
||||
self.flag_for_circ_array = True
|
||||
self.set_origin(point)
|
||||
self.draw_app.app.inform.emit(_("Click on the Pad Circular Array Start position"))
|
||||
else:
|
||||
self.destination = point
|
||||
self.make()
|
||||
self.flag_for_circ_array = None
|
||||
return
|
||||
|
||||
def utility_geometry(self, data=None):
|
||||
if len(self.points) == 1:
|
||||
p1 = self.points[0]
|
||||
p2 = data
|
||||
return DrawToolUtilityShape(LinearRing([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])]))
|
||||
def set_origin(self, origin):
|
||||
self.origin = origin
|
||||
|
||||
def utility_geometry(self, data=None, static=None):
|
||||
self.pad_axis = self.draw_app.pad_axis_radio.get_value()
|
||||
self.pad_direction = self.draw_app.pad_direction_radio.get_value()
|
||||
self.pad_array = self.draw_app.array_type_combo.get_value()
|
||||
try:
|
||||
self.pad_array_size = int(self.draw_app.pad_array_size_entry.get_value())
|
||||
try:
|
||||
self.pad_pitch = float(self.draw_app.pad_pitch_entry.get_value())
|
||||
self.pad_linear_angle = float(self.draw_app.linear_angle_spinner.get_value())
|
||||
self.pad_angle = float(self.draw_app.pad_angle_entry.get_value())
|
||||
except TypeError:
|
||||
self.draw_app.app.inform.emit(
|
||||
_("[ERROR_NOTCL] The value is not Float. Check for comma instead of dot separator."))
|
||||
return
|
||||
except Exception as e:
|
||||
self.draw_app.app.inform.emit(_("[ERROR_NOTCL] The value is mistyped. Check the value."))
|
||||
return
|
||||
|
||||
if self.pad_array == 'Linear':
|
||||
if data[0] is None and data[1] is None:
|
||||
dx = self.draw_app.x
|
||||
dy = self.draw_app.y
|
||||
else:
|
||||
dx = data[0]
|
||||
dy = data[1]
|
||||
|
||||
geo_list = []
|
||||
geo = None
|
||||
self.points = [dx, dy]
|
||||
|
||||
for item in range(self.pad_array_size):
|
||||
if self.pad_axis == 'X':
|
||||
geo = self.util_shape(((dx + (self.pad_pitch * item)), dy))
|
||||
if self.pad_axis == 'Y':
|
||||
geo = self.util_shape((dx, (dy + (self.pad_pitch * item))))
|
||||
if self.pad_axis == 'A':
|
||||
x_adj = self.pad_pitch * math.cos(math.radians(self.pad_linear_angle))
|
||||
y_adj = self.pad_pitch * math.sin(math.radians(self.pad_linear_angle))
|
||||
geo = self.util_shape(
|
||||
((dx + (x_adj * item)), (dy + (y_adj * item)))
|
||||
)
|
||||
|
||||
if static is None or static is False:
|
||||
geo_list.append(affinity.translate(geo, xoff=(dx - self.last_dx), yoff=(dy - self.last_dy)))
|
||||
else:
|
||||
geo_list.append(geo)
|
||||
# self.origin = data
|
||||
|
||||
self.last_dx = dx
|
||||
self.last_dy = dy
|
||||
return DrawToolUtilityShape(geo_list)
|
||||
else:
|
||||
if data[0] is None and data[1] is None:
|
||||
cdx = self.draw_app.x
|
||||
cdy = self.draw_app.y
|
||||
else:
|
||||
cdx = data[0]
|
||||
cdy = data[1]
|
||||
|
||||
if len(self.pt) > 0:
|
||||
temp_points = [x for x in self.pt]
|
||||
temp_points.append([cdx, cdy])
|
||||
return DrawToolUtilityShape(LineString(temp_points))
|
||||
|
||||
def util_shape(self, point):
|
||||
if point[0] is None and point[1] is None:
|
||||
point_x = self.draw_app.x
|
||||
point_y = self.draw_app.y
|
||||
else:
|
||||
point_x = point[0]
|
||||
point_y = point[1]
|
||||
|
||||
ap_type = self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['type']
|
||||
if ap_type == 'C':
|
||||
center = Point([point_x, point_y])
|
||||
return center.buffer(self.radius)
|
||||
elif ap_type == 'R':
|
||||
p1 = (point_x - self.half_width, point_y - self.half_height)
|
||||
p2 = (point_x + self.half_width, point_y - self.half_height)
|
||||
p3 = (point_x + self.half_width, point_y + self.half_height)
|
||||
p4 = (point_x - self.half_width, point_y + self.half_height)
|
||||
return Polygon([p1, p2, p3, p4, p1])
|
||||
else:
|
||||
self.draw_app.app.inform.emit(_("Incompatible aperture type. Select an aperture with type 'C' or 'R'."))
|
||||
return None
|
||||
|
||||
def make(self):
|
||||
p1 = self.points[0]
|
||||
p2 = self.points[1]
|
||||
# self.geometry = LinearRing([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])])
|
||||
self.geometry = DrawToolShape(Polygon([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])]))
|
||||
self.geometry = []
|
||||
geo = None
|
||||
|
||||
self.draw_app.current_storage = self.storage_obj
|
||||
|
||||
if self.pad_array == 'Linear':
|
||||
for item in range(self.pad_array_size):
|
||||
if self.pad_axis == 'X':
|
||||
geo = self.util_shape(((self.points[0] + (self.pad_pitch * item)), self.points[1]))
|
||||
if self.pad_axis == 'Y':
|
||||
geo = self.util_shape((self.points[0], (self.points[1] + (self.pad_pitch * item))))
|
||||
if self.pad_axis == 'A':
|
||||
x_adj = self.pad_pitch * math.cos(math.radians(self.pad_linear_angle))
|
||||
y_adj = self.pad_pitch * math.sin(math.radians(self.pad_linear_angle))
|
||||
geo = self.util_shape(
|
||||
((self.points[0] + (x_adj * item)), (self.points[1] + (y_adj * item)))
|
||||
)
|
||||
|
||||
self.geometry.append(DrawToolShape(geo))
|
||||
else:
|
||||
if (self.pad_angle * self.pad_array_size) > 360:
|
||||
self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Too many Pads for the selected spacing angle."))
|
||||
return
|
||||
|
||||
radius = distance(self.destination, self.origin)
|
||||
initial_angle = math.asin((self.destination[1] - self.origin[1]) / radius)
|
||||
for i in range(self.pad_array_size):
|
||||
angle_radians = math.radians(self.pad_angle * i)
|
||||
if self.pad_direction == 'CW':
|
||||
x = self.origin[0] + radius * math.cos(-angle_radians + initial_angle)
|
||||
y = self.origin[1] + radius * math.sin(-angle_radians + initial_angle)
|
||||
else:
|
||||
x = self.origin[0] + radius * math.cos(angle_radians + initial_angle)
|
||||
y = self.origin[1] + radius * math.sin(angle_radians + initial_angle)
|
||||
|
||||
geo = self.util_shape((x, y))
|
||||
if self.pad_direction == 'CW':
|
||||
geo = affinity.rotate(geo, angle=(math.pi - angle_radians), use_radians=True)
|
||||
else:
|
||||
geo = affinity.rotate(geo, angle=angle_radians, use_radians=True)
|
||||
|
||||
self.geometry.append(DrawToolShape(geo))
|
||||
self.complete = True
|
||||
self.draw_app.app.inform.emit(_("[success] Done. Rectangle completed."))
|
||||
self.draw_app.app.inform.emit(_("[success] Done. Pad Array added."))
|
||||
self.draw_app.in_action = True
|
||||
self.draw_app.array_frame.hide()
|
||||
return
|
||||
|
||||
|
||||
class FCRegion(FCShapeTool):
|
||||
@ -322,8 +503,7 @@ class FCApertureMove(FCShapeTool):
|
||||
|
||||
for index in self.draw_app.apertures_table.selectedIndexes():
|
||||
row = index.row()
|
||||
# on column 1 in tool tables we hold the diameters, and we retrieve them as strings
|
||||
# therefore below we convert to float
|
||||
# on column 1 in tool tables we hold the aperture codes, and we retrieve them as strings
|
||||
aperture_on_row = self.draw_app.apertures_table.item(row, 1).text()
|
||||
self.selected_apertures.append(aperture_on_row)
|
||||
|
||||
@ -756,6 +936,133 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
self.scale_button = QtWidgets.QPushButton(_("Scale"))
|
||||
hlay_scale.addWidget(self.scale_button)
|
||||
|
||||
# add a frame and inside add a vertical box layout. Inside this vbox layout I add
|
||||
# all the add Pad array widgets
|
||||
# this way I can hide/show the frame
|
||||
self.array_frame = QtWidgets.QFrame()
|
||||
self.array_frame.setContentsMargins(0, 0, 0, 0)
|
||||
self.custom_box.addWidget(self.array_frame)
|
||||
self.array_box = QtWidgets.QVBoxLayout()
|
||||
self.array_box.setContentsMargins(0, 0, 0, 0)
|
||||
self.array_frame.setLayout(self.array_box)
|
||||
|
||||
#### Add Pad Array ####
|
||||
self.emptyarray_label = QtWidgets.QLabel('')
|
||||
self.array_box.addWidget(self.emptyarray_label)
|
||||
|
||||
self.padarray_label = QtWidgets.QLabel('<b>%s</b>' % _("Add Pad Array"))
|
||||
self.padarray_label.setToolTip(
|
||||
_("Add an array of pads (linear or circular array)")
|
||||
)
|
||||
self.array_box.addWidget(self.padarray_label)
|
||||
|
||||
self.array_type_combo = FCComboBox()
|
||||
self.array_type_combo.setToolTip(
|
||||
_( "Select the type of pads array to create.\n"
|
||||
"It can be Linear X(Y) or Circular")
|
||||
)
|
||||
self.array_type_combo.addItem(_("Linear"))
|
||||
self.array_type_combo.addItem(_("Circular"))
|
||||
|
||||
self.array_box.addWidget(self.array_type_combo)
|
||||
|
||||
self.array_form = QtWidgets.QFormLayout()
|
||||
self.array_box.addLayout(self.array_form)
|
||||
|
||||
self.pad_array_size_label = QtWidgets.QLabel(_('Nr of pads:'))
|
||||
self.pad_array_size_label.setToolTip(
|
||||
_("Specify how many pads to be in the array.")
|
||||
)
|
||||
self.pad_array_size_label.setFixedWidth(100)
|
||||
|
||||
self.pad_array_size_entry = LengthEntry()
|
||||
self.array_form.addRow(self.pad_array_size_label, self.pad_array_size_entry)
|
||||
|
||||
self.array_linear_frame = QtWidgets.QFrame()
|
||||
self.array_linear_frame.setContentsMargins(0, 0, 0, 0)
|
||||
self.array_box.addWidget(self.array_linear_frame)
|
||||
self.linear_box = QtWidgets.QVBoxLayout()
|
||||
self.linear_box.setContentsMargins(0, 0, 0, 0)
|
||||
self.array_linear_frame.setLayout(self.linear_box)
|
||||
|
||||
self.linear_form = QtWidgets.QFormLayout()
|
||||
self.linear_box.addLayout(self.linear_form)
|
||||
|
||||
self.pad_axis_label = QtWidgets.QLabel(_('Direction:'))
|
||||
self.pad_axis_label.setToolTip(
|
||||
_("Direction on which the linear array is oriented:\n"
|
||||
"- 'X' - horizontal axis \n"
|
||||
"- 'Y' - vertical axis or \n"
|
||||
"- 'Angle' - a custom angle for the array inclination")
|
||||
)
|
||||
self.pad_axis_label.setFixedWidth(100)
|
||||
|
||||
self.pad_axis_radio = RadioSet([{'label': 'X', 'value': 'X'},
|
||||
{'label': 'Y', 'value': 'Y'},
|
||||
{'label': _('Angle'), 'value': 'A'}])
|
||||
self.pad_axis_radio.set_value('X')
|
||||
self.linear_form.addRow(self.pad_axis_label, self.pad_axis_radio)
|
||||
|
||||
self.pad_pitch_label = QtWidgets.QLabel(_('Pitch:'))
|
||||
self.pad_pitch_label.setToolTip(
|
||||
_("Pitch = Distance between elements of the array.")
|
||||
)
|
||||
self.pad_pitch_label.setFixedWidth(100)
|
||||
|
||||
self.pad_pitch_entry = LengthEntry()
|
||||
self.linear_form.addRow(self.pad_pitch_label, self.pad_pitch_entry)
|
||||
|
||||
self.linear_angle_label = QtWidgets.QLabel(_('Angle:'))
|
||||
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.")
|
||||
)
|
||||
self.linear_angle_label.setFixedWidth(100)
|
||||
|
||||
self.linear_angle_spinner = FCDoubleSpinner()
|
||||
self.linear_angle_spinner.set_precision(2)
|
||||
self.linear_angle_spinner.setRange(-359.99, 360.00)
|
||||
self.linear_form.addRow(self.linear_angle_label, self.linear_angle_spinner)
|
||||
|
||||
self.array_circular_frame = QtWidgets.QFrame()
|
||||
self.array_circular_frame.setContentsMargins(0, 0, 0, 0)
|
||||
self.array_box.addWidget(self.array_circular_frame)
|
||||
self.circular_box = QtWidgets.QVBoxLayout()
|
||||
self.circular_box.setContentsMargins(0, 0, 0, 0)
|
||||
self.array_circular_frame.setLayout(self.circular_box)
|
||||
|
||||
self.pad_direction_label = QtWidgets.QLabel(_('Direction:'))
|
||||
self.pad_direction_label.setToolTip(
|
||||
_( "Direction for circular array."
|
||||
"Can be CW = clockwise or CCW = counter clockwise.")
|
||||
)
|
||||
self.pad_direction_label.setFixedWidth(100)
|
||||
|
||||
self.circular_form = QtWidgets.QFormLayout()
|
||||
self.circular_box.addLayout(self.circular_form)
|
||||
|
||||
self.pad_direction_radio = RadioSet([{'label': 'CW', 'value': 'CW'},
|
||||
{'label': 'CCW.', 'value': 'CCW'}])
|
||||
self.pad_direction_radio.set_value('CW')
|
||||
self.circular_form.addRow(self.pad_direction_label, self.pad_direction_radio)
|
||||
|
||||
self.pad_angle_label = QtWidgets.QLabel(_('Angle:'))
|
||||
self.pad_angle_label.setToolTip(
|
||||
_("Angle at which each element in circular array is placed.")
|
||||
)
|
||||
self.pad_angle_label.setFixedWidth(100)
|
||||
|
||||
self.pad_angle_entry = LengthEntry()
|
||||
self.circular_form.addRow(self.pad_angle_label, self.pad_angle_entry)
|
||||
|
||||
self.array_circular_frame.hide()
|
||||
|
||||
self.linear_angle_spinner.hide()
|
||||
self.linear_angle_label.hide()
|
||||
|
||||
self.array_frame.hide()
|
||||
|
||||
self.custom_box.addStretch()
|
||||
|
||||
@ -765,6 +1072,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
"constructor": FCApertureSelect},
|
||||
"pad": {"button": self.app.ui.grb_add_pad_btn,
|
||||
"constructor": FCPad},
|
||||
"array": {"button": self.app.ui.add_pad_ar_btn,
|
||||
"constructor": FCPadArray},
|
||||
"track": {"button": self.app.ui.grb_add_track_btn,
|
||||
"constructor": FCTrack},
|
||||
"region": {"button": self.app.ui.grb_add_region_btn,
|
||||
@ -795,7 +1104,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
# store here the plot promises, if empty the delayed plot will be activated
|
||||
self.grb_plot_promises = []
|
||||
|
||||
# dictionary to store the tool_row and diameters in Tool_table
|
||||
# dictionary to store the tool_row and aperture codes in Tool_table
|
||||
# it will be updated everytime self.build_ui() is called
|
||||
self.olddia_newdia = {}
|
||||
|
||||
@ -887,7 +1196,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
self.buffer_button.clicked.connect(self.on_buffer)
|
||||
self.scale_button.clicked.connect(self.on_scale)
|
||||
|
||||
self.app.ui.delete_drill_btn.triggered.connect(self.on_delete_btn)
|
||||
self.app.ui.aperture_delete_btn.triggered.connect(self.on_delete_btn)
|
||||
self.name_entry.returnPressed.connect(self.on_name_activate)
|
||||
|
||||
self.aptype_cb.currentIndexChanged[str].connect(self.on_aptype_changed)
|
||||
@ -897,6 +1206,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
self.apertures_table.cellPressed.connect(self.on_row_selected)
|
||||
|
||||
self.app.ui.grb_add_pad_menuitem.triggered.connect(self.on_pad_add)
|
||||
self.app.ui.grb_add_pad_array_menuitem.triggered.connect(self.on_pad_add_array)
|
||||
|
||||
self.app.ui.grb_add_track_menuitem.triggered.connect(self.on_track_add)
|
||||
self.app.ui.grb_add_region_menuitem.triggered.connect(self.on_region_add)
|
||||
|
||||
@ -909,6 +1220,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
|
||||
self.app.ui.grb_move_menuitem.triggered.connect(self.on_move_button)
|
||||
|
||||
self.array_type_combo.currentIndexChanged.connect(self.on_array_type_combo)
|
||||
self.pad_axis_radio.activated_custom.connect(self.on_linear_angle_radio)
|
||||
|
||||
# store the status of the editor so the Delete at object level will not work until the edit is finished
|
||||
self.editor_active = False
|
||||
|
||||
@ -932,7 +1246,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
sort_temp.append(int(aperture))
|
||||
self.sorted_apid = sorted(sort_temp)
|
||||
|
||||
# populate self.intial_table_rows dict with the tool number as keys and tool diameters as values
|
||||
# populate self.intial_table_rows dict with the tool number as keys and aperture codes as values
|
||||
for i in range(len(self.sorted_apid)):
|
||||
tt_aperture = self.sorted_apid[i]
|
||||
self.tool2tooldia[i + 1] = tt_aperture
|
||||
@ -942,6 +1256,13 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
else:
|
||||
self.apsize_entry.set_value(1.00)
|
||||
|
||||
# Init GUI
|
||||
self.pad_array_size_entry.set_value(5)
|
||||
self.pad_pitch_entry.set_value(2.54)
|
||||
self.pad_angle_entry.set_value(12)
|
||||
self.pad_direction_radio.set_value('CW')
|
||||
self.pad_axis_radio.set_value('X')
|
||||
|
||||
def build_ui(self):
|
||||
|
||||
try:
|
||||
@ -1139,8 +1460,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
self.storage_dict[ap_id]['solid_geometry'] = []
|
||||
self.storage_dict[ap_id]['follow_geometry'] = []
|
||||
|
||||
# self.olddia_newdia dict keeps the evidence on current tools diameters as keys and gets updated on values
|
||||
# each time a tool diameter is edited or added
|
||||
# self.olddia_newdia dict keeps the evidence on current aperture codes as keys and gets updated on values
|
||||
# each time a aperture code is edited or added
|
||||
self.olddia_newdia[ap_id] = ap_id
|
||||
else:
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Aperture already in the aperture table."))
|
||||
@ -1150,7 +1471,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
# we add a new entry in the tool2tooldia dict
|
||||
self.tool2tooldia[len(self.olddia_newdia)] = int(ap_id)
|
||||
|
||||
self.app.inform.emit(_("[success] Added new aperture with dia: {apid}").format(apid=str(ap_id)))
|
||||
self.app.inform.emit(_("[success] Added new aperture with code: {apid}").format(apid=str(ap_id)))
|
||||
|
||||
self.build_ui()
|
||||
|
||||
@ -1164,7 +1485,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
|
||||
def on_aperture_delete(self, apid=None):
|
||||
self.is_modified = True
|
||||
deleted_tool_dia_list = []
|
||||
deleted_apcode_list = []
|
||||
deleted_tool_offset_list = []
|
||||
|
||||
try:
|
||||
@ -1172,37 +1493,38 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
# deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text())
|
||||
for index in self.apertures_table.selectionModel().selectedRows():
|
||||
row = index.row()
|
||||
deleted_tool_dia_list.append(self.apertures_table.item(row, 1).text())
|
||||
deleted_apcode_list.append(self.apertures_table.item(row, 1).text())
|
||||
else:
|
||||
if isinstance(apid, list):
|
||||
for dd in apid:
|
||||
deleted_tool_dia_list.append(dd)
|
||||
deleted_apcode_list.append(dd)
|
||||
else:
|
||||
deleted_tool_dia_list.append(apid)
|
||||
deleted_apcode_list.append(apid)
|
||||
except:
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Select a tool in Tool Table"))
|
||||
return
|
||||
|
||||
for deleted_tool_dia in deleted_tool_dia_list:
|
||||
for deleted_aperture in deleted_apcode_list:
|
||||
# delete the storage used for that tool
|
||||
self.storage_dict.pop(deleted_tool_dia, None)
|
||||
self.storage_dict.pop(deleted_aperture, None)
|
||||
|
||||
# I've added this flag_del variable because dictionary don't like
|
||||
# having keys deleted while iterating through them
|
||||
flag_del = []
|
||||
for deleted_tool in self.tool2tooldia:
|
||||
if self.tool2tooldia[deleted_tool] == deleted_tool_dia:
|
||||
if self.tool2tooldia[deleted_tool] == deleted_aperture:
|
||||
flag_del.append(deleted_tool)
|
||||
|
||||
if flag_del:
|
||||
for tool_to_be_deleted in flag_del:
|
||||
for aperture_to_be_deleted in flag_del:
|
||||
# delete the tool
|
||||
self.tool2tooldia.pop(tool_to_be_deleted, None)
|
||||
self.tool2tooldia.pop(aperture_to_be_deleted, None)
|
||||
flag_del = []
|
||||
|
||||
self.olddia_newdia.pop(deleted_tool_dia, None)
|
||||
self.olddia_newdia.pop(deleted_aperture, None)
|
||||
|
||||
self.app.inform.emit(_("[success] Deleted aperture with code: {del_dia}").format(del_dia=str(deleted_tool_dia)))
|
||||
self.app.inform.emit(_("[success] Deleted aperture with code: {del_dia}").format(
|
||||
del_dia=str(deleted_aperture)))
|
||||
|
||||
self.plot_all()
|
||||
self.build_ui()
|
||||
@ -1232,7 +1554,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
|
||||
dia_changed = self.tool2tooldia[key_in_tool2tooldia]
|
||||
|
||||
# tool diameter is not used so we create a new tool with the desired diameter
|
||||
# aperture code is not used so we create a new tool with the desired diameter
|
||||
if current_table_dia_edited not in self.olddia_newdia.values():
|
||||
# update the dict that holds as keys our initial diameters and as values the edited diameters
|
||||
self.olddia_newdia[dia_changed] = current_table_dia_edited
|
||||
@ -1245,7 +1567,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
|
||||
self.plot_all()
|
||||
else:
|
||||
# tool diameter is already in use so we move the drills from the prior tool to the new tool
|
||||
# aperture code is already in use so we move the pads from the prior tool to the new tool
|
||||
factor = current_table_dia_edited / dia_changed
|
||||
for shape in self.storage_dict[dia_changed].get_objects():
|
||||
geometry.append(DrawToolShape(
|
||||
@ -1432,7 +1754,6 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
# we activate this after the initial build as we don't need to see the tool been populated
|
||||
self.apertures_table.itemChanged.connect(self.on_tool_edit)
|
||||
|
||||
# build the geometry for each tool-diameter, each drill will be represented by a '+' symbol
|
||||
# and then add it to the storage elements (each storage elements is a member of a list
|
||||
|
||||
def job_thread(self, apid):
|
||||
@ -2143,6 +2464,25 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
if shape in self.selected:
|
||||
self.selected.remove(shape)
|
||||
|
||||
def on_array_type_combo(self):
|
||||
if self.array_type_combo.currentIndex() == 0:
|
||||
self.array_circular_frame.hide()
|
||||
self.array_linear_frame.show()
|
||||
else:
|
||||
self.delete_utility_geometry()
|
||||
self.array_circular_frame.show()
|
||||
self.array_linear_frame.hide()
|
||||
self.app.inform.emit(_("Click on the circular array Center position"))
|
||||
|
||||
def on_linear_angle_radio(self):
|
||||
val = self.pad_axis_radio.get_value()
|
||||
if val == 'A':
|
||||
self.linear_angle_spinner.show()
|
||||
self.linear_angle_label.show()
|
||||
else:
|
||||
self.linear_angle_spinner.hide()
|
||||
self.linear_angle_label.hide()
|
||||
|
||||
def on_copy_button(self):
|
||||
self.select_tool('copy')
|
||||
return
|
||||
@ -2154,6 +2494,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||
def on_pad_add(self):
|
||||
self.select_tool('pad')
|
||||
|
||||
def on_pad_add_array(self):
|
||||
self.select_tool('array')
|
||||
|
||||
def on_track_add(self):
|
||||
self.select_tool('track')
|
||||
|
||||
|
@ -462,6 +462,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
|
||||
self.grb_add_pad_menuitem = self.grb_editor_menu.addAction(
|
||||
QtGui.QIcon('share/aperture16.png'), _('Add Pad\tP'))
|
||||
self.grb_add_pad_array_menuitem = self.grb_editor_menu.addAction(
|
||||
QtGui.QIcon('share/padarray32.png'), _('Add Pad Array\tA'))
|
||||
self.grb_add_track_menuitem = self.grb_editor_menu.addAction(
|
||||
QtGui.QIcon('share/track32.png'), _('Add Track\tT'))
|
||||
self.grb_add_region_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/rectangle32.png'),
|
||||
@ -639,7 +641,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
self.select_drill_btn = self.exc_edit_toolbar.addAction(QtGui.QIcon('share/pointer32.png'), _("Select"))
|
||||
self.add_drill_btn = self.exc_edit_toolbar.addAction(QtGui.QIcon('share/plus16.png'), _('Add Drill Hole'))
|
||||
self.add_drill_array_btn = self.exc_edit_toolbar.addAction(
|
||||
QtGui.QIcon('share/addarray16.png'), 'Add Drill Hole Array')
|
||||
QtGui.QIcon('share/addarray16.png'), _('Add Drill Hole Array'))
|
||||
self.resize_drill_btn = self.exc_edit_toolbar.addAction(QtGui.QIcon('share/resize16.png'), _('Resize Drill'))
|
||||
self.exc_edit_toolbar.addSeparator()
|
||||
|
||||
@ -685,6 +687,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
### Gerber Editor Toolbar ###
|
||||
self.grb_select_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/pointer32.png'), _("Select"))
|
||||
self.grb_add_pad_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/aperture32.png'), _("Add Pad"))
|
||||
self.add_pad_ar_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/padarray32.png'), _('Add Pad Array'))
|
||||
self.grb_add_track_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/track32.png'), _("Add Track"))
|
||||
self.grb_add_region_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Add Region"))
|
||||
self.grb_edit_toolbar.addSeparator()
|
||||
@ -1779,6 +1782,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
### Gerber Editor Toolbar ###
|
||||
self.grb_select_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/pointer32.png'), _("Select"))
|
||||
self.grb_add_pad_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/aperture32.png'), _("Add Pad"))
|
||||
self.add_pad_ar_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/padarray32.png'), _('Add Pad Array'))
|
||||
self.grb_add_track_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/track32.png'), _("Add Track"))
|
||||
self.grb_add_region_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Add Region"))
|
||||
self.grb_edit_toolbar.addSeparator()
|
||||
@ -2513,6 +2517,24 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
self.app.on_select_tab('tool')
|
||||
return
|
||||
|
||||
# Add Array of pads
|
||||
if key == QtCore.Qt.Key_A or key == 'A':
|
||||
self.app.grb_editor.launched_from_shortcuts = True
|
||||
self.app.inform.emit("Click on target point.")
|
||||
self.app.ui.add_pad_ar_btn.setChecked(True)
|
||||
|
||||
self.app.grb_editor.x = self.app.mouse[0]
|
||||
self.app.grb_editor.y = self.app.mouse[1]
|
||||
|
||||
self.app.grb_editor.select_tool('array')
|
||||
return
|
||||
|
||||
# Scale Tool
|
||||
if key == QtCore.Qt.Key_B or key == 'B':
|
||||
self.app.grb_editor.launched_from_shortcuts = True
|
||||
self.app.grb_editor.select_tool('buffer')
|
||||
return
|
||||
|
||||
# Copy
|
||||
if key == QtCore.Qt.Key_C or key == 'C':
|
||||
self.app.grb_editor.launched_from_shortcuts = True
|
||||
@ -2526,12 +2548,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
self.app.inform.emit(_("[WARNING_NOTCL] Cancelled. Nothing selected to copy."))
|
||||
return
|
||||
|
||||
# Scale Tool
|
||||
if key == QtCore.Qt.Key_B or key == 'B':
|
||||
self.app.grb_editor.launched_from_shortcuts = True
|
||||
self.app.grb_editor.select_tool('buffer')
|
||||
return
|
||||
|
||||
# Grid Snap
|
||||
if key == QtCore.Qt.Key_G or key == 'G':
|
||||
self.app.grb_editor.launched_from_shortcuts = True
|
||||
@ -2570,7 +2586,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||
if key == QtCore.Qt.Key_P or key == 'P':
|
||||
self.app.grb_editor.launched_from_shortcuts = True
|
||||
self.app.inform.emit(_("Click on target point."))
|
||||
self.app.ui.grb_add_pad_btn.setChecked(True)
|
||||
self.app.ui.add_pad_ar_btn.setChecked(True)
|
||||
|
||||
self.app.grb_editor.x = self.app.mouse[0]
|
||||
self.app.grb_editor.y = self.app.mouse[1]
|
||||
|
Loading…
Reference in New Issue
Block a user