فهرست منبع

- remade the EDIT -> PREFERENCES window, the Excellon and Gerber sections. Created a new section named TOOLS

Marius Stanciu 7 سال پیش
والد
کامیت
ad69be0456
5فایلهای تغییر یافته به همراه382 افزوده شده و 282 حذف شده
  1. 139 109
      FlatCAMApp.py
  2. 212 152
      FlatCAMGUI.py
  3. 2 0
      README.md
  4. 10 2
      flatcamTools/ToolCutout.py
  5. 19 19
      flatcamTools/ToolNonCopperClear.py

+ 139 - 109
FlatCAMApp.py

@@ -288,6 +288,7 @@ class App(QtCore.QObject):
         self.excellon_defaults_form = ExcellonPreferencesUI()
         self.excellon_defaults_form = ExcellonPreferencesUI()
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
+        self.tools_defaults_form = ToolsPreferencesUI()
 
 
         # when adding entries here read the comments in the  method found bellow named:
         # when adding entries here read the comments in the  method found bellow named:
         # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
         # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
@@ -318,50 +319,41 @@ class App(QtCore.QObject):
             "gerber_isotooldia": self.gerber_defaults_form.gerber_group.iso_tool_dia_entry,
             "gerber_isotooldia": self.gerber_defaults_form.gerber_group.iso_tool_dia_entry,
             "gerber_isopasses": self.gerber_defaults_form.gerber_group.iso_width_entry,
             "gerber_isopasses": self.gerber_defaults_form.gerber_group.iso_width_entry,
             "gerber_isooverlap": self.gerber_defaults_form.gerber_group.iso_overlap_entry,
             "gerber_isooverlap": self.gerber_defaults_form.gerber_group.iso_overlap_entry,
-            "gerber_ncctools": self.gerber_defaults_form.gerber_group.ncc_tool_dia_entry,
-            "gerber_nccoverlap": self.gerber_defaults_form.gerber_group.ncc_overlap_entry,
-            "gerber_nccmargin": self.gerber_defaults_form.gerber_group.ncc_margin_entry,
-            "gerber_nccmethod": self.gerber_defaults_form.gerber_group.ncc_method_radio,
-            "gerber_nccconnect": self.gerber_defaults_form.gerber_group.ncc_connect_cb,
-            "gerber_ncccontour": self.gerber_defaults_form.gerber_group.ncc_contour_cb,
-            "gerber_nccrest": self.gerber_defaults_form.gerber_group.ncc_rest_cb,
 
 
             "gerber_combine_passes": self.gerber_defaults_form.gerber_group.combine_passes_cb,
             "gerber_combine_passes": self.gerber_defaults_form.gerber_group.combine_passes_cb,
             "gerber_milling_type": self.gerber_defaults_form.gerber_group.milling_type_radio,
             "gerber_milling_type": self.gerber_defaults_form.gerber_group.milling_type_radio,
-            "gerber_cutouttooldia": self.gerber_defaults_form.gerber_group.cutout_tooldia_entry,
-            "gerber_cutoutmargin": self.gerber_defaults_form.gerber_group.cutout_margin_entry,
-            "gerber_cutoutgapsize": self.gerber_defaults_form.gerber_group.cutout_gap_entry,
-            "gerber_gaps": self.gerber_defaults_form.gerber_group.gaps_radio,
             "gerber_noncoppermargin": self.gerber_defaults_form.gerber_group.noncopper_margin_entry,
             "gerber_noncoppermargin": self.gerber_defaults_form.gerber_group.noncopper_margin_entry,
             "gerber_noncopperrounded": self.gerber_defaults_form.gerber_group.noncopper_rounded_cb,
             "gerber_noncopperrounded": self.gerber_defaults_form.gerber_group.noncopper_rounded_cb,
             "gerber_bboxmargin": self.gerber_defaults_form.gerber_group.bbmargin_entry,
             "gerber_bboxmargin": self.gerber_defaults_form.gerber_group.bbmargin_entry,
             "gerber_bboxrounded": self.gerber_defaults_form.gerber_group.bbrounded_cb,
             "gerber_bboxrounded": self.gerber_defaults_form.gerber_group.bbrounded_cb,
             "gerber_circle_steps": self.gerber_defaults_form.gerber_group.circle_steps_entry,
             "gerber_circle_steps": self.gerber_defaults_form.gerber_group.circle_steps_entry,
-            "excellon_plot": self.excellon_defaults_form.excellon_group.plot_cb,
-            "excellon_solid": self.excellon_defaults_form.excellon_group.solid_cb,
-            "excellon_drillz": self.excellon_defaults_form.excellon_group.cutz_entry,
-            "excellon_travelz": self.excellon_defaults_form.excellon_group.travelz_entry,
-            "excellon_feedrate": self.excellon_defaults_form.excellon_group.feedrate_entry,
-            "excellon_feedrate_rapid": self.excellon_defaults_form.excellon_group.feedrate_rapid_entry,
-            "excellon_spindlespeed": self.excellon_defaults_form.excellon_group.spindlespeed_entry,
-            "excellon_dwell": self.excellon_defaults_form.excellon_group.dwell_cb,
-            "excellon_dwelltime": self.excellon_defaults_form.excellon_group.dwelltime_entry,
-            "excellon_toolchange": self.excellon_defaults_form.excellon_group.toolchange_cb,
-            "excellon_toolchangez": self.excellon_defaults_form.excellon_group.toolchangez_entry,
-            "excellon_toolchangexy": self.excellon_defaults_form.excellon_group.toolchangexy_entry,
-            "excellon_ppname_e": self.excellon_defaults_form.excellon_group.pp_excellon_name_cb,
-            "excellon_startz": self.excellon_defaults_form.excellon_group.estartz_entry,
-            "excellon_endz": self.excellon_defaults_form.excellon_group.eendz_entry,
-            "excellon_tooldia": self.excellon_defaults_form.excellon_group.tooldia_entry,
-            "excellon_slot_tooldia": self.excellon_defaults_form.excellon_group.slot_tooldia_entry,
-            "excellon_format_upper_in": self.excellon_defaults_form.excellon_group.excellon_format_upper_in_entry,
-            "excellon_format_lower_in": self.excellon_defaults_form.excellon_group.excellon_format_lower_in_entry,
-            "excellon_format_upper_mm": self.excellon_defaults_form.excellon_group.excellon_format_upper_mm_entry,
-            "excellon_format_lower_mm": self.excellon_defaults_form.excellon_group.excellon_format_lower_mm_entry,
-            "excellon_zeros": self.excellon_defaults_form.excellon_group.excellon_zeros_radio,
-            "excellon_units": self.excellon_defaults_form.excellon_group.excellon_units_radio,
-            "excellon_optimization_type": self.excellon_defaults_form.excellon_group.excellon_optimization_radio,
-            "excellon_gcode_type": self.excellon_defaults_form.excellon_group.excellon_gcode_type_radio,
+
+            "excellon_plot": self.excellon_defaults_form.excellon_gen_group.plot_cb,
+            "excellon_solid": self.excellon_defaults_form.excellon_gen_group.solid_cb,
+            "excellon_format_upper_in": self.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry,
+            "excellon_format_lower_in": self.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry,
+            "excellon_format_upper_mm": self.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry,
+            "excellon_format_lower_mm": self.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry,
+            "excellon_zeros": self.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio,
+            "excellon_units": self.excellon_defaults_form.excellon_gen_group.excellon_units_radio,
+            "excellon_optimization_type": self.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio,
+
+            "excellon_drillz": self.excellon_defaults_form.excellon_opt_group.cutz_entry,
+            "excellon_travelz": self.excellon_defaults_form.excellon_opt_group.travelz_entry,
+            "excellon_feedrate": self.excellon_defaults_form.excellon_opt_group.feedrate_entry,
+            "excellon_feedrate_rapid": self.excellon_defaults_form.excellon_opt_group.feedrate_rapid_entry,
+            "excellon_spindlespeed": self.excellon_defaults_form.excellon_opt_group.spindlespeed_entry,
+            "excellon_dwell": self.excellon_defaults_form.excellon_opt_group.dwell_cb,
+            "excellon_dwelltime": self.excellon_defaults_form.excellon_opt_group.dwelltime_entry,
+            "excellon_toolchange": self.excellon_defaults_form.excellon_opt_group.toolchange_cb,
+            "excellon_toolchangez": self.excellon_defaults_form.excellon_opt_group.toolchangez_entry,
+            "excellon_toolchangexy": self.excellon_defaults_form.excellon_opt_group.toolchangexy_entry,
+            "excellon_ppname_e": self.excellon_defaults_form.excellon_opt_group.pp_excellon_name_cb,
+            "excellon_startz": self.excellon_defaults_form.excellon_opt_group.estartz_entry,
+            "excellon_endz": self.excellon_defaults_form.excellon_opt_group.eendz_entry,
+            "excellon_tooldia": self.excellon_defaults_form.excellon_opt_group.tooldia_entry,
+            "excellon_slot_tooldia": self.excellon_defaults_form.excellon_opt_group.slot_tooldia_entry,
+            "excellon_gcode_type": self.excellon_defaults_form.excellon_opt_group.excellon_gcode_type_radio,
             "geometry_plot": self.geometry_defaults_form.geometry_group.plot_cb,
             "geometry_plot": self.geometry_defaults_form.geometry_group.plot_cb,
             "geometry_segx": self.geometry_defaults_form.geometry_group.segx_entry,
             "geometry_segx": self.geometry_defaults_form.geometry_group.segx_entry,
             "geometry_segy": self.geometry_defaults_form.geometry_group.segy_entry,
             "geometry_segy": self.geometry_defaults_form.geometry_group.segy_entry,
