- modified the GUI for Exclusion areas; now the shapes are displayed in a Table where they can be selected and deleted. Modification applied for Geometry Objects only (for now).

- fixed and error when converting units, error that acted when in those fields that accept lists of tools only one tool was added
This commit is contained in:
Marius Stanciu 2020-05-09 05:18:05 +03:00 committed by Marius
parent ee69744d6e
commit 0e07ea1541
6 changed files with 207 additions and 41 deletions

View File

@ -7,6 +7,11 @@ CHANGELOG for FlatCAM beta
=================================================
9.05.2020
- modified the GUI for Exclusion areas; now the shapes are displayed in a Table where they can be selected and deleted. Modification applied for Geometry Objects only (for now).
- fixed and error when converting units, error that acted when in those fields that accept lists of tools only one tool was added
8.05.2020
- added a parameter to the FlatCAMDefaults class, whenever a value in the self.defaults dict change it will call a callback function and send to it the modified key

View File

@ -4328,12 +4328,14 @@ class App(QtCore.QObject):
]:
if self.defaults[dim] is None or self.defaults[dim] == '':
continue
try:
coordinates = self.defaults[dim].split(",")
coords_xy = [float(eval(a)) for a in coordinates if a != '']
coords_xy[0] *= sfactor
coords_xy[1] *= sfactor
self.defaults[dim] = "%.*f, %.*f" % (self.decimals, coords_xy[0], self.decimals, coords_xy[1])
self.defaults[dim] = "%.*f, %.*f" % (
self.decimals, coords_xy[0], self.decimals, coords_xy[1])
except Exception as e:
log.debug("App.on_toggle_units.scale_defaults() --> 'string tuples': %s" % str(e))
@ -4343,9 +4345,10 @@ class App(QtCore.QObject):
if self.defaults[dim] is None or self.defaults[dim] == '':
continue
if isinstance(self.defaults[dim], float):
try:
self.defaults[dim] = float(self.defaults[dim])
tools_diameters = [self.defaults[dim]]
else:
except ValueError:
try:
tools_string = self.defaults[dim].split(",")
tools_diameters = [eval(a) for a in tools_string if a != '']
@ -4354,9 +4357,14 @@ class App(QtCore.QObject):
continue
self.defaults[dim] = ''
for t in range(len(tools_diameters)):
tools_diameters[t] *= sfactor
self.defaults[dim] += "%.*f," % (self.decimals, tools_diameters[t])
td_len = len(tools_diameters)
if td_len > 1:
for t in range(td_len):
tools_diameters[t] *= sfactor
self.defaults[dim] += "%.*f," % (self.decimals, tools_diameters[t])
else:
tools_diameters[0] *= sfactor
self.defaults[dim] += "%.*f" % (self.decimals, tools_diameters[0])
elif dim in ['global_gridx', 'global_gridy']:
# format the number of decimals to the one specified in self.decimals

View File

