From 50210820e2d5eaf382571246c3865c863f274d40 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Wed, 21 Aug 2019 02:13:10 +0300 Subject: [PATCH] - added feature in Paint Tool allowing the painting to be done on Gerber objects - added feature in Paint Tool to set how (and if) the tools are sorted - added Edit -> Preferences GUI entries for the above just added features --- FlatCAMApp.py | 2 + README.md | 6 ++ flatcamGUI/FlatCAMGUI.py | 50 ++++++++---- flatcamTools/ToolNonCopperClear.py | 12 +-- flatcamTools/ToolPaint.py | 121 +++++++++++++++++++++++++---- 5 files changed, 152 insertions(+), 39 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 8091d821..d94d33c4 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -596,6 +596,7 @@ class App(QtCore.QObject): # Paint Area Tool "tools_painttooldia": self.ui.tools_defaults_form.tools_paint_group.painttooldia_entry, + "tools_paintorder": self.ui.tools_defaults_form.tools_paint_group.paint_order_radio, "tools_paintoverlap": self.ui.tools_defaults_form.tools_paint_group.paintoverlap_entry, "tools_paintmargin": self.ui.tools_defaults_form.tools_paint_group.paintmargin_entry, "tools_paintmethod": self.ui.tools_defaults_form.tools_paint_group.paintmethod_combo, @@ -967,6 +968,7 @@ class App(QtCore.QObject): "tools_cutout_convexshape": False, "tools_painttooldia": 0.023622, + "tools_paintorder": 'rev', "tools_paintoverlap": 0.015748, "tools_paintmargin": 0.0, "tools_paintmethod": "seed", diff --git a/README.md b/README.md index 22ea0fbf..e26ed60b 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,12 @@ CAD program, and create G-Code for Isolation routing. ================================================= +21.08.2019 + +- added feature in Paint Tool allowing the painting to be done on Gerber objects +- added feature in Paint Tool to set how (and if) the tools are sorted +- added Edit -> Preferences GUI entries for the above just added features + 20.08.2019 - added ability to do copper clearing through NCC Tool on Geometry objects diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 0f43f9e5..5d2e7906 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -6346,8 +6346,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): grid0.addWidget(self.ncc_tool_dia_entry, 0, 1) self.ncc_order_label = QtWidgets.QLabel('%s:' % _('Tool order')) - self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used\n" - "for copper clearing.\n" + self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n" "'No' --> means that the used order is the one in the tool table\n" "'Forward' --> means that the tools will be ordered from small to big\n" "'Reverse' --> menas that the tools will ordered from big to small\n\n" @@ -6357,8 +6356,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.ncc_order_radio = RadioSet([{'label': _('No'), 'value': 'no'}, {'label': _('Forward'), 'value': 'fwd'}, {'label': _('Reverse'), 'value': 'rev'}]) - self.ncc_order_radio.setToolTip(_("This set the way that the tools in the tools table are used\n" - "for copper clearing.\n" + self.ncc_order_radio.setToolTip(_("This set the way that the tools in the tools table are used.\n" "'No' --> means that the used order is the one in the tool table\n" "'Forward' --> means that the tools will be ordered from small to big\n" "'Reverse' --> menas that the tools will ordered from big to small\n\n" @@ -6673,6 +6671,26 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): self.painttooldia_entry = LengthEntry() grid0.addWidget(self.painttooldia_entry, 0, 1) + self.paint_order_label = QtWidgets.QLabel('%s:' % _('Tool order')) + self.paint_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n" + "'No' --> means that the used order is the one in the tool table\n" + "'Forward' --> means that the tools will be ordered from small to big\n" + "'Reverse' --> menas that the tools will ordered from big to small\n\n" + "WARNING: using rest machining will automatically set the order\n" + "in reverse and disable this control.")) + + self.paint_order_radio = RadioSet([{'label': _('No'), 'value': 'no'}, + {'label': _('Forward'), 'value': 'fwd'}, + {'label': _('Reverse'), 'value': 'rev'}]) + self.paint_order_radio.setToolTip(_("This set the way that the tools in the tools table are used.\n" + "'No' --> means that the used order is the one in the tool table\n" + "'Forward' --> means that the tools will be ordered from small to big\n" + "'Reverse' --> menas that the tools will ordered from big to small\n\n" + "WARNING: using rest machining will automatically set the order\n" + "in reverse and disable this control.")) + grid0.addWidget(self.paint_order_label, 1, 0) + grid0.addWidget(self.paint_order_radio, 1, 1) + # Overlap ovlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate')) ovlabel.setToolTip( @@ -6686,9 +6704,9 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): "Higher values = slow processing and slow execution on CNC\n" "due of too many paths.") ) - grid0.addWidget(ovlabel, 1, 0) + grid0.addWidget(ovlabel, 2, 0) self.paintoverlap_entry = LengthEntry() - grid0.addWidget(self.paintoverlap_entry, 1, 1) + grid0.addWidget(self.paintoverlap_entry, 2, 1) # Margin marginlabel = QtWidgets.QLabel('%s:' % _('Margin')) @@ -6697,9 +6715,9 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): "the edges of the polygon to\n" "be painted.") ) - grid0.addWidget(marginlabel, 2, 0) + grid0.addWidget(marginlabel, 3, 0) self.paintmargin_entry = LengthEntry() - grid0.addWidget(self.paintmargin_entry, 2, 1) + grid0.addWidget(self.paintmargin_entry, 3, 1) # Method methodlabel = QtWidgets.QLabel('%s:' % _('Method')) @@ -6709,13 +6727,13 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): "Seed-based: Outwards from seed.
" "Line-based: Parallel lines.") ) - grid0.addWidget(methodlabel, 3, 0) + grid0.addWidget(methodlabel, 4, 0) self.paintmethod_combo = RadioSet([ {"label": _("Standard"), "value": "standard"}, {"label": _("Seed-based"), "value": "seed"}, {"label": _("Straight lines"), "value": "lines"} ], orientation='vertical', stretch=False) - grid0.addWidget(self.paintmethod_combo, 3, 1) + grid0.addWidget(self.paintmethod_combo, 4, 1) # Connect lines pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect")) @@ -6723,9 +6741,9 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): _("Draw lines between resulting\n" "segments to minimize tool lifts.") ) - grid0.addWidget(pathconnectlabel, 4, 0) + grid0.addWidget(pathconnectlabel, 5, 0) self.pathconnect_cb = FCCheckBox() - grid0.addWidget(self.pathconnect_cb, 4, 1) + grid0.addWidget(self.pathconnect_cb, 5, 1) # Paint contour contourlabel = QtWidgets.QLabel('%s:' % _("Contour")) @@ -6733,9 +6751,9 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): _("Cut around the perimeter of the polygon\n" "to trim rough edges.") ) - grid0.addWidget(contourlabel, 5, 0) + grid0.addWidget(contourlabel, 6, 0) self.contour_cb = FCCheckBox() - grid0.addWidget(self.contour_cb, 5, 1) + grid0.addWidget(self.contour_cb, 6, 1) # Polygon selection selectlabel = QtWidgets.QLabel('%s:' % _('Selection')) @@ -6747,14 +6765,14 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): "- All: paint all polygons.
" "- Ref: paint an area described by an external reference object.") ) - grid0.addWidget(selectlabel, 6, 0) + grid0.addWidget(selectlabel, 7, 0) self.selectmethod_combo = RadioSet([ {"label": _("Single"), "value": "single"}, {"label": _("Area"), "value": "area"}, {"label": _("All"), "value": "all"}, {"label": _("Ref."), "value": "ref"} ]) - grid0.addWidget(self.selectmethod_combo, 6, 1) + grid0.addWidget(self.selectmethod_combo, 7, 1) self.layout.addStretch() diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index 3dfaef8a..008214be 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -76,14 +76,16 @@ class NonCopperClear(FlatCAMTool, Gerber): self.type_obj_combo_label.setMinimumWidth(60) form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo) - # Object to be cutout + # ################################################ + # ##### The object to be copper cleaned ########## + # ################################################ self.obj_combo = QtWidgets.QComboBox() self.obj_combo.setModel(self.app.collection) self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) self.obj_combo.setCurrentIndex(1) self.object_label = QtWidgets.QLabel('%s:' % _("Object")) - self.object_label.setToolTip(_("Gerber object to be cleared of excess copper.")) + self.object_label.setToolTip(_("Object to be cleared of excess copper.")) form_layout.addRow(self.object_label, self.obj_combo) @@ -133,8 +135,7 @@ class NonCopperClear(FlatCAMTool, Gerber): "in the resulting geometry as Isolation.")) self.ncc_order_label = QtWidgets.QLabel('%s:' % _('Tool order')) - self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used\n" - "for copper clearing.\n" + self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n" "'No' --> means that the used order is the one in the tool table\n" "'Forward' --> means that the tools will be ordered from small to big\n" "'Reverse' --> menas that the tools will ordered from big to small\n\n" @@ -144,8 +145,7 @@ class NonCopperClear(FlatCAMTool, Gerber): self.ncc_order_radio = RadioSet([{'label': _('No'), 'value': 'no'}, {'label': _('Forward'), 'value': 'fwd'}, {'label': _('Reverse'), 'value': 'rev'}]) - self.ncc_order_radio.setToolTip(_("This set the way that the tools in the tools table are used\n" - "for copper clearing.\n" + self.ncc_order_radio.setToolTip(_("This set the way that the tools in the tools table are used.\n" "'No' --> means that the used order is the one in the tool table\n" "'Forward' --> means that the tools will be ordered from small to big\n" "'Reverse' --> menas that the tools will ordered from big to small\n\n" diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index 9f557b9d..68269148 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -22,7 +22,7 @@ if '_' not in builtins.__dict__: class ToolPaint(FlatCAMTool, Gerber): - toolName = _("Paint Area") + toolName = _("Paint Tool") def __init__(self, app): self.app = app @@ -52,18 +52,43 @@ class ToolPaint(FlatCAMTool, Gerber): form_layout = QtWidgets.QFormLayout() self.tools_box.addLayout(form_layout) - # ## Object - self.object_combo = QtWidgets.QComboBox() - self.object_combo.setModel(self.app.collection) - self.object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex())) - self.object_combo.setCurrentIndex(1) + # ################################################ + # ##### Type of object to be painted ############# + # ################################################ + self.type_obj_combo = QtWidgets.QComboBox() + self.type_obj_combo.addItem("Gerber") + self.type_obj_combo.addItem("Excellon") + self.type_obj_combo.addItem("Geometry") - self.object_label = QtWidgets.QLabel('%s:' % _("Geometry")) - self.object_label.setToolTip( - _("Geometry object to be painted. ") + # we get rid of item1 ("Excellon") as it is not suitable + self.type_obj_combo.view().setRowHidden(1, True) + self.type_obj_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png")) + self.type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png")) + + self.type_obj_combo_label = QtWidgets.QLabel('%s:' % _("Obj Type")) + self.type_obj_combo_label.setToolTip( + _("Specify the type of object to be painted.\n" + "It can be of type: Gerber or Geometry.\n" + "What is selected here will dictate the kind\n" + "of objects that will populate the 'Object' combobox.") ) + self.type_obj_combo_label.setMinimumWidth(60) + form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo) + + # ################################################ + # ##### The object to be painted ################# + # ################################################ + self.obj_combo = QtWidgets.QComboBox() + self.obj_combo.setModel(self.app.collection) + self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) + self.obj_combo.setCurrentIndex(1) + + self.object_label = QtWidgets.QLabel('%s:' % _("Object")) + self.object_label.setToolTip(_("Object to be painted.")) + + form_layout.addRow(self.object_label, self.obj_combo) + e_lab_0 = QtWidgets.QLabel('') - form_layout.addRow(self.object_label, self.object_combo) form_layout.addRow(e_lab_0) # ### Tools ## ## @@ -108,8 +133,27 @@ class ToolPaint(FlatCAMTool, Gerber): "Choosing the V-Shape Tool Type automatically will select the Operation Type " "in the resulting geometry as Isolation.")) - self.empty_label = QtWidgets.QLabel('') - self.tools_box.addWidget(self.empty_label) + self.order_label = QtWidgets.QLabel('%s:' % _('Tool order')) + self.order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n" + "'No' --> means that the used order is the one in the tool table\n" + "'Forward' --> means that the tools will be ordered from small to big\n" + "'Reverse' --> menas that the tools will ordered from big to small\n\n" + "WARNING: using rest machining will automatically set the order\n" + "in reverse and disable this control.")) + + self.order_radio = RadioSet([{'label': _('No'), 'value': 'no'}, + {'label': _('Forward'), 'value': 'fwd'}, + {'label': _('Reverse'), 'value': 'rev'}]) + self.order_radio.setToolTip(_("This set the way that the tools in the tools table are used.\n" + "'No' --> means that the used order is the one in the tool table\n" + "'Forward' --> means that the tools will be ordered from small to big\n" + "'Reverse' --> menas that the tools will ordered from big to small\n\n" + "WARNING: using rest machining will automatically set the order\n" + "in reverse and disable this control.")) + form = QtWidgets.QFormLayout() + self.tools_box.addLayout(form) + form.addRow(QtWidgets.QLabel(''), QtWidgets.QLabel('')) + form.addRow(self.order_label, self.order_radio) # ### Add a new Tool ## ## hlay = QtWidgets.QHBoxLayout() @@ -361,8 +405,16 @@ class ToolPaint(FlatCAMTool, Gerber): self.deltool_btn.clicked.connect(self.on_tool_delete) self.generate_paint_button.clicked.connect(self.on_paint_button_click) self.selectmethod_combo.activated_custom.connect(self.on_radio_selection) + self.order_radio.activated_custom[str].connect(self.on_order_changed) + self.rest_cb.stateChanged.connect(self.on_rest_machining_check) self.box_combo_type.currentIndexChanged.connect(self.on_combo_box_type) + self.type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed) + + def on_type_obj_index_changed(self, index): + obj_type = self.type_obj_combo.currentIndex() + self.obj_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex())) + self.obj_combo.setCurrentIndex(0) def install(self, icon=None, separator=None, **kwargs): FlatCAMTool.install(self, icon, separator, shortcut='ALT+P', **kwargs) @@ -425,11 +477,25 @@ class ToolPaint(FlatCAMTool, Gerber): self.deltool_btn.setDisabled(False) self.tools_table.setContextMenuPolicy(Qt.ActionsContextMenu) + def on_order_changed(self, order): + if order != 'no': + self.build_ui() + + def on_rest_machining_check(self, state): + if state: + self.order_radio.set_value('rev') + self.order_label.setDisabled(True) + self.order_radio.setDisabled(True) + else: + self.order_label.setDisabled(False) + self.order_radio.setDisabled(False) + def set_tool_ui(self): self.tools_frame.show() self.reset_fields() # ## Init the GUI interface + self.order_radio.set_value(self.app.defaults["tools_paintorder"]) self.paintmargin_entry.set_value(self.default_data["paintmargin"]) self.paintmethod_combo.set_value(self.default_data["paintmethod"]) self.selectmethod_combo.set_value(self.default_data["selectmethod"]) @@ -510,7 +576,14 @@ class ToolPaint(FlatCAMTool, Gerber): sorted_tools = [] for k, v in self.paint_tools.items(): sorted_tools.append(float('%.4f' % float(v['tooldia']))) - sorted_tools.sort() + + order = self.order_radio.get_value() + if order == 'fwd': + sorted_tools.sort(reverse=False) + elif order == 'rev': + sorted_tools.sort(reverse=True) + else: + pass n = len(sorted_tools) self.tools_table.setRowCount(n) @@ -827,7 +900,7 @@ class ToolPaint(FlatCAMTool, Gerber): contour = self.paintcontour_cb.get_value() select_method = self.selectmethod_combo.get_value() - self.obj_name = self.object_combo.currentText() + self.obj_name = self.obj_combo.currentText() # Get source object. try: @@ -1235,7 +1308,14 @@ class ToolPaint(FlatCAMTool, Gerber): sorted_tools = [] for row in range(self.tools_table.rowCount()): sorted_tools.append(float(self.tools_table.item(row, 1).text())) - sorted_tools.sort(reverse=True) + + order = self.order_radio.get_value() + if order == 'fwd': + sorted_tools.sort(reverse=False) + elif order == 'rev': + sorted_tools.sort(reverse=True) + else: + pass try: a, b, c, d = obj.bounds() @@ -1521,7 +1601,14 @@ class ToolPaint(FlatCAMTool, Gerber): sorted_tools = [] for row in range(self.tools_table.rowCount()): sorted_tools.append(float(self.tools_table.item(row, 1).text())) - sorted_tools.sort(reverse=True) + + order = self.order_radio.get_value() + if order == 'fwd': + sorted_tools.sort(reverse=False) + elif order == 'rev': + sorted_tools.sort(reverse=True) + else: + pass geo_to_paint = [] for poly in obj.solid_geometry: @@ -1769,4 +1856,4 @@ class ToolPaint(FlatCAMTool, Gerber): return bounds_rec(geometry) def reset_fields(self): - self.object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex())) + self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))