@@ -397,7 +389,20 @@ class App(QtCore.QObject):
             "cncjob_fr_decimals": self.cncjob_defaults_form.cncjob_group.fr_dec_entry,
             "cncjob_fr_decimals": self.cncjob_defaults_form.cncjob_group.fr_dec_entry,
             "cncjob_prepend": self.cncjob_defaults_form.cncjob_group.prepend_text,
             "cncjob_prepend": self.cncjob_defaults_form.cncjob_group.prepend_text,
             "cncjob_append": self.cncjob_defaults_form.cncjob_group.append_text,
             "cncjob_append": self.cncjob_defaults_form.cncjob_group.append_text,
-            "cncjob_steps_per_circle": self.cncjob_defaults_form.cncjob_group.steps_per_circle_entry
+            "cncjob_steps_per_circle": self.cncjob_defaults_form.cncjob_group.steps_per_circle_entry,
+
+            "tools_ncctools": self.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry,
+            "tools_nccoverlap": self.tools_defaults_form.tools_ncc_group.ncc_overlap_entry,
+            "tools_nccmargin": self.tools_defaults_form.tools_ncc_group.ncc_margin_entry,
+            "tools_nccmethod": self.tools_defaults_form.tools_ncc_group.ncc_method_radio,
+            "tools_nccconnect": self.tools_defaults_form.tools_ncc_group.ncc_connect_cb,
+            "tools_ncccontour": self.tools_defaults_form.tools_ncc_group.ncc_contour_cb,
+            "tools_nccrest": self.tools_defaults_form.tools_ncc_group.ncc_rest_cb,
+
+            "tools_cutouttooldia": self.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
+            "tools_cutoutmargin": self.tools_defaults_form.tools_cutout_group.cutout_margin_entry,
+            "tools_cutoutgapsize": self.tools_defaults_form.tools_cutout_group.cutout_gap_entry,
+            "tools_gaps_rect": self.tools_defaults_form.tools_cutout_group.gaps_radio
         }
         }
         # loads postprocessors
         # loads postprocessors
         self.postprocessors = load_postprocessors(self)
         self.postprocessors = load_postprocessors(self)
@@ -407,7 +412,7 @@ class App(QtCore.QObject):
             # HPGL postprocessor is only for Geometry objects therefore it should not be in the Excellon Preferences
             # HPGL postprocessor is only for Geometry objects therefore it should not be in the Excellon Preferences
             if name == 'hpgl':
             if name == 'hpgl':
                 continue
                 continue
-            self.excellon_defaults_form.excellon_group.pp_excellon_name_cb.addItem(name)
+            self.excellon_defaults_form.excellon_opt_group.pp_excellon_name_cb.addItem(name)
 
 
         self.defaults = LoudDict()
         self.defaults = LoudDict()
         self.defaults.set_change_callback(self.on_defaults_dict_change)  # When the dictionary changes.
         self.defaults.set_change_callback(self.on_defaults_dict_change)  # When the dictionary changes.
@@ -440,20 +445,9 @@ class App(QtCore.QObject):
             "gerber_isotooldia": 0.016,
             "gerber_isotooldia": 0.016,
             "gerber_isopasses": 1,
             "gerber_isopasses": 1,
             "gerber_isooverlap": 0.15,
             "gerber_isooverlap": 0.15,
-            "gerber_ncctools": "1.0, 0.5",
-            "gerber_nccoverlap": 0.4,
-            "gerber_nccmargin": 1,
-            "gerber_nccmethod": "seed",
-            "gerber_nccconnect": True,
-            "gerber_ncccontour": True,
-            "gerber_nccrest": False,
 
 
             "gerber_combine_passes": False,
             "gerber_combine_passes": False,
             "gerber_milling_type": "cl",
             "gerber_milling_type": "cl",
-            "gerber_cutouttooldia": 0.07,
-            "gerber_cutoutmargin": 0.1,
-            "gerber_cutoutgapsize": 0.15,
-            "gerber_gaps": "4",
             "gerber_noncoppermargin": 0.0,
             "gerber_noncoppermargin": 0.0,
             "gerber_noncopperrounded": False,
             "gerber_noncopperrounded": False,
             "gerber_bboxmargin": 0.0,
             "gerber_bboxmargin": 0.0,
@@ -462,6 +456,15 @@ class App(QtCore.QObject):
 
 
             "excellon_plot": True,
             "excellon_plot": True,
             "excellon_solid": False,
             "excellon_solid": False,
+            "excellon_format_upper_in": 2,
+            "excellon_format_lower_in": 4,
+            "excellon_format_upper_mm": 3,
+            "excellon_format_lower_mm": 3,
+            "excellon_zeros": "L",
+            "excellon_units": "INCH",
+            "excellon_optimization_type": 'B',
+            "excellon_search_time": 3,
+
             "excellon_drillz": -0.1,
             "excellon_drillz": -0.1,
             "excellon_travelz": 0.1,
             "excellon_travelz": 0.1,
             "excellon_feedrate": 3.0,
             "excellon_feedrate": 3.0,
@@ -477,14 +480,6 @@ class App(QtCore.QObject):
             "excellon_startz": None,
             "excellon_startz": None,
             "excellon_endz": 2.0,
             "excellon_endz": 2.0,
             "excellon_ppname_e": 'default',
             "excellon_ppname_e": 'default',
-            "excellon_format_upper_in": 2,
-            "excellon_format_lower_in": 4,
-            "excellon_format_upper_mm": 3,
-            "excellon_format_lower_mm": 3,
-            "excellon_zeros": "L",
-            "excellon_units": "INCH",
-            "excellon_optimization_type": 'B',
-            "excellon_search_time": 3,
             "excellon_gcode_type": "drills",
             "excellon_gcode_type": "drills",
 
 
             "geometry_plot": True,
             "geometry_plot": True,
@@ -524,6 +519,19 @@ class App(QtCore.QObject):
             "cncjob_prepend": "",
             "cncjob_prepend": "",
             "cncjob_append": "",
             "cncjob_append": "",
             "cncjob_steps_per_circle": 64,
             "cncjob_steps_per_circle": 64,
+
+            "tools_ncctools": "1.0, 0.5",
+            "tools_nccoverlap": 0.4,
+            "tools_nccmargin": 1,
+            "tools_nccmethod": "seed",
+            "tools_nccconnect": True,
+            "tools_ncccontour": True,
+            "tools_nccrest": False,
+            "tools_cutouttooldia": 0.07,
+            "tools_cutoutmargin": 0.1,
+            "tools_cutoutgapsize": 0.15,
+            "tools_gaps_rect": "4",
+
             "global_background_timeout": 300000,  # Default value is 5 minutes
             "global_background_timeout": 300000,  # Default value is 5 minutes
             "global_verbose_error_level": 0,  # Shell verbosity 0 = default
             "global_verbose_error_level": 0,  # Shell verbosity 0 = default
                                        # (python trace only for unknown errors),
                                        # (python trace only for unknown errors),