@ -10,6 +10,7 @@
# File Modified (major mod): Marius Adrian Stanciu #
# Date: 11/4/2019 #
# ##########################################################
from PyQt5 import QtCore
from shapely.geometry import Polygon, MultiPolygon
@ -17,7 +18,6 @@ from flatcamGUI.VisPyVisuals import ShapeCollection
from FlatCAMTool import FlatCAMTool
import numpy as np
import re
import gettext
import FlatCAMTranslation as fcTranslate
@ -129,9 +129,13 @@ def color_variant(hex_color, bright_factor=1):
return "#" + "".join([i for i in new_rgb])
class ExclusionAreas:
class ExclusionAreas(QtCore.QObject):
e_shape_modified = QtCore.pyqtSignal()
def __init__(self, app):
super().__init__()
self.app = app
# Storage for shapes, storage that can be used by FlatCAm tools for utility geometry
@ -401,6 +405,7 @@ class ExclusionAreas:
'%s %s' % (_("Generate the CNC Job object."), _("With Exclusion areas."))
)
self.e_shape_modified.emit()
for k in self.exclusion_areas_storage:
print(k)
@ -514,3 +519,52 @@ class ExclusionAreas:
FlatCAMTool.delete_moving_selection_shape(self)
self.app.delete_selection_shape()
FlatCAMTool.delete_tool_selection_shape(self, shapes_storage=self.exclusion_shapes)
self.app.inform.emit('[success] %s' % _("All exclusion zones deleted."))
def delete_sel_shapes(self, idxs):
"""
:param idxs: list of indexes in self.exclusion_areas_storage list to be deleted
:return:
"""
# delete all plotted shapes
FlatCAMTool.delete_tool_selection_shape(self, shapes_storage=self.exclusion_shapes)
# delete shapes
for idx in sorted(idxs, reverse=True):
del self.exclusion_areas_storage[idx]
# re-add what's left after deletion in first step
if self.obj_type == 'excellon':
color = "#FF7400"
face_color = "#FF7400BF"
else:
color = "#098a8f"
face_color = "#FF7400BF"
face_alpha = 0.3
color_t = face_color[:-2] + str(hex(int(face_alpha * 255)))[2:]
for geo_el in self.exclusion_areas_storage:
if isinstance(geo_el['shape'], Polygon):
self.exclusion_shapes.add(
geo_el['shape'], color=color, face_color=color_t, update=True, layer=0, tolerance=None)
if self.app.is_legacy is True:
self.exclusion_shapes.redraw()
if self.exclusion_areas_storage:
self.app.inform.emit('[success] %s' % _("Selected exclusion zones deleted."))
else:
# restore the default StyleSheet
self.cnc_button.setStyleSheet("")
# update the StyleSheet
self.cnc_button.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
self.cnc_button.setToolTip('%s' % _("Generate the CNC Job object."))
self.app.inform.emit('[success] %s' % _("All exclusion zones deleted."))

View File

