diff --git a/AppEditors/FlatCAMGrbEditor.py b/AppEditors/FlatCAMGrbEditor.py index ae8db62c..e545d05b 100644 --- a/AppEditors/FlatCAMGrbEditor.py +++ b/AppEditors/FlatCAMGrbEditor.py @@ -1084,15 +1084,6 @@ class FCRegion(FCShapeTool): self.draw_app.app.inform.emit('[success] %s' % _("Done.")) - def clean_up(self): - self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() - self.draw_app.plot_all() - try: - self.draw_app.app.jump_signal.disconnect() - except (TypeError, AttributeError): - pass - def on_key(self, key): # Jump to coords if key == QtCore.Qt.Key_J or key == 'J': @@ -1158,16 +1149,36 @@ class FCRegion(FCShapeTool): return msg + def clean_up(self): + self.draw_app.selected = [] + self.draw_app.apertures_table.clearSelection() + self.draw_app.plot_all() + try: + self.draw_app.app.jump_signal.disconnect() + except (TypeError, AttributeError): + pass -class FCTrack(FCRegion): + +class FCTrack(FCShapeTool): """ Resulting type: Polygon """ def __init__(self, draw_app): - FCRegion.__init__(self, draw_app) + DrawTool.__init__(self, draw_app) self.name = 'track' self.draw_app = draw_app + self.steps_per_circle = self.draw_app.app.defaults["gerber_circle_steps"] + + size_ap = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size']) + self.buf_val = (size_ap / 2) if size_ap > 0 else 0.0000001 + + self.gridx_size = float(self.draw_app.app.ui.grid_gap_x_entry.get_value()) + self.gridy_size = float(self.draw_app.app.ui.grid_gap_y_entry.get_value()) + + self.temp_points = [] + + self. final_click = False try: QtGui.QGuiApplication.restoreOverrideCursor() except Exception as e: @@ -1181,49 +1192,23 @@ class FCTrack(FCRegion): self.draw_app.app.inform.emit(_('Track Mode 1: 45 degrees ...')) - def make(self): - new_geo_el = {} - if len(self.temp_points) == 1: - new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, - resolution=int(self.steps_per_circle / 4)) - new_geo_el['follow'] = Point(self.temp_points) - else: - new_geo_el['solid'] = (LineString(self.temp_points).buffer( - self.buf_val, resolution=int(self.steps_per_circle / 4))).buffer(0) - new_geo_el['follow'] = LineString(self.temp_points) - - self.geometry = DrawToolShape(new_geo_el) - - self.draw_app.in_action = False - self.complete = True - - self.draw_app.app.jump_signal.disconnect() - self.draw_app.app.inform.emit('[success] %s' % _("Done.")) - - def clean_up(self): - self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() - self.draw_app.plot_all() - try: - self.draw_app.app.jump_signal.disconnect() - except (TypeError, AttributeError): - pass - def click(self, point): self.draw_app.in_action = True - try: - if point != self.points[-1]: - self.points.append(point) - except IndexError: + + if not self.points: self.points.append(point) + elif point != self.points[-1]: + self.points.append(point) + else: + return new_geo_el = {} if len(self.temp_points) == 1: - new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle / 4)) + new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle)) new_geo_el['follow'] = Point(self.temp_points) else: - new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle / 4)) + new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle)) new_geo_el['follow'] = LineString(self.temp_points) self.draw_app.add_gerber_shape(DrawToolShape(new_geo_el), @@ -1236,23 +1221,25 @@ class FCTrack(FCRegion): return "" + def update_grid_info(self): + self.gridx_size = float(self.draw_app.app.ui.grid_gap_x_entry.get_value()) + self.gridy_size = float(self.draw_app.app.ui.grid_gap_y_entry.get_value()) + def utility_geometry(self, data=None): self.update_grid_info() new_geo_el = {} - if len(self.points) == 0: - new_geo_el['solid'] = Point(data).buffer(self.buf_val, - resolution=int(self.steps_per_circle / 4)) - + if not self.points: + new_geo_el['solid'] = Point(data).buffer(self.buf_val, int(self.steps_per_circle)) return DrawToolUtilityShape(new_geo_el) - elif len(self.points) > 0: - - self.temp_points = [self.points[-1]] + else: old_x = self.points[-1][0] old_y = self.points[-1][1] x = data[0] y = data[1] + self.temp_points = [self.points[-1]] + mx = abs(round((x - old_x) / self.gridx_size)) my = abs(round((y - old_y) / self.gridy_size)) @@ -1300,14 +1287,30 @@ class FCTrack(FCRegion): self.temp_points.append(data) if len(self.temp_points) == 1: - new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, - resolution=int(self.steps_per_circle / 4)) + new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle)) return DrawToolUtilityShape(new_geo_el) - new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, - resolution=int(self.steps_per_circle / 4)) + new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle)) return DrawToolUtilityShape(new_geo_el) + def make(self): + new_geo_el = {} + if len(self.temp_points) == 1: + new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle)) + new_geo_el['follow'] = Point(self.temp_points) + else: + new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle)) + new_geo_el['solid'] = new_geo_el['solid'].buffer(0) # try to clean the geometry + new_geo_el['follow'] = LineString(self.temp_points) + + self.geometry = DrawToolShape(new_geo_el) + + self.draw_app.in_action = False + self.complete = True + + self.draw_app.app.jump_signal.disconnect() + self.draw_app.app.inform.emit('[success] %s' % _("Done.")) + def on_key(self, key): if key == 'Backspace' or key == QtCore.Qt.Key_Backspace: if len(self.points) > 0: @@ -1400,6 +1403,15 @@ class FCTrack(FCRegion): return msg + def clean_up(self): + self.draw_app.selected = [] + self.draw_app.apertures_table.clearSelection() + self.draw_app.plot_all() + try: + self.draw_app.app.jump_signal.disconnect() + except (TypeError, AttributeError): + pass + class FCDisc(FCShapeTool): """ @@ -4535,6 +4547,7 @@ class FlatCAMGrbEditor(QtCore.QObject): if self.current_storage is not None: self.on_grb_shape_complete(self.current_storage) self.build_ui() + # MS: always return to the Select Tool if modifier key is not pressed # else return to the current tool key_modifier = QtWidgets.QApplication.keyboardModifiers() @@ -4542,6 +4555,7 @@ class FlatCAMGrbEditor(QtCore.QObject): modifier_to_use = Qt.ControlModifier else: modifier_to_use = Qt.ShiftModifier + # if modifier key is pressed then we add to the selected list the current shape but if it's already # in the selected list, we removed it. Therefore first click selects, second deselects. if key_modifier == modifier_to_use: @@ -4602,12 +4616,14 @@ class FlatCAMGrbEditor(QtCore.QObject): # if right click on canvas and the active tool need to be finished (like Path or Polygon) # right mouse click will finish the action if isinstance(self.active_tool, FCShapeTool): - self.active_tool.click(self.app.geo_editor.snap(self.x, self.y)) - self.active_tool.make() + if isinstance(self.active_tool, FCTrack): + self.active_tool.make() + else: + self.active_tool.click(self.app.geo_editor.snap(self.x, self.y)) + self.active_tool.make() if self.active_tool.complete: self.on_grb_shape_complete() - self.app.inform.emit('[success] %s' % - _("Done.")) + self.app.inform.emit('[success] %s' % _("Done.")) # MS: always return to the Select Tool if modifier key is not pressed # else return to the current tool but not for FCTrack diff --git a/AppGUI/ObjectUI.py b/AppGUI/ObjectUI.py index 8f42d44e..f2d52a06 100644 --- a/AppGUI/ObjectUI.py +++ b/AppGUI/ObjectUI.py @@ -1754,10 +1754,10 @@ class GeometryObjectUI(ObjectUI): # ################# GRID LAYOUT 3 ############################### # ################################################################# - grid3 = QtWidgets.QGridLayout() - grid3.setColumnStretch(0, 0) - grid3.setColumnStretch(1, 1) - self.geo_param_box.addLayout(grid3) + self.grid3 = QtWidgets.QGridLayout() + self.grid3.setColumnStretch(0, 0) + self.grid3.setColumnStretch(1, 1) + self.geo_param_box.addLayout(self.grid3) # ### Tools Data ## ## self.tool_data_label = QtWidgets.QLabel( @@ -1768,7 +1768,7 @@ class GeometryObjectUI(ObjectUI): "Each tool store it's own set of such data." ) ) - grid3.addWidget(self.tool_data_label, 0, 0, 1, 2) + self.grid3.addWidget(self.tool_data_label, 0, 0, 1, 2) # Tip Dia self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia')) @@ -1782,8 +1782,8 @@ class GeometryObjectUI(ObjectUI): self.tipdia_entry.set_range(0.00001, 9999.9999) self.tipdia_entry.setSingleStep(0.1) - grid3.addWidget(self.tipdialabel, 1, 0) - grid3.addWidget(self.tipdia_entry, 1, 1) + self.grid3.addWidget(self.tipdialabel, 1, 0) + self.grid3.addWidget(self.tipdia_entry, 1, 1) # Tip Angle self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle')) @@ -1798,8 +1798,8 @@ class GeometryObjectUI(ObjectUI): self.tipangle_entry.set_range(1.0, 180.0) self.tipangle_entry.setSingleStep(1) - grid3.addWidget(self.tipanglelabel, 2, 0) - grid3.addWidget(self.tipangle_entry, 2, 1) + self.grid3.addWidget(self.tipanglelabel, 2, 0) + self.grid3.addWidget(self.tipangle_entry, 2, 1) # Cut Z self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) @@ -1819,8 +1819,8 @@ class GeometryObjectUI(ObjectUI): self.cutz_entry.setSingleStep(0.1) - grid3.addWidget(self.cutzlabel, 3, 0) - grid3.addWidget(self.cutz_entry, 3, 1) + self.grid3.addWidget(self.cutzlabel, 3, 0) + self.grid3.addWidget(self.cutz_entry, 3, 1) # Multi-pass self.mpass_cb = FCCheckBox('%s:' % _("Multi-Depth")) @@ -1845,8 +1845,8 @@ class GeometryObjectUI(ObjectUI): ) self.ois_mpass_geo = OptionalInputSection(self.mpass_cb, [self.maxdepth_entry]) - grid3.addWidget(self.mpass_cb, 4, 0) - grid3.addWidget(self.maxdepth_entry, 4, 1) + self.grid3.addWidget(self.mpass_cb, 4, 0) + self.grid3.addWidget(self.maxdepth_entry, 4, 1) # Travel Z self.travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z')) @@ -1864,8 +1864,8 @@ class GeometryObjectUI(ObjectUI): self.travelz_entry.setSingleStep(0.1) - grid3.addWidget(self.travelzlabel, 5, 0) - grid3.addWidget(self.travelz_entry, 5, 1) + self.grid3.addWidget(self.travelzlabel, 5, 0) + self.grid3.addWidget(self.travelz_entry, 5, 1) # Feedrate X-Y self.frlabel = QtWidgets.QLabel('%s:' % _('Feedrate X-Y')) @@ -1878,8 +1878,8 @@ class GeometryObjectUI(ObjectUI): self.cncfeedrate_entry.set_range(0, 99999.9999) self.cncfeedrate_entry.setSingleStep(0.1) - grid3.addWidget(self.frlabel, 10, 0) - grid3.addWidget(self.cncfeedrate_entry, 10, 1) + self.grid3.addWidget(self.frlabel, 10, 0) + self.grid3.addWidget(self.cncfeedrate_entry, 10, 1) # Feedrate Z (Plunge) self.frzlabel = QtWidgets.QLabel('%s:' % _('Feedrate Z')) @@ -1893,8 +1893,8 @@ class GeometryObjectUI(ObjectUI): self.feedrate_z_entry.set_range(0, 99999.9999) self.feedrate_z_entry.setSingleStep(0.1) - grid3.addWidget(self.frzlabel, 11, 0) - grid3.addWidget(self.feedrate_z_entry, 11, 1) + self.grid3.addWidget(self.frzlabel, 11, 0) + self.grid3.addWidget(self.feedrate_z_entry, 11, 1) # Feedrate rapids self.fr_rapidlabel = QtWidgets.QLabel('%s:' % _('Feedrate Rapids')) @@ -1910,8 +1910,8 @@ class GeometryObjectUI(ObjectUI): self.feedrate_rapid_entry.set_range(0, 99999.9999) self.feedrate_rapid_entry.setSingleStep(0.1) - grid3.addWidget(self.fr_rapidlabel, 12, 0) - grid3.addWidget(self.feedrate_rapid_entry, 12, 1) + self.grid3.addWidget(self.fr_rapidlabel, 12, 0) + self.grid3.addWidget(self.feedrate_rapid_entry, 12, 1) # default values is to hide self.fr_rapidlabel.hide() self.feedrate_rapid_entry.hide() @@ -1936,8 +1936,8 @@ class GeometryObjectUI(ObjectUI): "meet with last cut, we generate an\n" "extended cut over the first cut section.") ) - grid3.addWidget(self.extracut_cb, 13, 0) - grid3.addWidget(self.e_cut_entry, 13, 1) + self.grid3.addWidget(self.extracut_cb, 13, 0) + self.grid3.addWidget(self.e_cut_entry, 13, 1) # Spindlespeed self.spindle_label = QtWidgets.QLabel('%s:' % _('Spindle speed')) @@ -1952,8 +1952,8 @@ class GeometryObjectUI(ObjectUI): self.cncspindlespeed_entry.set_range(0, 1000000) self.cncspindlespeed_entry.set_step(100) - grid3.addWidget(self.spindle_label, 14, 0) - grid3.addWidget(self.cncspindlespeed_entry, 14, 1) + self.grid3.addWidget(self.spindle_label, 14, 0) + self.grid3.addWidget(self.cncspindlespeed_entry, 14, 1) # Dwell self.dwell_cb = FCCheckBox('%s:' % _('Dwell')) @@ -1973,8 +1973,8 @@ class GeometryObjectUI(ObjectUI): ) self.ois_dwell_geo = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) - grid3.addWidget(self.dwell_cb, 15, 0) - grid3.addWidget(self.dwelltime_entry, 15, 1) + self.grid3.addWidget(self.dwell_cb, 15, 0) + self.grid3.addWidget(self.dwelltime_entry, 15, 1) # Probe depth self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) @@ -1987,8 +1987,8 @@ class GeometryObjectUI(ObjectUI): self.pdepth_entry.set_range(-9999.9999, 9999.9999) self.pdepth_entry.setSingleStep(0.1) - grid3.addWidget(self.pdepth_label, 17, 0) - grid3.addWidget(self.pdepth_entry, 17, 1) + self.grid3.addWidget(self.pdepth_label, 17, 0) + self.grid3.addWidget(self.pdepth_entry, 17, 1) self.pdepth_label.hide() self.pdepth_entry.setVisible(False) @@ -2003,8 +2003,8 @@ class GeometryObjectUI(ObjectUI): self.feedrate_probe_entry.set_range(0.0, 9999.9999) self.feedrate_probe_entry.setSingleStep(0.1) - grid3.addWidget(self.feedrate_probe_label, 18, 0) - grid3.addWidget(self.feedrate_probe_entry, 18, 1) + self.grid3.addWidget(self.feedrate_probe_label, 18, 0) + self.grid3.addWidget(self.feedrate_probe_entry, 18, 1) self.feedrate_probe_label.hide() self.feedrate_probe_entry.setVisible(False) diff --git a/AppObjects/FlatCAMGeometry.py b/AppObjects/FlatCAMGeometry.py index 83744fcd..16c85c8f 100644 --- a/AppObjects/FlatCAMGeometry.py +++ b/AppObjects/FlatCAMGeometry.py @@ -304,25 +304,9 @@ class GeometryObject(FlatCAMObj, Geometry): self.set_tool_offset_visibility(selected_row) - # HACK: for whatever reasons the name in Selected tab is reverted to the original one after a successful rename - # done in the collection view but only for Geometry objects. Perhaps some references remains. Should be fixed. - self.ui.name_entry.set_value(self.options['name']) - self.ui_connect() - - self.ui.e_cut_entry.setDisabled(False) if self.ui.extracut_cb.get_value() else \ - self.ui.e_cut_entry.setDisabled(True) - - # set the text on tool_data_label after loading the object - sel_rows = [] - sel_items = self.ui.geo_tools_table.selectedItems() - for it in sel_items: - sel_rows.append(it.row()) - if len(sel_rows) > 1: - self.ui.tool_data_label.setText( - "%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) @@ -374,6 +358,27 @@ class GeometryObject(FlatCAMObj, Geometry): self.ui.exclusion_table.setMinimumHeight(self.ui.exclusion_table.getHeight()) self.ui.exclusion_table.setMaximumHeight(self.ui.exclusion_table.getHeight()) + # End Build Exclusion Areas + # ----------------------------- + + # HACK: for whatever reasons the name in Selected tab is reverted to the original one after a successful rename + # done in the collection view but only for Geometry objects. Perhaps some references remains. Should be fixed. + self.ui.name_entry.set_value(self.options['name']) + self.ui_connect() + + self.ui.e_cut_entry.setDisabled(False) if self.ui.extracut_cb.get_value() else \ + self.ui.e_cut_entry.setDisabled(True) + + # set the text on tool_data_label after loading the object + sel_rows = [] + sel_items = self.ui.geo_tools_table.selectedItems() + for it in sel_items: + sel_rows.append(it.row()) + if len(sel_rows) > 1: + self.ui.tool_data_label.setText( + "%s: %s" % (_('Parameters for'), _("Multiple Tools")) + ) + def set_ui(self, ui): FlatCAMObj.set_ui(self, ui) @@ -652,8 +657,7 @@ class GeometryObject(FlatCAMObj, Geometry): self.ui.tool_offset_entry.get_value().replace(',', '.') ) except ValueError: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _("Wrong value format entered, use a number.")) + self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number.")) return def ui_connect(self): @@ -661,6 +665,7 @@ class GeometryObject(FlatCAMObj, Geometry): # changes in geometry UI for i in self.param_fields: current_widget = self.param_fields[i] + if isinstance(current_widget, FCCheckBox): current_widget.stateChanged.connect(self.gui_form_to_storage) elif isinstance(current_widget, FCComboBox): @@ -1382,16 +1387,18 @@ class GeometryObject(FlatCAMObj, Geometry): self.ui_connect() def gui_form_to_storage(self): + self.ui_disconnect() + if self.ui.geo_tools_table.rowCount() == 0: # there is no tool in tool table so we can't save the GUI elements values to storage log.debug("GeometryObject.gui_form_to_storage() --> no tool in Tools Table, aborting.") return - self.ui_disconnect() widget_changed = self.sender() try: widget_idx = self.ui.grid3.indexOf(widget_changed) - except Exception: + except Exception as e: + log.debug("GeometryObject.gui_form_to_storage() -- wdg index -> %s" % str(e)) return # those are the indexes for the V-Tip Dia and V-Tip Angle, if edited calculate the new Cut Z diff --git a/CHANGELOG.md b/CHANGELOG.md index 961d99e8..fbbf7a44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ CHANGELOG for FlatCAM beta - finished the Etch Compensation Tool - fixed unreliable work of Gerber Editor and optimized the App.editor2object() method - updated the Gerber parser such that it will parse correctly Gerber files that have only one solid polygon inside with multiple clear polygons (like those generated by the Invert Tool) +- fixed a small bug in the Geometry UI that made updating the storage from GUI not to work +- some small changes in Gerber Editor 23.05.2020