@@ -585,6 +593,7 @@ class App(QtCore.QObject):
         self.excellon_options_form = ExcellonPreferencesUI()
         self.excellon_options_form = ExcellonPreferencesUI()
         self.geometry_options_form = GeometryPreferencesUI()
         self.geometry_options_form = GeometryPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
+        self.tools_options_form = ToolsPreferencesUI()
 
 
         self.options_form_fields = {
         self.options_form_fields = {
             "units": self.general_options_form.general_app_group.units_radio,
             "units": self.general_options_form.general_app_group.units_radio,
@@ -596,41 +605,37 @@ class App(QtCore.QObject):
             "gerber_isotooldia": self.gerber_options_form.gerber_group.iso_tool_dia_entry,
             "gerber_isotooldia": self.gerber_options_form.gerber_group.iso_tool_dia_entry,
             "gerber_isopasses": self.gerber_options_form.gerber_group.iso_width_entry,
             "gerber_isopasses": self.gerber_options_form.gerber_group.iso_width_entry,
             "gerber_isooverlap": self.gerber_options_form.gerber_group.iso_overlap_entry,
             "gerber_isooverlap": self.gerber_options_form.gerber_group.iso_overlap_entry,
-            "gerber_ncctools": self.gerber_options_form.gerber_group.ncc_tool_dia_entry,
-            "gerber_nccoverlap": self.gerber_options_form.gerber_group.ncc_overlap_entry,
-            "gerber_nccmargin": self.gerber_options_form.gerber_group.ncc_margin_entry,
             "gerber_combine_passes": self.gerber_options_form.gerber_group.combine_passes_cb,
             "gerber_combine_passes": self.gerber_options_form.gerber_group.combine_passes_cb,
-            "gerber_cutouttooldia": self.gerber_options_form.gerber_group.cutout_tooldia_entry,
-            "gerber_cutoutmargin": self.gerber_options_form.gerber_group.cutout_margin_entry,
-            "gerber_cutoutgapsize": self.gerber_options_form.gerber_group.cutout_gap_entry,
-            "gerber_gaps": self.gerber_options_form.gerber_group.gaps_radio,
             "gerber_noncoppermargin": self.gerber_options_form.gerber_group.noncopper_margin_entry,
             "gerber_noncoppermargin": self.gerber_options_form.gerber_group.noncopper_margin_entry,
             "gerber_noncopperrounded": self.gerber_options_form.gerber_group.noncopper_rounded_cb,
             "gerber_noncopperrounded": self.gerber_options_form.gerber_group.noncopper_rounded_cb,
             "gerber_bboxmargin": self.gerber_options_form.gerber_group.bbmargin_entry,
             "gerber_bboxmargin": self.gerber_options_form.gerber_group.bbmargin_entry,
             "gerber_bboxrounded": self.gerber_options_form.gerber_group.bbrounded_cb,
             "gerber_bboxrounded": self.gerber_options_form.gerber_group.bbrounded_cb,
-            "excellon_plot": self.excellon_options_form.excellon_group.plot_cb,
-            "excellon_solid": self.excellon_options_form.excellon_group.solid_cb,
-            "excellon_drillz": self.excellon_options_form.excellon_group.cutz_entry,
-            "excellon_travelz": self.excellon_options_form.excellon_group.travelz_entry,
-            "excellon_feedrate": self.excellon_options_form.excellon_group.feedrate_entry,
-            "excellon_feedrate_rapid": self.excellon_options_form.excellon_group.feedrate_rapid_entry,
-            "excellon_spindlespeed": self.excellon_options_form.excellon_group.spindlespeed_entry,
-            "excellon_dwell": self.excellon_options_form.excellon_group.dwell_cb,
-            "excellon_dwelltime": self.excellon_options_form.excellon_group.dwelltime_entry,
-            "excellon_toolchange": self.excellon_options_form.excellon_group.toolchange_cb,
-            "excellon_toolchangez": self.excellon_options_form.excellon_group.toolchangez_entry,
-            "excellon_toolchangexy": self.excellon_options_form.excellon_group.toolchangexy_entry,
-            "excellon_tooldia": self.excellon_options_form.excellon_group.tooldia_entry,
-            "excellon_ppname_e": self.excellon_options_form.excellon_group.pp_excellon_name_cb,
-            "excellon_startz": self.excellon_options_form.excellon_group.estartz_entry,
-            "excellon_endz": self.excellon_options_form.excellon_group.eendz_entry,
-            "excellon_format_upper_in": self.excellon_options_form.excellon_group.excellon_format_upper_in_entry,
-            "excellon_format_lower_in": self.excellon_options_form.excellon_group.excellon_format_lower_in_entry,
-            "excellon_format_upper_mm": self.excellon_options_form.excellon_group.excellon_format_upper_mm_entry,
-            "excellon_format_lower_mm": self.excellon_options_form.excellon_group.excellon_format_lower_mm_entry,
-            "excellon_zeros": self.excellon_options_form.excellon_group.excellon_zeros_radio,
-            "excellon_units": self.excellon_options_form.excellon_group.excellon_units_radio,
-            "excellon_optimization_type": self.excellon_options_form.excellon_group.excellon_optimization_radio,
+
+            "excellon_plot": self.excellon_options_form.excellon_gen_group.plot_cb,
+            "excellon_solid": self.excellon_options_form.excellon_gen_group.solid_cb,
+            "excellon_format_upper_in": self.excellon_options_form.excellon_gen_group.excellon_format_upper_in_entry,
+            "excellon_format_lower_in": self.excellon_options_form.excellon_gen_group.excellon_format_lower_in_entry,
+            "excellon_format_upper_mm": self.excellon_options_form.excellon_gen_group.excellon_format_upper_mm_entry,
+            "excellon_format_lower_mm": self.excellon_options_form.excellon_gen_group.excellon_format_lower_mm_entry,
+            "excellon_zeros": self.excellon_options_form.excellon_gen_group.excellon_zeros_radio,
+            "excellon_units": self.excellon_options_form.excellon_gen_group.excellon_units_radio,
+            "excellon_optimization_type": self.excellon_options_form.excellon_gen_group.excellon_optimization_radio,
+
+            "excellon_drillz": self.excellon_options_form.excellon_opt_group.cutz_entry,
+            "excellon_travelz": self.excellon_options_form.excellon_opt_group.travelz_entry,
+            "excellon_feedrate": self.excellon_options_form.excellon_opt_group.feedrate_entry,
+            "excellon_feedrate_rapid": self.excellon_options_form.excellon_opt_group.feedrate_rapid_entry,
+            "excellon_spindlespeed": self.excellon_options_form.excellon_opt_group.spindlespeed_entry,
+            "excellon_dwell": self.excellon_options_form.excellon_opt_group.dwell_cb,
+            "excellon_dwelltime": self.excellon_options_form.excellon_opt_group.dwelltime_entry,
+            "excellon_toolchange": self.excellon_options_form.excellon_opt_group.toolchange_cb,
+            "excellon_toolchangez": self.excellon_options_form.excellon_opt_group.toolchangez_entry,
+            "excellon_toolchangexy": self.excellon_options_form.excellon_opt_group.toolchangexy_entry,
+            "excellon_tooldia": self.excellon_options_form.excellon_opt_group.tooldia_entry,
+            "excellon_ppname_e": self.excellon_options_form.excellon_opt_group.pp_excellon_name_cb,
+            "excellon_startz": self.excellon_options_form.excellon_opt_group.estartz_entry,
+            "excellon_endz": self.excellon_options_form.excellon_opt_group.eendz_entry,
+
             "geometry_plot": self.geometry_options_form.geometry_group.plot_cb,
             "geometry_plot": self.geometry_options_form.geometry_group.plot_cb,
             "geometry_segx": self.geometry_options_form.geometry_group.segx_entry,
             "geometry_segx": self.geometry_options_form.geometry_group.segx_entry,
             "geometry_segy": self.geometry_options_form.geometry_group.segy_entry,
             "geometry_segy": self.geometry_options_form.geometry_group.segy_entry,
@@ -656,15 +661,25 @@ class App(QtCore.QObject):
             "geometry_depthperpass": self.geometry_options_form.geometry_group.depthperpass_entry,
             "geometry_depthperpass": self.geometry_options_form.geometry_group.depthperpass_entry,
             "geometry_multidepth": self.geometry_options_form.geometry_group.multidepth_cb,
             "geometry_multidepth": self.geometry_options_form.geometry_group.multidepth_cb,
             "geometry_extracut": self.geometry_options_form.geometry_group.extracut_cb,
             "geometry_extracut": self.geometry_options_form.geometry_group.extracut_cb,
+
             "cncjob_plot": self.cncjob_options_form.cncjob_group.plot_cb,
             "cncjob_plot": self.cncjob_options_form.cncjob_group.plot_cb,
             "cncjob_tooldia": self.cncjob_options_form.cncjob_group.tooldia_entry,
             "cncjob_tooldia": self.cncjob_options_form.cncjob_group.tooldia_entry,
             "cncjob_prepend": self.cncjob_options_form.cncjob_group.prepend_text,
             "cncjob_prepend": self.cncjob_options_form.cncjob_group.prepend_text,
-            "cncjob_append": self.cncjob_options_form.cncjob_group.append_text
+            "cncjob_append": self.cncjob_options_form.cncjob_group.append_text,
+
+            "tools_ncctools": self.tools_options_form.tools_ncc_group.ncc_tool_dia_entry,
+            "tools_nccoverlap": self.tools_options_form.tools_ncc_group.ncc_overlap_entry,
+            "tools_nccmargin": self.tools_options_form.tools_ncc_group.ncc_margin_entry,
+
+            "tools_cutouttooldia": self.tools_options_form.tools_cutout_group.cutout_tooldia_entry,
+            "tools_cutoutmargin": self.tools_options_form.tools_cutout_group.cutout_margin_entry,
+            "tools_cutoutgapsize": self.tools_options_form.tools_cutout_group.cutout_gap_entry,
+            "tools_gaps": self.tools_options_form.tools_cutout_group.gaps_radio,
         }
         }
 
 
         for name in list(self.postprocessors.keys()):
         for name in list(self.postprocessors.keys()):
             self.geometry_options_form.geometry_group.pp_geometry_name_cb.addItem(name)
             self.geometry_options_form.geometry_group.pp_geometry_name_cb.addItem(name)