@ -2125,35 +2125,29 @@ class GeometryObjectUI(ObjectUI):
self.exclusion_box.setContentsMargins(0, 0, 0, 0)
self.exclusion_frame.setLayout(self.exclusion_box)
h_lay = QtWidgets.QHBoxLayout()
self.exclusion_box.addLayout(h_lay)
self.exclusion_table = FCTable()
self.exclusion_box.addWidget(self.exclusion_table)
self.exclusion_table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
# Button Add Area
self.add_area_button = QtWidgets.QPushButton(_('Add area'))
self.add_area_button.setToolTip(_("Add an Exclusion Area."))
h_lay.addWidget(self.add_area_button)
self.exclusion_table.setColumnCount(4)
self.exclusion_table.setColumnWidth(0, 20)
self.exclusion_table.setHorizontalHeaderLabels(['#', _('Object'), _('Strategy'), _('Over Z')])
# Button Delete Area
self.delete_area_button = QtWidgets.QPushButton(_('Clear areas'))
self.delete_area_button.setToolTip(_("Delete all exclusion areas."))
h_lay.addWidget(self.delete_area_button)
self.exclusion_table.horizontalHeaderItem(0).setToolTip(_("This is the Area ID."))
self.exclusion_table.horizontalHeaderItem(1).setToolTip(
_("Type of the object where the exclusion area was added."))
self.exclusion_table.horizontalHeaderItem(2).setToolTip(
_("The strategy used for exclusion area. Go around the exclusion areas or over it."))
self.exclusion_table.horizontalHeaderItem(3).setToolTip(
_("If the strategy is to go over the area then this is the height at which the tool will go to avoid the "
"exclusion area."))
grid_l = QtWidgets.QGridLayout()
grid_l.setColumnStretch(0, 0)
grid_l.setColumnStretch(1, 1)
self.exclusion_box.addLayout(grid_l)
self.exclusion_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
# Area Selection shape
self.area_shape_label = QtWidgets.QLabel('%s:' % _("Shape"))
self.area_shape_label.setToolTip(
_("The kind of selection shape used for area selection.")
)
self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'},
{'label': _("Polygon"), 'value': 'polygon'}])
grid_l.addWidget(self.area_shape_label, 0, 0)
grid_l.addWidget(self.area_shape_radio, 0, 1)
grid_a1 = QtWidgets.QGridLayout()
grid_a1.setColumnStretch(0, 0)
grid_a1.setColumnStretch(1, 1)
self.exclusion_box.addLayout(grid_a1)
# Chose Strategy
self.strategy_label = FCLabel('%s:' % _("Strategy"))
@ -2164,8 +2158,8 @@ class GeometryObjectUI(ObjectUI):
self.strategy_radio = RadioSet([{'label': _('Over'), 'value': 'over'},
{'label': _('Around'), 'value': 'around'}])
grid_l.addWidget(self.strategy_label, 1, 0)
grid_l.addWidget(self.strategy_radio, 1, 1)
grid_a1.addWidget(self.strategy_label, 1, 0)
grid_a1.addWidget(self.strategy_radio, 1, 1)
# Over Z
self.over_z_label = FCLabel('%s:' % _("Over Z"))
@ -2175,8 +2169,36 @@ class GeometryObjectUI(ObjectUI):
self.over_z_entry.set_range(0.000, 9999.9999)
self.over_z_entry.set_precision(self.decimals)
grid_l.addWidget(self.over_z_label, 2, 0)
grid_l.addWidget(self.over_z_entry, 2, 1)
grid_a1.addWidget(self.over_z_label, 2, 0)
grid_a1.addWidget(self.over_z_entry, 2, 1)
# Button Add Area
self.add_area_button = QtWidgets.QPushButton(_('Add area'))
self.add_area_button.setToolTip(_("Add an Exclusion Area."))
# Area Selection shape
self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'},
{'label': _("Polygon"), 'value': 'polygon'}])
self.area_shape_radio.setToolTip(
_("The kind of selection shape used for area selection.")
)
grid_a1.addWidget(self.add_area_button, 4, 0)
grid_a1.addWidget(self.area_shape_radio, 4, 1)
h_lay_1 = QtWidgets.QHBoxLayout()
self.exclusion_box.addLayout(h_lay_1)
# Button Delete All Areas
self.delete_area_button = QtWidgets.QPushButton(_('Clear areas'))
self.delete_area_button.setToolTip(_("Delete all exclusion areas."))
# Button Delete Selected Areas
self.delete_sel_area_button = QtWidgets.QPushButton(_('Delete Selected'))
self.delete_sel_area_button.setToolTip(_("Delete all exclusion areas that are selected in the table."))
h_lay_1.addWidget(self.delete_area_button)
h_lay_1.addWidget(self.delete_sel_area_button)
# -------------------------- EXCLUSION AREAS END -------------------------------------------------------------
# ------------------------------------------------------------------------------------------------------------

View File

