- 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:
Marius Stanciu 2019-04-11 23:08:30 +03:00
parent 036e886af4
commit cc6ff98529
3 changed files with 412 additions and 51 deletions

View File

@ -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

View File

@ -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
return None
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')

View File

@ -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]