-            self.excellon_options_form.excellon_group.pp_excellon_name_cb.addItem(name)
+            self.excellon_options_form.excellon_opt_group.pp_excellon_name_cb.addItem(name)
 
 
         self.options = LoudDict()
         self.options = LoudDict()
         self.options.set_change_callback(self.on_options_dict_change)
         self.options.set_change_callback(self.on_options_dict_change)
@@ -678,20 +693,22 @@ class App(QtCore.QObject):
             "gerber_isotooldia": 0.016,
             "gerber_isotooldia": 0.016,
             "gerber_isopasses": 1,
             "gerber_isopasses": 1,
             "gerber_isooverlap": 0.15,
             "gerber_isooverlap": 0.15,
-            "gerber_ncctools": "1.0, 0.5",
-            "gerber_nccoverlap": 0.4,
-            "gerber_nccmargin": 1,
             "gerber_combine_passes": True,
             "gerber_combine_passes": True,
-            "gerber_cutouttooldia": 0.07,
-            "gerber_cutoutmargin": 0.1,
-            "gerber_cutoutgapsize": 0.15,
-            "gerber_gaps": "4",
             "gerber_noncoppermargin": 0.0,
             "gerber_noncoppermargin": 0.0,
             "gerber_noncopperrounded": False,
             "gerber_noncopperrounded": False,
             "gerber_bboxmargin": 0.0,
             "gerber_bboxmargin": 0.0,
             "gerber_bboxrounded": False,
             "gerber_bboxrounded": False,
             "excellon_plot": True,
             "excellon_plot": True,
             "excellon_solid": False,
             "excellon_solid": False,
+            "excellon_format_upper_in": 2,
+            "excellon_format_lower_in": 4,
+            "excellon_format_upper_mm": 3,
+            "excellon_format_lower_mm": 3,
+            "excellon_units": 'INCH',
+            "excellon_optimization_type": 'B',
+            "excellon_search_time": 3,
+            "excellon_zeros": "L",
+
             "excellon_drillz": -0.1,
             "excellon_drillz": -0.1,
             "excellon_travelz": 0.1,
             "excellon_travelz": 0.1,
             "excellon_feedrate": 3.0,
             "excellon_feedrate": 3.0,
@@ -704,16 +721,9 @@ class App(QtCore.QObject):
             "excellon_toolchangexy": "0.0, 0.0",
             "excellon_toolchangexy": "0.0, 0.0",
             "excellon_tooldia": 0.016,
             "excellon_tooldia": 0.016,
             "excellon_ppname_e": 'default',
             "excellon_ppname_e": 'default',
-            "excellon_format_upper_in": 2,
-            "excellon_format_lower_in": 4,
-            "excellon_format_upper_mm": 3,
-            "excellon_format_lower_mm": 3,
-            "excellon_units": 'INCH',
-            "excellon_optimization_type": 'B',
-            "excellon_search_time": 3,
             "excellon_startz": None,
             "excellon_startz": None,
             "excellon_endz": 2.0,
             "excellon_endz": 2.0,
-            "excellon_zeros": "L",
+
             "geometry_plot": True,
             "geometry_plot": True,
             "geometry_segx": 0.0,
             "geometry_segx": 0.0,
             "geometry_segy": 0.0,
             "geometry_segy": 0.0,
@@ -739,10 +749,20 @@ class App(QtCore.QObject):
             "geometry_depthperpass": 0.002,
             "geometry_depthperpass": 0.002,
             "geometry_multidepth": False,
             "geometry_multidepth": False,
             "geometry_extracut": False,
             "geometry_extracut": False,
+
             "cncjob_plot": True,
             "cncjob_plot": True,
             "cncjob_tooldia": 0.016,
             "cncjob_tooldia": 0.016,
             "cncjob_prepend": "",
             "cncjob_prepend": "",
             "cncjob_append": "",
             "cncjob_append": "",
+
+            "tools_ncctools": "1.0, 0.5",
+            "tools_nccoverlap": 0.4,
+            "tools_nccmargin": 1,
+            "tools_cutouttooldia": 0.07,
+            "tools_cutoutmargin": 0.1,
+            "tools_cutoutgapsize": 0.15,
+            "tools_gaps": "4",
+
             "global_background_timeout": 300000,  # Default value is 5 minutes
             "global_background_timeout": 300000,  # Default value is 5 minutes
             "global_verbose_error_level": 0,  # Shell verbosity:
             "global_verbose_error_level": 0,  # Shell verbosity:
                                        # 0 = default(python trace only for unknown errors),
                                        # 0 = default(python trace only for unknown errors),
@@ -756,6 +776,7 @@ class App(QtCore.QObject):
         self.exc_form = None
         self.exc_form = None
         self.geo_form = None
         self.geo_form = None
         self.cnc_form = None
         self.cnc_form = None
+        self.tools_form = None
         self.on_options_combo_change(0)  # Will show the initial form
         self.on_options_combo_change(0)  # Will show the initial form
 
 
         ### Define OBJECT COLLECTION ###
         ### Define OBJECT COLLECTION ###
@@ -1091,11 +1112,11 @@ class App(QtCore.QObject):
         self.general_defaults_form.general_app_group.shell_startup_cb.clicked.connect(self.on_toggle_shell)
         self.general_defaults_form.general_app_group.shell_startup_cb.clicked.connect(self.on_toggle_shell)
 
 
         # Load the defaults values into the Excellon Format and Excellon Zeros fields
         # Load the defaults values into the Excellon Format and Excellon Zeros fields
-        self.excellon_defaults_form.excellon_group.excellon_defaults_button.clicked.connect(
+        self.excellon_defaults_form.excellon_opt_group.excellon_defaults_button.clicked.connect(
             self.on_excellon_defaults_button)
             self.on_excellon_defaults_button)
 
 
         # Load the defaults values into the Excellon Format and Excellon Zeros fields
         # Load the defaults values into the Excellon Format and Excellon Zeros fields
-        self.excellon_options_form.excellon_group.excellon_defaults_button.clicked.connect(
+        self.excellon_options_form.excellon_opt_group.excellon_defaults_button.clicked.connect(
             self.on_excellon_options_button)
             self.on_excellon_options_button)
 
 
         # this is a flag to signal to other tools that the ui tooltab is locked and not accessible
         # this is a flag to signal to other tools that the ui tooltab is locked and not accessible
@@ -2540,9 +2561,9 @@ class App(QtCore.QObject):
             return
             return
 
 
         # Options to scale
         # Options to scale