@ -159,6 +159,15 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui_disconnect()
FlatCAMObj.build_ui(self)
# Area Exception - exclusion shape added signal
# first disconnect it from any other object
try:
self.app.exc_areas.e_shape_modified.disconnect()
except (TypeError, AttributeError):
pass
# then connect it to the current build_ui() method
self.app.exc_areas.e_shape_modified.connect(self.build_ui)
self.units = self.app.defaults['units']
tool_idx = 0
@ -179,7 +188,6 @@ class GeometryObject(FlatCAMObj, Geometry):
# For INCH the decimals should be no more than 3. There are no tools under 10mils.
dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(tooluid_value['tooldia'])))
dia_item.setFlags(QtCore.Qt.ItemIsEnabled)
offset_item = FCComboBox()
@ -310,6 +318,58 @@ class GeometryObject(FlatCAMObj, Geometry):
"<b>%s: <font color='#0000FF'>%s</font></b>" % (_('Parameters for'), _("Multiple Tools"))
)
# Build Exclusion Areas section
e_len = len(self.app.exc_areas.exclusion_areas_storage)
self.ui.exclusion_table.setRowCount(e_len)
area_id = 0
for area in range(e_len):
area_id += 1
area_dict = self.app.exc_areas.exclusion_areas_storage[area]
area_id_item = QtWidgets.QTableWidgetItem('%d' % int(area_id))
area_id_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.ui.exclusion_table.setItem(area, 0, area_id_item) # Area id
object_item = QtWidgets.QTableWidgetItem('%s' % area_dict["obj_type"])
object_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.ui.exclusion_table.setItem(area, 1, object_item) # Origin Object
strategy_item = QtWidgets.QTableWidgetItem('%s' % area_dict["strategy"])
strategy_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.ui.exclusion_table.setItem(area, 2, strategy_item) # Strategy
overz_item = QtWidgets.QTableWidgetItem('%s' % area_dict["overz"])
overz_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.ui.exclusion_table.setItem(area, 3, overz_item) # Over Z
self.ui.exclusion_table.resizeColumnsToContents()
self.ui.exclusion_table.resizeRowsToContents()
area_vheader = self.ui.exclusion_table.verticalHeader()
area_vheader.hide()
self.ui.exclusion_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
area_hheader = self.ui.exclusion_table.horizontalHeader()
area_hheader.setMinimumSectionSize(10)
area_hheader.setDefaultSectionSize(70)
area_hheader.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
area_hheader.resizeSection(0, 20)
area_hheader.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
area_hheader.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
area_hheader.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
# area_hheader.setStretchLastSection(True)
self.ui.exclusion_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.ui.exclusion_table.setColumnWidth(0, 20)
self.ui.exclusion_table.setMinimumHeight(self.ui.exclusion_table.getHeight())
self.ui.exclusion_table.setMaximumHeight(self.ui.exclusion_table.getHeight())
def set_ui(self, ui):
FlatCAMObj.set_ui(self, ui)
@ -534,8 +594,11 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked)
self.ui.cutz_entry.returnPressed.connect(self.on_cut_z_changed)
# Exclusion areas
self.ui.exclusion_table.horizontalHeader().sectionClicked.connect(self.ui.exclusion_table.selectAll)
self.ui.add_area_button.clicked.connect(self.on_add_area_click)
self.ui.delete_area_button.clicked.connect(self.on_clear_area_click)
self.ui.delete_sel_area_button.clicked.connect(self.on_delete_sel_areas)
def on_cut_z_changed(self):
self.old_cutz = self.ui.cutz_entry.get_value()
@ -2463,6 +2526,20 @@ class GeometryObject(FlatCAMObj, Geometry):
def on_clear_area_click(self):
self.app.exc_areas.on_clear_area_click()
self.app.exc_areas.e_shape_modified.emit()
def on_delete_sel_areas(self):
sel_model = self.ui.exclusion_table.selectionModel()
sel_indexes = sel_model.selectedIndexes()
# it will iterate over all indexes which means all items in all columns too but I'm interested only on rows
# so the duplicate rows will not be added
sel_rows = set()
for idx in sel_indexes:
sel_rows.add(idx.row())
self.app.exc_areas.delete_sel_shapes(idxs=list(sel_rows))
self.app.exc_areas.e_shape_modified.emit()
def plot_element(self, element, color=None, visible=None):

View File

@ -308,8 +308,8 @@ class FlatCAMObj(QtCore.QObject):
for option in self.options:
try:
self.set_form_item(option)
except Exception:
self.app.log.warning("Unexpected error:", sys.exc_info())
except Exception as err:
self.app.log.warning("Unexpected error: %s" % str(sys.exc_info()), str(err))
def read_form(self):
"""
@ -323,7 +323,7 @@ class FlatCAMObj(QtCore.QObject):
try:
self.read_form_item(option)
except Exception:
self.app.log.warning("Unexpected error:", sys.exc_info())
self.app.log.warning("Unexpected error: %s" % str(sys.exc_info()))
def set_form_item(self, option):
"""