diff --git a/CHANGELOG.md b/CHANGELOG.md index b9606d7a..a4cccac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ CHANGELOG for FlatCAM beta ================================================= +25.09.2021 + +- solved more Shapely 2.0 deprecation warnings +- in Isolation Plugin and NCC Plugin changed the UI and the Preferences for those Plugins + 24.09.2021 - in Extract Plugin some minor UI changes diff --git a/appGUI/GUIElements.py b/appGUI/GUIElements.py index 63407afd..919f3d7f 100644 --- a/appGUI/GUIElements.py +++ b/appGUI/GUIElements.py @@ -1356,6 +1356,7 @@ class FCDoubleSpinner(QtWidgets.QDoubleSpinBox): :param alignment: the value is aligned to left or right :param parent: :param callback: called when the entered value is outside limits; the min and max value will be passed to it + :param policy: by default the widget will not stretch as much as possible on horizontal """ super(FCDoubleSpinner, self).__init__(parent) self.readyToEdit = True diff --git a/appGUI/preferences/PreferencesUIManager.py b/appGUI/preferences/PreferencesUIManager.py index 83c93a1e..1f74d5db 100644 --- a/appGUI/preferences/PreferencesUIManager.py +++ b/appGUI/preferences/PreferencesUIManager.py @@ -280,7 +280,7 @@ class PreferencesUIManager: # Isolation Routing Tool "tools_iso_tooldia": self.ui.plugin_eng_pref_form.tools_iso_group.tool_dia_entry, - "tools_iso_order": self.ui.plugin_eng_pref_form.tools_iso_group.order_radio, + "tools_iso_order": self.ui.plugin_eng_pref_form.tools_iso_group.iso_order_combo, "tools_iso_tool_cutz": self.ui.plugin_eng_pref_form.tools_iso_group.cutz_entry, "tools_iso_newdia": self.ui.plugin_eng_pref_form.tools_iso_group.newdia_entry, @@ -408,7 +408,7 @@ class PreferencesUIManager: # NCC Tool "tools_ncc_tools": self.ui.plugin_eng_pref_form.tools_ncc_group.ncc_tool_dia_entry, - "tools_ncc_order": self.ui.plugin_eng_pref_form.tools_ncc_group.ncc_order_radio, + "tools_ncc_order": self.ui.plugin_eng_pref_form.tools_ncc_group.ncc_order_combo, "tools_ncc_overlap": self.ui.plugin_eng_pref_form.tools_ncc_group.ncc_overlap_entry, "tools_ncc_margin": self.ui.plugin_eng_pref_form.tools_ncc_group.ncc_margin_entry, "tools_ncc_method": self.ui.plugin_eng_pref_form.tools_ncc_group.ncc_method_combo, diff --git a/appGUI/preferences/tools/ToolsISOPrefGroupUI.py b/appGUI/preferences/tools/ToolsISOPrefGroupUI.py index ff9a6ad2..e4dbf973 100644 --- a/appGUI/preferences/tools/ToolsISOPrefGroupUI.py +++ b/appGUI/preferences/tools/ToolsISOPrefGroupUI.py @@ -1,7 +1,7 @@ from PyQt6 import QtWidgets from appGUI.GUIElements import RadioSet, FCDoubleSpinner, FCComboBox2, FCCheckBox, FCSpinner, NumericalEvalTupleEntry, \ - FCLabel, FCGridLayout + FCLabel, FCGridLayout, FCFrame from appGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext @@ -22,15 +22,21 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.defaults = defaults # ## Clear non-copper regions - self.iso_label = FCLabel("%s:" % _("Parameters")) + self.iso_label = FCLabel('%s' % _("Parameters")) self.iso_label.setToolTip( _("Create a Geometry object with\n" "toolpaths to cut around polygons.") ) self.layout.addWidget(self.iso_label) - grid0 = FCGridLayout(v_spacing=5, h_spacing=3) - self.layout.addLayout(grid0) + # ############################################################################################################# + # Parameters Frame + # ############################################################################################################# + par_frame = FCFrame() + self.layout.addWidget(par_frame) + + par_grid = FCGridLayout(v_spacing=5, h_spacing=3) + par_frame.setLayout(par_grid) # Tool Dias isotdlabel = FCLabel('%s:' % _('Tools Dia')) @@ -42,24 +48,49 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.tool_dia_entry = NumericalEvalTupleEntry(border_color='#0069A9') self.tool_dia_entry.setPlaceholderText(_("Comma separated values")) - grid0.addWidget(isotdlabel, 0, 0) - grid0.addWidget(self.tool_dia_entry, 0, 1, 1, 2) + par_grid.addWidget(isotdlabel, 0, 0) + par_grid.addWidget(self.tool_dia_entry, 0, 1, 1, 2) - # Tool order Radio Button - self.order_label = FCLabel('%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' --> means 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.")) + # Tool order + self.iso_order_label = FCLabel('%s:' % _('Tool order')) + self.iso_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' --> means 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.iso_order_combo = FCComboBox2() + self.iso_order_combo.addItems([_('Default'), _('Forward'), _('Reverse')]) - grid0.addWidget(self.order_label, 2, 0) - grid0.addWidget(self.order_radio, 2, 1, 1, 2) + par_grid.addWidget(self.iso_order_label, 2, 0) + par_grid.addWidget(self.iso_order_combo, 2, 1, 1, 2) + + # Tip Dia + self.tipdialabel = FCLabel('%s:' % _('V-Tip Dia')) + self.tipdialabel.setToolTip( + _("The tip diameter for V-Shape Tool")) + self.tipdia_entry = FCDoubleSpinner() + self.tipdia_entry.set_precision(self.decimals) + self.tipdia_entry.set_range(0, 1000) + self.tipdia_entry.setSingleStep(0.1) + + par_grid.addWidget(self.tipdialabel, 4, 0) + par_grid.addWidget(self.tipdia_entry, 4, 1, 1, 2) + + # Tip Angle + self.tipanglelabel = FCLabel('%s:' % _('V-Tip Angle')) + self.tipanglelabel.setToolTip( + _("The tip angle for V-Shape Tool.\n" + "In degree.")) + self.tipangle_entry = FCDoubleSpinner() + self.tipangle_entry.set_precision(self.decimals) + self.tipangle_entry.set_range(1, 180) + self.tipangle_entry.setSingleStep(5) + self.tipangle_entry.setWrapping(True) + + par_grid.addWidget(self.tipanglelabel, 6, 0) + par_grid.addWidget(self.tipangle_entry, 6, 1, 1, 2) # Cut Z entry cutzlabel = FCLabel('%s:' % _('Cut Z')) @@ -77,8 +108,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): "In application units.") ) - grid0.addWidget(cutzlabel, 6, 0) - grid0.addWidget(self.cutz_entry, 6, 1, 1, 2) + par_grid.addWidget(cutzlabel, 8, 0) + par_grid.addWidget(self.cutz_entry, 8, 1, 1, 2) # New Diameter self.newdialabel = FCLabel('%s:' % _('New Dia')) @@ -92,13 +123,26 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.newdia_entry.set_range(0.0001, 10000.0000) self.newdia_entry.setSingleStep(0.1) - grid0.addWidget(self.newdialabel, 8, 0) - grid0.addWidget(self.newdia_entry, 8, 1, 1, 2) + par_grid.addWidget(self.newdialabel, 10, 0) + par_grid.addWidget(self.newdia_entry, 10, 1, 1, 2) - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 10, 0, 1, 3) + # separator_line = QtWidgets.QFrame() + # separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) + # separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) + # par_grid.addWidget(separator_line, 10, 0, 1, 3) + + # ############################################################################################################# + # Tool Frame + # ############################################################################################################# + # ### Tools ## ## + self.tools_table_label = FCLabel('%s' % _("Tool Parameters")) + self.layout.addWidget(self.tools_table_label) + + tt_frame = FCFrame() + self.layout.addWidget(tt_frame) + + tool_grid = FCGridLayout(v_spacing=5, h_spacing=3) + tt_frame.setLayout(tool_grid) # Shape tool_shape_label = FCLabel('%s:' % _('Shape')) @@ -113,8 +157,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.tool_shape_combo = FCComboBox2(policy=False) self.tool_shape_combo.addItems(["C1", "C2", "C3", "C4", "B", "V"]) - grid0.addWidget(tool_shape_label, 12, 0) - grid0.addWidget(self.tool_shape_combo, 12, 1, 1, 2) + tool_grid.addWidget(tool_shape_label, 0, 0) + tool_grid.addWidget(self.tool_shape_combo, 0, 1, 1, 2) # Passes passlabel = FCLabel('%s:' % _('Passes')) @@ -125,8 +169,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.passes_entry = FCSpinner() self.passes_entry.set_range(1, 999) - grid0.addWidget(passlabel, 14, 0) - grid0.addWidget(self.passes_entry, 14, 1, 1, 2) + tool_grid.addWidget(passlabel, 2, 0) + tool_grid.addWidget(self.passes_entry, 2, 1, 1, 2) # Pad Passes padpasslabel = FCLabel('%s:' % _('Pad Passes')) @@ -137,8 +181,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.pad_passes_entry = FCSpinner() self.pad_passes_entry.set_range(0, 999) - grid0.addWidget(padpasslabel, 16, 0) - grid0.addWidget(self.pad_passes_entry, 16, 1, 1, 2) + tool_grid.addWidget(padpasslabel, 4, 0) + tool_grid.addWidget(self.pad_passes_entry, 4, 1, 1, 2) # Overlap Entry overlabel = FCLabel('%s:' % _('Overlap')) @@ -151,8 +195,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.overlap_entry.set_range(0.0000, 99.9999) self.overlap_entry.setSingleStep(0.1) - grid0.addWidget(overlabel, 20, 0) - grid0.addWidget(self.overlap_entry, 20, 1, 1, 2) + tool_grid.addWidget(overlabel, 6, 0) + tool_grid.addWidget(self.overlap_entry, 6, 1, 1, 2) # Milling Type Radio Button self.milling_type_label = FCLabel('%s:' % _('Milling Type')) @@ -170,8 +214,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): "- conventional / useful when there is no backlash compensation") ) - grid0.addWidget(self.milling_type_label, 22, 0) - grid0.addWidget(self.milling_type_radio, 22, 1, 1, 2) + tool_grid.addWidget(self.milling_type_label, 8, 0) + tool_grid.addWidget(self.milling_type_radio, 8, 1, 1, 2) # Isolation Type self.iso_type_label = FCLabel('%s:' % _('Isolation Type')) @@ -189,13 +233,28 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): {'label': _('Ext'), 'value': 'ext'}, {'label': _('Int'), 'value': 'int'}]) - grid0.addWidget(self.iso_type_label, 24, 0) - grid0.addWidget(self.iso_type_radio, 24, 1, 1, 2) + tool_grid.addWidget(self.iso_type_label, 10, 0) + tool_grid.addWidget(self.iso_type_radio, 10, 1, 1, 2) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 26, 0, 1, 3) + tool_grid.addWidget(separator_line, 12, 0, 1, 3) + + # ############################################################################################################# + # General Parameters Frame + # ############################################################################################################# + self.gen_param_label = FCLabel('%s' % _("Common Parameters")) + self.gen_param_label.setToolTip( + _("Parameters that are common for all tools.") + ) + self.layout.addWidget(self.gen_param_label) + + gp_frame = FCFrame() + self.layout.addWidget(gp_frame) + + gen_grid = FCGridLayout(v_spacing=5, h_spacing=3) + gp_frame.setLayout(gen_grid) # Rest machining CheckBox self.rest_cb = FCCheckBox('%s' % _("Rest")) @@ -209,7 +268,7 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): "If not checked, use the standard algorithm.") ) - grid0.addWidget(self.rest_cb, 28, 0) + gen_grid.addWidget(self.rest_cb, 0, 0) # Combine All Passes self.combine_passes_cb = FCCheckBox(label=_('Combine')) @@ -217,14 +276,14 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): _("Combine all passes into one object") ) - grid0.addWidget(self.combine_passes_cb, 28, 1) + gen_grid.addWidget(self.combine_passes_cb, 0, 1) # Exception Areas self.except_cb = FCCheckBox(label=_('Except')) self.except_cb.setToolTip(_("When the isolation geometry is generated,\n" "by checking this, the area of the object below\n" "will be subtracted from the isolation geometry.")) - grid0.addWidget(self.except_cb, 28, 2) + gen_grid.addWidget(self.except_cb, 0, 2) # Check Tool validity self.valid_cb = FCCheckBox(label=_('Check validity')) @@ -233,7 +292,7 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): "if they will provide a complete isolation.") ) - grid0.addWidget(self.valid_cb, 30, 0, 1, 3) + gen_grid.addWidget(self.valid_cb, 2, 0, 1, 3) # Isolation Scope self.select_label = FCLabel('%s:' % _("Selection")) @@ -249,8 +308,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): [_("All"), _("Area Selection"), _("Polygon Selection"), _("Reference Object")] ) - grid0.addWidget(self.select_label, 32, 0) - grid0.addWidget(self.select_combo, 32, 1, 1, 2) + gen_grid.addWidget(self.select_label, 4, 0) + gen_grid.addWidget(self.select_combo, 4, 1, 1, 2) # Area Shape self.area_shape_label = FCLabel('%s:' % _("Shape")) @@ -261,8 +320,8 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'}, {'label': _("Polygon"), 'value': 'polygon'}]) - grid0.addWidget(self.area_shape_label, 34, 0) - grid0.addWidget(self.area_shape_radio, 34, 1, 1, 2) + gen_grid.addWidget(self.area_shape_label, 6, 0) + gen_grid.addWidget(self.area_shape_radio, 6, 1, 1, 2) # Polygon interiors selection self.poly_int_cb = FCCheckBox(_("Interiors")) @@ -278,13 +337,13 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): "interiors of a polygon (holes in the polygon) could not be isolated.\n" "Works when 'rest machining' is used.") ) - grid0.addWidget(self.poly_int_cb, 36, 0) - grid0.addWidget(self.force_iso_cb, 36, 1) + gen_grid.addWidget(self.poly_int_cb, 8, 0) + gen_grid.addWidget(self.force_iso_cb, 8, 1) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 38, 0, 1, 3) + gen_grid.addWidget(separator_line, 10, 0, 1, 3) # ## Plotting type self.plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'}, @@ -294,7 +353,9 @@ class ToolsISOPrefGroupUI(OptionsGroupUI): _("- 'Normal' - normal plotting, done at the end of the job\n" "- 'Progressive' - each shape is plotted after it is generated") ) - grid0.addWidget(plotting_label, 40, 0) - grid0.addWidget(self.plotting_radio, 40, 1, 1, 2) + gen_grid.addWidget(plotting_label, 12, 0) + gen_grid.addWidget(self.plotting_radio, 12, 1, 1, 2) - self.layout.addStretch() + FCGridLayout.set_common_column_size([par_grid, tool_grid, gen_grid], 0) + + # self.layout.addStretch() diff --git a/appGUI/preferences/tools/ToolsNCCPrefGroupUI.py b/appGUI/preferences/tools/ToolsNCCPrefGroupUI.py index a5401325..51fed78b 100644 --- a/appGUI/preferences/tools/ToolsNCCPrefGroupUI.py +++ b/appGUI/preferences/tools/ToolsNCCPrefGroupUI.py @@ -1,7 +1,7 @@ from PyQt6 import QtWidgets from appGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, NumericalEvalTupleEntry, FCComboBox2, FCLabel, \ - FCGridLayout + FCGridLayout, FCFrame from appGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext @@ -23,34 +23,49 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.defaults = defaults # ## Clear non-copper regions - self.clearcopper_label = FCLabel("%s:" % _("Parameters")) + self.clearcopper_label = FCLabel('%s' % _("Parameters")) self.clearcopper_label.setToolTip( _("Create a Geometry object with\n" "toolpaths to cut all non-copper regions.") ) self.layout.addWidget(self.clearcopper_label) - grid0 = FCGridLayout(v_spacing=5, h_spacing=3) - self.layout.addLayout(grid0) + # ############################################################################################################# + # Parameters Frame + # ############################################################################################################# + par_frame = FCFrame() + self.layout.addWidget(par_frame) + par_grid = FCGridLayout(v_spacing=5, h_spacing=3) + par_frame.setLayout(par_grid) + + # Tools Diameters ncctdlabel = FCLabel('%s:' % _('Tools Dia')) ncctdlabel.setToolTip( _("Diameters of the tools, separated by comma.\n" "The value of the diameter has to use the dot decimals separator.\n" "Valid values: 0.3, 1.0") ) - grid0.addWidget(ncctdlabel, 0, 0) self.ncc_tool_dia_entry = NumericalEvalTupleEntry(border_color='#0069A9') self.ncc_tool_dia_entry.setPlaceholderText(_("Comma separated values")) - grid0.addWidget(self.ncc_tool_dia_entry, 0, 1) - # Tool Type Radio Button - self.tool_type_label = FCLabel('%s:' % _('Tool Type')) - self.tool_type_label.setToolTip( - _("Default tool type:\n" - "- 'V-shape'\n" - "- Circular") - ) + par_grid.addWidget(ncctdlabel, 0, 0) + par_grid.addWidget(self.ncc_tool_dia_entry, 0, 1) + + # Tool order + self.ncc_order_label = FCLabel('%s:' % _('Tool order')) + 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' --> means 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.ncc_order_combo = FCComboBox2() + self.ncc_order_combo.addItems([_('Default'), _('Forward'), _('Reverse')]) + + par_grid.addWidget(self.ncc_order_label, 2, 0) + par_grid.addWidget(self.ncc_order_combo, 2, 1) # Tip Dia self.tipdialabel = FCLabel('%s:' % _('V-Tip Dia')) @@ -61,8 +76,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.tipdia_entry.set_range(0, 1000) self.tipdia_entry.setSingleStep(0.1) - grid0.addWidget(self.tipdialabel, 2, 0) - grid0.addWidget(self.tipdia_entry, 2, 1) + par_grid.addWidget(self.tipdialabel, 4, 0) + par_grid.addWidget(self.tipdia_entry, 4, 1) # Tip Angle self.tipanglelabel = FCLabel('%s:' % _('V-Tip Angle')) @@ -75,8 +90,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.tipangle_entry.setSingleStep(5) self.tipangle_entry.setWrapping(True) - grid0.addWidget(self.tipanglelabel, 3, 0) - grid0.addWidget(self.tipangle_entry, 3, 1) + par_grid.addWidget(self.tipanglelabel, 6, 0) + par_grid.addWidget(self.tipangle_entry, 6, 1) # Cut Z entry cutzlabel = FCLabel('%s:' % _('Cut Z')) @@ -94,8 +109,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "In application units.") ) - grid0.addWidget(cutzlabel, 4, 0) - grid0.addWidget(self.cutz_entry, 4, 1) + par_grid.addWidget(cutzlabel, 8, 0) + par_grid.addWidget(self.cutz_entry, 8, 1) # New Diameter self.newdialabel = FCLabel('%s:' % _('New Dia')) @@ -109,13 +124,13 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.newdia_entry.set_range(0.0001, 10000.0000) self.newdia_entry.setSingleStep(0.1) - grid0.addWidget(self.newdialabel, 5, 0) - grid0.addWidget(self.newdia_entry, 5, 1) + par_grid.addWidget(self.newdialabel, 10, 0) + par_grid.addWidget(self.newdia_entry, 10, 1) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 6, 0, 1, 2) + par_grid.addWidget(separator_line, 12, 0, 1, 2) # Milling Type Radio Button self.milling_type_label = FCLabel('%s:' % _('Milling Type')) @@ -133,34 +148,21 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "- conventional / useful when there is no backlash compensation") ) - grid0.addWidget(self.milling_type_label, 7, 0) - grid0.addWidget(self.milling_type_radio, 7, 1) + par_grid.addWidget(self.milling_type_label, 14, 0) + par_grid.addWidget(self.milling_type_radio, 14, 1) - # Tool order Radio Button - self.ncc_order_label = FCLabel('%s:' % _('Tool order')) - 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' --> means 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.")) + # ############################################################################################################# + # Tool Frame + # ############################################################################################################# + # ### Tools ## ## + self.tools_table_label = FCLabel('%s' % _("Tool Parameters")) + self.layout.addWidget(self.tools_table_label) - 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" - "'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' --> means 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.ncc_order_label, 8, 0) - grid0.addWidget(self.ncc_order_radio, 8, 1) + tt_frame = FCFrame() + self.layout.addWidget(tt_frame) - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 9, 0, 1, 2) + tool_grid = FCGridLayout(v_spacing=5, h_spacing=3) + tt_frame.setLayout(tool_grid) # Overlap Entry nccoverlabel = FCLabel('%s:' % _('Overlap')) @@ -179,8 +181,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.ncc_overlap_entry.setRange(0.0000, 99.9999) self.ncc_overlap_entry.setSingleStep(0.1) - grid0.addWidget(nccoverlabel, 10, 0) - grid0.addWidget(self.ncc_overlap_entry, 10, 1) + tool_grid.addWidget(nccoverlabel, 0, 0) + tool_grid.addWidget(self.ncc_overlap_entry, 0, 1) # Margin entry nccmarginlabel = FCLabel('%s:' % _('Margin')) @@ -192,8 +194,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.ncc_margin_entry.set_range(-10000, 10000) self.ncc_margin_entry.setSingleStep(0.1) - grid0.addWidget(nccmarginlabel, 11, 0) - grid0.addWidget(self.ncc_margin_entry, 11, 1) + tool_grid.addWidget(nccmarginlabel, 2, 0) + tool_grid.addWidget(self.ncc_margin_entry, 2, 1) # Method methodlabel = FCLabel('%s:' % _('Method')) @@ -214,8 +216,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): [_("Standard"), _("Seed"), _("Lines"), _("Combo")] ) - grid0.addWidget(methodlabel, 12, 0) - grid0.addWidget(self.ncc_method_combo, 12, 1) + tool_grid.addWidget(methodlabel, 4, 0) + tool_grid.addWidget(self.ncc_method_combo, 4, 1) # Connect lines self.ncc_connect_cb = FCCheckBox('%s' % _("Connect")) @@ -224,7 +226,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "segments to minimize tool lifts.") ) - grid0.addWidget(self.ncc_connect_cb, 13, 0) + tool_grid.addWidget(self.ncc_connect_cb, 6, 0) # Contour Checkbox self.ncc_contour_cb = FCCheckBox('%s' % _("Contour")) @@ -233,7 +235,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "to trim rough edges.") ) - grid0.addWidget(self.ncc_contour_cb, 13, 1) + tool_grid.addWidget(self.ncc_contour_cb, 6, 1) # ## NCC Offset choice self.ncc_choice_offset_cb = FCCheckBox('%s' % _("Offset")) @@ -243,7 +245,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "from the copper features.") ) - grid0.addWidget(self.ncc_choice_offset_cb, 14, 0, 1, 2) + tool_grid.addWidget(self.ncc_choice_offset_cb, 8, 0, 1, 2) # ## NCC Offset value self.ncc_offset_label = FCLabel('%s:' % _("Offset value")) @@ -258,13 +260,28 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.ncc_offset_spinner.setWrapping(True) self.ncc_offset_spinner.setSingleStep(0.1) - grid0.addWidget(self.ncc_offset_label, 15, 0) - grid0.addWidget(self.ncc_offset_spinner, 15, 1) + tool_grid.addWidget(self.ncc_offset_label, 10, 0) + tool_grid.addWidget(self.ncc_offset_spinner, 10, 1) - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 16, 0, 1, 2) + # separator_line = QtWidgets.QFrame() + # separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) + # separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) + # par_grid.addWidget(separator_line, 16, 0, 1, 2) + + # ############################################################################################################# + # General Parameters Frame + # ############################################################################################################# + self.gen_param_label = FCLabel('%s' % _("Common Parameters")) + self.gen_param_label.setToolTip( + _("Parameters that are common for all tools.") + ) + self.layout.addWidget(self.gen_param_label) + + gp_frame = FCFrame() + self.layout.addWidget(gp_frame) + + gen_grid = FCGridLayout(v_spacing=5, h_spacing=3) + gp_frame.setLayout(gen_grid) # Rest machining CheckBox self.ncc_rest_cb = FCCheckBox('%s' % _("Rest")) @@ -278,7 +295,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "If not checked, use the standard algorithm.") ) - grid0.addWidget(self.ncc_rest_cb, 17, 0, 1, 2) + gen_grid.addWidget(self.ncc_rest_cb, 0, 0, 1, 2) # ## Reference # self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'}, @@ -298,8 +315,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): "- 'Reference Object' - will process the area specified by another object.") ) - grid0.addWidget(select_label, 18, 0) - grid0.addWidget(self.select_combo, 18, 1) + gen_grid.addWidget(select_label, 2, 0) + gen_grid.addWidget(self.select_combo, 2, 1) self.area_shape_label = FCLabel('%s:' % _("Shape")) self.area_shape_label.setToolTip( @@ -309,13 +326,13 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'}, {'label': _("Polygon"), 'value': 'polygon'}]) - grid0.addWidget(self.area_shape_label, 19, 0) - grid0.addWidget(self.area_shape_radio, 19, 1) + gen_grid.addWidget(self.area_shape_label, 4, 0) + gen_grid.addWidget(self.area_shape_radio, 4, 1) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid0.addWidget(separator_line, 20, 0, 1, 2) + gen_grid.addWidget(separator_line, 6, 0, 1, 2) # ## Plotting type self.plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'}, @@ -325,8 +342,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): _("- 'Normal' - normal plotting, done at the end of the job\n" "- 'Progressive' - each shape is plotted after it is generated") ) - grid0.addWidget(plotting_label, 21, 0) - grid0.addWidget(self.plotting_radio, 21, 1) + gen_grid.addWidget(plotting_label, 8, 0) + gen_grid.addWidget(self.plotting_radio, 8, 1) # Check Tool validity self.valid_cb = FCCheckBox(label=_('Check validity')) @@ -336,6 +353,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): ) self.valid_cb.setObjectName("n_check") - grid0.addWidget(self.valid_cb, 23, 0, 1, 2) + gen_grid.addWidget(self.valid_cb, 10, 0, 1, 2) - self.layout.addStretch() + FCGridLayout.set_common_column_size([par_grid, tool_grid, gen_grid], 0) + + # self.layout.addStretch() diff --git a/appPlugins/ToolCorners.py b/appPlugins/ToolCorners.py index f105589c..d15b5345 100644 --- a/appPlugins/ToolCorners.py +++ b/appPlugins/ToolCorners.py @@ -882,8 +882,8 @@ class CornersUI: self.tools_box.addWidget(par_frame) # ## Grid Layout - grid_par = FCGridLayout(v_spacing=5, h_spacing=3) - par_frame.setLayout(grid_par) + par_grid = FCGridLayout(v_spacing=5, h_spacing=3) + par_frame.setLayout(par_grid) # Type of Marker self.type_label = FCLabel('%s:' % _("Type")) @@ -896,8 +896,8 @@ class CornersUI: {"label": _("Cross"), "value": "c"}, ]) - grid_par.addWidget(self.type_label, 2, 0) - grid_par.addWidget(self.type_radio, 2, 1) + par_grid.addWidget(self.type_label, 2, 0) + par_grid.addWidget(self.type_radio, 2, 1) # Thickness # self.thick_label = FCLabel('%s:' % _("Thickness")) @@ -910,8 +910,8 @@ class CornersUI: self.thick_entry.setWrapping(True) self.thick_entry.setSingleStep(10 ** -self.decimals) - grid_par.addWidget(self.thick_label, 4, 0) - grid_par.addWidget(self.thick_entry, 4, 1) + par_grid.addWidget(self.thick_label, 4, 0) + par_grid.addWidget(self.thick_entry, 4, 1) # Length # self.l_label = FCLabel('%s:' % _("Length")) @@ -923,8 +923,8 @@ class CornersUI: self.l_entry.set_precision(self.decimals) self.l_entry.setSingleStep(10 ** -self.decimals) - grid_par.addWidget(self.l_label, 6, 0) - grid_par.addWidget(self.l_entry, 6, 1) + par_grid.addWidget(self.l_label, 6, 0) + par_grid.addWidget(self.l_entry, 6, 1) # Margin # self.margin_label = FCLabel('%s:' % _("Margin")) @@ -936,8 +936,8 @@ class CornersUI: self.margin_entry.set_precision(self.decimals) self.margin_entry.setSingleStep(0.1) - grid_par.addWidget(self.margin_label, 8, 0) - grid_par.addWidget(self.margin_entry, 8, 1) + par_grid.addWidget(self.margin_label, 8, 0) + par_grid.addWidget(self.margin_entry, 8, 1) # ############################################################################################################# # Locations Frame @@ -1050,7 +1050,7 @@ class CornersUI: grid_drill.addWidget(self.drill_dia_label, 0, 0) grid_drill.addWidget(self.drill_dia_entry, 0, 1) - FCGridLayout.set_common_column_size([grid_sel, grid_par, grid_loc, grid_drill], 0) + FCGridLayout.set_common_column_size([grid_sel, par_grid, grid_loc, grid_drill], 0) # ## Create an Excellon object self.drill_button = FCButton(_("Create Excellon Object")) diff --git a/appPlugins/ToolDrilling.py b/appPlugins/ToolDrilling.py index 292f307a..e6ce5a5d 100644 --- a/appPlugins/ToolDrilling.py +++ b/appPlugins/ToolDrilling.py @@ -2301,8 +2301,8 @@ class DrillingUI: self.tools_box.addWidget(self.obj_combo_label) # Grid Layout - grid0 = FCGridLayout(v_spacing=5, h_spacing=3) - self.tools_box.addLayout(grid0) + obj_grid = FCGridLayout(v_spacing=5, h_spacing=3) + self.tools_box.addLayout(obj_grid) # ################################################ # ##### The object to be drilled ################# @@ -2313,12 +2313,12 @@ class DrillingUI: # self.object_combo.setCurrentIndex(1) self.object_combo.is_last = True - grid0.addWidget(self.object_combo, 0, 0, 1, 2) + obj_grid.addWidget(self.object_combo, 0, 0, 1, 2) # separator_line = QtWidgets.QFrame() # separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) # separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - # grid0.addWidget(separator_line, 2, 0, 1, 2) + # obj_grid.addWidget(separator_line, 2, 0, 1, 2) # ############################################################################################################# # Excellon Tool Table Frame @@ -2331,11 +2331,12 @@ class DrillingUI: self.tools_box.addWidget(tt_frame) # Grid Layout - grid1 = FCGridLayout(v_spacing=5, h_spacing=3, c_stretch=[0, 0]) - tt_frame.setLayout(grid1) + tool_grid = FCGridLayout(v_spacing=5, h_spacing=3, c_stretch=[0, 0]) + tt_frame.setLayout(tool_grid) + # Tools Table self.tools_table = FCTable(drag_drop=True) - grid1.addWidget(self.tools_table, 0, 0, 1, 2) + tool_grid.addWidget(self.tools_table, 0, 0, 1, 2) self.tools_table.setColumnCount(5) self.tools_table.setColumnHidden(3, True) @@ -2369,8 +2370,8 @@ class DrillingUI: self.order_combo = FCComboBox2() self.order_combo.addItems([_('Default'), _('Forward'), _('Reverse')]) - grid1.addWidget(self.order_label, 2, 0) - grid1.addWidget(self.order_combo, 2, 1) + tool_grid.addWidget(self.order_label, 2, 0) + tool_grid.addWidget(self.order_combo, 2, 1) # Manual Load of Tools from DB self.search_load_db_btn = FCButton(_("Search DB")) @@ -2380,7 +2381,7 @@ class DrillingUI: "with tools from DB that have a close diameter value.") ) - grid1.addWidget(self.search_load_db_btn, 4, 0, 1, 2) + tool_grid.addWidget(self.search_load_db_btn, 4, 0, 1, 2) # ############################################################################################################# # ALL Parameters Frame @@ -2410,8 +2411,8 @@ class DrillingUI: self.exc_tools_box.addWidget(tp_frame) # Grid Layout - grid2 = FCGridLayout(v_spacing=5, h_spacing=3) - tp_frame.setLayout(grid2) + param_grid = FCGridLayout(v_spacing=5, h_spacing=3) + tp_frame.setLayout(param_grid) # Cut Z self.cutzlabel = FCLabel('%s:' % _('Cut Z')) @@ -2427,8 +2428,8 @@ class DrillingUI: self.cutz_entry.setSingleStep(0.1) self.cutz_entry.setObjectName("e_cutz") - grid2.addWidget(self.cutzlabel, 4, 0) - grid2.addWidget(self.cutz_entry, 4, 1) + param_grid.addWidget(self.cutzlabel, 4, 0) + param_grid.addWidget(self.cutz_entry, 4, 1) # Multi-Depth self.mpass_cb = FCCheckBox('%s:' % _("Multi-Depth")) @@ -2452,8 +2453,8 @@ class DrillingUI: self.mis_mpass_geo = OptionalInputSection(self.mpass_cb, [self.maxdepth_entry]) - grid2.addWidget(self.mpass_cb, 5, 0) - grid2.addWidget(self.maxdepth_entry, 5, 1) + param_grid.addWidget(self.mpass_cb, 5, 0) + param_grid.addWidget(self.maxdepth_entry, 5, 1) # Travel Z (z_move) self.travelzlabel = FCLabel('%s:' % _('Travel Z')) @@ -2469,8 +2470,8 @@ class DrillingUI: self.travelz_entry.setSingleStep(0.1) self.travelz_entry.setObjectName("e_travelz") - grid2.addWidget(self.travelzlabel, 6, 0) - grid2.addWidget(self.travelz_entry, 6, 1) + param_grid.addWidget(self.travelzlabel, 6, 0) + param_grid.addWidget(self.travelz_entry, 6, 1) # Excellon Feedrate Z self.frzlabel = FCLabel('%s:' % _('Feedrate Z')) @@ -2486,8 +2487,8 @@ class DrillingUI: self.feedrate_z_entry.setSingleStep(0.1) self.feedrate_z_entry.setObjectName("e_feedratez") - grid2.addWidget(self.frzlabel, 14, 0) - grid2.addWidget(self.feedrate_z_entry, 14, 1) + param_grid.addWidget(self.frzlabel, 14, 0) + param_grid.addWidget(self.feedrate_z_entry, 14, 1) # Excellon Rapid Feedrate self.feedrate_rapid_label = FCLabel('%s:' % _('Feedrate Rapids')) @@ -2504,8 +2505,8 @@ class DrillingUI: self.feedrate_rapid_entry.setSingleStep(0.1) self.feedrate_rapid_entry.setObjectName("e_fr_rapid") - grid2.addWidget(self.feedrate_rapid_label, 16, 0) - grid2.addWidget(self.feedrate_rapid_entry, 16, 1) + param_grid.addWidget(self.feedrate_rapid_label, 16, 0) + param_grid.addWidget(self.feedrate_rapid_entry, 16, 1) # default values is to hide self.feedrate_rapid_label.hide() @@ -2523,8 +2524,8 @@ class DrillingUI: self.spindlespeed_entry.set_step(100) self.spindlespeed_entry.setObjectName("e_spindlespeed") - grid2.addWidget(self.spindle_label, 19, 0) - grid2.addWidget(self.spindlespeed_entry, 19, 1) + param_grid.addWidget(self.spindle_label, 19, 0) + param_grid.addWidget(self.spindlespeed_entry, 19, 1) # Dwell self.dwell_cb = FCCheckBox('%s:' % _('Dwell')) @@ -2545,8 +2546,8 @@ class DrillingUI: ) self.dwelltime_entry.setObjectName("e_dwelltime") - grid2.addWidget(self.dwell_cb, 20, 0) - grid2.addWidget(self.dwelltime_entry, 20, 1) + param_grid.addWidget(self.dwell_cb, 20, 0) + param_grid.addWidget(self.dwelltime_entry, 20, 1) self.ois_dwell = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) @@ -2563,8 +2564,8 @@ class DrillingUI: self.offset_entry.set_range(-10000.0000, 10000.0000) self.offset_entry.setObjectName("e_offset") - grid2.addWidget(self.tool_offset_label, 25, 0) - grid2.addWidget(self.offset_entry, 25, 1) + param_grid.addWidget(self.tool_offset_label, 25, 0) + param_grid.addWidget(self.offset_entry, 25, 1) # Drill slots self.drill_slots_cb = FCCheckBox('%s' % _('Drill slots')) @@ -2572,7 +2573,7 @@ class DrillingUI: _("If the selected tool has slots then they will be drilled.") ) self.drill_slots_cb.setObjectName("e_drill_slots") - grid2.addWidget(self.drill_slots_cb, 27, 0, 1, 2) + param_grid.addWidget(self.drill_slots_cb, 27, 0, 1, 2) # Drill Overlap self.drill_overlap_label = FCLabel('%s:' % _('Overlap')) @@ -2587,8 +2588,8 @@ class DrillingUI: self.drill_overlap_entry.setObjectName("e_drill_slots_overlap") - grid2.addWidget(self.drill_overlap_label, 28, 0) - grid2.addWidget(self.drill_overlap_entry, 28, 1) + param_grid.addWidget(self.drill_overlap_label, 28, 0) + param_grid.addWidget(self.drill_overlap_entry, 28, 1) # Last drill in slot self.last_drill_cb = FCCheckBox('%s' % _('Last drill')) @@ -2597,7 +2598,7 @@ class DrillingUI: "add a drill hole on the slot end point.") ) self.last_drill_cb.setObjectName("e_drill_last_drill") - grid2.addWidget(self.last_drill_cb, 30, 0, 1, 2) + param_grid.addWidget(self.last_drill_cb, 30, 0, 1, 2) self.drill_overlap_label.hide() self.drill_overlap_entry.hide() @@ -2633,8 +2634,8 @@ class DrillingUI: gp_frame = FCFrame() self.exc_tools_box.addWidget(gp_frame) - grid3 = FCGridLayout(v_spacing=5, h_spacing=3) - gp_frame.setLayout(grid3) + all_par_grid = FCGridLayout(v_spacing=5, h_spacing=3) + gp_frame.setLayout(all_par_grid) # Tool change self.toolchange_cb = FCCheckBox('%s:' % _("Tool change Z")) @@ -2656,8 +2657,8 @@ class DrillingUI: self.toolchangez_entry.setSingleStep(0.1) - grid3.addWidget(self.toolchange_cb, 0, 0) - grid3.addWidget(self.toolchangez_entry, 0, 1) + all_par_grid.addWidget(self.toolchange_cb, 0, 0) + all_par_grid.addWidget(self.toolchangez_entry, 0, 1) # Tool change X-Y self.toolchange_xy_label = FCLabel('%s:' % _('Toolchange X-Y')) @@ -2667,8 +2668,8 @@ class DrillingUI: self.toolchangexy_entry = NumericalEvalTupleEntry(border_color='#0069A9') self.toolchangexy_entry.setObjectName("e_toolchangexy") - grid3.addWidget(self.toolchange_xy_label, 2, 0) - grid3.addWidget(self.toolchangexy_entry, 2, 1) + all_par_grid.addWidget(self.toolchange_xy_label, 2, 0) + all_par_grid.addWidget(self.toolchangexy_entry, 2, 1) self.ois_tcz_e = OptionalInputSection(self.toolchange_cb, [ @@ -2686,8 +2687,8 @@ class DrillingUI: self.estartz_entry = NumericalEvalEntry(border_color='#0069A9') self.estartz_entry.setObjectName("e_startz") - grid3.addWidget(self.estartz_label, 4, 0) - grid3.addWidget(self.estartz_entry, 4, 1) + all_par_grid.addWidget(self.estartz_label, 4, 0) + all_par_grid.addWidget(self.estartz_entry, 4, 1) # End move Z: self.endz_label = FCLabel('%s:' % _("End move Z")) @@ -2702,8 +2703,8 @@ class DrillingUI: self.endz_entry.setSingleStep(0.1) - grid3.addWidget(self.endz_label, 6, 0) - grid3.addWidget(self.endz_entry, 6, 1) + all_par_grid.addWidget(self.endz_label, 6, 0) + all_par_grid.addWidget(self.endz_entry, 6, 1) # End Move X,Y self.endmove_xy_label = FCLabel('%s:' % _('End move X,Y')) @@ -2716,8 +2717,8 @@ class DrillingUI: self.endxy_entry.setPlaceholderText(_("X,Y coordinates")) self.endxy_entry.setObjectName("e_endxy") - grid3.addWidget(self.endmove_xy_label, 8, 0) - grid3.addWidget(self.endxy_entry, 8, 1) + all_par_grid.addWidget(self.endmove_xy_label, 8, 0) + all_par_grid.addWidget(self.endxy_entry, 8, 1) # Probe depth self.pdepth_label = FCLabel('%s:' % _("Probe Z depth")) @@ -2732,8 +2733,8 @@ class DrillingUI: self.pdepth_entry.setSingleStep(0.1) self.pdepth_entry.setObjectName("e_depth_probe") - grid3.addWidget(self.pdepth_label, 10, 0) - grid3.addWidget(self.pdepth_entry, 10, 1) + all_par_grid.addWidget(self.pdepth_label, 10, 0) + all_par_grid.addWidget(self.pdepth_entry, 10, 1) self.pdepth_label.hide() self.pdepth_entry.setVisible(False) @@ -2750,8 +2751,8 @@ class DrillingUI: self.feedrate_probe_entry.setSingleStep(0.1) self.feedrate_probe_entry.setObjectName("e_fr_probe") - grid3.addWidget(self.feedrate_probe_label, 12, 0) - grid3.addWidget(self.feedrate_probe_entry, 12, 1) + all_par_grid.addWidget(self.feedrate_probe_label, 12, 0) + all_par_grid.addWidget(self.feedrate_probe_entry, 12, 1) self.feedrate_probe_label.hide() self.feedrate_probe_entry.setVisible(False) @@ -2766,8 +2767,8 @@ class DrillingUI: self.pp_excellon_name_cb.setFocusPolicy(QtCore.Qt.FocusPolicy.StrongFocus) self.pp_excellon_name_cb.setObjectName("e_pp") - grid3.addWidget(pp_excellon_label, 14, 0) - grid3.addWidget(self.pp_excellon_name_cb, 14, 1) + all_par_grid.addWidget(pp_excellon_label, 14, 0) + all_par_grid.addWidget(self.pp_excellon_name_cb, 14, 1) # ------------------------------------------------------------------------------------------------------------ # ------------------------- EXCLUSION AREAS ------------------------------------------------------------------ @@ -2783,11 +2784,11 @@ class DrillingUI: )) self.exclusion_cb.setObjectName("e_area_exclusion") - grid3.addWidget(self.exclusion_cb, 16, 0, 1, 2) + all_par_grid.addWidget(self.exclusion_cb, 16, 0, 1, 2) self.exclusion_frame = QtWidgets.QFrame() self.exclusion_frame.setContentsMargins(0, 0, 0, 0) - grid3.addWidget(self.exclusion_frame, 18, 0, 1, 2) + all_par_grid.addWidget(self.exclusion_frame, 18, 0, 1, 2) self.exclusion_box = QtWidgets.QVBoxLayout() self.exclusion_box.setContentsMargins(0, 0, 0, 0) @@ -2812,8 +2813,8 @@ class DrillingUI: self.exclusion_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) - grid_a1 = FCGridLayout(v_spacing=5, h_spacing=3) - self.exclusion_box.addLayout(grid_a1) + exclud_grid = FCGridLayout(v_spacing=5, h_spacing=3) + self.exclusion_box.addLayout(exclud_grid) # Chose Strategy self.strategy_label = FCLabel('%s:' % _("Strategy")) @@ -2825,8 +2826,8 @@ class DrillingUI: {'label': _('Around'), 'value': 'around'}]) self.strategy_radio.setObjectName("e_area_strategy") - grid_a1.addWidget(self.strategy_label, 1, 0) - grid_a1.addWidget(self.strategy_radio, 1, 1) + exclud_grid.addWidget(self.strategy_label, 1, 0) + exclud_grid.addWidget(self.strategy_radio, 1, 1) # Over Z self.over_z_label = FCLabel('%s:' % _("Over Z")) @@ -2837,8 +2838,8 @@ class DrillingUI: self.over_z_entry.set_precision(self.decimals) self.over_z_entry.setObjectName("e_area_overz") - grid_a1.addWidget(self.over_z_label, 2, 0) - grid_a1.addWidget(self.over_z_entry, 2, 1) + exclud_grid.addWidget(self.over_z_label, 2, 0) + exclud_grid.addWidget(self.over_z_entry, 2, 1) # Button Add Area self.add_area_button = QtWidgets.QPushButton(_('Add Area:')) @@ -2852,8 +2853,8 @@ class DrillingUI: ) self.area_shape_radio.setObjectName("e_area_shape") - grid_a1.addWidget(self.add_area_button, 4, 0) - grid_a1.addWidget(self.area_shape_radio, 4, 1) + exclud_grid.addWidget(self.add_area_button, 4, 0) + exclud_grid.addWidget(self.area_shape_radio, 4, 1) h_lay_1 = QtWidgets.QHBoxLayout() self.exclusion_box.addLayout(h_lay_1) @@ -2876,9 +2877,9 @@ class DrillingUI: # separator_line = QtWidgets.QFrame() # separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) # separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - # grid3.addWidget(separator_line, 25, 0, 1, 2) + # all_par_grid.addWidget(separator_line, 25, 0, 1, 2) - FCGridLayout.set_common_column_size([grid0, grid1, grid2, grid3], 0) + FCGridLayout.set_common_column_size([obj_grid, tool_grid, param_grid, all_par_grid], 0) self.generate_cnc_button = QtWidgets.QPushButton(_('Generate CNCJob object')) self.generate_cnc_button.setIcon(QtGui.QIcon(self.app.resource_location + '/cnc16.png')) diff --git a/appPlugins/ToolIsolation.py b/appPlugins/ToolIsolation.py index 17fafb59..c23b39a8 100644 --- a/appPlugins/ToolIsolation.py +++ b/appPlugins/ToolIsolation.py @@ -324,7 +324,7 @@ class ToolIsolation(AppTool, Gerber): self.on_type_excobj_index_changed(val="gerber") self.on_reference_combo_changed() - self.ui.order_radio.set_value(self.app.defaults["tools_iso_order"]) + self.ui.iso_order_combo.set_value(self.app.defaults["tools_iso_order"]) self.ui.tool_shape_combo.set_value(self.app.defaults["tools_iso_tool_shape"]) self.ui.passes_entry.set_value(self.app.defaults["tools_iso_passes"]) self.ui.pad_passes_entry.set_value(self.app.defaults["tools_iso_pad_passes"]) @@ -661,7 +661,7 @@ class ToolIsolation(AppTool, Gerber): current_widget.currentIndexChanged.connect(self.form_to_storage) self.ui.rest_cb.stateChanged.connect(self.on_rest_machining_check) - self.ui.order_radio.activated_custom[str].connect(self.on_order_changed) + self.ui.iso_order_combo.currentIndexChanged.connect(self.on_order_changed) def ui_disconnect(self): @@ -710,20 +710,20 @@ class ToolIsolation(AppTool, Gerber): except (TypeError, ValueError): pass try: - self.ui.order_radio.activated_custom[str].disconnect() + self.ui.iso_order_combo.currentIndexChanged.disconnect() except (TypeError, ValueError): pass def sort_iso_tools(self): - order = self.ui.order_radio.get_value() - if order == 'no': + order = self.ui.iso_order_combo.get_value() + if order == 0: # "Default" return # sort the tools dictionary having the 'tooldia' as sorting key new_tools_list = [] - if order == 'fwd': + if order == 1: # "Forward" new_tools_list = deepcopy(sorted(self.iso_tools.items(), key=lambda x: x[1]['tooldia'], reverse=False)) - elif order == 'rev': + elif order == 2: # "Reverse" new_tools_list = deepcopy(sorted(self.iso_tools.items(), key=lambda x: x[1]['tooldia'], reverse=True)) # clear the tools dictionary @@ -991,9 +991,9 @@ class ToolIsolation(AppTool, Gerber): def on_rest_machining_check(self, state): if state: - self.ui.order_radio.set_value('rev') + self.ui.iso_order_combo.set_value(2) # "Reverse" self.ui.order_label.setDisabled(True) - self.ui.order_radio.setDisabled(True) + self.ui.iso_order_combo.setDisabled(True) self.old_combine_state = self.ui.combine_passes_cb.get_value() self.ui.combine_passes_cb.set_value(True) @@ -1002,7 +1002,7 @@ class ToolIsolation(AppTool, Gerber): self.ui.forced_rest_iso_cb.setDisabled(False) else: self.ui.order_label.setDisabled(False) - self.ui.order_radio.setDisabled(False) + self.ui.iso_order_combo.setDisabled(False) self.ui.combine_passes_cb.set_value(self.old_combine_state) self.ui.combine_passes_cb.setDisabled(False) @@ -1854,10 +1854,10 @@ class ToolIsolation(AppTool, Gerber): self.app.inform.emit('[ERROR_NOTCL] %s' % _("There are no tools selected in the Tool Table.")) return 'fail' - order = self.ui.order_radio.get_value() - if order == 'fwd': + order = self.ui.iso_order_combo.get_value() + if order == 1: # "Forward" sorted_tools.sort(reverse=False) - elif order == 'rev': + elif order == 2: # "Reverse" sorted_tools.sort(reverse=True) else: pass @@ -2087,10 +2087,11 @@ class ToolIsolation(AppTool, Gerber): if iso_geo == 'fail': self.app.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated.")) continue - try: - for geo in iso_geo: + + if isinstance(iso_geo, (MultiLineString, MultiPolygon)): + for geo in iso_geo.geoms: solid_geo.append(geo) - except TypeError: + else: solid_geo.append(iso_geo) # ############################################################ @@ -2893,12 +2894,17 @@ class ToolIsolation(AppTool, Gerber): """ try: - geom = self.grb_obj.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type, - passes=nr_passes, prog_plot=prog_plot) + geom_shp = self.grb_obj.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type, + passes=nr_passes, prog_plot=prog_plot) except Exception as e: log.error('ToolIsolation.generate_envelope() --> %s' % str(e)) return 'fail' + if isinstance(geom_shp, (MultiPolygon, MultiLineString)): + geom = geom_shp.geoms + else: + geom = geom_shp + if invert: try: pl = [] @@ -3025,21 +3031,22 @@ class ToolIsolation(AppTool, Gerber): else: not_isolated_geo.append(geo) + work_geo_shp = work_geo.geoms if isinstance(work_geo, MultiPolygon) else work_geo if invert: try: pl = [] - for p in work_geo: + for p in work_geo_shp: if p is not None: if isinstance(p, Polygon): pl.append(Polygon(p.exterior.coords[::-1], p.interiors)) elif isinstance(p, LinearRing): pl.append(Polygon(p.coords[::-1])) - work_geo = MultiPolygon(pl) + work_geo_shp = MultiPolygon(pl) except TypeError: - if isinstance(work_geo, Polygon) and work_geo is not None: - work_geo = [Polygon(work_geo.exterior.coords[::-1], work_geo.interiors)] - elif isinstance(work_geo, LinearRing) and work_geo is not None: - work_geo = [Polygon(work_geo.coords[::-1])] + if isinstance(work_geo_shp, Polygon) and work_geo_shp is not None: + work_geo_shp = [Polygon(work_geo_shp.exterior.coords[::-1], work_geo_shp.interiors)] + elif isinstance(work_geo_shp, LinearRing) and work_geo_shp is not None: + work_geo_shp = [Polygon(work_geo_shp.coords[::-1])] else: log.debug("ToolIsolation.generate_rest_geometry() Error --> Unexpected Geometry %s" % type(work_geo)) @@ -3047,14 +3054,15 @@ class ToolIsolation(AppTool, Gerber): log.error("ToolIsolation.generate_rest_geometry() Error --> %s" % str(e)) return 'fail', 'fail' + actual_geo = work_geo_shp.geoms if isinstance(work_geo, MultiPolygon) else work_geo_shp if env_iso_type == 0: # exterior - for geo in work_geo: + for geo in actual_geo: isolated_geo.append(geo.exterior) elif env_iso_type == 1: # interiors - for geo in work_geo: + for geo in actual_geo: isolated_geo += [interior for interior in geo.interiors] else: # exterior + interiors - for geo in work_geo: + for geo in actual_geo: isolated_geo += [geo.exterior] + [interior for interior in geo.interiors] return isolated_geo, not_isolated_geo @@ -3189,11 +3197,11 @@ class IsoUI: self.tools_box.addWidget(tt_frame) # Grid Layout - grid1 = FCGridLayout(v_spacing=5, h_spacing=3) - tt_frame.setLayout(grid1) + tool_grid = FCGridLayout(v_spacing=5, h_spacing=3) + tt_frame.setLayout(tool_grid) self.tools_table = FCTable(drag_drop=True) - grid1.addWidget(self.tools_table, 0, 0, 1, 2) + tool_grid.addWidget(self.tools_table, 0, 0, 1, 2) self.tools_table.setColumnCount(4) # 3rd column is reserved (and hidden) for the tool ID @@ -3224,41 +3232,37 @@ class IsoUI: "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.iso_order_combo = FCComboBox2() + self.iso_order_combo.addItems([_('Default'), _('Forward'), _('Reverse')]) - grid1.addWidget(self.order_label, 2, 0) - grid1.addWidget(self.order_radio, 2, 1) + tool_grid.addWidget(self.order_label, 2, 0) + tool_grid.addWidget(self.iso_order_combo, 2, 1) # ############################################################# # ############### Tool adding ################################# # ############################################################# self.add_tool_frame = QtWidgets.QFrame() self.add_tool_frame.setContentsMargins(0, 0, 0, 0) - grid1.addWidget(self.add_tool_frame, 6, 0, 1, 2) + tool_grid.addWidget(self.add_tool_frame, 4, 0, 1, 2) - grid_add_tool = FCGridLayout(v_spacing=5, h_spacing=3) - grid_add_tool.setContentsMargins(0, 0, 0, 0) - self.add_tool_frame.setLayout(grid_add_tool) + new_tool_grid = FCGridLayout(v_spacing=5, h_spacing=3) + new_tool_grid.setContentsMargins(0, 0, 0, 0) + self.add_tool_frame.setLayout(new_tool_grid) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - grid_add_tool.addWidget(separator_line, 0, 0, 1, 2) + new_tool_grid.addWidget(separator_line, 0, 0, 1, 3) self.tool_sel_label = FCLabel('%s' % _('Add from DB')) - grid_add_tool.addWidget(self.tool_sel_label, 2, 0, 1, 2) + new_tool_grid.addWidget(self.tool_sel_label, 2, 0, 1, 3) # ### Tool Diameter #### self.new_tooldia_lbl = FCLabel('%s: ' % _('Tool Dia')) self.new_tooldia_lbl.setToolTip( _("Diameter for the new tool") ) - grid_add_tool.addWidget(self.new_tooldia_lbl, 4, 0) - - new_tool_lay = QtWidgets.QHBoxLayout() - grid_add_tool.addLayout(new_tool_lay, 4, 1) + new_tool_grid.addWidget(self.new_tooldia_lbl, 4, 0) # Tool diameter entry self.new_tooldia_entry = FCDoubleSpinner(callback=self.confirmation_message) @@ -3276,16 +3280,14 @@ class IsoUI: "to do a complete isolation.") ) - new_tool_lay.addWidget(self.new_tooldia_entry) - new_tool_lay.addWidget(self.find_optimal_button) + new_tool_grid.addWidget(self.new_tooldia_entry, 4, 1) + new_tool_grid.addWidget(self.find_optimal_button, 4, 2) # ############################################################################################################# # ################################ Button Grid ########################################################### # ############################################################################################################# - button_grid = FCGridLayout(v_spacing=5, h_spacing=3) - button_grid.setColumnStretch(0, 1) - button_grid.setColumnStretch(1, 0) - grid_add_tool.addLayout(button_grid, 6, 0, 1, 2) + button_grid = FCGridLayout(v_spacing=5, h_spacing=3, c_stretch=[1, 0]) + new_tool_grid.addLayout(button_grid, 6, 0, 1, 3) self.search_and_add_btn = FCButton(_('Search and Add')) self.search_and_add_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png')) @@ -3350,8 +3352,8 @@ class IsoUI: self.tool_params_box.addWidget(tp_frame) # Grid Layout - grid2 = FCGridLayout(v_spacing=5, h_spacing=3) - tp_frame.setLayout(grid2) + tool_param_grid = FCGridLayout(v_spacing=5, h_spacing=3) + tp_frame.setLayout(tool_param_grid) # Tool Type self.tool_shape_label = FCLabel('%s:' % _('Shape')) @@ -3374,8 +3376,8 @@ class IsoUI: else: self.tool_shape_combo.setCurrentIndex(idx) - grid2.addWidget(self.tool_shape_label, 0, 0) - grid2.addWidget(self.tool_shape_combo, 0, 1) + tool_param_grid.addWidget(self.tool_shape_label, 0, 0) + tool_param_grid.addWidget(self.tool_shape_combo, 0, 1) # Passes passlabel = FCLabel('%s:' % _('Passes')) @@ -3387,8 +3389,8 @@ class IsoUI: self.passes_entry.set_range(1, 999) self.passes_entry.setObjectName("i_passes") - grid2.addWidget(passlabel, 2, 0) - grid2.addWidget(self.passes_entry, 2, 1) + tool_param_grid.addWidget(passlabel, 2, 0) + tool_param_grid.addWidget(self.passes_entry, 2, 1) # Pad Passes padpasslabel = FCLabel('%s:' % _('Pad Passes')) @@ -3400,8 +3402,8 @@ class IsoUI: self.pad_passes_entry.set_range(0, 999) self.pad_passes_entry.setObjectName("i_pad_passes") - grid2.addWidget(padpasslabel, 4, 0) - grid2.addWidget(self.pad_passes_entry, 4, 1, 1, 2) + tool_param_grid.addWidget(padpasslabel, 4, 0) + tool_param_grid.addWidget(self.pad_passes_entry, 4, 1) # Overlap Entry overlabel = FCLabel('%s:' % _('Overlap')) @@ -3415,8 +3417,8 @@ class IsoUI: self.iso_overlap_entry.setSingleStep(0.1) self.iso_overlap_entry.setObjectName("i_overlap") - grid2.addWidget(overlabel, 6, 0) - grid2.addWidget(self.iso_overlap_entry, 6, 1) + tool_param_grid.addWidget(overlabel, 6, 0) + tool_param_grid.addWidget(self.iso_overlap_entry, 6, 1) # Milling Type Radio Button self.milling_type_label = FCLabel('%s:' % _('Milling Type')) @@ -3435,8 +3437,8 @@ class IsoUI: ) self.milling_type_radio.setObjectName("i_milling_type") - grid2.addWidget(self.milling_type_label, 8, 0) - grid2.addWidget(self.milling_type_radio, 8, 1) + tool_param_grid.addWidget(self.milling_type_label, 8, 0) + tool_param_grid.addWidget(self.milling_type_radio, 8, 1) # Isolation Type self.iso_type_label = FCLabel('%s:' % _('Isolation Type')) @@ -3455,8 +3457,8 @@ class IsoUI: {'label': _('Int'), 'value': 'int'}]) self.iso_type_radio.setObjectName("i_iso_type") - grid2.addWidget(self.iso_type_label, 10, 0) - grid2.addWidget(self.iso_type_radio, 10, 1) + tool_param_grid.addWidget(self.iso_type_label, 10, 0) + tool_param_grid.addWidget(self.iso_type_radio, 10, 1) # ############################################################################################################## # Apply to All Parameters Button @@ -3482,8 +3484,8 @@ class IsoUI: gp_frame = FCFrame() self.tool_params_box.addWidget(gp_frame) - grid3 = FCGridLayout(v_spacing=5, h_spacing=3) - gp_frame.setLayout(grid3) + gen_grid = FCGridLayout(v_spacing=5, h_spacing=3) + gp_frame.setLayout(gen_grid) # Rest Machining self.rest_cb = FCCheckBox('%s' % _("Rest")) @@ -3498,7 +3500,7 @@ class IsoUI: "If not checked, use the standard algorithm.") ) - grid3.addWidget(self.rest_cb, 0, 0) + gen_grid.addWidget(self.rest_cb, 0, 0) # Force isolation even if the interiors are not isolated self.forced_rest_iso_cb = FCCheckBox(_("Forced Rest")) @@ -3508,7 +3510,7 @@ class IsoUI: "Works when 'rest machining' is used.") ) - grid3.addWidget(self.forced_rest_iso_cb, 0, 1) + gen_grid.addWidget(self.forced_rest_iso_cb, 0, 1) # Combine All Passes self.combine_passes_cb = FCCheckBox(label=_('Combine')) @@ -3517,7 +3519,7 @@ class IsoUI: ) self.combine_passes_cb.setObjectName("i_combine") - grid3.addWidget(self.combine_passes_cb, 2, 0, 1, 2) + gen_grid.addWidget(self.combine_passes_cb, 2, 0, 1, 2) # Check Tool validity self.valid_cb = FCCheckBox(label=_('Check validity')) @@ -3527,7 +3529,7 @@ class IsoUI: ) self.valid_cb.setObjectName("i_check") - grid3.addWidget(self.valid_cb, 4, 0, 1, 2) + gen_grid.addWidget(self.valid_cb, 4, 0, 1, 2) # Exception Areas self.except_cb = FCCheckBox(label=_('Except')) @@ -3535,7 +3537,7 @@ class IsoUI: "by checking this, the area of the object below\n" "will be subtracted from the isolation geometry.")) self.except_cb.setObjectName("i_except") - grid3.addWidget(self.except_cb, 6, 0) + gen_grid.addWidget(self.except_cb, 6, 0) # Type of object to be excepted self.type_excobj_radio = RadioSet([{'label': _("Geometry"), 'value': 'geometry'}, @@ -3547,7 +3549,7 @@ class IsoUI: "of objects that will populate the 'Object' combobox.") ) - grid3.addWidget(self.type_excobj_radio, 6, 1) + gen_grid.addWidget(self.type_excobj_radio, 6, 1) # The object to be excepted self.exc_obj_combo = FCComboBox() @@ -3559,7 +3561,7 @@ class IsoUI: self.exc_obj_combo.is_last = True self.exc_obj_combo.obj_type = "gerber" - grid3.addWidget(self.exc_obj_combo, 8, 0, 1, 2) + gen_grid.addWidget(self.exc_obj_combo, 8, 0, 1, 2) self.e_ois = OptionalInputSection(self.except_cb, [ @@ -3582,8 +3584,8 @@ class IsoUI: ) self.select_combo.setObjectName("i_selection") - grid3.addWidget(self.select_label, 10, 0) - grid3.addWidget(self.select_combo, 10, 1) + gen_grid.addWidget(self.select_label, 10, 0) + gen_grid.addWidget(self.select_combo, 10, 1) # Reference Type self.reference_combo_type_label = FCLabel('%s:' % _("Type")) @@ -3591,15 +3593,15 @@ class IsoUI: self.reference_combo_type = FCComboBox2() self.reference_combo_type.addItems([_("Gerber"), _("Excellon"), _("Geometry")]) - grid3.addWidget(self.reference_combo_type_label, 12, 0) - grid3.addWidget(self.reference_combo_type, 12, 1) + gen_grid.addWidget(self.reference_combo_type_label, 12, 0) + gen_grid.addWidget(self.reference_combo_type, 12, 1) self.reference_combo = FCComboBox() self.reference_combo.setModel(self.app.collection) self.reference_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) self.reference_combo.is_last = True - grid3.addWidget(self.reference_combo, 14, 0, 1, 2) + gen_grid.addWidget(self.reference_combo, 14, 0, 1, 2) self.reference_combo.hide() self.reference_combo_type.hide() @@ -3612,7 +3614,7 @@ class IsoUI: "(holes in the polygon).") ) - grid3.addWidget(self.poly_int_cb, 16, 0) + gen_grid.addWidget(self.poly_int_cb, 16, 0) self.poly_int_cb.hide() @@ -3636,7 +3638,7 @@ class IsoUI: sel_hlay.addWidget(self.sel_all_btn) sel_hlay.addWidget(self.clear_all_btn) - grid3.addLayout(sel_hlay, 18, 0, 1, 2) + gen_grid.addLayout(sel_hlay, 18, 0, 1, 2) # Area Selection shape self.area_shape_label = FCLabel('%s:' % _("Shape")) @@ -3647,12 +3649,14 @@ class IsoUI: self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'}, {'label': _("Polygon"), 'value': 'polygon'}]) - grid3.addWidget(self.area_shape_label, 20, 0) - grid3.addWidget(self.area_shape_radio, 20, 1) + gen_grid.addWidget(self.area_shape_label, 20, 0) + gen_grid.addWidget(self.area_shape_radio, 20, 1) self.area_shape_label.hide() self.area_shape_radio.hide() + FCGridLayout.set_common_column_size([tool_grid, new_tool_grid, tool_param_grid, gen_grid], 0) + # ############################################################################################################# # Generate Geometry object # ############################################################################################################# diff --git a/appPlugins/ToolNCC.py b/appPlugins/ToolNCC.py index 6dca2c30..7ec6fec9 100644 --- a/appPlugins/ToolNCC.py +++ b/appPlugins/ToolNCC.py @@ -254,7 +254,7 @@ class NonCopperClear(AppTool, Gerber): self.ui.select_combo.currentIndexChanged.connect(self.ui.on_toggle_reference) self.ui.ncc_rest_cb.stateChanged.connect(self.ui.on_rest_machining_check) - self.ui.ncc_order_radio.activated_custom[str].connect(self.on_order_changed) + self.ui.ncc_order_combo.currentIndexChanged.connect(self.on_order_changed) self.ui.type_obj_radio.activated_custom.connect(self.on_type_obj_index_changed) self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked) @@ -326,7 +326,7 @@ class NonCopperClear(AppTool, Gerber): self.on_reference_combo_changed() self.ui.op_radio.set_value(self.app.defaults["tools_ncc_operation"]) - self.ui.ncc_order_radio.set_value(self.app.defaults["tools_ncc_order"]) + self.ui.ncc_order_combo.set_value(self.app.defaults["tools_ncc_order"]) self.ui.ncc_overlap_entry.set_value(self.app.defaults["tools_ncc_overlap"]) self.ui.ncc_margin_entry.set_value(self.app.defaults["tools_ncc_margin"]) self.ui.ncc_method_combo.set_value(self.app.defaults["tools_ncc_method"]) @@ -803,10 +803,10 @@ class NonCopperClear(AppTool, Gerber): else: sorted_tools.append(float('%.*f' % (self.decimals, float(v['tooldia'])))) - order = self.ui.ncc_order_radio.get_value() - if order == 'fwd': + order = self.ui.ncc_order_combo.get_value() + if order == 1: # "Forward" sorted_tools.sort(reverse=False) - elif order == 'rev': + elif order == 2: # "Reverse" sorted_tools.sort(reverse=True) else: pass @@ -903,7 +903,7 @@ class NonCopperClear(AppTool, Gerber): current_widget.currentIndexChanged.connect(self.form_to_storage) self.ui.ncc_rest_cb.stateChanged.connect(self.ui.on_rest_machining_check) - self.ui.ncc_order_radio.activated_custom[str].connect(self.on_order_changed) + self.ui.ncc_order_combo.currentIndexChanged.connect(self.on_order_changed) def ui_disconnect(self): @@ -948,7 +948,7 @@ class NonCopperClear(AppTool, Gerber): except (TypeError, ValueError): pass try: - self.ui.ncc_order_radio.activated_custom[str].disconnect(self.on_order_changed) + self.ui.ncc_order_combo.currentIndexChanged.disconnect(self.on_order_changed) except (TypeError, ValueError): pass @@ -969,7 +969,7 @@ class NonCopperClear(AppTool, Gerber): self.ui.reference_combo.obj_type = {0: "Gerber", 1: "Excellon", 2: "Geometry"}[obj_type] def on_order_changed(self, order): - if order != 'no': + if order != 0: # "Default" self.build_ui() def on_tooltable_cellwidget_change(self): @@ -1016,8 +1016,8 @@ class NonCopperClear(AppTool, Gerber): min_dict = {} idx = 1 - for geo in total_geo: - for s_geo in total_geo[idx:]: + for geo in total_geo.geoms: + for s_geo in total_geo.geoms[idx:]: # minimize the number of distances by not taking into considerations # those that are too small dist = geo.distance(s_geo) @@ -1161,8 +1161,8 @@ class NonCopperClear(AppTool, Gerber): min_dict = {} idx = 1 - for geo in total_geo: - for s_geo in total_geo[idx:]: + for geo in total_geo.geoms: + for s_geo in total_geo.geoms[idx:]: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -2330,7 +2330,7 @@ class NonCopperClear(AppTool, Gerber): # ###################################################################################################### units = self.app.defaults['units'] - order = order if order else self.ui.ncc_order_radio.get_value() + order = order if order else self.ui.ncc_order_combo.get_value() ncc_select = self.ui.select_combo.get_value() rest_machining_choice = self.ui.ncc_rest_cb.get_value() @@ -2368,9 +2368,9 @@ class NonCopperClear(AppTool, Gerber): tool = None - if order == 'fwd': + if order == 1: # "Forward" sorted_clear_tools.sort(reverse=False) - elif order == 'rev': + elif order == 2: # "Reverse" sorted_clear_tools.sort(reverse=True) else: pass @@ -2845,9 +2845,9 @@ class NonCopperClear(AppTool, Gerber): def job_thread(a_obj): try: if rest_machining_choice is True: - a_obj.app_obj.new_object("geometry", name, gen_clear_area_rest) + a_obj.app_obj.new_object("geometry", name, gen_clear_area_rest, autoselected=False) else: - a_obj.app_obj.new_object("geometry", name, gen_clear_area) + a_obj.app_obj.new_object("geometry", name, gen_clear_area, autoselected=False) except grace: if run_threaded: proc.done() @@ -2864,7 +2864,7 @@ class NonCopperClear(AppTool, Gerber): a_obj.proc_container.view.set_idle() # focus on Properties Tab - self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab) + # self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab) if run_threaded: # Promise object with the new name @@ -3050,9 +3050,9 @@ class NonCopperClear(AppTool, Gerber): # will store the number of tools for which the isolation is broken warning_flag = 0 - if order == 'fwd': + if order == 1: # "Forward" sorted_tools.sort(reverse=False) - elif order == 'rev': + elif order == 2: # "Reverse" sorted_tools.sort(reverse=True) else: pass @@ -4121,8 +4121,8 @@ class NccUI: self.tools_box.addWidget(obj_frame) # Grid Layout - grid0 = FCGridLayout(v_spacing=5, h_spacing=3) - obj_frame.setLayout(grid0) + obj_grid = FCGridLayout(v_spacing=5, h_spacing=3) + obj_frame.setLayout(obj_grid) # ############################################################################################################# # Type of object to be painted @@ -4139,8 +4139,8 @@ class NccUI: self.type_obj_radio = RadioSet([{'label': _("Geometry"), 'value': 'geometry'}, {'label': _("Gerber"), 'value': 'gerber'}]) - grid0.addWidget(self.type_obj_combo_label, 0, 0) - grid0.addWidget(self.type_obj_radio, 0, 1) + obj_grid.addWidget(self.type_obj_combo_label, 0, 0) + obj_grid.addWidget(self.type_obj_radio, 0, 1) # ############################################################################################################# # The object to be copper cleared @@ -4150,12 +4150,12 @@ class NccUI: self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) self.object_combo.is_last = True - grid0.addWidget(self.object_combo, 2, 0, 1, 2) + obj_grid.addWidget(self.object_combo, 2, 0, 1, 2) # separator_line = QtWidgets.QFrame() # separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) # separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - # grid0.addWidget(separator_line, 4, 0, 1, 2) + # obj_grid.addWidget(separator_line, 4, 0, 1, 2) # ############################################################################################################# # Tool Table Frame @@ -4171,13 +4171,13 @@ class NccUI: tt_frame = FCFrame() self.tools_box.addWidget(tt_frame) - # Grid Layout - grid1 = FCGridLayout(v_spacing=5, h_spacing=3) - tt_frame.setLayout(grid1) + tool_grid = FCGridLayout(v_spacing=5, h_spacing=3) + tt_frame.setLayout(tool_grid) + # Tools Table self.tools_table = FCTable(drag_drop=True) # self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - grid1.addWidget(self.tools_table, 2, 0, 1, 2) + tool_grid.addWidget(self.tools_table, 0, 0, 1, 2) self.tools_table.setColumnCount(4) # 3rd column is reserved (and hidden) for the tool ID @@ -4214,25 +4214,21 @@ class NccUI: "WARNING: using rest machining will automatically set the order\n" "in reverse and disable this control.")) - 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" - "'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' --> means 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.ncc_order_combo = RadioSet([{'label': _('No'), 'value': 'no'}, + # {'label': _('Forward'), 'value': 'fwd'}, + # {'label': _('Reverse'), 'value': 'rev'}]) + self.ncc_order_combo = FCComboBox2() + self.ncc_order_combo.addItems([_('Default'), _('Forward'), _('Reverse')]) - grid1.addWidget(self.ncc_order_label, 4, 0) - grid1.addWidget(self.ncc_order_radio, 4, 1) + tool_grid.addWidget(self.ncc_order_label, 4, 0) + tool_grid.addWidget(self.ncc_order_combo, 4, 1) # ############################################################################## # ###################### ADD A NEW TOOL ######################################## # ############################################################################## self.add_tool_frame = QtWidgets.QFrame() self.add_tool_frame.setContentsMargins(0, 0, 0, 0) - grid1.addWidget(self.add_tool_frame, 6, 0, 1, 2) + tool_grid.addWidget(self.add_tool_frame, 6, 0, 1, 2) new_tool_grid = FCGridLayout(v_spacing=5, h_spacing=3) new_tool_grid.setContentsMargins(0, 0, 0, 0) @@ -4241,13 +4237,13 @@ class NccUI: separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.Shape.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken) - new_tool_grid.addWidget(separator_line, 0, 0, 1, 2) + new_tool_grid.addWidget(separator_line, 0, 0, 1, 3) # ############################################################# # ############### Tool selection ############################## # ############################################################# self.tool_sel_label = FCLabel('%s' % _('Add from DB')) - new_tool_grid.addWidget(self.tool_sel_label, 2, 0, 1, 2) + new_tool_grid.addWidget(self.tool_sel_label, 2, 0, 1, 3) # ### Tool Diameter #### self.new_tooldia_lbl = FCLabel('%s:' % _('Tool Dia')) @@ -4256,14 +4252,16 @@ class NccUI: ) new_tool_grid.addWidget(self.new_tooldia_lbl, 4, 0) - new_tool_lay = QtWidgets.QHBoxLayout() + # nt_grid = FCGridLayout(v_spacing=5, h_spacing=3, c_stretch=[1, 0]) + # nt_grid.setContentsMargins(0, 0, 0, 0) + # new_tool_grid.addLayout(nt_grid, 4, 1) self.new_tooldia_entry = FCDoubleSpinner(callback=self.confirmation_message) self.new_tooldia_entry.set_precision(self.decimals) self.new_tooldia_entry.set_range(-10000.0000, 10000.0000) self.new_tooldia_entry.setObjectName(_("Tool Dia")) - new_tool_lay.addWidget(self.new_tooldia_entry) + new_tool_grid.addWidget(self.new_tooldia_entry, 4, 1) # Find Optimal Tooldia self.find_optimal_button = QtWidgets.QToolButton() @@ -4274,9 +4272,7 @@ class NccUI: _("Find a tool diameter that is guaranteed\n" "to do a complete isolation.") ) - new_tool_lay.addWidget(self.find_optimal_button) - - new_tool_grid.addLayout(new_tool_lay, 4, 1) + new_tool_grid.addWidget(self.find_optimal_button, 4, 2) # ############################################################################################################# # ################################ Button Grid ########################################################### @@ -4284,7 +4280,7 @@ class NccUI: button_grid = FCGridLayout(v_spacing=5, h_spacing=3) button_grid.setColumnStretch(0, 1) button_grid.setColumnStretch(1, 0) - new_tool_grid.addLayout(button_grid, 6, 0, 1, 2) + new_tool_grid.addLayout(button_grid, 6, 0, 1, 3) self.search_and_add_btn = FCButton(_('Search and Add')) self.search_and_add_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png')) @@ -4325,10 +4321,8 @@ class NccUI: self.tool_data_label = FCLabel( "%s: %s %d" % (_('Parameters for'), _("Tool"), int(1))) self.tool_data_label.setToolTip( - _( - "The data used for creating GCode.\n" - "Each tool store it's own set of such data." - ) + _("The data used for creating GCode.\n" + "Each tool store it's own set of such data.") ) self.tools_box.addWidget(self.tool_data_label) @@ -4595,9 +4589,10 @@ class NccUI: "- 'Area Selection' - left mouse click to start selection of the area to be processed.\n" "- 'Reference Object' - will process the area specified by another object.") ) - gen_grid.addWidget(self.select_label, 8, 0, ) + gen_grid.addWidget(self.select_label, 8, 0) gen_grid.addWidget(self.select_combo, 8, 1) + # Reference Type self.reference_combo_type_label = FCLabel('%s:' % _("Type")) self.reference_combo_type_label.setToolTip( _("The type of FlatCAM object to be used as non copper clearing reference.\n" @@ -4606,7 +4601,7 @@ class NccUI: self.reference_combo_type = FCComboBox2() self.reference_combo_type.addItems([_("Gerber"), _("Excellon"), _("Geometry")]) - gen_grid.addWidget(self.reference_combo_type_label, 10, 0, ) + gen_grid.addWidget(self.reference_combo_type_label, 10, 0) gen_grid.addWidget(self.reference_combo_type, 10, 1) self.reference_combo = FCComboBox() @@ -4645,6 +4640,8 @@ class NccUI: gen_grid.addWidget(self.valid_cb, 16, 0, 1, 2) + FCGridLayout.set_common_column_size([obj_grid, tool_grid, new_tool_grid, par_grid, gen_grid], 0) + # ############################################################################################################# # Generate NCC Geometry Button # ############################################################################################################# @@ -4744,9 +4741,9 @@ class NccUI: def on_rest_machining_check(self, state): if state: - self.ncc_order_radio.set_value('rev') + self.ncc_order_combo.set_value(2) # "Reverse" self.ncc_order_label.setDisabled(True) - self.ncc_order_radio.setDisabled(True) + self.ncc_order_combo.setDisabled(True) self.nccmarginlabel.hide() self.ncc_margin_entry.hide() @@ -4764,7 +4761,7 @@ class NccUI: else: self.ncc_order_label.setDisabled(False) - self.ncc_order_radio.setDisabled(False) + self.ncc_order_combo.setDisabled(False) self.nccmarginlabel.show() self.ncc_margin_entry.show() diff --git a/camlib.py b/camlib.py index 20259054..8b38bcc0 100644 --- a/camlib.py +++ b/camlib.py @@ -1071,7 +1071,10 @@ class Geometry(object): working_geo = self.solid_geometry try: - geo_len = len(working_geo) + if isinstance(working_geo, (MultiPolygon, MultiLineString)): + geo_len = len(working_geo.geoms) + else: + geo_len = len(working_geo) except TypeError: geo_len = 1 @@ -1079,7 +1082,11 @@ class Geometry(object): pol_nr = 0 # yet, it can be done by issuing an unary_union in the end, thus getting rid of the overlapping geo try: - for pol in working_geo: + if isinstance(working_geo, (MultiPolygon, MultiLineString)): + working_geo_shp = working_geo.geoms + else: + working_geo_shp = working_geo + for pol in working_geo_shp: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -1118,7 +1125,7 @@ class Geometry(object): # end of replaced block if iso_type == 2: - ret_geo = geo_iso + ret_geo = flatten_shapely_geometry(geo_iso) elif iso_type == 0: self.app.proc_container.update_view_text(' %s' % _("Get Exteriors")) ret_geo = self.get_exteriors(geo_iso) @@ -1573,8 +1580,8 @@ class Geometry(object): def get_pts(o): return [o.coords[0], o.coords[-1]] - geoms = FlatCAMRTreeStorage() - geoms.get_points = get_pts + geom_elems = FlatCAMRTreeStorage() + geom_elems.get_points = get_pts # Path margin path_margin = polygon_to_clear.buffer(-tooldia / 2, int(steps_per_circle)) @@ -1603,16 +1610,16 @@ class Geometry(object): if path.is_empty: break else: - # geoms.append(path) - # geoms.insert(path) + # geom_elems.append(path) + # geom_elems.insert(path) # path can be a collection of paths. try: for p in path: - geoms.insert(p) + geom_elems.insert(p) if prog_plot: self.plot_temp_shapes(p) except TypeError: - geoms.insert(path) + geom_elems.insert(path) if prog_plot: self.plot_temp_shapes(path) @@ -1631,10 +1638,10 @@ class Geometry(object): for x in buffered_poly: for y in x.interiors: # Over interiors of each polygon inner_edges.append(y) - # geoms += outer_edges + inner_edges + # geom_elems += outer_edges + inner_edges for g in outer_edges + inner_edges: if g and not g.is_empty: - geoms.insert(g) + geom_elems.insert(g) if prog_plot: self.plot_temp_shapes(g) @@ -1643,16 +1650,16 @@ class Geometry(object): # Optimization connect touching paths # log.debug("Connecting paths...") - # geoms = Geometry.path_connect(geoms) + # geom_elems = Geometry.path_connect(geom_elems) # Optimization: Reduce lifts if connect: # log.debug("Reducing tool lifts...") - geoms_conn = Geometry.paint_connect(geoms, polygon_to_clear, tooldia, steps_per_circle) + geoms_conn = Geometry.paint_connect(geom_elems, polygon_to_clear, tooldia, steps_per_circle) if geoms_conn: return geoms_conn - return geoms + return geom_elems def clear_polygon3(self, polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True, prog_plot=False): @@ -8578,6 +8585,8 @@ def dict2obj(d): def autolist(obj): try: + if isinstance(obj, (MultiPoint, MultiPolygon, MultiLineString)): + return obj.geoms __ = iter(obj) return obj except TypeError: diff --git a/defaults.py b/defaults.py index bd16c758..18dc3adf 100644 --- a/defaults.py +++ b/defaults.py @@ -351,7 +351,7 @@ class FlatCAMDefaults: # Isolation Routing Plugin "tools_iso_tooldia": "0.1", - "tools_iso_order": 'rev', + "tools_iso_order": 2, # Reverse "tools_iso_tool_cutz": -0.05, "tools_iso_newdia": 0.1, @@ -479,7 +479,7 @@ class FlatCAMDefaults: # NCC Plugin "tools_ncc_tools": "0.5", - "tools_ncc_order": 'rev', + "tools_ncc_order": 2, # "Reverse" "tools_ncc_operation": 'clear', "tools_ncc_overlap": 40, "tools_ncc_margin": 1.0,