-        dimensions = ['gerber_isotooldia', 'gerber_cutoutmargin', 'gerber_cutoutgapsize',
-                      'gerber_noncoppermargin', 'gerber_bboxmargin','gerber_isooverlap','gerber_nccoverlap',
-                      'gerber_nccmargin','gerber_cutouttooldia','gerber_cutoutgapsize','gerber_cutoutmargin',
+        dimensions = ['gerber_isotooldia', 'tools_cutoutmargin', 'tools_cutoutgapsize',
+                      'gerber_noncoppermargin', 'gerber_bboxmargin','gerber_isooverlap','tools_nccoverlap',
+                      'tools_nccmargin','tools_cutouttooldia','tools_cutoutgapsize',
                       'gerber_noncoppermargin','gerber_bboxmargin',
                       'gerber_noncoppermargin','gerber_bboxmargin',
                       'excellon_drillz', "excellon_toolchangexy",
                       'excellon_drillz', "excellon_toolchangexy",
                       'excellon_travelz', 'excellon_feedrate', 'excellon_feedrate_rapid', 'excellon_toolchangez',
                       'excellon_travelz', 'excellon_feedrate', 'excellon_feedrate_rapid', 'excellon_toolchangez',
@@ -2675,12 +2696,14 @@ class App(QtCore.QObject):
             self.exc_form = self.excellon_defaults_form
             self.exc_form = self.excellon_defaults_form
             self.geo_form = self.geometry_defaults_form
             self.geo_form = self.geometry_defaults_form
             self.cnc_form = self.cncjob_defaults_form
             self.cnc_form = self.cncjob_defaults_form
+            self.tools_form = self.tools_defaults_form
         elif sel == 1:
         elif sel == 1:
             self.gen_form = self.general_options_form
             self.gen_form = self.general_options_form
             self.ger_form = self.gerber_options_form
             self.ger_form = self.gerber_options_form
             self.exc_form = self.excellon_options_form
             self.exc_form = self.excellon_options_form
             self.geo_form = self.geometry_options_form
             self.geo_form = self.geometry_options_form
             self.cnc_form = self.cncjob_options_form
             self.cnc_form = self.cncjob_options_form
+            self.tools_form = self.tools_options_form
         else:
         else:
             return
             return
 
 
@@ -2719,6 +2742,13 @@ class App(QtCore.QObject):
         self.ui.cncjob_scroll_area.setWidget(self.cnc_form)
         self.ui.cncjob_scroll_area.setWidget(self.cnc_form)
         self.cnc_form.show()
         self.cnc_form.show()
 
 
+        try:
+            self.ui.tools_scroll_area.takeWidget()
+        except:
+            self.log.debug("Nothing to remove")
+        self.ui.tools_scroll_area.setWidget(self.tools_form)
+        self.tools_form.show()
+
         self.log.debug("Finished GUI form initialization.")
         self.log.debug("Finished GUI form initialization.")
 
 
         # self.options2form()
         # self.options2form()

+ 212 - 152
FlatCAMGUI.py

@@ -604,6 +604,15 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.cncjob_scroll_area = VerticalScrollArea()
         self.cncjob_scroll_area = VerticalScrollArea()
         self.cncjob_tab_lay.addWidget(self.cncjob_scroll_area)
         self.cncjob_tab_lay.addWidget(self.cncjob_scroll_area)
 
 
+        self.tools_tab = QtWidgets.QWidget()
+        self.pref_tab_area.addTab(self.tools_tab, "TOOLS")
+        self.tools_tab_lay = QtWidgets.QVBoxLayout()
+        self.tools_tab_lay.setContentsMargins(2, 2, 2, 2)
+        self.tools_tab.setLayout(self.tools_tab_lay)
+
+        self.tools_scroll_area = VerticalScrollArea()
+        self.tools_tab_lay.addWidget(self.tools_scroll_area)
+
         self.pref_tab_bottom_layout = QtWidgets.QHBoxLayout()
         self.pref_tab_bottom_layout = QtWidgets.QHBoxLayout()
         self.pref_tab_bottom_layout.setAlignment(QtCore.Qt.AlignVCenter)
         self.pref_tab_bottom_layout.setAlignment(QtCore.Qt.AlignVCenter)
         self.pref_tab_layout.addLayout(self.pref_tab_bottom_layout)
         self.pref_tab_layout.addLayout(self.pref_tab_bottom_layout)
@@ -911,12 +920,17 @@ class ExcellonPreferencesUI(QtWidgets.QWidget):
 
 
     def __init__(self, parent=None):
     def __init__(self, parent=None):
         QtWidgets.QWidget.__init__(self, parent=parent)
         QtWidgets.QWidget.__init__(self, parent=parent)
-        self.layout = QtWidgets.QVBoxLayout()
+        self.layout = QtWidgets.QHBoxLayout()
         self.setLayout(self.layout)
         self.setLayout(self.layout)
 
 
-        self.excellon_group = ExcellonPrefGroupUI()
-        self.excellon_group.setFixedWidth(260)
-        self.layout.addWidget(self.excellon_group)
+        self.excellon_gen_group = ExcellonGenPrefGroupUI()
+        self.excellon_gen_group.setFixedWidth(260)
+        self.excellon_opt_group = ExcellonOptPrefGroupUI()
+        self.excellon_opt_group.setFixedWidth(260)
+
+        self.layout.addWidget(self.excellon_gen_group)
+        self.layout.addWidget(self.excellon_opt_group)
+        self.layout.addStretch()
 
 
 
 
 class GeometryPreferencesUI(QtWidgets.QWidget):
 class GeometryPreferencesUI(QtWidgets.QWidget):
@@ -931,6 +945,22 @@ class GeometryPreferencesUI(QtWidgets.QWidget):
         self.layout.addWidget(self.geometry_group)
         self.layout.addWidget(self.geometry_group)
 
 
 
 
+class ToolsPreferencesUI(QtWidgets.QWidget):
+
+    def __init__(self, parent=None):
+        QtWidgets.QWidget.__init__(self, parent=parent)
+        self.layout = QtWidgets.QHBoxLayout()
+        self.setLayout(self.layout)
+
+        self.tools_ncc_group = ToolsNCCPrefGroupUI()
+        self.tools_ncc_group.setFixedWidth(260)
+        self.tools_cutout_group = ToolsCutoutPrefGroupUI()
+        self.tools_cutout_group.setFixedWidth(260)
+
+        self.layout.addWidget(self.tools_ncc_group)
+        self.layout.addWidget(self.tools_cutout_group)
+        self.layout.addStretch()
+
 class CNCJobPreferencesUI(QtWidgets.QWidget):
 class CNCJobPreferencesUI(QtWidgets.QWidget):
 
 
     def __init__(self, parent=None):
     def __init__(self, parent=None):
@@ -1345,7 +1375,7 @@ class GerberPrefGroupUI(OptionsGroupUI):
         grid0.addWidget(self.solid_cb, 0, 1)
         grid0.addWidget(self.solid_cb, 0, 1)
 
 
         # Multicolored CB
         # Multicolored CB
-        self.multicolored_cb = FCCheckBox(label='Multicolored')
+        self.multicolored_cb = FCCheckBox(label='M-Color')
         self.multicolored_cb.setToolTip(
         self.multicolored_cb.setToolTip(
             "Draw polygons in different colors."
             "Draw polygons in different colors."
         )
         )
@@ -1427,148 +1457,6 @@ class GerberPrefGroupUI(OptionsGroupUI):
         )
         )
         self.layout.addWidget(self.clearcopper_label)
         self.layout.addWidget(self.clearcopper_label)
 
 
