Procházet zdrojové kódy

Merged marius_stanciu/flatcam_beta/Beta_8.993 into Beta

Marius Stanciu před 5 roky
rodič
revize
0d870dcde6

+ 5 - 0
CHANGELOG.md

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

+ 14 - 6
FlatCAMApp.py

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

+ 56 - 2
FlatCAMCommon.py

@@ -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."))

+ 55 - 33
flatcamGUI/ObjectUI.py

@@ -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)
-
-        # 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)
-
-        # 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)
-
-        grid_l = QtWidgets.QGridLayout()
-        grid_l.setColumnStretch(0, 0)
-        grid_l.setColumnStretch(1, 1)
-        self.exclusion_box.addLayout(grid_l)
-
-        # 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)
+        self.exclusion_table = FCTable()
+        self.exclusion_box.addWidget(self.exclusion_table)
+        self.exclusion_table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
+
+        self.exclusion_table.setColumnCount(4)
+        self.exclusion_table.setColumnWidth(0, 20)
+        self.exclusion_table.setHorizontalHeaderLabels(['#', _('Object'), _('Strategy'), _('Over Z')])
+
+        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."))
+
+        self.exclusion_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+
+        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 -------------------------------------------------------------
         # ------------------------------------------------------------------------------------------------------------

+ 78 - 1
flatcamObjects/FlatCAMGeometry.py

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

+ 3 - 3
flatcamObjects/FlatCAMObj.py

@@ -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):
         """