- the Plugins object combo boxes are no longer updated on object selection on Project tab generally but only for the Plugin that is current, if any

- in Corner Markers Plugin I added a new feature, ability to insert existing markers into external objects. Finished the work for external Gerbers and work in progress for the external Geometry
This commit is contained in:
Marius Stanciu
2021-10-08 01:53:36 +03:00
committed by Marius
parent 26354e1f9e
commit 6f884f4d64
14 changed files with 453 additions and 122 deletions

View File

@@ -42,7 +42,8 @@ class ToolCorners(AppTool):
self.units = ''
# here we store the locations of the selected corners
self.points = {}
self.points = LoudDict()
self.points.set_change_callback(self.on_points_changed)
# #############################################################################
# ######################### Tool GUI ##########################################
@@ -66,6 +67,33 @@ class ToolCorners(AppTool):
self.handlers_connected = False
def on_insert_type_changed(self, val):
obj_type = 2 if val == 'geo' else 0
self.ui.obj_insert_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
self.ui.obj_insert_combo.setCurrentIndex(0)
self.ui.obj_insert_combo.obj_type = {
"grb": "gerber", "geo": "geometry"
}[self.ui.insert_type_radio.get_value()]
def on_object_selection_changed(self, current, previous):
found_idx = None
for tab_idx in range(self.app.ui.notebook.count()):
if self.app.ui.notebook.tabText(tab_idx) == self.ui.pluginName:
found_idx = True
break
if found_idx:
try:
name = current.indexes()[0].internalPointer().obj.options['name']
kind = current.indexes()[0].internalPointer().obj.kind
if kind in ['gerber', 'geometry']:
obj_type = {'gerber': 'grb', 'geometry': 'geo'}[kind]
self.ui.insert_type_radio.set_value(obj_type)
self.ui.obj_insert_combo.set_value(name)
except Exception:
pass
def run(self, toggle=True):
self.app.defaults.report_usage("ToolCorners()")
@@ -136,6 +164,10 @@ class ToolCorners(AppTool):
self.ui.drill_button.clicked.connect(self.on_create_drill_object)
self.ui.check_button.clicked.connect(self.on_create_check_object)
self.ui.mode_radio.activated_custom.connect(self.on_selection_changed)
self.ui.insert_type_radio.activated_custom.connect(self.on_insert_type_changed)
self.app.proj_selection_changed.connect(self.on_object_selection_changed)
self.ui.insert_markers_button.clicked.connect(self.on_insert_markers_in_external_objects)
def set_tool_ui(self):
self.units = self.app.app_units
@@ -153,6 +185,11 @@ class ToolCorners(AppTool):
self.ui.drill_dia_entry.set_value(self.app.defaults["tools_corners_drill_dia"])
self.ui.mode_radio.set_value("a")
self.ui.insert_type_radio.set_value(val="grb")
self.points.clear()
self.on_points_changed()
# SELECT THE CURRENT OBJECT
obj = self.app.collection.get_active()
if obj and obj.kind == 'gerber':
@@ -195,6 +232,10 @@ class ToolCorners(AppTool):
self.ui.drill_button.hide()
self.ui.check_label.hide()
self.ui.check_button.hide()
self.ui.insert_label.hide()
self.ui.insert_frame.hide()
self.ui.insert_markers_button.hide()
else:
self.ui.level.setText('%s' % _('Advanced'))
self.ui.level.setStyleSheet("""
@@ -210,6 +251,10 @@ class ToolCorners(AppTool):
self.ui.check_label.show()
self.ui.check_button.show()
self.ui.insert_label.show()
self.ui.insert_frame.show()
self.ui.insert_markers_button.show()
def on_toggle_all(self, val):
self.ui.bl_cb.set_value(val)
self.ui.br_cb.set_value(val)
@@ -318,6 +363,18 @@ class ToolCorners(AppTool):
:return: None
"""
geo_list = self.create_marker_geometry(points_storage)
if geo_list == "fail" or not geo_list:
return "fail"
assert isinstance(geo_list, list), 'Geometry list should be a list but the type is: %s' % str(type(geo_list))
new_name = '%s_%s' % (str(self.grb_object.options['name']), 'corners')
return_val = self.generate_gerber_obj_with_markers(new_grb_obj=g_obj, marker_geometry=geo_list, outname=new_name)
return return_val
def create_marker_geometry(self, points_storage):
marker_type = self.ui.type_radio.get_value()
line_thickness = self.ui.thick_entry.get_value()
margin = self.ui.margin_entry.get_value()
@@ -431,7 +488,23 @@ class ToolCorners(AppTool):
self.app.log.warning("Not enough points.")
return "fail"
new_apertures = deepcopy(g_obj.tools)
return geo_list
def generate_gerber_obj_with_markers(self, new_grb_obj, marker_geometry, outname):
"""
:param new_grb_obj: a Gerber App object
:type new_grb_obj:
:param marker_geometry: a list of Shapely geometries
:type marker_geometry: list
:param outname: the name for the new Gerber object
:type outname: str
:return:
:rtype:
"""
line_thickness = self.ui.thick_entry.get_value()
new_apertures = deepcopy(new_grb_obj.tools)
aperture_found = None
for ap_id, ap_val in new_apertures.items():
@@ -441,7 +514,7 @@ class ToolCorners(AppTool):
geo_buff_list = []
if aperture_found:
for geo in geo_list:
for geo in marker_geometry:
geo_buff = geo.buffer(line_thickness / 2.0, resolution=self.grb_steps_per_circle, join_style=2)
geo_buff_list.append(geo_buff)
@@ -455,12 +528,12 @@ class ToolCorners(AppTool):
new_apid = 10
new_apertures[new_apid] = {
'type': 'C',
'size': line_thickness,
'geometry': []
'type': 'C',
'size': line_thickness,
'geometry': []
}
for geo in geo_list:
for geo in marker_geometry:
geo_buff = geo.buffer(line_thickness / 2.0, resolution=self.grb_steps_per_circle, join_style=3)
geo_buff_list.append(geo_buff)
@@ -468,11 +541,11 @@ class ToolCorners(AppTool):
new_apertures[new_apid]['geometry'].append(deepcopy(dict_el))
s_list = []
if g_obj.solid_geometry:
if isinstance(g_obj.solid_geometry, MultiPolygon):
work_geo = g_obj.solid_geometry.geoms
if new_grb_obj.solid_geometry:
if isinstance(new_grb_obj.solid_geometry, MultiPolygon):
work_geo = new_grb_obj.solid_geometry.geoms
else:
work_geo = g_obj.solid_geometry
work_geo = new_grb_obj.solid_geometry
try:
for poly in work_geo:
s_list.append(poly)
@@ -489,20 +562,18 @@ class ToolCorners(AppTool):
except TypeError:
s_list.append(geo_buff_list)
outname = '%s_%s' % (str(self.grb_object.options['name']), 'corners')
def initialize(grb_obj, app_obj):
grb_obj.options = LoudDict()
for opt in g_obj.options:
for opt in new_grb_obj.options:
if opt != 'name':
grb_obj.options[opt] = deepcopy(g_obj.options[opt])
grb_obj.options[opt] = deepcopy(new_grb_obj.options[opt])
grb_obj.options['name'] = outname
grb_obj.multitool = False
grb_obj.multigeo = False
grb_obj.follow = deepcopy(g_obj.follow)
grb_obj.follow = deepcopy(new_grb_obj.follow)
grb_obj.tools = new_apertures
grb_obj.solid_geometry = flatten_shapely_geometry(unary_union(s_list))
grb_obj.follow_geometry = flatten_shapely_geometry(g_obj.follow_geometry + geo_list)
grb_obj.follow_geometry = flatten_shapely_geometry(new_grb_obj.follow_geometry + marker_geometry)
grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=outname, filename=None, local_use=grb_obj,
use_thread=False)
@@ -511,6 +582,93 @@ class ToolCorners(AppTool):
return ret
def generate_geo_obj_with_markers(self, new_geo_obj, marker_geometry, outname):
"""
:param new_geo_obj: a Geometry App object
:type new_geo_obj:
:param marker_geometry: a list of Shapely geometries
:type marker_geometry: list
:param outname: the name for the new Geometry object
:type outname: str
:return:
:rtype:
"""
tooldia = self.ui.thick_entry.get_value()
new_tools = deepcopy(new_geo_obj.tools)
tool_found = None
for tool, tool_dict in new_tools.items():
if tool_dict['tooldia'] == tooldia:
tool_found = tool
break
geo_buff_list = []
if tool_found:
new_tools[tool_found]['solid_geometry'] += marker_geometry
else:
obj_tools = list(new_tools.keys())
if obj_tools:
new_tool = max(obj_tools) + 1
else:
new_tool = 1
new_data = {}
for opt_key in self.app.options:
if opt_key.find('geometry' + "_") == 0:
oname = opt_key[len('geometry') + 1:]
new_data[oname] = self.app.options[opt_key]
for opt_key in self.app.options:
if opt_key.find('tools_') == 0:
new_data[opt_key] = self.app.options[opt_key]
new_tools = {
new_tool: {
'tooldia': tooldia,
'data': deepcopy(new_data),
'solid_geometry': marker_geometry
}
}
s_list = []
if new_geo_obj.solid_geometry:
if isinstance(new_geo_obj.solid_geometry, MultiPolygon):
work_geo = new_geo_obj.solid_geometry.geoms
else:
work_geo = new_geo_obj.solid_geometry
try:
for poly in work_geo:
s_list.append(poly)
except TypeError:
s_list.append(work_geo)
geo_buff_list = flatten_shapely_geometry(geo_buff_list)
try:
for poly in geo_buff_list + marker_geometry:
s_list.append(poly)
except TypeError:
s_list.append(geo_buff_list)
def initialize(geo_obj, app_obj):
geo_obj.options = LoudDict()
for opt in new_geo_obj.options:
if opt != 'name' and opt in geo_obj.options:
geo_obj.options[opt] = deepcopy(app_obj.options[opt])
geo_obj.options['name'] = outname
# Propagate options
geo_obj.options["tools_mill_tooldia"] = app_obj.defaults["tools_mill_tooldia"]
geo_obj.solid_geometry = flatten_shapely_geometry(unary_union(s_list))
geo_obj.multitool = False
geo_obj.multigeo = False
geo_obj.tools = new_tools
ret = self.app.app_obj.new_object('geometry', outname, initialize, plot=True, autoselected=False)
return ret
def on_create_drill_object(self):
self.app.call_source = "corners_tool"
@@ -737,6 +895,60 @@ class ToolCorners(AppTool):
else:
self.app.inform.emit('[success] %s' % _("Excellon object with corner drills created."))
def on_insert_markers_in_external_objects(self):
obj_type = self.ui.insert_type_radio.get_value() # values in ["grb", "geo"]
geo_list = self.create_marker_geometry(self.points)
if geo_list == "fail" or not geo_list:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
assert isinstance(geo_list, list), 'Geometry list should be a list but the type is: %s' % str(
type(geo_list))
if obj_type == 'grb':
# get the Gerber object on which the corner marker will be inserted
selection_index = self.ui.obj_insert_combo.currentIndex()
model_index = self.app.collection.index(selection_index, 0, self.ui.obj_insert_combo.rootModelIndex())
try:
new_grb_obj = model_index.internalPointer().obj
except Exception as e:
self.app.log.error("ToolCorners.on_insert_markers_in_external_objects() Gerber --> %s" % str(e))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
self.app.call_source = "app"
return
new_name = '%s_%s' % (str(new_grb_obj.options['name']), 'corners')
return_val = self.generate_gerber_obj_with_markers(new_grb_obj=new_grb_obj, marker_geometry=geo_list,
outname=new_name)
else:
# get the Geometry object on which the corner marker will be inserted
geo_obj_name = self.ui.obj_insert_combo.get_value()
try:
new_geo_obj = self.app.collection.get_by_name(geo_obj_name)
except Exception as e:
self.app.log.error("ToolCorners.on_insert_markers_in_external_objects() Geometry --> %s" % str(e))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Geometry object available."))
self.app.call_source = "app"
return
new_name = '%s_%s' % (str(new_geo_obj.options['name']), 'corners')
return_val = self.generate_geo_obj_with_markers(new_geo_obj=new_geo_obj, marker_geometry=geo_list,
outname=new_name)
if return_val == "fail":
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
else:
self.app.inform.emit('[success] %s' % _("Done."))
def on_points_changed(self, *args):
if self.points:
self.ui.insert_frame.setDisabled(False)
self.ui.insert_markers_button.setDisabled(False)
else:
self.ui.insert_frame.setDisabled(True)
self.ui.insert_markers_button.setDisabled(True)
def replot(self, obj, run_thread=True):
def worker_task():
with self.app.proc_container.new('%s ...' % _("Plotting")):
@@ -1049,7 +1261,7 @@ class CornersUI:
self.add_marker_button = FCButton(_("Add Marker"))
self.add_marker_button.setIcon(QtGui.QIcon(self.app.resource_location + '/corners_32.png'))
self.add_marker_button.setToolTip(
_("Will add corner markers to the selected Gerber file.")
_("Will add corner markers to the selected object.")
)
self.add_marker_button.setStyleSheet("""
QPushButton
@@ -1086,8 +1298,6 @@ class CornersUI:
grid_drill.addWidget(self.drill_dia_label, 0, 0)
grid_drill.addWidget(self.drill_dia_entry, 0, 1)
FCGridLayout.set_common_column_size([grid_sel, param_grid, grid_loc, grid_drill], 0)
# ## Create an Excellon object
self.drill_button = FCButton(_("Create Excellon Object"))
self.drill_button.setIcon(QtGui.QIcon(self.app.resource_location + '/drill32.png'))
@@ -1105,7 +1315,6 @@ class CornersUI:
# #############################################################################################################
# Check in Locations Frame
# #############################################################################################################
# Check in corners
self.check_label = FCLabel('<span style="color:indigo;"><b>%s</b></span>' % _('Check in Locations'))
self.tools_box.addWidget(self.check_label)
@@ -1126,6 +1335,54 @@ class CornersUI:
""")
self.tools_box.addWidget(self.check_button)
# #############################################################################################################
# Insert Markers Frame
# #############################################################################################################
self.insert_label = FCLabel('<span style="color:teal;"><b>%s</b></span>' % _('Insert Markers'))
self.tools_box.addWidget(self.insert_label)
self.insert_frame = FCFrame()
self.tools_box.addWidget(self.insert_frame)
insert_grid = FCGridLayout(v_spacing=5, h_spacing=3)
self.insert_frame.setLayout(insert_grid)
self.insert_type_label = FCLabel('%s:' % _("Type"))
self.insert_type_label.setToolTip(
_("Specify the type of object where the markers are inserted.")
)
# Type of object into which to insert the markers
self.insert_type_radio = RadioSet([{'label': _('Gerber'), 'value': 'grb'},
{'label': _('Geometry'), 'value': 'geo'}])
insert_grid.addWidget(self.insert_type_label, 0, 0)
insert_grid.addWidget(self.insert_type_radio, 0, 1)
# The object into which to insert existing markers
self.obj_insert_combo = FCComboBox()
self.obj_insert_combo.setModel(self.app.collection)
self.obj_insert_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
self.obj_insert_combo.is_last = False
insert_grid.addWidget(self.obj_insert_combo, 2, 0, 1, 2)
# Insert Markers
self.insert_markers_button = FCButton(_("Insert Marker"))
self.insert_markers_button.setIcon(QtGui.QIcon(self.app.resource_location + '/corners_32.png'))
self.insert_markers_button.setToolTip(
_("Will add corner markers to the selected object.")
)
self.insert_markers_button.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
self.tools_box.addWidget(self.insert_markers_button)
FCGridLayout.set_common_column_size([grid_sel, param_grid, grid_loc, grid_drill, insert_grid], 0)
self.layout.addStretch(1)
# ## Reset Tool