-        grid5 = QtWidgets.QGridLayout()
-        self.layout.addLayout(grid5)
-        ncctdlabel = QtWidgets.QLabel('Tools dia:')
-        ncctdlabel.setToolTip(
-            "Diameters of the cutting tools, separated by ','"
-        )
-        grid5.addWidget(ncctdlabel, 0, 0)
-        self.ncc_tool_dia_entry = FCEntry()
-        grid5.addWidget(self.ncc_tool_dia_entry, 0, 1)
-
-        nccoverlabel = QtWidgets.QLabel('Overlap:')
-        nccoverlabel.setToolTip(
-            "How much (fraction) of the tool width to overlap each tool pass.\n"
-            "Example:\n"
-            "A value here of 0.25 means 25% from the tool diameter found above.\n\n"
-            "Adjust the value starting with lower values\n"
-            "and increasing it if areas that should be cleared are still \n"
-            "not cleared.\n"
-            "Lower values = faster processing, faster execution on PCB.\n"
-            "Higher values = slow processing and slow execution on CNC\n"
-            "due of too many paths."
-        )
-        grid5.addWidget(nccoverlabel, 1, 0)
-        self.ncc_overlap_entry = FloatEntry()
-        grid5.addWidget(self.ncc_overlap_entry, 1, 1)
-
-        nccmarginlabel = QtWidgets.QLabel('Margin:')
-        nccmarginlabel.setToolTip(
-            "Bounding box margin."
-        )
-        grid5.addWidget(nccmarginlabel, 2, 0)
-        self.ncc_margin_entry = FloatEntry()
-        grid5.addWidget(self.ncc_margin_entry, 2, 1)
-
-        # Method
-        methodlabel = QtWidgets.QLabel('Method:')
-        methodlabel.setToolTip(
-            "Algorithm for non-copper clearing:<BR>"
-            "<B>Standard</B>: Fixed step inwards.<BR>"
-            "<B>Seed-based</B>: Outwards from seed.<BR>"
-            "<B>Line-based</B>: Parallel lines."
-        )
-        grid5.addWidget(methodlabel, 3, 0)
-        self.ncc_method_radio = RadioSet([
-            {"label": "Standard", "value": "standard"},
-            {"label": "Seed-based", "value": "seed"},
-            {"label": "Straight lines", "value": "lines"}
-        ], orientation='vertical', stretch=False)
-        grid5.addWidget(self.ncc_method_radio, 3, 1)
-
-        # Connect lines
-        pathconnectlabel = QtWidgets.QLabel("Connect:")
-        pathconnectlabel.setToolTip(
-            "Draw lines between resulting\n"
-            "segments to minimize tool lifts."
-        )
-        grid5.addWidget(pathconnectlabel, 4, 0)
-        self.ncc_connect_cb = FCCheckBox()
-        grid5.addWidget(self.ncc_connect_cb, 4, 1)
-
-        contourlabel = QtWidgets.QLabel("Contour:")
-        contourlabel.setToolTip(
-            "Cut around the perimeter of the polygon\n"
-            "to trim rough edges."
-        )
-        grid5.addWidget(contourlabel, 5, 0)
-        self.ncc_contour_cb = FCCheckBox()
-        grid5.addWidget(self.ncc_contour_cb, 5, 1)
-
-        restlabel = QtWidgets.QLabel("Rest M.:")
-        restlabel.setToolTip(
-            "If checked, use 'rest machining'.\n"
-            "Basically it will clear copper outside PCB features,\n"
-            "using the biggest tool and continue with the next tools,\n"
-            "from bigger to smaller, to clear areas of copper that\n"
-            "could not be cleared by previous tool.\n"
-            "If not checked, use the standard algorithm."
-        )
-        grid5.addWidget(restlabel, 6, 0)
-        self.ncc_rest_cb = FCCheckBox()
-        grid5.addWidget(self.ncc_rest_cb, 6, 1)
-
-        ## Board cuttout
-        self.board_cutout_label = QtWidgets.QLabel("<b>Board cutout:</b>")
-        self.board_cutout_label.setToolTip(
-            "Create toolpaths to cut around\n"
-            "the PCB and separate it from\n"
-            "the original board."
-        )
-        self.layout.addWidget(self.board_cutout_label)
-
-        grid2 = QtWidgets.QGridLayout()
-        self.layout.addLayout(grid2)
-        tdclabel = QtWidgets.QLabel('Tool dia:')
-        tdclabel.setToolTip(
-            "Diameter of the cutting tool."
-        )
-        grid2.addWidget(tdclabel, 0, 0)
-        self.cutout_tooldia_entry = LengthEntry()
-        grid2.addWidget(self.cutout_tooldia_entry, 0, 1)
-
-        marginlabel = QtWidgets.QLabel('Margin:')
-        marginlabel.setToolTip(
-            "Distance from objects at which\n"
-            "to draw the cutout."
-        )
-        grid2.addWidget(marginlabel, 1, 0)
-        self.cutout_margin_entry = LengthEntry()
-        grid2.addWidget(self.cutout_margin_entry, 1, 1)
-
-        gaplabel = QtWidgets.QLabel('Gap size:')
-        gaplabel.setToolTip(
-            "Size of the gaps in the toolpath\n"
-            "that will remain to hold the\n"
-            "board in place."
-        )
-        grid2.addWidget(gaplabel, 2, 0)
-        self.cutout_gap_entry = LengthEntry()
-        grid2.addWidget(self.cutout_gap_entry, 2, 1)
-
-        gapslabel = QtWidgets.QLabel('Gaps:')
-        gapslabel.setToolTip(
-            "Where to place the gaps, Top/Bottom\n"
-            "Left/Rigt, or on all 4 sides."
-        )
-        grid2.addWidget(gapslabel, 3, 0)
-        self.gaps_radio = RadioSet([{'label': '2 (T/B)', 'value': 'tb'},
-                                    {'label': '2 (L/R)', 'value': 'lr'},
-                                    {'label': '4', 'value': '4'}])
-        grid2.addWidget(self.gaps_radio, 3, 1)
-
-        ## Non-copper regions
-        self.noncopper_label = QtWidgets.QLabel("<b>Non-copper regions:</b>")
-        self.noncopper_label.setToolTip(
-            "Create polygons covering the\n"
-            "areas without copper on the PCB.\n"
-            "Equivalent to the inverse of this\n"
-            "object. Can be used to remove all\n"
-            "copper from a specified region."
-        )
-        self.layout.addWidget(self.noncopper_label)
-
         grid3 = QtWidgets.QGridLayout()
         grid3 = QtWidgets.QGridLayout()
         self.layout.addLayout(grid3)
         self.layout.addLayout(grid3)
 
 
@@ -1619,13 +1507,13 @@ class GerberPrefGroupUI(OptionsGroupUI):
         self.layout.addStretch()
         self.layout.addStretch()
 
 
 
 
-class ExcellonPrefGroupUI(OptionsGroupUI):
+class ExcellonGenPrefGroupUI(OptionsGroupUI):
 
 
     def __init__(self, parent=None):
     def __init__(self, parent=None):
         # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent)
         # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent)
-        super(ExcellonPrefGroupUI, self).__init__(self)
+        super(ExcellonGenPrefGroupUI, self).__init__(self)
 
 
-        self.setTitle(str("Excellon Options"))
+        self.setTitle(str("Excellon General"))
 
 
         # Plot options
         # Plot options
         self.plot_options_label = QtWidgets.QLabel("<b>Plot Options:</b>")
         self.plot_options_label = QtWidgets.QLabel("<b>Plot Options:</b>")
@@ -1741,7 +1629,7 @@ class ExcellonPrefGroupUI(OptionsGroupUI):
         hlay3 = QtWidgets.QHBoxLayout()
         hlay3 = QtWidgets.QHBoxLayout()
         self.layout.addLayout(hlay3)
         self.layout.addLayout(hlay3)
 
 
