From 541813c22b447e058b499fefac2215ce3f1f03b3 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sun, 10 May 2020 01:05:02 +0300 Subject: [PATCH] - finished the GUI for exclusion areas both in the Excellon and Geometry Objects. Need to think if to make it visible only in Advanced Mode --- CHANGELOG.md | 3 +- flatcamGUI/GUIElements.py | 5 + flatcamGUI/ObjectUI.py | 117 ++++++++++++++-------- flatcamObjects/FlatCAMExcellon.py | 161 ++++++++++++++++++++++++++++++ flatcamObjects/FlatCAMGeometry.py | 88 +++++++++++++++- flatcamObjects/FlatCAMObj.py | 4 +- 6 files changed, 327 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3e35ee0..7770a326 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ 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 +- fixed an error when converting units, error that acted when in those fields that accept lists of tools only one tool was added +- finished the GUI for exclusion areas both in the Excellon and Geometry Objects. Need to think if to make it visible only in Advanced Mode 8.05.2020 diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index bc283456..7b9b38f4 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -2232,6 +2232,7 @@ class OptionalHideInputSection: class FCTable(QtWidgets.QTableWidget): drag_drop_sig = QtCore.pyqtSignal() + lost_focus = QtCore.pyqtSignal() def __init__(self, drag_drop=False, protected_rows=None, parent=None): super(FCTable, self).__init__(parent) @@ -2295,6 +2296,10 @@ class FCTable(QtWidgets.QTableWidget): else: QtWidgets.QTableWidget.mousePressEvent(self, event) + def focusOutEvent(self, event): + self.lost_focus.emit() + super().focusOutEvent(event) + def setupContextMenu(self): self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) diff --git a/flatcamGUI/ObjectUI.py b/flatcamGUI/ObjectUI.py index 8aa848d3..6cdb71a7 100644 --- a/flatcamGUI/ObjectUI.py +++ b/flatcamGUI/ObjectUI.py @@ -1292,6 +1292,10 @@ class ExcellonObjectUI(ObjectUI): self.grid5.addWidget(pp_geo_label, 16, 0) self.grid5.addWidget(self.pp_geo_name_cb, 16, 1) + # ------------------------------------------------------------------------------------------------------------ + # ------------------------- EXCLUSION AREAS ------------------------------------------------------------------ + # ------------------------------------------------------------------------------------------------------------ + # Exclusion Areas self.exclusion_cb = FCCheckBox('%s' % _("Add exclusion areas")) self.exclusion_cb.setToolTip( @@ -1301,48 +1305,39 @@ class ExcellonObjectUI(ObjectUI): "is forbidden." ) ) - self.grid5.addWidget(self.exclusion_cb, 17, 0, 1, 2) + self.grid5.addWidget(self.exclusion_cb, 20, 0, 1, 2) - # ------------------------------------------------------------------------------------------------------------ - # ------------------------- EXCLUSION AREAS ------------------------------------------------------------------ - # ------------------------------------------------------------------------------------------------------------ self.exclusion_frame = QtWidgets.QFrame() self.exclusion_frame.setContentsMargins(0, 0, 0, 0) - self.grid5.addWidget(self.exclusion_frame, 18, 0, 1, 2) + self.grid5.addWidget(self.exclusion_frame, 22, 0, 1, 2) self.exclusion_box = QtWidgets.QVBoxLayout() 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")) @@ -1353,8 +1348,8 @@ class ExcellonObjectUI(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")) @@ -1364,17 +1359,45 @@ class ExcellonObjectUI(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(_('Delete All')) + 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) + + self.ois_exclusion_exc = OptionalHideInputSection(self.exclusion_cb, [self.exclusion_frame]) # -------------------------- EXCLUSION AREAS END ------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------ - self.ois_exclusion_geo = OptionalHideInputSection(self.exclusion_cb, [self.exclusion_frame]) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - self.grid5.addWidget(separator_line, 19, 0, 1, 2) + self.grid5.addWidget(separator_line, 25, 0, 1, 2) # ################################################################# # ################# GRID LAYOUT 6 ############################### @@ -1391,7 +1414,7 @@ class ExcellonObjectUI(ObjectUI): "for custom selection of tools." )) - self.grid6.addWidget(QtWidgets.QLabel(''), 1, 0, 1, 3) + # self.grid6.addWidget(QtWidgets.QLabel(''), 1, 0, 1, 3) self.grid6.addWidget(warning_lbl, 2, 0, 1, 3) self.generate_cnc_button = QtWidgets.QPushButton(_('Generate CNCJob object')) @@ -2103,6 +2126,10 @@ class GeometryObjectUI(ObjectUI): # grid4.addWidget(QtWidgets.QLabel(''), 12, 0, 1, 2) + # ------------------------------------------------------------------------------------------------------------ + # ------------------------- EXCLUSION AREAS ------------------------------------------------------------------ + # ------------------------------------------------------------------------------------------------------------ + # Exclusion Areas self.exclusion_cb = FCCheckBox('%s' % _("Add exclusion areas")) self.exclusion_cb.setToolTip( @@ -2114,9 +2141,6 @@ class GeometryObjectUI(ObjectUI): ) grid4.addWidget(self.exclusion_cb, 12, 0, 1, 2) - # ------------------------------------------------------------------------------------------------------------ - # ------------------------- EXCLUSION AREAS ------------------------------------------------------------------ - # ------------------------------------------------------------------------------------------------------------ self.exclusion_frame = QtWidgets.QFrame() self.exclusion_frame.setContentsMargins(0, 0, 0, 0) grid4.addWidget(self.exclusion_frame, 14, 0, 1, 2) @@ -2173,7 +2197,7 @@ class GeometryObjectUI(ObjectUI): grid_a1.addWidget(self.over_z_entry, 2, 1) # Button Add Area - self.add_area_button = QtWidgets.QPushButton(_('Add area')) + self.add_area_button = QtWidgets.QPushButton(_('Add area:')) self.add_area_button.setToolTip(_("Add an Exclusion Area.")) # Area Selection shape @@ -2190,7 +2214,7 @@ class GeometryObjectUI(ObjectUI): self.exclusion_box.addLayout(h_lay_1) # Button Delete All Areas - self.delete_area_button = QtWidgets.QPushButton(_('Clear areas')) + self.delete_area_button = QtWidgets.QPushButton(_('Delete All')) self.delete_area_button.setToolTip(_("Delete all exclusion areas.")) # Button Delete Selected Areas @@ -2200,9 +2224,14 @@ class GeometryObjectUI(ObjectUI): h_lay_1.addWidget(self.delete_area_button) h_lay_1.addWidget(self.delete_sel_area_button) + self.ois_exclusion_geo = OptionalHideInputSection(self.exclusion_cb, [self.exclusion_frame]) # -------------------------- EXCLUSION AREAS END ------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------ - self.ois_exclusion_geo = OptionalHideInputSection(self.exclusion_cb, [self.exclusion_frame]) + + separator_line2 = QtWidgets.QFrame() + separator_line2.setFrameShape(QtWidgets.QFrame.HLine) + separator_line2.setFrameShadow(QtWidgets.QFrame.Sunken) + grid4.addWidget(separator_line2, 15, 0, 1, 2) warning_lbl = QtWidgets.QLabel( _( @@ -2210,7 +2239,7 @@ class GeometryObjectUI(ObjectUI): "Click the # header to select all, or Ctrl + LMB\n" "for custom selection of tools." )) - grid4.addWidget(warning_lbl, 15, 0, 1, 2) + grid4.addWidget(warning_lbl, 16, 0, 1, 2) # Button self.generate_cnc_button = QtWidgets.QPushButton(_('Generate CNCJob object')) diff --git a/flatcamObjects/FlatCAMExcellon.py b/flatcamObjects/FlatCAMExcellon.py index a682495b..2e97db1e 100644 --- a/flatcamObjects/FlatCAMExcellon.py +++ b/flatcamObjects/FlatCAMExcellon.py @@ -125,6 +125,10 @@ class ExcellonObject(FlatCAMObj, Excellon): self.outline_color = self.app.defaults['excellon_plot_line'] self.alpha_level = 'bf' + # store here the state of the exclusion checkbox state to be restored after building the UI + # TODO add this in the sel.app.defaults dict and in Preferences + self.exclusion_area_cb_is_checked = False + # Attributes to be included in serialization # Always append to it because it carries contents # from predecessors. @@ -314,6 +318,15 @@ class ExcellonObject(FlatCAMObj, Excellon): def build_ui(self): 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.update_exclusion_table) + self.units = self.app.defaults['units'].upper() for row in range(self.ui.tools_table.rowCount()): @@ -514,6 +527,58 @@ class ExcellonObject(FlatCAMObj, Excellon): "%s: %s" % (_('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()) + self.ui_connect() def set_ui(self, ui): @@ -632,14 +697,21 @@ class ExcellonObject(FlatCAMObj, Excellon): assert isinstance(self.ui, ExcellonObjectUI), \ "Expected a ExcellonObjectUI, got %s" % type(self.ui) + self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click) self.ui.solid_cb.stateChanged.connect(self.on_solid_cb_click) self.ui.generate_cnc_button.clicked.connect(self.on_create_cncjob_button_click) self.ui.generate_milling_button.clicked.connect(self.on_generate_milling_button_click) self.ui.generate_milling_slots_button.clicked.connect(self.on_generate_milling_slots_button_click) + # Exclusion areas signals + self.ui.exclusion_table.horizontalHeader().sectionClicked.connect(self.exclusion_table_toggle_all) + self.ui.exclusion_table.lost_focus.connect(self.clear_selection) + self.ui.exclusion_table.itemClicked.connect(self.draw_sel_shape) 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) + self.ui.strategy_radio.activated_custom.connect(self.on_strategy) self.on_operation_type(val='drill') self.ui.operation_radio.activated_custom.connect(self.on_operation_type) @@ -1487,7 +1559,96 @@ class ExcellonObject(FlatCAMObj, Excellon): solid_geo=solid_geo, obj_type=obj_type) def on_clear_area_click(self): + if not self.app.exc_areas.exclusion_areas_storage: + self.app.inform.emit("[WARNING_NOTCL] %s" % _("Delete failed. There are no exclusion areas to delete.")) + return + 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()) + + if not sel_rows: + self.app.inform.emit("[WARNING_NOTCL] %s" % _("Delete failed. Nothing is selected.")) + return + + self.app.exc_areas.delete_sel_shapes(idxs=list(sel_rows)) + self.app.exc_areas.e_shape_modified.emit() + + def draw_sel_shape(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 + sel_rows = set() + for idx in sel_indexes: + sel_rows.add(idx.row()) + + self.delete_sel_shape() + + if self.app.is_legacy is False: + face = self.app.defaults['global_sel_fill'][:-2] + str(hex(int(0.2 * 255)))[2:] + outline = self.app.defaults['global_sel_line'][:-2] + str(hex(int(0.8 * 255)))[2:] + else: + face = self.app.defaults['global_sel_fill'][:-2] + str(hex(int(0.4 * 255)))[2:] + outline = self.app.defaults['global_sel_line'][:-2] + str(hex(int(1.0 * 255)))[2:] + + for row in sel_rows: + sel_rect = self.app.exc_areas.exclusion_areas_storage[row]['shape'] + self.app.move_tool.sel_shapes.add(sel_rect, color=outline, face_color=face, update=True, layer=0, + tolerance=None) + if self.app.is_legacy is True: + self.app.move_tool.sel_shapes.redraw() + + def clear_selection(self): + self.app.delete_selection_shape() + # self.ui.exclusion_table.clearSelection() + + def delete_sel_shape(self): + self.app.delete_selection_shape() + + def update_exclusion_table(self): + self.exclusion_area_cb_is_checked = True if self.ui.exclusion_cb.isChecked() else False + + self.build_ui() + self.ui.exclusion_cb.set_value(self.exclusion_area_cb_is_checked) + + def on_strategy(self, val): + if val == 'around': + self.ui.over_z_label.setDisabled(True) + self.ui.over_z_entry.setDisabled(True) + else: + self.ui.over_z_label.setDisabled(False) + self.ui.over_z_entry.setDisabled(False) + + def exclusion_table_toggle_all(self): + """ + will toggle the selection of all rows in Exclusion Areas table + + :return: + """ + 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 + sel_rows = set() + for idx in sel_indexes: + sel_rows.add(idx.row()) + + if sel_rows: + self.ui.exclusion_table.clearSelection() + self.delete_sel_shape() + else: + self.ui.exclusion_table.selectAll() + self.draw_sel_shape() def on_solid_cb_click(self, *args): if self.muted_ui: diff --git a/flatcamObjects/FlatCAMGeometry.py b/flatcamObjects/FlatCAMGeometry.py index 18d9aaae..dfde372f 100644 --- a/flatcamObjects/FlatCAMGeometry.py +++ b/flatcamObjects/FlatCAMGeometry.py @@ -150,6 +150,10 @@ class GeometryObject(FlatCAMObj, Geometry): self.param_fields = {} + # store here the state of the exclusion checkbox state to be restored after building the UI + # TODO add this in the sel.app.defaults dict and in Preferences + self.exclusion_area_cb_is_checked = False + # Attributes to be included in serialization # Always append to it because it carries contents # from predecessors. @@ -166,7 +170,7 @@ class GeometryObject(FlatCAMObj, Geometry): 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.app.exc_areas.e_shape_modified.connect(self.update_exclusion_table) self.units = self.app.defaults['units'] @@ -594,11 +598,14 @@ 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) + # Exclusion areas signals + self.ui.exclusion_table.horizontalHeader().sectionClicked.connect(self.exclusion_table_toggle_all) + self.ui.exclusion_table.lost_focus.connect(self.clear_selection) + self.ui.exclusion_table.itemClicked.connect(self.draw_sel_shape) 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) + self.ui.strategy_radio.activated_custom.connect(self.on_strategy) def on_cut_z_changed(self): self.old_cutz = self.ui.cutz_entry.get_value() @@ -2525,6 +2532,10 @@ class GeometryObject(FlatCAMObj, Geometry): solid_geo=solid_geo, obj_type=obj_type) def on_clear_area_click(self): + if not self.app.exc_areas.exclusion_areas_storage: + self.app.inform.emit("[WARNING_NOTCL] %s" % _("Delete failed. There are no exclusion areas to delete.")) + return + self.app.exc_areas.on_clear_area_click() self.app.exc_areas.e_shape_modified.emit() @@ -2538,9 +2549,80 @@ class GeometryObject(FlatCAMObj, Geometry): for idx in sel_indexes: sel_rows.add(idx.row()) + if not sel_rows: + self.app.inform.emit("[WARNING_NOTCL] %s" % _("Delete failed. Nothing is selected.")) + return + self.app.exc_areas.delete_sel_shapes(idxs=list(sel_rows)) self.app.exc_areas.e_shape_modified.emit() + def draw_sel_shape(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 + sel_rows = set() + for idx in sel_indexes: + sel_rows.add(idx.row()) + + self.delete_sel_shape() + + if self.app.is_legacy is False: + face = self.app.defaults['global_sel_fill'][:-2] + str(hex(int(0.2 * 255)))[2:] + outline = self.app.defaults['global_sel_line'][:-2] + str(hex(int(0.8 * 255)))[2:] + else: + face = self.app.defaults['global_sel_fill'][:-2] + str(hex(int(0.4 * 255)))[2:] + outline = self.app.defaults['global_sel_line'][:-2] + str(hex(int(1.0 * 255)))[2:] + + for row in sel_rows: + sel_rect = self.app.exc_areas.exclusion_areas_storage[row]['shape'] + self.app.move_tool.sel_shapes.add(sel_rect, color=outline, face_color=face, update=True, layer=0, + tolerance=None) + if self.app.is_legacy is True: + self.app.move_tool.sel_shapes.redraw() + + def clear_selection(self): + self.app.delete_selection_shape() + # self.ui.exclusion_table.clearSelection() + + def delete_sel_shape(self): + self.app.delete_selection_shape() + + def update_exclusion_table(self): + self.exclusion_area_cb_is_checked = True if self.ui.exclusion_cb.isChecked() else False + + self.build_ui() + self.ui.exclusion_cb.set_value(self.exclusion_area_cb_is_checked) + + def on_strategy(self, val): + if val == 'around': + self.ui.over_z_label.setDisabled(True) + self.ui.over_z_entry.setDisabled(True) + else: + self.ui.over_z_label.setDisabled(False) + self.ui.over_z_entry.setDisabled(False) + + def exclusion_table_toggle_all(self): + """ + will toggle the selection of all rows in Exclusion Areas table + + :return: + """ + 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 + sel_rows = set() + for idx in sel_indexes: + sel_rows.add(idx.row()) + + if sel_rows: + self.ui.exclusion_table.clearSelection() + self.delete_sel_shape() + else: + self.ui.exclusion_table.selectAll() + self.draw_sel_shape() + def plot_element(self, element, color=None, visible=None): if color is None: diff --git a/flatcamObjects/FlatCAMObj.py b/flatcamObjects/FlatCAMObj.py index 19ee7257..22a12117 100644 --- a/flatcamObjects/FlatCAMObj.py +++ b/flatcamObjects/FlatCAMObj.py @@ -186,11 +186,9 @@ class FlatCAMObj(QtCore.QObject): def build_ui(self): """ - Sets up the UI/form for this object. Show the UI - in the App. + Sets up the UI/form for this object. Show the UI in the App. :return: None - :rtype: None """ self.muted_ui = True