-        self.excellon_zeros_label = QtWidgets.QLabel('Default <b>Zeros</b> Type:')
+        self.excellon_zeros_label = QtWidgets.QLabel('Default <b>Zeros</b>:')
         self.excellon_zeros_label.setAlignment(QtCore.Qt.AlignLeft)
         self.excellon_zeros_label.setAlignment(QtCore.Qt.AlignLeft)
         self.excellon_zeros_label.setToolTip(
         self.excellon_zeros_label.setToolTip(
             "This sets the type of Excellon zeros.\n"
             "This sets the type of Excellon zeros.\n"
@@ -1769,7 +1657,7 @@ class ExcellonPrefGroupUI(OptionsGroupUI):
         hlay4 = QtWidgets.QHBoxLayout()
         hlay4 = QtWidgets.QHBoxLayout()
         self.layout.addLayout(hlay4)
         self.layout.addLayout(hlay4)
 
 
-        self.excellon_units_label = QtWidgets.QLabel('Default <b>Units</b> Type:')
+        self.excellon_units_label = QtWidgets.QLabel('Default <b>Units</b>:')
         self.excellon_units_label.setAlignment(QtCore.Qt.AlignLeft)
         self.excellon_units_label.setAlignment(QtCore.Qt.AlignLeft)
         self.excellon_units_label.setToolTip(
         self.excellon_units_label.setToolTip(
             "This sets the default units of Excellon files.\n"
             "This sets the default units of Excellon files.\n"
@@ -1842,6 +1730,17 @@ class ExcellonPrefGroupUI(OptionsGroupUI):
             self.excellon_optimization_label.setDisabled(True)
             self.excellon_optimization_label.setDisabled(True)
             self.excellon_optimization_radio.setDisabled(True)
             self.excellon_optimization_radio.setDisabled(True)
 
 
+        self.layout.addStretch()
+
+
+class ExcellonOptPrefGroupUI(OptionsGroupUI):
+
+    def __init__(self, parent=None):
+        # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent)
+        super(ExcellonOptPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str("Excellon Options"))
+
         ## Create CNC Job
         ## Create CNC Job
         self.cncjob_label = QtWidgets.QLabel('<b>Create CNC Job</b>')
         self.cncjob_label = QtWidgets.QLabel('<b>Create CNC Job</b>')
         self.cncjob_label.setToolTip(
         self.cncjob_label.setToolTip(
@@ -2477,6 +2376,167 @@ class CNCJobPrefGroupUI(OptionsGroupUI):
         self.layout.addLayout(grid0)
         self.layout.addLayout(grid0)
 
 
 
 
+class ToolsNCCPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+        # OptionsGroupUI.__init__(self, "NCC Tool Options", parent=parent)
+        super(ToolsNCCPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str("NCC Tool Options"))
+
+        ## Clear non-copper regions
+        self.clearcopper_label = QtWidgets.QLabel("<b>Clear non-copper:</b>")
+        self.clearcopper_label.setToolTip(
+            "Create a Geometry object with\n"
+            "toolpaths to cut all non-copper regions."
+        )
+        self.layout.addWidget(self.clearcopper_label)
+
+        grid0 = QtWidgets.QGridLayout()
+        self.layout.addLayout(grid0)
+
+        ncctdlabel = QtWidgets.QLabel('Tools dia:')
+        ncctdlabel.setToolTip(
+            "Diameters of the cutting tools, separated by ','"
+        )
+        grid0.addWidget(ncctdlabel, 0, 0)
+        self.ncc_tool_dia_entry = FCEntry()
+        grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
+
+        nccoverlabel = QtWidgets.QLabel('Overlap:')
+        nccoverlabel.setToolTip(
+            "How much (fraction) of the tool width to overlap each tool pass.\n"
+            "Example:\n"
+            "A value here of 0.25 means 25% from the tool diameter found above.\n\n"
+            "Adjust the value starting with lower values\n"
+            "and increasing it if areas that should be cleared are still \n"
+            "not cleared.\n"
+            "Lower values = faster processing, faster execution on PCB.\n"
+            "Higher values = slow processing and slow execution on CNC\n"
+            "due of too many paths."
+        )
+        grid0.addWidget(nccoverlabel, 1, 0)
+        self.ncc_overlap_entry = FloatEntry()
+        grid0.addWidget(self.ncc_overlap_entry, 1, 1)
+
+        nccmarginlabel = QtWidgets.QLabel('Margin:')
+        nccmarginlabel.setToolTip(
+            "Bounding box margin."
+        )
+        grid0.addWidget(nccmarginlabel, 2, 0)
+        self.ncc_margin_entry = FloatEntry()
+        grid0.addWidget(self.ncc_margin_entry, 2, 1)
+
+        # Method
+        methodlabel = QtWidgets.QLabel('Method:')
+        methodlabel.setToolTip(
+            "Algorithm for non-copper clearing:<BR>"
+            "<B>Standard</B>: Fixed step inwards.<BR>"
+            "<B>Seed-based</B>: Outwards from seed.<BR>"
+            "<B>Line-based</B>: Parallel lines."
+        )
+        grid0.addWidget(methodlabel, 3, 0)
+        self.ncc_method_radio = RadioSet([
+            {"label": "Standard", "value": "standard"},
+            {"label": "Seed-based", "value": "seed"},
+            {"label": "Straight lines", "value": "lines"}
+        ], orientation='vertical', stretch=False)
+        grid0.addWidget(self.ncc_method_radio, 3, 1)
+
+        # Connect lines
+        pathconnectlabel = QtWidgets.QLabel("Connect:")
+        pathconnectlabel.setToolTip(
+            "Draw lines between resulting\n"
+            "segments to minimize tool lifts."
+        )
+        grid0.addWidget(pathconnectlabel, 4, 0)
+        self.ncc_connect_cb = FCCheckBox()
+        grid0.addWidget(self.ncc_connect_cb, 4, 1)
+
+        contourlabel = QtWidgets.QLabel("Contour:")
+        contourlabel.setToolTip(
+            "Cut around the perimeter of the polygon\n"
+            "to trim rough edges."
+        )
+        grid0.addWidget(contourlabel, 5, 0)
+        self.ncc_contour_cb = FCCheckBox()
+        grid0.addWidget(self.ncc_contour_cb, 5, 1)
+
+        restlabel = QtWidgets.QLabel("Rest M.:")
+        restlabel.setToolTip(
+            "If checked, use 'rest machining'.\n"
+            "Basically it will clear copper outside PCB features,\n"
+            "using the biggest tool and continue with the next tools,\n"
+            "from bigger to smaller, to clear areas of copper that\n"
+            "could not be cleared by previous tool.\n"
+            "If not checked, use the standard algorithm."
+        )
+        grid0.addWidget(restlabel, 6, 0)
+        self.ncc_rest_cb = FCCheckBox()
+        grid0.addWidget(self.ncc_rest_cb, 6, 1)
+
+        self.layout.addStretch()
+
+
+class ToolsCutoutPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+        # OptionsGroupUI.__init__(self, "Cutout Tool Options", parent=parent)
+        super(ToolsCutoutPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str("Cutout Tool Options"))
+
+        ## Board cuttout
+        self.board_cutout_label = QtWidgets.QLabel("<b>Board cutout:</b>")
+        self.board_cutout_label.setToolTip(
+            "Create toolpaths to cut around\n"
+            "the PCB and separate it from\n"
+            "the original board."
+        )
+        self.layout.addWidget(self.board_cutout_label)
+
+        grid0 = QtWidgets.QGridLayout()
+        self.layout.addLayout(grid0)
+
+        tdclabel = QtWidgets.QLabel('Tool dia:')
+        tdclabel.setToolTip(
+            "Diameter of the cutting tool."
+        )
+        grid0.addWidget(tdclabel, 0, 0)
+        self.cutout_tooldia_entry = LengthEntry()
+        grid0.addWidget(self.cutout_tooldia_entry, 0, 1)
+
+        marginlabel = QtWidgets.QLabel('Margin:')
+        marginlabel.setToolTip(
+            "Distance from objects at which\n"
+            "to draw the cutout."
+        )
+        grid0.addWidget(marginlabel, 1, 0)
+        self.cutout_margin_entry = LengthEntry()
+        grid0.addWidget(self.cutout_margin_entry, 1, 1)
+
+        gaplabel = QtWidgets.QLabel('Gap size:')
+        gaplabel.setToolTip(
+            "Size of the gaps in the toolpath\n"
+            "that will remain to hold the\n"
+            "board in place."
+        )
+        grid0.addWidget(gaplabel, 2, 0)
+        self.cutout_gap_entry = LengthEntry()
+        grid0.addWidget(self.cutout_gap_entry, 2, 1)
+
+        gapslabel = QtWidgets.QLabel('Gaps:')
+        gapslabel.setToolTip(
+            "Where to place the gaps, Top/Bottom\n"
+            "Left/Rigt, or on all 4 sides."
+        )
+        grid0.addWidget(gapslabel, 3, 0)
+        self.gaps_radio = RadioSet([{'label': '2 (T/B)', 'value': 'tb'},
+                                    {'label': '2 (L/R)', 'value': 'lr'},
+                                    {'label': '4', 'value': '4'}])
+        grid0.addWidget(self.gaps_radio, 3, 1)
+
+        self.layout.addStretch()
+
+
 class FlatCAMActivityView(QtWidgets.QWidget):
 class FlatCAMActivityView(QtWidgets.QWidget):
 
 
     def __init__(self, parent=None):
     def __init__(self, parent=None):

+ 2 - 0
README.md

@@ -18,6 +18,8 @@ CAD program, and create G-Code for Isolation routing.
 - added shortcut key 'L' for creating 'New Excellon' 
 - added shortcut key 'L' for creating 'New Excellon' 
 - added shortcut key combo 'SHIFT+S' for Running a Script.
 - added shortcut key combo 'SHIFT+S' for Running a Script.
 - modified grbl_laser postprocessor file so it includes a Sxxxx command on the line with M02 (laser active) whenever a value is enter in the Spindlespeed entry field
 - modified grbl_laser postprocessor file so it includes a Sxxxx command on the line with M02 (laser active) whenever a value is enter in the Spindlespeed entry field
+- remade the EDIT -> PREFERENCES window, the Excellon and Gerber sections. Created a new section named TOOLS
+
 
 
 26.01.2019
 26.01.2019
 
 

+ 10 - 2
flatcamTools/ToolCutout.py

@@ -146,8 +146,8 @@ class ToolCutout(FlatCAMTool):
             "- one gap Left / one gap Right\n"
             "- one gap Left / one gap Right\n"
             "- one gap on each of the 4 sides."
             "- one gap on each of the 4 sides."
         )
         )
-        self.gaps_rect_radio = RadioSet([{'label': 'T/B', 'value': 'tb'},
-                                    {'label': 'L/R', 'value': 'lr'},
+        self.gaps_rect_radio = RadioSet([{'label': '2(T/B)', 'value': 'tb'},
+                                    {'label': '2(L/R)', 'value': 'lr'},
                                     {'label': '4', 'value': '4'}])
                                     {'label': '4', 'value': '4'}])
         form_layout_3.addRow(gapslabel_rect, self.gaps_rect_radio)
         form_layout_3.addRow(gapslabel_rect, self.gaps_rect_radio)
 
 
@@ -186,11 +186,19 @@ class ToolCutout(FlatCAMTool):
 
 
     def run(self):
     def run(self):
         FlatCAMTool.run(self)
         FlatCAMTool.run(self)
+        self.set_ui()
         self.app.ui.notebook.setTabText(2, "Cutout Tool")
         self.app.ui.notebook.setTabText(2, "Cutout Tool")
 
 
     def install(self, icon=None, separator=None, **kwargs):
     def install(self, icon=None, separator=None, **kwargs):
         FlatCAMTool.install(self, icon, separator, shortcut='ALT+U', **kwargs)
         FlatCAMTool.install(self, icon, separator, shortcut='ALT+U', **kwargs)
 
 
+    def set_ui(self):
+        self.dia.set_value(float(self.app.defaults["tools_cutouttooldia"]))
+        self.margin.set_value(float(self.app.defaults["tools_cutoutmargin"]))
+        self.gapsize.set_value(float(self.app.defaults["tools_cutoutgapsize"]))
+        self.gaps.set_value(4)
+        self.gaps_rect_radio.set_value(str(self.app.defaults["tools_gaps_rect"]))
+
     def on_freeform_cutout(self):
     def on_freeform_cutout(self):
 
 
         def subtract_rectangle(obj_, x0, y0, x1, y1):
         def subtract_rectangle(obj_, x0, y0, x1, y1):

+ 19 - 19
flatcamTools/ToolNonCopperClear.py

@@ -244,12 +244,12 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.app.ui.notebook.setTabText(2, "NCC Tool")
         self.app.ui.notebook.setTabText(2, "NCC Tool")
 
 
     def set_ui(self):
     def set_ui(self):
-        self.ncc_overlap_entry.set_value(self.app.defaults["gerber_nccoverlap"])
-        self.ncc_margin_entry.set_value(self.app.defaults["gerber_nccmargin"])
-        self.ncc_method_radio.set_value(self.app.defaults["gerber_nccmethod"])
-        self.ncc_connect_cb.set_value(self.app.defaults["gerber_nccconnect"])
-        self.ncc_contour_cb.set_value(self.app.defaults["gerber_ncccontour"])
-        self.ncc_rest_cb.set_value(self.app.defaults["gerber_nccrest"])
+        self.ncc_overlap_entry.set_value(self.app.defaults["tools_nccoverlap"])
+        self.ncc_margin_entry.set_value(self.app.defaults["tools_nccmargin"])
+        self.ncc_method_radio.set_value(self.app.defaults["tools_nccmethod"])
+        self.ncc_connect_cb.set_value(self.app.defaults["tools_nccconnect"])
+        self.ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"])
+        self.ncc_rest_cb.set_value(self.app.defaults["tools_nccrest"])
 
 
         self.tools_table.setupContextMenu()
         self.tools_table.setupContextMenu()
         self.tools_table.addContextMenu(
         self.tools_table.addContextMenu(
@@ -289,18 +289,18 @@ class NonCopperClear(FlatCAMTool, Gerber):
             "pathconnect": self.app.defaults["geometry_pathconnect"],
             "pathconnect": self.app.defaults["geometry_pathconnect"],
             "paintcontour": self.app.defaults["geometry_paintcontour"],
             "paintcontour": self.app.defaults["geometry_paintcontour"],
             "paintoverlap": self.app.defaults["geometry_paintoverlap"],
             "paintoverlap": self.app.defaults["geometry_paintoverlap"],
-            "nccoverlap": self.app.defaults["gerber_nccoverlap"],
-            "nccmargin": self.app.defaults["gerber_nccmargin"],
-            "nccmethod": self.app.defaults["gerber_nccmethod"],
-            "nccconnect": self.app.defaults["gerber_nccconnect"],
-            "ncccontour": self.app.defaults["gerber_ncccontour"],
-            "nccrest": self.app.defaults["gerber_nccrest"]
+            "nccoverlap": self.app.defaults["tools_nccoverlap"],
+            "nccmargin": self.app.defaults["tools_nccmargin"],
+            "nccmethod": self.app.defaults["tools_nccmethod"],
+            "nccconnect": self.app.defaults["tools_nccconnect"],
+            "ncccontour": self.app.defaults["tools_ncccontour"],
+            "nccrest": self.app.defaults["tools_nccrest"]
         })
         })
 
 
         try:
         try:
             dias = [float(eval(dia)) for dia in self.app.defaults["gerber_ncctools"].split(",")]
             dias = [float(eval(dia)) for dia in self.app.defaults["gerber_ncctools"].split(",")]
         except:
         except:
-            log.error("At least one tool diameter needed. Verify in Edit -> Preferences -> Gerber Object -> NCC Tools.")
+            log.error("At least one tool diameter needed. Verify in Edit -> Preferences -> TOOLS -> NCC Tools.")
             return
             return
 
 
         self.tooluid = 0
         self.tooluid = 0
@@ -550,22 +550,22 @@ class NonCopperClear(FlatCAMTool, Gerber):
     def on_ncc(self):
     def on_ncc(self):
 
 
         over = self.ncc_overlap_entry.get_value()
         over = self.ncc_overlap_entry.get_value()
-        over = over if over else self.app.defaults["gerber_nccoverlap"]
+        over = over if over else self.app.defaults["tools_nccoverlap"]
 
 
         margin = self.ncc_margin_entry.get_value()
         margin = self.ncc_margin_entry.get_value()
-        margin = margin if margin else self.app.defaults["gerber_nccmargin"]
+        margin = margin if margin else self.app.defaults["tools_nccmargin"]
 
 
         connect = self.ncc_connect_cb.get_value()
         connect = self.ncc_connect_cb.get_value()
-        connect = connect if connect else self.app.defaults["gerber_nccconnect"]
+        connect = connect if connect else self.app.defaults["tools_nccconnect"]
 
 
         contour = self.ncc_contour_cb.get_value()
         contour = self.ncc_contour_cb.get_value()
-        contour = contour if contour else self.app.defaults["gerber_ncccontour"]
+        contour = contour if contour else self.app.defaults["tools_ncccontour"]
 
 
         clearing_method = self.ncc_rest_cb.get_value()
         clearing_method = self.ncc_rest_cb.get_value()
-        clearing_method = clearing_method if clearing_method else self.app.defaults["gerber_nccrest"]
+        clearing_method = clearing_method if clearing_method else self.app.defaults["tools_nccrest"]
 
 
         pol_method = self.ncc_method_radio.get_value()
         pol_method = self.ncc_method_radio.get_value()
-        pol_method = pol_method if pol_method else self.app.defaults["gerber_nccmethod"]
+        pol_method = pol_method if pol_method else self.app.defaults["tools_nccmethod"]
 
 
         self.obj_name = self.object_combo.currentText()
         self.obj_name = self.object_combo.currentText()
         # Get source object.
         # Get source object.