Просмотр исходного кода

jpcgt/flatcam/Beta слито с Beta

Camellan 6 лет назад
Родитель
Сommit
36f0257ace

+ 65 - 12
FlatCAMApp.py

@@ -84,7 +84,7 @@ class App(QtCore.QObject):
         elif opt == '--shellfile':
         elif opt == '--shellfile':
             cmd_line_shellfile = arg
             cmd_line_shellfile = arg
 
 
-    # Logging # ##
+    # ## Logging ###
     log = logging.getLogger('base')
     log = logging.getLogger('base')
     log.setLevel(logging.DEBUG)
     log.setLevel(logging.DEBUG)
     # log.setLevel(logging.WARNING)
     # log.setLevel(logging.WARNING)
@@ -93,9 +93,11 @@ class App(QtCore.QObject):
     handler.setFormatter(formatter)
     handler.setFormatter(formatter)
     log.addHandler(handler)
     log.addHandler(handler)
 
 
-    # Version
+    # ####################################
+    # Version and VERSION DATE ###########
+    # ####################################
     version = 8.920
     version = 8.920
-    version_date = "2019/07/14"
+    version_date = "2019/07/31"
     beta = True
     beta = True
 
 
     # current date now
     # current date now
@@ -502,6 +504,7 @@ class App(QtCore.QObject):
 
 
             # CutOut Tool
             # CutOut Tool
             "tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
             "tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
+            "tools_cutoutkind": self.ui.tools_defaults_form.tools_cutout_group.obj_kind_combo,
             "tools_cutoutmargin": self.ui.tools_defaults_form.tools_cutout_group.cutout_margin_entry,
             "tools_cutoutmargin": self.ui.tools_defaults_form.tools_cutout_group.cutout_margin_entry,
             "tools_cutoutgapsize": self.ui.tools_defaults_form.tools_cutout_group.cutout_gap_entry,
             "tools_cutoutgapsize": self.ui.tools_defaults_form.tools_cutout_group.cutout_gap_entry,
             "tools_gaps_ff": self.ui.tools_defaults_form.tools_cutout_group.gaps_combo,
             "tools_gaps_ff": self.ui.tools_defaults_form.tools_cutout_group.gaps_combo,
@@ -781,6 +784,8 @@ class App(QtCore.QObject):
 
 
             # Geometry Options
             # Geometry Options
             "geometry_cutz": -0.002,
             "geometry_cutz": -0.002,
+            "geometry_vtipdia": 0.1,
+            "geometry_vtipangle": 30,
             "geometry_multidepth": False,
             "geometry_multidepth": False,
             "geometry_depthperpass": 0.002,
             "geometry_depthperpass": 0.002,
             "geometry_travelz": 0.1,
             "geometry_travelz": 0.1,
@@ -837,6 +842,7 @@ class App(QtCore.QObject):
             "tools_nccrest": False,
             "tools_nccrest": False,
 
 
             "tools_cutouttooldia": 0.00393701,
             "tools_cutouttooldia": 0.00393701,
+            "tools_cutoutkind": "single",
             "tools_cutoutmargin": 0.00393701,
             "tools_cutoutmargin": 0.00393701,
             "tools_cutoutgapsize": 0.005905512,
             "tools_cutoutgapsize": 0.005905512,
             "tools_gaps_ff": "8",
             "tools_gaps_ff": "8",
@@ -1125,6 +1131,8 @@ class App(QtCore.QObject):
             "geometry_segx": 0.0,
             "geometry_segx": 0.0,
             "geometry_segy": 0.0,
             "geometry_segy": 0.0,
             "geometry_cutz": -0.002,
             "geometry_cutz": -0.002,
+            "geometry_vtipdia": 0.1,
+            "geometry_vtipangle": 30,
             "geometry_travelz": 0.1,
             "geometry_travelz": 0.1,
             "geometry_feedrate": 3.0,
             "geometry_feedrate": 3.0,
             "geometry_feedrate_z": 3.0,
             "geometry_feedrate_z": 3.0,
@@ -1454,7 +1462,7 @@ class App(QtCore.QObject):
         self.connect_toolbar_signals()
         self.connect_toolbar_signals()
 
 
         # Context Menu
         # Context Menu
-        self.ui.popmenu_disable.triggered.connect(lambda: self.disable_plots(self.collection.get_selected()))
+        self.ui.popmenu_disable.triggered.connect(lambda: self.toggle_plots(self.collection.get_selected()))
         self.ui.popmenu_panel_toggle.triggered.connect(self.on_toggle_notebook)
         self.ui.popmenu_panel_toggle.triggered.connect(self.on_toggle_notebook)
 
 
         self.ui.popmenu_new_geo.triggered.connect(self.new_geometry_object)
         self.ui.popmenu_new_geo.triggered.connect(self.new_geometry_object)
@@ -3869,6 +3877,9 @@ class App(QtCore.QObject):
                 scale_defaults(factor)
                 scale_defaults(factor)
                 self.defaults_write_form(fl_units=new_units)
                 self.defaults_write_form(fl_units=new_units)
 
 
+                # save the defaults to file, some may assume that the conversion is enough and it's not
+                self.on_save_button()
+
             self.should_we_save = True
             self.should_we_save = True
 
 
             # change this only if the workspace is active
             # change this only if the workspace is active
@@ -3914,12 +3925,17 @@ class App(QtCore.QObject):
         self.defaults_read_form()
         self.defaults_read_form()
 
 
     def on_toggle_units_click(self):
     def on_toggle_units_click(self):
-        self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect()
+        try:
+            self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect()
+        except TypeError:
+            pass
+
         if self.defaults["units"] == 'MM':
         if self.defaults["units"] == 'MM':
             self.ui.general_defaults_form.general_app_group.units_radio.set_value("IN")
             self.ui.general_defaults_form.general_app_group.units_radio.set_value("IN")
         else:
         else:
             self.ui.general_defaults_form.general_app_group.units_radio.set_value("MM")
             self.ui.general_defaults_form.general_app_group.units_radio.set_value("MM")
         self.on_toggle_units(no_pref=True)
         self.on_toggle_units(no_pref=True)
+
         self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect(
         self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect(
             lambda: self.on_toggle_units(no_pref=False))
             lambda: self.on_toggle_units(no_pref=False))
 
 
@@ -4416,7 +4432,7 @@ class App(QtCore.QObject):
             self.ui.removeToolBar(self.ui.grb_edit_toolbar)
             self.ui.removeToolBar(self.ui.grb_edit_toolbar)
             self.ui.removeToolBar(self.ui.snap_toolbar)
             self.ui.removeToolBar(self.ui.snap_toolbar)
             self.ui.removeToolBar(self.ui.toolbarshell)
             self.ui.removeToolBar(self.ui.toolbarshell)
-        except:
+        except Exception as e:
             pass
             pass
 
 
         if current_layout == 'standard':
         if current_layout == 'standard':
@@ -4524,6 +4540,8 @@ class App(QtCore.QObject):
             self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text.insertPlainText('%%%s%%' % signal_text)
             self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text.insertPlainText('%%%s%%' % signal_text)
 
 
     def on_save_button(self):
     def on_save_button(self):
+        log.debug("App.on_save_button() --> Saving preferences to file.")
+
         self.save_defaults(silent=False)
         self.save_defaults(silent=False)
         # load the defaults so they are updated into the app
         # load the defaults so they are updated into the app
         self.load_defaults(filename='current_defaults')
         self.load_defaults(filename='current_defaults')
@@ -6127,11 +6145,12 @@ class App(QtCore.QObject):
         self.report_usage("on_fileopengerber")
         self.report_usage("on_fileopengerber")
         App.log.debug("on_fileopengerber()")
         App.log.debug("on_fileopengerber()")
 
 
-        _filter_ = "Gerber Files (*.gbr *.ger *.gtl *.gbl *.gts *.gbs *.gtp *.gbp *.gto *.gbo *.gm1 *.gml *.gm3 *.gko " \
-                   "*.cmp *.sol *.stc *.sts *.plc *.pls *.crc *.crs *.tsm *.bsm *.ly2 *.ly15 *.dim *.mil *.grb" \
+        _filter_ = "Gerber Files (*.gbr *.ger *.gtl *.gbl *.gts *.gbs *.gtp *.gbp *.gto *.gbo *.gm1 *.gml *.gm3 *" \
+                   ".gko *.cmp *.sol *.stc *.sts *.plc *.pls *.crc *.crs *.tsm *.bsm *.ly2 *.ly15 *.dim *.mil *.grb" \
                    "*.top *.bot *.smt *.smb *.sst *.ssb *.spt *.spb *.pho *.gdo *.art *.gbd *.gb*);;" \
                    "*.top *.bot *.smt *.smb *.sst *.ssb *.spt *.spb *.pho *.gdo *.art *.gbd *.gb*);;" \
                    "Protel Files (*.gtl *.gbl *.gts *.gbs *.gto *.gbo *.gtp *.gbp *.gml *.gm1 *.gm3 *.gko);;" \
                    "Protel Files (*.gtl *.gbl *.gts *.gbs *.gto *.gbo *.gtp *.gbp *.gml *.gm1 *.gm3 *.gko);;" \
-                   "Eagle Files (*.cmp *.sol *.stc *.sts *.plc *.pls *.crc *.crs *.tsm *.bsm *.ly2 *.ly15 *.dim *.mil);;" \
+                   "Eagle Files (*.cmp *.sol *.stc *.sts *.plc *.pls *.crc *.crs *.tsm *.bsm *.ly2 *.ly15 *.dim " \
+                   "*.mil);;" \
                    "OrCAD Files (*.top *.bot *.smt *.smb *.sst *.ssb *.spt *.spb);;" \
                    "OrCAD Files (*.top *.bot *.smt *.smb *.sst *.ssb *.spt *.spb);;" \
                    "Allegro Files (*.art);;" \
                    "Allegro Files (*.art);;" \
                    "Mentor Files (*.pho *.gdo);;" \
                    "Mentor Files (*.pho *.gdo);;" \
@@ -7666,9 +7685,9 @@ class App(QtCore.QObject):
                 app_obj.progress.emit(0)
                 app_obj.progress.emit(0)
                 self.log.error(str(err))
                 self.log.error(str(err))
                 return "fail"
                 return "fail"
-
-            except:
-                msg = _("[ERROR] An internal error has ocurred. See shell.\n")
+            except Exception as e:
+                log.debug("App.open_gerber() --> %s" % str(e))
+                msg = _("[ERROR] An internal error has occurred. See shell.\n")
                 msg += traceback.format_exc()
                 msg += traceback.format_exc()
                 app_obj.inform.emit(msg)
                 app_obj.inform.emit(msg)
                 return "fail"
                 return "fail"
@@ -8513,12 +8532,46 @@ The normal flow when working in FlatCAM is the following:</span></p>
         :return:
         :return:
         """
         """
 
 
+        # if no objects selected then do nothing
+        if not self.collection.get_selected():
+            return
+
+        # if at least one object is visible then do the disable
+        exit_flag = True
+        for obj in objects:
+            if obj.options['plot'] is True:
+                exit_flag = False
+                break
+
+        if exit_flag:
+            return
+
         log.debug("Disabling plots ...")
         log.debug("Disabling plots ...")
         self.inform.emit(_("Working ..."))
         self.inform.emit(_("Working ..."))
         for obj in objects:
         for obj in objects:
             obj.options['plot'] = False
             obj.options['plot'] = False
         self.plots_updated.emit()
         self.plots_updated.emit()
 
 
+    def toggle_plots(self, objects):
+        """
+        Toggle plots visibility
+        :param objects: list of Objects for which to be toggled the visibility
+        :return:
+        """
+
+        # if no objects selected then do nothing
+        if not self.collection.get_selected():
+            return
+
+        log.debug("Toggling plots ...")
+        self.inform.emit(_("Working ..."))
+        for obj in objects:
+            if obj.options['plot'] is False:
+                obj.options['plot'] = True
+            else:
+                obj.options['plot'] = False
+        self.plots_updated.emit()
+
     def clear_plots(self):
     def clear_plots(self):
 
 
         objects = self.collection.get_list()
         objects = self.collection.get_list()

+ 164 - 77
FlatCAMObj.py

@@ -93,7 +93,8 @@ class FlatCAMObj(QtCore.QObject):
         self.isHovering = False
         self.isHovering = False
         self.notHovering = True
         self.notHovering = True
 
 
-        self.units = 'IN'
+        # self.units = 'IN'
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
 
         # assert isinstance(self.ui, ObjectUI)
         # assert isinstance(self.ui, ObjectUI)
         # self.ui.name_entry.returnPressed.connect(self.on_name_activate)
         # self.ui.name_entry.returnPressed.connect(self.on_name_activate)
@@ -181,7 +182,7 @@ class FlatCAMObj(QtCore.QObject):
         # self.app.ui.selected_layout.addWidget(self.ui)
         # self.app.ui.selected_layout.addWidget(self.ui)
         try:
         try:
             self.app.ui.selected_scroll_area.takeWidget()
             self.app.ui.selected_scroll_area.takeWidget()
-        except:
+        except Exception as e:
             self.app.log.debug("Nothing to remove")
             self.app.log.debug("Nothing to remove")
         self.app.ui.selected_scroll_area.setWidget(self.ui)
         self.app.ui.selected_scroll_area.setWidget(self.ui)
 
 
@@ -198,7 +199,7 @@ class FlatCAMObj(QtCore.QObject):
                 self.app.myKeywords.append(new_name)
                 self.app.myKeywords.append(new_name)
                 self.app.shell._edit.set_model_data(self.app.myKeywords)
                 self.app.shell._edit.set_model_data(self.app.myKeywords)
                 self.app.ui.code_editor.set_model_data(self.app.myKeywords)
                 self.app.ui.code_editor.set_model_data(self.app.myKeywords)
-            except:
+            except Exception as e:
                 log.debug("on_name_activate() --> Could not remove the old object name from auto-completer model list")
                 log.debug("on_name_activate() --> Could not remove the old object name from auto-completer model list")
 
 
             self.options["name"] = self.ui.name_entry.get_value()
             self.options["name"] = self.ui.name_entry.get_value()
@@ -242,7 +243,7 @@ class FlatCAMObj(QtCore.QObject):
         for option in self.options:
         for option in self.options:
             try:
             try:
                 self.set_form_item(option)
                 self.set_form_item(option)
-            except:
+            except Exception as e:
                 self.app.log.warning("Unexpected error:", sys.exc_info())
                 self.app.log.warning("Unexpected error:", sys.exc_info())
 
 
     def read_form(self):
     def read_form(self):
@@ -256,7 +257,7 @@ class FlatCAMObj(QtCore.QObject):
         for option in self.options:
         for option in self.options:
             try:
             try:
                 self.read_form_item(option)
                 self.read_form_item(option)
-            except:
+            except Exception as e:
                 self.app.log.warning("Unexpected error:", sys.exc_info())
                 self.app.log.warning("Unexpected error:", sys.exc_info())
 
 
     def set_form_item(self, option):
     def set_form_item(self, option):
@@ -581,7 +582,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             self.ui.apertures_table.itemChanged.disconnect()
             self.ui.apertures_table.itemChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         self.apertures_row = 0
         self.apertures_row = 0
@@ -725,12 +726,12 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         for row in range(self.ui.apertures_table.rowCount()):
         for row in range(self.ui.apertures_table.rowCount()):
             try:
             try:
                 self.ui.apertures_table.cellWidget(row, 5).clicked.disconnect()
                 self.ui.apertures_table.cellWidget(row, 5).clicked.disconnect()
-            except:
+            except TypeError:
                 pass
                 pass
 
 
         try:
         try:
             self.ui.mark_all_cb.clicked.disconnect(self.on_mark_all_click)
             self.ui.mark_all_cb.clicked.disconnect(self.on_mark_all_click)
-        except:
+        except TypeError:
             pass
             pass
 
 
     def on_generatenoncopper_button_click(self, *args):
     def on_generatenoncopper_button_click(self, *args):
@@ -767,7 +768,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
 
 
     def on_ext_iso_button_click(self, *args):
     def on_ext_iso_button_click(self, *args):
 
 
-        if self.ui.follow_cb.get_value() == True:
+        if self.ui.follow_cb.get_value() is True:
             obj = self.app.collection.get_active()
             obj = self.app.collection.get_active()
             obj.follow()
             obj.follow()
             # in the end toggle the visibility of the origin object so we can see the generated Geometry
             # in the end toggle the visibility of the origin object so we can see the generated Geometry
@@ -889,7 +890,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             return geom
             return geom
 
 
         if combine:
         if combine:
-
             if self.iso_type == 0:
             if self.iso_type == 0:
                 iso_name = self.options["name"] + "_ext_iso"
                 iso_name = self.options["name"] + "_ext_iso"
             elif self.iso_type == 1:
             elif self.iso_type == 1:
@@ -913,6 +913,46 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                         geom = generate_envelope(iso_offset, 0, envelope_iso_type=self.iso_type, follow=follow)
                         geom = generate_envelope(iso_offset, 0, envelope_iso_type=self.iso_type, follow=follow)
                     geo_obj.solid_geometry.append(geom)
                     geo_obj.solid_geometry.append(geom)
 
 
+                    # store here the default data for Geometry Data
+                    default_data = {}
+                    default_data.update({
+                        "name": iso_name,
+                        "plot": self.app.defaults['geometry_plot'],
+                        "cutz": self.app.defaults['geometry_cutz'],
+                        "vtipdia": self.app.defaults['geometry_vtipdia'],
+                        "vtipangle": self.app.defaults['geometry_vtipangle'],
+                        "travelz": self.app.defaults['geometry_travelz'],
+                        "feedrate": self.app.defaults['geometry_feedrate'],
+                        "feedrate_z": self.app.defaults['geometry_feedrate_z'],
+                        "feedrate_rapid": self.app.defaults['geometry_feedrate_rapid'],
+                        "dwell": self.app.defaults['geometry_dwell'],
+                        "dwelltime": self.app.defaults['geometry_dwelltime'],
+                        "multidepth": self.app.defaults['geometry_multidepth'],
+                        "ppname_g": self.app.defaults['geometry_ppname_g'],
+                        "depthperpass": self.app.defaults['geometry_depthperpass'],
+                        "extracut": self.app.defaults['geometry_extracut'],
+                        "toolchange": self.app.defaults['geometry_toolchange'],
+                        "toolchangez": self.app.defaults['geometry_toolchangez'],
+                        "endz": self.app.defaults['geometry_endz'],
+                        "spindlespeed": self.app.defaults['geometry_spindlespeed'],
+                        "toolchangexy": self.app.defaults['geometry_toolchangexy'],
+                        "startz": self.app.defaults['geometry_startz']
+                    })
+
+                    geo_obj.tools = dict()
+                    geo_obj.tools['1'] = dict()
+                    geo_obj.tools.update({
+                        '1': {
+                            'tooldia': float(self.options["isotooldia"]),
+                            'offset': 'Path',
+                            'offset_value': 0.0,
+                            'type': _('Rough'),
+                            'tool_type': 'C1',
+                            'data': default_data,
+                            'solid_geometry': geo_obj.solid_geometry
+                        }
+                    })
+
                 # detect if solid_geometry is empty and this require list flattening which is "heavy"
                 # detect if solid_geometry is empty and this require list flattening which is "heavy"
                 # or just looking in the lists (they are one level depth) and if any is not empty
                 # or just looking in the lists (they are one level depth) and if any is not empty
                 # proceed with object creation, if there are empty and the number of them is the length
                 # proceed with object creation, if there are empty and the number of them is the length
@@ -932,7 +972,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
 
 
                 if empty_cnt == len(geo_obj.solid_geometry):
                 if empty_cnt == len(geo_obj.solid_geometry):
                     raise ValidationError("Empty Geometry", None)
                     raise ValidationError("Empty Geometry", None)
-                geo_obj.multigeo = False
+                geo_obj.multigeo = True
 
 
             # TODO: Do something if this is None. Offer changing name?
             # TODO: Do something if this is None. Offer changing name?
             self.app.new_object("geometry", iso_name, iso_init)
             self.app.new_object("geometry", iso_name, iso_init)
@@ -1278,7 +1318,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         :return: Gerber_code
         :return: Gerber_code
         """
         """
 
 
-        def tz_format(x, y ,fac):
+        def tz_format(x, y, fac):
             x_c = x * fac
             x_c = x * fac
             y_c = y * fac
             y_c = y * fac
 
 
@@ -1501,7 +1541,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                                                 else:
                                                 else:
                                                     x_formatted, y_formatted = lz_format(coord[0], coord[1], factor)
                                                     x_formatted, y_formatted = lz_format(coord[0], coord[1], factor)
                                                     gerber_code += "X{xform}Y{yform}D01*\n".format(xform=x_formatted,
                                                     gerber_code += "X{xform}Y{yform}D01*\n".format(xform=x_formatted,
-                                                                                                  yform=y_formatted)
+                                                                                                   yform=y_formatted)
 
 
                                             prev_coord = coord
                                             prev_coord = coord
                                         # gerber_code += "D02*\n"
                                         # gerber_code += "D02*\n"
@@ -1585,7 +1625,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
         self.tool_cbs = {}
         self.tool_cbs = {}
 
 
         # dict to hold the tool number as key and tool offset as value
         # dict to hold the tool number as key and tool offset as value
-        self.tool_offset ={}
+        self.tool_offset = {}
 
 
         # variable to store the total amount of drills per job
         # variable to store the total amount of drills per job
         self.tot_drill_cnt = 0
         self.tot_drill_cnt = 0
@@ -1787,10 +1827,12 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
     def build_ui(self):
     def build_ui(self):
         FlatCAMObj.build_ui(self)
         FlatCAMObj.build_ui(self)
 
 
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
+
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             self.ui.tools_table.itemChanged.disconnect()
             self.ui.tools_table.itemChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         n = len(self.tools)
         n = len(self.tools)
@@ -1857,7 +1899,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
                 else:
                 else:
                     t_offset = self.tool_offset[float('%.4f' % float(self.tools[tool_no]['C']))]
                     t_offset = self.tool_offset[float('%.4f' % float(self.tools[tool_no]['C']))]
             except KeyError:
             except KeyError:
-                    t_offset = self.app.defaults['excellon_offset']
+                t_offset = self.app.defaults['excellon_offset']
+
             tool_offset_item = QtWidgets.QTableWidgetItem('%s' % str(t_offset))
             tool_offset_item = QtWidgets.QTableWidgetItem('%s' % str(t_offset))
 
 
             plot_item = FCCheckBox()
             plot_item = FCCheckBox()
@@ -1992,6 +2035,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
 
 
         FlatCAMApp.App.log.debug("FlatCAMExcellon.set_ui()")
         FlatCAMApp.App.log.debug("FlatCAMExcellon.set_ui()")
 
 
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
+
         self.form_fields.update({
         self.form_fields.update({
             "plot": self.ui.plot_cb,
             "plot": self.ui.plot_cb,
             "solid": self.ui.solid_cb,
             "solid": self.ui.solid_cb,
@@ -2075,12 +2120,12 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
         for row in range(self.ui.tools_table.rowCount()):
         for row in range(self.ui.tools_table.rowCount()):
             try:
             try:
                 self.ui.tools_table.cellWidget(row, 5).clicked.disconnect()
                 self.ui.tools_table.cellWidget(row, 5).clicked.disconnect()
-            except Exception as e:
+            except TypeError:
                 pass
                 pass
 
 
         try:
         try:
             self.ui.plot_cb.stateChanged.disconnect()
             self.ui.plot_cb.stateChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
     def on_tool_offset_edit(self):
     def on_tool_offset_edit(self):
@@ -2088,6 +2133,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
         self.ui.tools_table.itemChanged.disconnect()
         self.ui.tools_table.itemChanged.disconnect()
         # self.tools_table_exc.selectionModel().currentChanged.disconnect()
         # self.tools_table_exc.selectionModel().currentChanged.disconnect()
 
 
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
+
         self.is_modified = True
         self.is_modified = True
 
 
         row_of_item_changed = self.ui.tools_table.currentRow()
         row_of_item_changed = self.ui.tools_table.currentRow()
@@ -2854,7 +2901,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 if option is not 'name':
                 if option is not 'name':
                     try:
                     try:
                         geo_final.options[option] = geo.options[option]
                         geo_final.options[option] = geo.options[option]
-                    except:
+                    except Exception as e:
                         log.warning("Failed to copy option.", option)
                         log.warning("Failed to copy option.", option)
 
 
             # Expand lists
             # Expand lists
@@ -2879,6 +2926,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 geo_final_uid_list = []
                 geo_final_uid_list = []
                 for key in geo_final.tools:
                 for key in geo_final.tools:
                     geo_final_uid_list.append(int(key))
                     geo_final_uid_list.append(int(key))
+
                 try:
                 try:
                     max_uid = max(geo_final_uid_list, key=int)
                     max_uid = max(geo_final_uid_list, key=int)
                 except ValueError:
                 except ValueError:
@@ -3022,10 +3070,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         self.ser_attrs += ['options', 'kind', 'tools', 'multigeo']
         self.ser_attrs += ['options', 'kind', 'tools', 'multigeo']
 
 
     def build_ui(self):
     def build_ui(self):
-
         self.ui_disconnect()
         self.ui_disconnect()
         FlatCAMObj.build_ui(self)
         FlatCAMObj.build_ui(self)
 
 
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
+
         offset = 0
         offset = 0
         tool_idx = 0
         tool_idx = 0
 
 
@@ -3089,7 +3138,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
 
             try:
             try:
                 self.ui.tool_offset_entry.set_value(tooluid_value['offset_value'])
                 self.ui.tool_offset_entry.set_value(tooluid_value['offset_value'])
-            except:
+            except Exception as e:
                 log.debug("build_ui() --> Could not set the 'offset_value' key in self.tools")
                 log.debug("build_ui() --> Could not set the 'offset_value' key in self.tools")
 
 
         # make the diameter column editable
         # make the diameter column editable
@@ -3308,7 +3357,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
 
             self.ui.geo_tools_table.setColumnHidden(2, True)
             self.ui.geo_tools_table.setColumnHidden(2, True)
             self.ui.geo_tools_table.setColumnHidden(3, True)
             self.ui.geo_tools_table.setColumnHidden(3, True)
-            self.ui.geo_tools_table.setColumnHidden(4, True)
+            # self.ui.geo_tools_table.setColumnHidden(4, True)
             self.ui.addtool_entry_lbl.hide()
             self.ui.addtool_entry_lbl.hide()
             self.ui.addtool_entry.hide()
             self.ui.addtool_entry.hide()
             self.ui.addtool_btn.hide()
             self.ui.addtool_btn.hide()
@@ -3384,23 +3433,31 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                             return
                             return
 
 
     def ui_connect(self):
     def ui_connect(self):
-
         # on any change to the widgets that matter it will be called self.gui_form_to_storage which will save the
         # on any change to the widgets that matter it will be called self.gui_form_to_storage which will save the
         # changes in geometry UI
         # changes in geometry UI
         for i in range(self.ui.grid3.count()):
         for i in range(self.ui.grid3.count()):
-            try:
-                # works for CheckBoxes
-                self.ui.grid3.itemAt(i).widget().stateChanged.connect(self.gui_form_to_storage)
-            except Exception as e:
-                # works for ComboBoxes
-                try:
-                    self.ui.grid3.itemAt(i).widget().currentIndexChanged.connect(self.gui_form_to_storage)
-                except Exception as e2:
-                    # works for Entry
-                    try:
-                        self.ui.grid3.itemAt(i).widget().editingFinished.connect(self.gui_form_to_storage)
-                    except Exception as e3:
-                        pass
+            # try:
+            #     # works for CheckBoxes
+            #     self.ui.grid3.itemAt(i).widget().stateChanged.connect(self.gui_form_to_storage)
+            # except Exception as e:
+            #     # works for ComboBoxes
+            #     try:
+            #         self.ui.grid3.itemAt(i).widget().currentIndexChanged.connect(self.gui_form_to_storage)
+            #     except Exception as e2:
+            #         # works for Entry
+            #         try:
+            #             self.ui.grid3.itemAt(i).widget().editingFinished.connect(self.gui_form_to_storage)
+            #         except Exception as e3:
+            #             pass
+
+            current_widget = self.ui.grid3.itemAt(i).widget()
+            if isinstance(current_widget, FCCheckBox):
+                current_widget.stateChanged.connect(self.gui_form_to_storage)
+            elif isinstance(current_widget, FCComboBox):
+                current_widget.currentIndexChanged.connect(self.gui_form_to_storage)
+            elif isinstance(current_widget, FloatEntry) or isinstance(current_widget, LengthEntry) or \
+                    isinstance(current_widget, FCEntry) or isinstance(current_widget, IntEntry):
+                current_widget.editingFinished.connect(self.gui_form_to_storage)
 
 
         for row in range(self.ui.geo_tools_table.rowCount()):
         for row in range(self.ui.geo_tools_table.rowCount()):
             for col in [2, 3, 4]:
             for col in [2, 3, 4]:
@@ -3423,75 +3480,94 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
 
     def ui_disconnect(self):
     def ui_disconnect(self):
 
 
-        try:
-            # on any change to the widgets that matter it will be called self.gui_form_to_storage which will save the
-            # changes in geometry UI
-            for i in range(self.ui.grid3.count()):
-                if isinstance(self.ui.grid3.itemAt(i).widget(), FCCheckBox):
-                    self.ui.grid3.itemAt(i).widget().stateChanged.disconnect()
-
-                if isinstance(self.ui.grid3.itemAt(i).widget(), FCComboBox):
-                    self.ui.grid3.itemAt(i).widget().currentIndexChanged.disconnect()
-
-                if isinstance(self.ui.grid3.itemAt(i).widget(), LengthEntry) or \
-                        isinstance(self.ui.grid3.itemAt(i).widget(), IntEntry) or \
-                        isinstance(self.ui.grid3.itemAt(i).widget(), FCEntry):
-                    self.ui.grid3.itemAt(i).widget().editingFinished.disconnect()
-        except Exception as e:
-            pass
+        # on any change to the widgets that matter it will be called self.gui_form_to_storage which will save the
+        # changes in geometry UI
+        for i in range(self.ui.grid3.count()):
+            # try:
+            #     # works for CheckBoxes
+            #     self.ui.grid3.itemAt(i).widget().stateChanged.disconnect(self.gui_form_to_storage)
+            # except Exception as e:
+            #     # works for ComboBoxes
+            #     try:
+            #         self.ui.grid3.itemAt(i).widget().currentIndexChanged.disconnect(self.gui_form_to_storage)
+            #     except Exception as e2:
+            #         # works for Entry
+            #         try:
+            #             self.ui.grid3.itemAt(i).widget().editingFinished.disconnect(self.gui_form_to_storage)
+            #         except Exception as e3:
+            #             pass
+
+            current_widget = self.ui.grid3.itemAt(i).widget()
+            if isinstance(current_widget, FCCheckBox):
+                try:
+                    self.ui.grid3.itemAt(i).widget().stateChanged.disconnect(self.gui_form_to_storage)
+                except TypeError:
+                    pass
+            elif isinstance(current_widget, FCComboBox):
+                try:
+                    self.ui.grid3.itemAt(i).widget().currentIndexChanged.disconnect(self.gui_form_to_storage)
+                except TypeError:
+                    pass
+            elif isinstance(current_widget, LengthEntry) or isinstance(current_widget, IntEntry) or \
+                    isinstance(current_widget, FCEntry) or isinstance(current_widget, FloatEntry):
+                try:
+                    self.ui.grid3.itemAt(i).widget().editingFinished.disconnect(self.gui_form_to_storage)
+                except TypeError:
+                    pass
 
 
-        try:
-            for row in range(self.ui.geo_tools_table.rowCount()):
-                for col in [2, 3, 4]:
+        for row in range(self.ui.geo_tools_table.rowCount()):
+            for col in [2, 3, 4]:
+                try:
                     self.ui.geo_tools_table.cellWidget(row, col).currentIndexChanged.disconnect()
                     self.ui.geo_tools_table.cellWidget(row, col).currentIndexChanged.disconnect()
-        except Exception as e:
-            pass
+                except TypeError:
+                    pass
 
 
-        # I use lambda's because the connected functions have parameters that could be used in certain scenarios
         try:
         try:
             self.ui.addtool_btn.clicked.disconnect()
             self.ui.addtool_btn.clicked.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.ui.copytool_btn.clicked.disconnect()
             self.ui.copytool_btn.clicked.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.ui.deltool_btn.clicked.disconnect()
             self.ui.deltool_btn.clicked.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.ui.geo_tools_table.currentItemChanged.disconnect()
             self.ui.geo_tools_table.currentItemChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.ui.geo_tools_table.itemChanged.disconnect()
             self.ui.geo_tools_table.itemChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.ui.tool_offset_entry.editingFinished.disconnect()
             self.ui.tool_offset_entry.editingFinished.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         for row in range(self.ui.geo_tools_table.rowCount()):
         for row in range(self.ui.geo_tools_table.rowCount()):
             try:
             try:
                 self.ui.geo_tools_table.cellWidget(row, 6).clicked.disconnect()
                 self.ui.geo_tools_table.cellWidget(row, 6).clicked.disconnect()
-            except Exception as e:
+            except TypeError:
                 pass
                 pass
 
 
         try:
         try:
             self.ui.plot_cb.stateChanged.disconnect()
             self.ui.plot_cb.stateChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
     def on_tool_add(self, dia=None):
     def on_tool_add(self, dia=None):
         self.ui_disconnect()
         self.ui_disconnect()
 
 
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
+
         # if a Tool diameter entered is a char instead a number the final message of Tool adding is changed
         # if a Tool diameter entered is a char instead a number the final message of Tool adding is changed
         # because the Default value for Tool is used.
         # because the Default value for Tool is used.
         change_message = False
         change_message = False
@@ -3507,7 +3583,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                     tooldia = float(self.ui.addtool_entry.get_value().replace(',', '.'))
                     tooldia = float(self.ui.addtool_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
                     change_message = True
                     change_message = True
-                    tooldia = self.options["cnctooldia"][0]
+                    tooldia = float(self.options["cnctooldia"][0])
 
 
             if tooldia is None:
             if tooldia is None:
                 self.build_ui()
                 self.build_ui()
@@ -3581,7 +3657,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         # we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
         # we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
         try:
         try:
             self.ser_attrs.remove('tools')
             self.ser_attrs.remove('tools')
-        except Exception as e:
+        except TypeError:
             pass
             pass
         self.ser_attrs.append('tools')
         self.ser_attrs.append('tools')
 
 
@@ -3592,10 +3668,14 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         else:
         else:
             change_message = False
             change_message = False
             self.app.inform.emit(_(
             self.app.inform.emit(_(
-                "[ERROR_NOTCL] Default Tool added. Wrong value format entered."
+                "[WARNING_NOTCL] Default Tool added. Wrong value format entered."
             ))
             ))
         self.build_ui()
         self.build_ui()
 
 
+        # if there is no tool left in the Tools Table, enable the parameters GUI
+        if self.ui.geo_tools_table.rowCount() != 0:
+            self.ui.geo_param_frame.setDisabled(False)
+
     def on_tool_copy(self, all=None):
     def on_tool_copy(self, all=None):
         self.ui_disconnect()
         self.ui_disconnect()
 
 
@@ -3655,7 +3735,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         # we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
         # we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
         try:
         try:
             self.ser_attrs.remove('tools')
             self.ser_attrs.remove('tools')
-        except:
+        except Exception as e:
             pass
             pass
         self.ser_attrs.append('tools')
         self.ser_attrs.append('tools')
 
 
@@ -3690,7 +3770,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         try:
         try:
             self.ser_attrs.remove('tools')
             self.ser_attrs.remove('tools')
             self.ser_attrs.append('tools')
             self.ser_attrs.append('tools')
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         self.app.inform.emit(_(
         self.app.inform.emit(_(
@@ -3699,7 +3779,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         self.build_ui()
         self.build_ui()
 
 
     def on_tool_delete(self, all=None):
     def on_tool_delete(self, all=None):
-
         self.ui_disconnect()
         self.ui_disconnect()
 
 
         if all is None:
         if all is None:
@@ -3749,7 +3828,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         # we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
         # we do this HACK to make sure the tools attribute to be serialized is updated in the self.ser_attrs list
         try:
         try:
             self.ser_attrs.remove('tools')
             self.ser_attrs.remove('tools')
-        except Exception as e:
+        except TypeError:
             pass
             pass
         self.ser_attrs.append('tools')
         self.ser_attrs.append('tools')
 
 
@@ -3779,6 +3858,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 obj_active.options['xmax'] = 0
                 obj_active.options['xmax'] = 0
                 obj_active.options['ymax'] = 0
                 obj_active.options['ymax'] = 0
 
 
+        # if there is no tool left in the Tools Table, disable the parameters GUI
+        if self.ui.geo_tools_table.rowCount() == 0:
+            self.ui.geo_param_frame.setDisabled(True)
+
     def on_row_selection_change(self):
     def on_row_selection_change(self):
         self.update_ui()
         self.update_ui()
 
 
@@ -3838,7 +3921,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                             self.update_cutz()
                             self.update_cutz()
         except Exception as e:
         except Exception as e:
             log.debug("FlatCAMObj ---> update_ui() " + str(e))
             log.debug("FlatCAMObj ---> update_ui() " + str(e))
-
         self.ui_connect()
         self.ui_connect()
 
 
     def ui_update_v_shape(self, tool_type_txt):
     def ui_update_v_shape(self, tool_type_txt):
@@ -3952,6 +4034,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
 
     def gui_form_to_storage(self):
     def gui_form_to_storage(self):
 
 
+        if self.ui.geo_tools_table.rowCount() == 0:
+            # there is no tool in tool table so we can't save the GUI elements values to storage
+            log.debug("FlatCAMGeometry.gui_form_to_storage() --> no tool in Tools Table, aborting.")
+            return
+
         self.ui_disconnect()
         self.ui_disconnect()
         widget_changed = self.sender()
         widget_changed = self.sender()
         try:
         try:
@@ -4345,7 +4432,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
 
                     if diadict_key == 'data':
                     if diadict_key == 'data':
                         for data_key, data_value in diadict_value.items():
                         for data_key, data_value in diadict_value.items():
-                            if data_key ==  "multidepth":
+                            if data_key == "multidepth":
                                 multidepth = data_value
                                 multidepth = data_value
                             if data_key == "depthperpass":
                             if data_key == "depthperpass":
                                 depthpercut = data_value
                                 depthpercut = data_value
@@ -5459,7 +5546,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
 
 
         try:
         try:
             self.ui.annotation_cb.stateChanged.disconnect(self.on_annotation_change)
             self.ui.annotation_cb.stateChanged.disconnect(self.on_annotation_change)
-        except:
+        except TypeError:
             pass
             pass
         self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
         self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
 
 
@@ -5503,7 +5590,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
             self.ui.cnc_tools_table.cellWidget(row, 6).clicked.disconnect(self.on_plot_cb_click_table)
             self.ui.cnc_tools_table.cellWidget(row, 6).clicked.disconnect(self.on_plot_cb_click_table)
         try:
         try:
             self.ui.plot_cb.stateChanged.disconnect(self.on_plot_cb_click)
             self.ui.plot_cb.stateChanged.disconnect(self.on_plot_cb_click)
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
     def on_updateplot_button_click(self, *args):
     def on_updateplot_button_click(self, *args):

+ 6 - 6
FlatCAMTranslation.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 import os
 import os
 import sys
 import sys
@@ -16,10 +16,10 @@ from PyQt5.QtCore import QSettings
 from flatcamGUI.GUIElements import log
 from flatcamGUI.GUIElements import log
 import gettext
 import gettext
 
 
-import builtins
-
-if '_' not in builtins.__dict__:
-    _ = gettext.gettext
+# import builtins
+#
+# if '_' not in builtins.__dict__:
+#     _ = gettext.gettext
 
 
 # ISO639-1 codes from here: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
 # ISO639-1 codes from here: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
 languages_dict = {
 languages_dict = {

+ 34 - 1
README.md

@@ -9,11 +9,44 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+30.07.2019
+
+- fixed bug that crashed the software when trying to edit a GUI value in Geometry selected tab without having a tool in the Tools Table
+- fixed bug that crashed the app when trying to add a tool without a tool diameter value
+- Spanish Google translation at 77%
+- changed the Disable plots menu entry in the context menu, into a Toggle Visibility menu entry
+- Spanish Google translation 100% but two strings (big ones) - needs review
+- added two more strings to translation strings (due of German language)
+- completed the Russian translation using the Google and Yandex translation engines (minus two big strings) - needs review
+
+28.07.2019
+
+- fixed issue with not using the current units in the tool tables after unit conversion
+- after unit conversion from Preferences, the default values are automatically saved by the app
+- in Basic mode, the tool type column is no longer hidden as it may create issues when using an painted geometry
+- some PEP8 clean-up in FlatCAMGui.py
+- fixed Panelize Tool to do panelization for multiple passes type of geometry that comes out of the isolation done with multiple passes
+
+20.07.2019
+
+- updated the CutOut tool so it will work on single PCB Gerbers or on PCB panel Gerbers
+- updated languages
+- 70% progress in Spanish Google translation
+
+19.07.2019
+
+- fixed bug in FlatCAMObj.FlatCAMGeometry.ui_disconnect(); the widgets signals were not disconnected from handlers when required therefore the signals were connected in an exponential way
+- some changes in the widgets used in the Selected tab for Geometry object
+- some PEP8 cleanup in FlatCAMObj.py
+- updated languages
+- 60% progress in Spanish Google translation
+
 17.07.2019
 17.07.2019
 
 
-- added some more strings to the translateable ones, especially the radio button labels
+- added some more strings to the translatable ones, especially the radio button labels
 - updated the .POT file and the available translations
 - updated the .POT file and the available translations
 - 51% progress in Spanish Google translation
 - 51% progress in Spanish Google translation
+- version date change
 
 
 16.07.2019
 16.07.2019
 
 

+ 12 - 11
camlib.py

@@ -710,12 +710,12 @@ class Geometry(object):
 
 
             try:
             try:
                 green = src.read(2)
                 green = src.read(2)
-            except:
+            except Exception as e:
                 pass
                 pass
 
 
             try:
             try:
                 blue = src.read(3)
                 blue = src.read(3)
-            except:
+            except Exception as e:
                 pass
                 pass
 
 
         if mode == 'black':
         if mode == 'black':
@@ -2154,11 +2154,12 @@ class Gerber (Geometry):
 
 
                         # Otherwise leave as is.
                         # Otherwise leave as is.
                         else:
                         else:
-                            # yield cleanline
+                            # yield clean line
                             yield line
                             yield line
                             break
                             break
 
 
-            self.parse_lines(line_generator())
+            processed_lines = list(line_generator())
+            self.parse_lines(processed_lines)
 
 
     # @profile
     # @profile
     def parse_lines(self, glines):
     def parse_lines(self, glines):
@@ -2241,10 +2242,10 @@ class Gerber (Geometry):
                 gline = gline.strip(' \r\n')
                 gline = gline.strip(' \r\n')
                 # log.debug("Line=%3s %s" % (line_num, gline))
                 # log.debug("Line=%3s %s" % (line_num, gline))
 
 
-                # ############################################################# ##
-                # Ignored lines #
-                # Comments #### ##
-                # ############################################################# ##
+                # ###################
+                # Ignored lines #####
+                # Comments      #####
+                # ###################
                 match = self.comm_re.search(gline)
                 match = self.comm_re.search(gline)
                 if match:
                 if match:
                     continue
                     continue
@@ -2713,7 +2714,7 @@ class Gerber (Geometry):
                                         if 'geometry' not in self.apertures[current_aperture]:
                                         if 'geometry' not in self.apertures[current_aperture]:
                                             self.apertures[current_aperture]['geometry'] = []
                                             self.apertures[current_aperture]['geometry'] = []
                                         self.apertures[current_aperture]['geometry'].append(deepcopy(geo_dict))
                                         self.apertures[current_aperture]['geometry'].append(deepcopy(geo_dict))
-                                except:
+                                except Exception as e:
                                     pass
                                     pass
                             last_path_aperture = current_aperture
                             last_path_aperture = current_aperture
                             # we do this for the case that a region is done without having defined any aperture
                             # we do this for the case that a region is done without having defined any aperture
@@ -4086,7 +4087,7 @@ class Excellon(Geometry):
                             slot_dia = 0.05
                             slot_dia = 0.05
                             try:
                             try:
                                 slot_dia = float(self.tools[current_tool]['C'])
                                 slot_dia = float(self.tools[current_tool]['C'])
-                            except:
+                            except Exception as e:
                                 pass
                                 pass
                             log.debug(
                             log.debug(
                                 'Milling/Drilling slot with tool %s, diam=%f' % (
                                 'Milling/Drilling slot with tool %s, diam=%f' % (
@@ -4155,7 +4156,7 @@ class Excellon(Geometry):
                             slot_dia = 0.05
                             slot_dia = 0.05
                             try:
                             try:
                                 slot_dia = float(self.tools[current_tool]['C'])
                                 slot_dia = float(self.tools[current_tool]['C'])
-                            except:
+                            except Exception as e:
                                 pass
                                 pass
                             log.debug(
                             log.debug(
                                 'Milling/Drilling slot with tool %s, diam=%f' % (
                                 'Milling/Drilling slot with tool %s, diam=%f' % (

+ 12 - 11
flatcamEditors/FlatCAMExcEditor.py

@@ -49,7 +49,7 @@ class FCDrillAdd(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_drill.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_drill.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -91,7 +91,7 @@ class FCDrillAdd(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         # add the point to drills if the diameter is a key in the dict, if not, create it add the drill location
         # add the point to drills if the diameter is a key in the dict, if not, create it add the drill location
@@ -152,8 +152,9 @@ class FCDrillArray(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
+
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_drill_array.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_drill_array.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
 
 
@@ -274,7 +275,7 @@ class FCDrillArray(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         # add the point to drills if the diameter is a key in the dict, if not, create it add the drill location
         # add the point to drills if the diameter is a key in the dict, if not, create it add the drill location
@@ -599,7 +600,7 @@ class FCDrillSelect(DrawTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         self.exc_editor_app = exc_editor_app
         self.exc_editor_app = exc_editor_app
@@ -668,7 +669,7 @@ class FCDrillSelect(DrawTool):
             # select the diameter of the selected shape in the tool table
             # select the diameter of the selected shape in the tool table
             try:
             try:
                 self.draw_app.tools_table_exc.cellPressed.disconnect()
                 self.draw_app.tools_table_exc.cellPressed.disconnect()
-            except:
+            except TypeError:
                 pass
                 pass
 
 
             sel_tools = set()
             sel_tools = set()
@@ -1257,12 +1258,12 @@ class FlatCAMExcEditor(QtCore.QObject):
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             self.tools_table_exc.itemChanged.disconnect()
             self.tools_table_exc.itemChanged.disconnect()
-        except:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.tools_table_exc.cellPressed.disconnect()
             self.tools_table_exc.cellPressed.disconnect()
-        except:
+        except TypeError:
             pass
             pass
 
 
         # updated units
         # updated units
@@ -1704,7 +1705,7 @@ class FlatCAMExcEditor(QtCore.QObject):
     def deactivate(self):
     def deactivate(self):
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         # adjust the status of the menu entries related to the editor
         # adjust the status of the menu entries related to the editor
@@ -2311,7 +2312,7 @@ class FlatCAMExcEditor(QtCore.QObject):
                 if self.app.ui.popMenu.mouse_is_panning is False:
                 if self.app.ui.popMenu.mouse_is_panning is False:
                     try:
                     try:
                         QtGui.QGuiApplication.restoreOverrideCursor()
                         QtGui.QGuiApplication.restoreOverrideCursor()
-                    except:
+                    except Exception as e:
                         pass
                         pass
                     if self.active_tool.complete is False and not isinstance(self.active_tool, FCDrillSelect):
                     if self.active_tool.complete is False and not isinstance(self.active_tool, FCDrillSelect):
                         self.active_tool.complete = True
                         self.active_tool.complete = True
@@ -2380,7 +2381,7 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         try:
         try:
             self.tools_table_exc.cellPressed.disconnect()
             self.tools_table_exc.cellPressed.disconnect()
-        except:
+        except Exception as e:
             pass
             pass
         # select the diameter of the selected shape in the tool table
         # select the diameter of the selected shape in the tool table
         self.tools_table_exc.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
         self.tools_table_exc.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)

+ 14 - 14
flatcamEditors/FlatCAMGeoEditor.py

@@ -1921,7 +1921,7 @@ class FCCircle(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_circle_geo.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_circle_geo.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -1954,7 +1954,7 @@ class FCCircle(FCShapeTool):
     def make(self):
     def make(self):
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         p1 = self.points[0]
         p1 = self.points[0]
@@ -1972,7 +1972,7 @@ class FCArc(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_arc.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_arc.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -2190,7 +2190,7 @@ class FCRectangle(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -2221,7 +2221,7 @@ class FCRectangle(FCShapeTool):
     def make(self):
     def make(self):
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         p1 = self.points[0]
         p1 = self.points[0]
@@ -2243,7 +2243,7 @@ class FCPolygon(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -2276,7 +2276,7 @@ class FCPolygon(FCShapeTool):
     def make(self):
     def make(self):
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         # self.geometry = LinearRing(self.points)
         # self.geometry = LinearRing(self.points)
@@ -2305,7 +2305,7 @@ class FCPath(FCPolygon):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_path5.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_path5.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -2316,7 +2316,7 @@ class FCPath(FCPolygon):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
@@ -2349,7 +2349,7 @@ class FCSelect(DrawTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         self.storage = self.draw_app.storage
         self.storage = self.draw_app.storage
@@ -2433,7 +2433,7 @@ class FCMove(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         self.storage = self.draw_app.storage
         self.storage = self.draw_app.storage
@@ -2613,7 +2613,7 @@ class FCText(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_text.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_text.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -3173,7 +3173,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
     def deactivate(self):
     def deactivate(self):
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
 
 
         # adjust the status of the menu entries related to the editor
         # adjust the status of the menu entries related to the editor
@@ -3638,7 +3638,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
                     if self.in_action is False:
                     if self.in_action is False:
                         try:
                         try:
                             QtGui.QGuiApplication.restoreOverrideCursor()
                             QtGui.QGuiApplication.restoreOverrideCursor()
-                        except:
+                        except Exception as e:
                             pass
                             pass
 
 
                         if self.active_tool.complete is False and not isinstance(self.active_tool, FCSelect):
                         if self.active_tool.complete is False and not isinstance(self.active_tool, FCSelect):

+ 5 - 5
flatcamEditors/FlatCAMGrbEditor.py

@@ -188,7 +188,7 @@ class FCPad(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_circle.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_circle.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -403,7 +403,7 @@ class FCPadArray(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_array.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_array.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -1341,7 +1341,7 @@ class FCDisc(FCShapeTool):
 
 
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except:
+        except Exception as e:
             pass
             pass
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_disc.png'))
         self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_disc.png'))
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
         QtGui.QGuiApplication.setOverrideCursor(self.cursor)
@@ -2934,12 +2934,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             self.apertures_table.itemChanged.disconnect()
             self.apertures_table.itemChanged.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.apertures_table.cellPressed.disconnect()
             self.apertures_table.cellPressed.disconnect()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         # updated units
         # updated units

+ 92 - 88
flatcamGUI/FlatCAMGUI.py

@@ -20,12 +20,13 @@ from flatcamEditors.FlatCAMGeoEditor import FCShapeTool
 
 
 import gettext
 import gettext
 import FlatCAMTranslation as fcTranslate
 import FlatCAMTranslation as fcTranslate
+import builtins
 
 
 fcTranslate.apply_language('strings')
 fcTranslate.apply_language('strings')
-import builtins
 if '_' not in builtins.__dict__:
 if '_' not in builtins.__dict__:
     _ = gettext.gettext
     _ = gettext.gettext
 
 
+
 class FlatCAMGUI(QtWidgets.QMainWindow):
 class FlatCAMGUI(QtWidgets.QMainWindow):
     # Emitted when persistent window geometry needs to be retained
     # Emitted when persistent window geometry needs to be retained
     geom_update = QtCore.pyqtSignal(int, int, int, int, int, name='geomUpdate')
     geom_update = QtCore.pyqtSignal(int, int, int, int, int, name='geomUpdate')
@@ -87,8 +88,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
 
         # Open Excellon ...
         # Open Excellon ...
         self.menufileopenexcellon = QtWidgets.QAction(QtGui.QIcon('share/open_excellon32.png'),
         self.menufileopenexcellon = QtWidgets.QAction(QtGui.QIcon('share/open_excellon32.png'),
-                                                      _('Open &Excellon ...\tCTRL+E'),
-                                                  self)
+                                                      _('Open &Excellon ...\tCTRL+E'), self)
         self.menufile_open.addAction(self.menufileopenexcellon)
         self.menufile_open.addAction(self.menufileopenexcellon)
 
 
         # Open G-Code ...
         # Open G-Code ...
@@ -115,16 +115,14 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.menufile_scripting = self.menufile.addMenu(QtGui.QIcon('share/script16.png'), _('Scripting'))
         self.menufile_scripting = self.menufile.addMenu(QtGui.QIcon('share/script16.png'), _('Scripting'))
         self.menufile_scripting.setToolTipsVisible(True)
         self.menufile_scripting.setToolTipsVisible(True)
 
 
-        self.menufilenewscript = QtWidgets.QAction(QtGui.QIcon('share/script_new16.png'), _('New Script ...'),
-                                                   self)
-        self.menufileopenscript = QtWidgets.QAction(QtGui.QIcon('share/script_open16.png'), _('Open Script ...'),
-                                                   self)
-        self.menufilerunscript = QtWidgets.QAction(QtGui.QIcon('share/script16.png'), _('Run Script ...\tSHIFT+S'),
-                                                   self)
+        self.menufilenewscript = QtWidgets.QAction(QtGui.QIcon('share/script_new16.png'), _('New Script ...'), self)
+        self.menufileopenscript = QtWidgets.QAction(QtGui.QIcon('share/script_open16.png'), _('Open Script ...'), self)
+        self.menufilerunscript = QtWidgets.QAction(QtGui.QIcon('share/script16.png'),
+                                                   _('Run Script ...\tSHIFT+S'), self)
         self.menufilerunscript.setToolTip(
         self.menufilerunscript.setToolTip(
-           _( "Will run the opened Tcl Script thus\n"
-            "enabling the automation of certain\n"
-            "functions of FlatCAM.")
+           _("Will run the opened Tcl Script thus\n"
+             "enabling the automation of certain\n"
+             "functions of FlatCAM.")
         )
         )
         self.menufile_scripting.addAction(self.menufilenewscript)
         self.menufile_scripting.addAction(self.menufilenewscript)
         self.menufile_scripting.addAction(self.menufileopenscript)
         self.menufile_scripting.addAction(self.menufileopenscript)
@@ -174,8 +172,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
 
         self.menufileexport.addSeparator()
         self.menufileexport.addSeparator()
 
 
-        self.menufileexportexcellon = QtWidgets.QAction(QtGui.QIcon('share/drill32.png'), _('Export &Excellon ...'),
-                                                        self)
+        self.menufileexportexcellon = QtWidgets.QAction(QtGui.QIcon('share/drill32.png'),
+                                                        _('Export &Excellon ...'), self)
         self.menufileexportexcellon.setToolTip(
         self.menufileexportexcellon.setToolTip(
            _("Will export an Excellon Object as Excellon file,\n"
            _("Will export an Excellon Object as Excellon file,\n"
              "the coordinates format, the file units and zeros\n"
              "the coordinates format, the file units and zeros\n"
@@ -183,8 +181,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         )
         )
         self.menufileexport.addAction(self.menufileexportexcellon)
         self.menufileexport.addAction(self.menufileexportexcellon)
 
 
-        self.menufileexportgerber = QtWidgets.QAction(QtGui.QIcon('share/flatcam_icon32.png'), _('Export &Gerber ...'),
-                                                        self)
+        self.menufileexportgerber = QtWidgets.QAction(QtGui.QIcon('share/flatcam_icon32.png'),
+                                                      _('Export &Gerber ...'), self)
         self.menufileexportgerber.setToolTip(
         self.menufileexportgerber.setToolTip(
             _("Will export an Gerber Object as Gerber file,\n"
             _("Will export an Gerber Object as Gerber file,\n"
               "the coordinates format, the file units and zeros\n"
               "the coordinates format, the file units and zeros\n"
@@ -214,8 +212,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.menufile_save.addAction(self.menufilesaveprojectas)
         self.menufile_save.addAction(self.menufilesaveprojectas)
 
 
         # Save Project Copy ...
         # Save Project Copy ...
-        self.menufilesaveprojectcopy = QtWidgets.QAction(QtGui.QIcon('share/floppy16.png'), _('Save Project C&opy ...'),
-                                                     self)
+        self.menufilesaveprojectcopy = QtWidgets.QAction(QtGui.QIcon('share/floppy16.png'),
+                                                         _('Save Project C&opy ...'), self)
         self.menufile_save.addAction(self.menufilesaveprojectcopy)
         self.menufile_save.addAction(self.menufilesaveprojectcopy)
 
 
         # Separator
         # Separator
@@ -253,7 +251,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.menuedit_convertjoinexc = self.menuedit_convert.addAction(
         self.menuedit_convertjoinexc = self.menuedit_convert.addAction(
             QtGui.QIcon('share/join16.png'), _('Join Excellon(s) -> Excellon'))
             QtGui.QIcon('share/join16.png'), _('Join Excellon(s) -> Excellon'))
         self.menuedit_convertjoinexc.setToolTip(
         self.menuedit_convertjoinexc.setToolTip(
-           _( "Merge a selection of Excellon objects into a new combo Excellon object.")
+           _("Merge a selection of Excellon objects into a new combo Excellon object.")
         )
         )
         self.menuedit_convertjoingrb = self.menuedit_convert.addAction(
         self.menuedit_convertjoingrb = self.menuedit_convert.addAction(
             QtGui.QIcon('share/join16.png'), _('Join Gerber(s) -> Gerber'))
             QtGui.QIcon('share/join16.png'), _('Join Gerber(s) -> Gerber'))
@@ -279,7 +277,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.menueditconvert_any2geo = self.menuedit_convert.addAction(QtGui.QIcon('share/copy_geo.png'),
         self.menueditconvert_any2geo = self.menuedit_convert.addAction(QtGui.QIcon('share/copy_geo.png'),
                                                                        _('Convert Any to Geo'))
                                                                        _('Convert Any to Geo'))
         self.menueditconvert_any2gerber = self.menuedit_convert.addAction(QtGui.QIcon('share/copy_geo.png'),
         self.menueditconvert_any2gerber = self.menuedit_convert.addAction(QtGui.QIcon('share/copy_geo.png'),
-                                                                       _('Convert Any to Gerber'))
+                                                                          _('Convert Any to Gerber'))
         self.menuedit_convert.setToolTipsVisible(True)
         self.menuedit_convert.setToolTipsVisible(True)
 
 
         # Separator
         # Separator
@@ -297,10 +295,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
 
         # Separator
         # Separator
         self.menuedit.addSeparator()
         self.menuedit.addSeparator()
-        self.menuedittoggleunits= self.menuedit.addAction(QtGui.QIcon('share/toggle_units16.png'),
-                                                         _('Toggle Units\tQ'))
-        self.menueditselectall = self.menuedit.addAction(QtGui.QIcon('share/select_all.png'),
-                                                         _('&Select All\tCTRL+A'))
+        self.menuedittoggleunits = self.menuedit.addAction(QtGui.QIcon('share/toggle_units16.png'),
+                                                           _('Toggle Units\tQ'))
+        self.menueditselectall = self.menuedit.addAction(QtGui.QIcon('share/select_all.png'), _('&Select All\tCTRL+A'))
 
 
         # Separator
         # Separator
         self.menuedit.addSeparator()
         self.menuedit.addSeparator()
@@ -329,7 +326,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.menuoptions_transform_skewx = self.menuoptions.addAction(QtGui.QIcon('share/skewX.png'),
         self.menuoptions_transform_skewx = self.menuoptions.addAction(QtGui.QIcon('share/skewX.png'),
                                                                       _("&Skew on X axis\tSHIFT+X"))
                                                                       _("&Skew on X axis\tSHIFT+X"))
         self.menuoptions_transform_skewy = self.menuoptions.addAction(QtGui.QIcon('share/skewY.png'),
         self.menuoptions_transform_skewy = self.menuoptions.addAction(QtGui.QIcon('share/skewY.png'),
-                                                                      _( "S&kew on Y axis\tSHIFT+Y"))
+                                                                      _("S&kew on Y axis\tSHIFT+Y"))
 
 
         # Separator
         # Separator
         self.menuoptions.addSeparator()
         self.menuoptions.addSeparator()
@@ -430,13 +427,13 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geo_editor_menu.addSeparator()
         self.geo_editor_menu.addSeparator()
         self.geo_move_menuitem = self.geo_editor_menu.addAction(QtGui.QIcon('share/move32.png'), _("Move\tM"))
         self.geo_move_menuitem = self.geo_editor_menu.addAction(QtGui.QIcon('share/move32.png'), _("Move\tM"))
         self.geo_buffer_menuitem = self.geo_editor_menu.addAction(
         self.geo_buffer_menuitem = self.geo_editor_menu.addAction(
-            QtGui.QIcon('share/buffer16.png'),_( "Buffer Tool\tB")
+            QtGui.QIcon('share/buffer16.png'), _("Buffer Tool\tB")
         )
         )
         self.geo_paint_menuitem = self.geo_editor_menu.addAction(
         self.geo_paint_menuitem = self.geo_editor_menu.addAction(
             QtGui.QIcon('share/paint16.png'), _("Paint Tool\tI")
             QtGui.QIcon('share/paint16.png'), _("Paint Tool\tI")
         )
         )
         self.geo_transform_menuitem = self.geo_editor_menu.addAction(
         self.geo_transform_menuitem = self.geo_editor_menu.addAction(
-            QtGui.QIcon('share/transform.png'),_( "Transform Tool\tALT+R")
+            QtGui.QIcon('share/transform.png'), _("Transform Tool\tALT+R")
         )
         )
         self.geo_editor_menu.addSeparator()
         self.geo_editor_menu.addSeparator()
         self.geo_cornersnap_menuitem = self.geo_editor_menu.addAction(
         self.geo_cornersnap_menuitem = self.geo_editor_menu.addAction(
@@ -461,50 +458,45 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         )
         )
         self.exc_editor_menu.addSeparator()
         self.exc_editor_menu.addSeparator()
 
 
-        self.exc_move_drill_menuitem = self.exc_editor_menu.addAction(
-            QtGui.QIcon('share/move32.png'),_( 'Move Drill(s)\tM'))
+        self.exc_move_drill_menuitem = self.exc_editor_menu.addAction(QtGui.QIcon('share/move32.png'),
+                                                                      _('Move Drill(s)\tM'))
 
 
         # ## APPLICATION GERBER EDITOR MENU ###
         # ## APPLICATION GERBER EDITOR MENU ###
         self.grb_editor_menu = QtWidgets.QMenu(_(">Gerber Editor<"))
         self.grb_editor_menu = QtWidgets.QMenu(_(">Gerber Editor<"))
         self.menu.addMenu(self.grb_editor_menu)
         self.menu.addMenu(self.grb_editor_menu)
 
 
-        self.grb_add_pad_menuitem = self.grb_editor_menu.addAction(
-            QtGui.QIcon('share/aperture16.png'), _('Add Pad\tP'))
-        self.grb_add_pad_array_menuitem = self.grb_editor_menu.addAction(
-            QtGui.QIcon('share/padarray32.png'), _('Add Pad Array\tA'))
-        self.grb_add_track_menuitem = self.grb_editor_menu.addAction(
-            QtGui.QIcon('share/track32.png'), _('Add Track\tT'))
+        self.grb_add_pad_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/aperture16.png'),
+                                                                   _('Add Pad\tP'))
+        self.grb_add_pad_array_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/padarray32.png'),
+                                                                         _('Add Pad Array\tA'))
+        self.grb_add_track_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/track32.png'),
+                                                                     _('Add Track\tT'))
         self.grb_add_region_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/rectangle32.png'),
         self.grb_add_region_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/rectangle32.png'),
                                                                       _('Add Region\tN'))
                                                                       _('Add Region\tN'))
         self.grb_editor_menu.addSeparator()
         self.grb_editor_menu.addSeparator()
 
 
-        self.grb_convert_poly_menuitem  = self.grb_editor_menu.addAction(QtGui.QIcon('share/poligonize32.png'),
-                                                                         _("Poligonize\tALT+N"))
+        self.grb_convert_poly_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/poligonize32.png'),
+                                                                        _("Poligonize\tALT+N"))
         self.grb_add_semidisc_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/semidisc32.png'),
         self.grb_add_semidisc_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/semidisc32.png'),
                                                                         _("Add SemiDisc\tE"))
                                                                         _("Add SemiDisc\tE"))
-        self.grb_add_disc_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/disc32.png'),
-                                                                        _("Add Disc\tD"))
+        self.grb_add_disc_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/disc32.png'), _("Add Disc\tD"))
         self.grb_add_buffer_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/buffer16-2.png'),
         self.grb_add_buffer_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/buffer16-2.png'),
                                                                       _('Buffer\tB'))
                                                                       _('Buffer\tB'))
-        self.grb_add_scale_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/scale32.png'),
-                                                                     _('Scale\tS'))
+        self.grb_add_scale_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/scale32.png'), _('Scale\tS'))
         self.grb_add_markarea_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/markarea32.png'),
         self.grb_add_markarea_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/markarea32.png'),
-                                                                     _('Mark Area\tALT+A'))
+                                                                        _('Mark Area\tALT+A'))
         self.grb_add_eraser_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/eraser26.png'),
         self.grb_add_eraser_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/eraser26.png'),
-                                                                     _('Eraser\tCTRL+E'))
-        self.grb_transform_menuitem = self.grb_editor_menu.addAction(
-            QtGui.QIcon('share/transform.png'),_( "Transform\tALT+R")
-        )
+                                                                      _('Eraser\tCTRL+E'))
+        self.grb_transform_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/transform.png'),
+                                                                     _("Transform\tALT+R"))
         self.grb_editor_menu.addSeparator()
         self.grb_editor_menu.addSeparator()
 
 
         self.grb_copy_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/copy32.png'), _('Copy\tC'))
         self.grb_copy_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/copy32.png'), _('Copy\tC'))
-        self.grb_delete_menuitem = self.grb_editor_menu.addAction(
-            QtGui.QIcon('share/deleteshape32.png'), _('Delete\tDEL')
-        )
+        self.grb_delete_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/deleteshape32.png'),
+                                                                  _('Delete\tDEL'))
         self.grb_editor_menu.addSeparator()
         self.grb_editor_menu.addSeparator()
 
 
-        self.grb_move_menuitem = self.grb_editor_menu.addAction(
-            QtGui.QIcon('share/move32.png'),_( 'Move\tM'))
+        self.grb_move_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/move32.png'), _('Move\tM'))
 
 
         self.grb_editor_menu.menuAction().setVisible(False)
         self.grb_editor_menu.menuAction().setVisible(False)
         self.grb_editor_menu.setDisabled(True)
         self.grb_editor_menu.setDisabled(True)
@@ -529,7 +521,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.menuprojectedit = self.menuproject.addAction(QtGui.QIcon('share/edit_ok32.png'), _('Edit'))
         self.menuprojectedit = self.menuproject.addAction(QtGui.QIcon('share/edit_ok32.png'), _('Edit'))
         self.menuprojectcopy = self.menuproject.addAction(QtGui.QIcon('share/copy32.png'), _('Copy'))
         self.menuprojectcopy = self.menuproject.addAction(QtGui.QIcon('share/copy32.png'), _('Copy'))
         self.menuprojectdelete = self.menuproject.addAction(QtGui.QIcon('share/delete32.png'), _('Delete'))
         self.menuprojectdelete = self.menuproject.addAction(QtGui.QIcon('share/delete32.png'), _('Delete'))
-        self.menuprojectsave= self.menuproject.addAction(QtGui.QIcon('share/save_as.png'), _('Save'))
+        self.menuprojectsave = self.menuproject.addAction(QtGui.QIcon('share/save_as.png'), _('Save'))
         self.menuproject.addSeparator()
         self.menuproject.addSeparator()
 
 
         self.menuprojectproperties = self.menuproject.addAction(QtGui.QIcon('share/properties32.png'), _('Properties'))
         self.menuprojectproperties = self.menuproject.addAction(QtGui.QIcon('share/properties32.png'), _('Properties'))
@@ -648,7 +640,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.toolbartools.addSeparator()
         self.toolbartools.addSeparator()
 
 
         self.panelize_btn = self.toolbartools.addAction(QtGui.QIcon('share/panel16.png'), _("Panel Tool"))
         self.panelize_btn = self.toolbartools.addAction(QtGui.QIcon('share/panel16.png'), _("Panel Tool"))
-        self.film_btn = self.toolbartools.addAction(QtGui.QIcon('share/film16.png'),_( "Film Tool"))
+        self.film_btn = self.toolbartools.addAction(QtGui.QIcon('share/film16.png'), _("Film Tool"))
         self.solder_btn = self.toolbartools.addAction(QtGui.QIcon('share/solderpastebis32.png'), _("SolderPaste Tool"))
         self.solder_btn = self.toolbartools.addAction(QtGui.QIcon('share/solderpastebis32.png'), _("SolderPaste Tool"))
         self.sub_btn = self.toolbartools.addAction(QtGui.QIcon('share/sub32.png'), _("Substract Tool"))
         self.sub_btn = self.toolbartools.addAction(QtGui.QIcon('share/sub32.png'), _("Substract Tool"))
 
 
@@ -1593,7 +1585,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         # ########################################################### ##
         # ########################################################### ##
         self.popMenu = FCMenu()
         self.popMenu = FCMenu()
 
 
-        self.popmenu_disable = self.popMenu.addAction(QtGui.QIcon('share/disable32.png'), _("Disable Plot"))
+        self.popmenu_disable = self.popMenu.addAction(QtGui.QIcon('share/disable32.png'), _("Toggle Visibility"))
         self.popmenu_panel_toggle = self.popMenu.addAction(QtGui.QIcon('share/notebook16.png'), _("Toggle Panel"))
         self.popmenu_panel_toggle = self.popMenu.addAction(QtGui.QIcon('share/notebook16.png'), _("Toggle Panel"))
 
 
         self.popMenu.addSeparator()
         self.popMenu.addSeparator()
@@ -1641,10 +1633,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.popmenu_move = self.popMenu.addAction(QtGui.QIcon('share/move32.png'), _("Move"))
         self.popmenu_move = self.popMenu.addAction(QtGui.QIcon('share/move32.png'), _("Move"))
         self.popmenu_properties = self.popMenu.addAction(QtGui.QIcon('share/properties32.png'), _("Properties"))
         self.popmenu_properties = self.popMenu.addAction(QtGui.QIcon('share/properties32.png'), _("Properties"))
 
 
-
-        ################################## ##
-        # ## Here we build the CNCJob Tab # ##
-        ################################## ##
+        # ###################################
+        # ## Here we build the CNCJob Tab ###
+        # ###################################
         self.cncjob_tab = QtWidgets.QWidget()
         self.cncjob_tab = QtWidgets.QWidget()
         self.cncjob_tab_layout = QtWidgets.QGridLayout(self.cncjob_tab)
         self.cncjob_tab_layout = QtWidgets.QGridLayout(self.cncjob_tab)
         self.cncjob_tab_layout.setContentsMargins(2, 2, 2, 2)
         self.cncjob_tab_layout.setContentsMargins(2, 2, 2, 2)
@@ -1701,9 +1692,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         cnc_tab_lay_4.addWidget(self.buttonSave)
         cnc_tab_lay_4.addWidget(self.buttonSave)
         self.cncjob_tab_layout.addLayout(cnc_tab_lay_4, 2, 4, 1, 1)
         self.cncjob_tab_layout.addLayout(cnc_tab_lay_4, 2, 4, 1, 1)
 
 
-        ################################ ##
-        # ## Build InfoBar is done here # ##
-        ################################ ##
+        # #################################
+        # ## Build InfoBar is done here ###
+        # #################################
         self.infobar = self.statusBar()
         self.infobar = self.statusBar()
         self.fcinfo = FlatCAMInfoBar()
         self.fcinfo = FlatCAMInfoBar()
         self.infobar.addWidget(self.fcinfo, stretch=1)
         self.infobar.addWidget(self.fcinfo, stretch=1)
@@ -1925,16 +1916,14 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                                                                    _('Add Polygon'))
                                                                    _('Add Polygon'))
         self.geo_edit_toolbar.addSeparator()
         self.geo_edit_toolbar.addSeparator()
         self.geo_add_text_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/text32.png'), _('Add Text'))
         self.geo_add_text_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/text32.png'), _('Add Text'))
-        self.geo_add_buffer_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/buffer16-2.png'),
-                                                                  _('Add Buffer'))
+        self.geo_add_buffer_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/buffer16-2.png'), _('Add Buffer'))
         self.geo_add_paint_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/paint20_1.png'), _('Paint Shape'))
         self.geo_add_paint_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/paint20_1.png'), _('Paint Shape'))
         self.geo_eraser_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/eraser26.png'), _('Eraser'))
         self.geo_eraser_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/eraser26.png'), _('Eraser'))
 
 
-
         self.geo_edit_toolbar.addSeparator()
         self.geo_edit_toolbar.addSeparator()
         self.geo_union_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/union32.png'), _('Polygon Union'))
         self.geo_union_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/union32.png'), _('Polygon Union'))
         self.geo_intersection_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/intersection32.png'),
         self.geo_intersection_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/intersection32.png'),
-                                                               _('Polygon Intersection'))
+                                                                    _('Polygon Intersection'))
         self.geo_subtract_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/subtract32.png'),
         self.geo_subtract_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/subtract32.png'),
                                                                 _('Polygon Subtraction'))
                                                                 _('Polygon Subtraction'))
 
 
@@ -2266,7 +2255,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                     # try to disconnect the slot from Set Origin
                     # try to disconnect the slot from Set Origin
                     try:
                     try:
                         self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_set_zero_click)
                         self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_set_zero_click)
-                    except:
+                    except TypeError:
                         pass
                         pass
                     self.app.inform.emit("")
                     self.app.inform.emit("")
 
 
@@ -2378,10 +2367,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                     if self.app.geo_editor.get_selected() is not None:
                     if self.app.geo_editor.get_selected() is not None:
                         self.app.geo_editor.cutpath()
                         self.app.geo_editor.cutpath()
                     else:
                     else:
-                        msg = _('Please first select a geometry item to be cutted\n' \
-                              'then select the geometry item that will be cutted\n' \
-                              'out of the first item. In the end press ~X~ key or\n' \
-                              'the toolbar button.')
+                        msg = _('Please first select a geometry item to be cutted\n'
+                                'then select the geometry item that will be cutted\n'
+                                'out of the first item. In the end press ~X~ key or\n'
+                                'the toolbar button.')
 
 
                         messagebox = QtWidgets.QMessageBox()
                         messagebox = QtWidgets.QMessageBox()
                         messagebox.setText(msg)
                         messagebox.setText(msg)
@@ -2517,8 +2506,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                         if self.app.geo_editor.get_selected() is not None:
                         if self.app.geo_editor.get_selected() is not None:
                             self.app.geo_editor.intersection()
                             self.app.geo_editor.intersection()
                         else:
                         else:
-                            msg = _("Please select geometry items \n" \
-                                  "on which to perform Intersection Tool.")
+                            msg = _("Please select geometry items \n"
+                                    "on which to perform Intersection Tool.")
 
 
                             messagebox = QtWidgets.QMessageBox()
                             messagebox = QtWidgets.QMessageBox()
                             messagebox.setText(msg)
                             messagebox.setText(msg)
@@ -2597,7 +2586,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                             self.app.geo_editor.union()
                             self.app.geo_editor.union()
                         else:
                         else:
                             msg = _("Please select geometry items \n"
                             msg = _("Please select geometry items \n"
-                                  "on which to perform union.")
+                                    "on which to perform union.")
 
 
                             messagebox = QtWidgets.QMessageBox()
                             messagebox = QtWidgets.QMessageBox()
                             messagebox.setText(msg)
                             messagebox.setText(msg)
@@ -3152,7 +3141,7 @@ class GeneralPreferencesUI(QtWidgets.QWidget):
         self.setLayout(self.layout)
         self.setLayout(self.layout)
 
 
         self.general_app_group = GeneralAppPrefGroupUI()
         self.general_app_group = GeneralAppPrefGroupUI()
-        self.general_app_group.setFixedWidth(280)
+        self.general_app_group.setFixedWidth(290)
 
 
         self.general_gui_group = GeneralGUIPrefGroupUI()
         self.general_gui_group = GeneralGUIPrefGroupUI()
         self.general_gui_group.setFixedWidth(250)
         self.general_gui_group.setFixedWidth(250)
@@ -3177,7 +3166,7 @@ class GerberPreferencesUI(QtWidgets.QWidget):
         self.gerber_gen_group = GerberGenPrefGroupUI()
         self.gerber_gen_group = GerberGenPrefGroupUI()
         self.gerber_gen_group.setFixedWidth(250)
         self.gerber_gen_group.setFixedWidth(250)
         self.gerber_opt_group = GerberOptPrefGroupUI()
         self.gerber_opt_group = GerberOptPrefGroupUI()
-        self.gerber_opt_group.setFixedWidth(230)
+        self.gerber_opt_group.setFixedWidth(250)
         self.gerber_exp_group = GerberExpPrefGroupUI()
         self.gerber_exp_group = GerberExpPrefGroupUI()
         self.gerber_exp_group.setFixedWidth(230)
         self.gerber_exp_group.setFixedWidth(230)
         self.gerber_adv_opt_group = GerberAdvOptPrefGroupUI()
         self.gerber_adv_opt_group = GerberAdvOptPrefGroupUI()
@@ -3862,8 +3851,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
         # Multiple Selection Modifier Key
         # Multiple Selection Modifier Key
         self.mselectlabel = QtWidgets.QLabel(_('<b>Multiple Sel:</b>'))
         self.mselectlabel = QtWidgets.QLabel(_('<b>Multiple Sel:</b>'))
         self.mselectlabel.setToolTip(_("Select the key used for multiple selection."))
         self.mselectlabel.setToolTip(_("Select the key used for multiple selection."))
-        self.mselect_radio = RadioSet([{'label': 'CTRL', 'value': 'Control'},
-                                       {'label': 'SHIFT', 'value': 'Shift'}])
+        self.mselect_radio = RadioSet([{'label': _('CTRL'), 'value': 'Control'},
+                                       {'label': _('SHIFT'), 'value': 'Shift'}])
 
 
         # Project at StartUp CB
         # Project at StartUp CB
         self.project_startup_label = QtWidgets.QLabel(_('Project at StartUp:'))
         self.project_startup_label = QtWidgets.QLabel(_('Project at StartUp:'))
@@ -4053,7 +4042,7 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
         self.circle_steps_label = QtWidgets.QLabel(_("Circle Steps:"))
         self.circle_steps_label = QtWidgets.QLabel(_("Circle Steps:"))
         self.circle_steps_label.setToolTip(
         self.circle_steps_label.setToolTip(
             _("The number of circle steps for Gerber \n"
             _("The number of circle steps for Gerber \n"
-            "circular aperture linear approximation.")
+              "circular aperture linear approximation.")
         )
         )
         grid0.addWidget(self.circle_steps_label, 1, 0)
         grid0.addWidget(self.circle_steps_label, 1, 0)
         self.circle_steps_entry = IntEntry()
         self.circle_steps_entry = IntEntry()
@@ -4302,7 +4291,7 @@ class GerberExpPrefGroupUI(OptionsGroupUI):
         )
         )
         hlay1.addWidget(self.format_whole_entry, QtCore.Qt.AlignLeft)
         hlay1.addWidget(self.format_whole_entry, QtCore.Qt.AlignLeft)
 
 
-        gerber_separator_label= QtWidgets.QLabel(':')
+        gerber_separator_label = QtWidgets.QLabel(':')
         gerber_separator_label.setFixedWidth(5)
         gerber_separator_label.setFixedWidth(5)
         hlay1.addWidget(gerber_separator_label, QtCore.Qt.AlignLeft)
         hlay1.addWidget(gerber_separator_label, QtCore.Qt.AlignLeft)
 
 
@@ -4450,7 +4439,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
         )
         )
         hlay1.addWidget(self.excellon_format_upper_in_entry, QtCore.Qt.AlignLeft)
         hlay1.addWidget(self.excellon_format_upper_in_entry, QtCore.Qt.AlignLeft)
 
 
-        excellon_separator_in_label= QtWidgets.QLabel(':')
+        excellon_separator_in_label = QtWidgets.QLabel(':')
         excellon_separator_in_label.setFixedWidth(5)
         excellon_separator_in_label.setFixedWidth(5)
         hlay1.addWidget(excellon_separator_in_label, QtCore.Qt.AlignLeft)
         hlay1.addWidget(excellon_separator_in_label, QtCore.Qt.AlignLeft)
 
 
@@ -5909,14 +5898,29 @@ class ToolsCutoutPrefGroupUI(OptionsGroupUI):
         self.cutout_tooldia_entry = LengthEntry()
         self.cutout_tooldia_entry = LengthEntry()
         grid0.addWidget(self.cutout_tooldia_entry, 0, 1)
         grid0.addWidget(self.cutout_tooldia_entry, 0, 1)
 
 
+        # Object kind
+        kindlabel = QtWidgets.QLabel(_('Obj kind:'))
+        kindlabel.setToolTip(
+            _("Choice of what kind the object we want to cutout is.<BR>"
+              "- <B>Single</B>: contain a single PCB Gerber outline object.<BR>"
+              "- <B>Panel</B>: a panel PCB Gerber object, which is made\n"
+              "out of many individual PCB outlines.")
+        )
+        grid0.addWidget(kindlabel, 1, 0)
+        self.obj_kind_combo = RadioSet([
+            {"label": _("Single"), "value": "single"},
+            {"label": _("Panel"), "value": "panel"},
+        ])
+        grid0.addWidget(self.obj_kind_combo, 1, 1)
+
         marginlabel = QtWidgets.QLabel(_('Margin:'))
         marginlabel = QtWidgets.QLabel(_('Margin:'))
         marginlabel.setToolTip(
         marginlabel.setToolTip(
             _("Distance from objects at which\n"
             _("Distance from objects at which\n"
               "to draw the cutout.")
               "to draw the cutout.")
         )
         )
-        grid0.addWidget(marginlabel, 1, 0)
+        grid0.addWidget(marginlabel, 2, 0)
         self.cutout_margin_entry = LengthEntry()
         self.cutout_margin_entry = LengthEntry()
-        grid0.addWidget(self.cutout_margin_entry, 1, 1)
+        grid0.addWidget(self.cutout_margin_entry, 2, 1)
 
 
         gaplabel = QtWidgets.QLabel(_('Gap size:'))
         gaplabel = QtWidgets.QLabel(_('Gap size:'))
         gaplabel.setToolTip(
         gaplabel.setToolTip(
@@ -5924,9 +5928,9 @@ class ToolsCutoutPrefGroupUI(OptionsGroupUI):
               "that will remain to hold the\n"
               "that will remain to hold the\n"
               "board in place.")
               "board in place.")
         )
         )
-        grid0.addWidget(gaplabel, 2, 0)
+        grid0.addWidget(gaplabel, 3, 0)
         self.cutout_gap_entry = LengthEntry()
         self.cutout_gap_entry = LengthEntry()
-        grid0.addWidget(self.cutout_gap_entry, 2, 1)
+        grid0.addWidget(self.cutout_gap_entry, 3, 1)
 
 
         gaps_label = QtWidgets.QLabel(_('Gaps:'))
         gaps_label = QtWidgets.QLabel(_('Gaps:'))
         gaps_label.setToolTip(
         gaps_label.setToolTip(
@@ -5940,9 +5944,9 @@ class ToolsCutoutPrefGroupUI(OptionsGroupUI):
               "- 2tb  - 2*top + 2*bottom\n"
               "- 2tb  - 2*top + 2*bottom\n"
               "- 8     - 2*left + 2*right +2*top + 2*bottom")
               "- 8     - 2*left + 2*right +2*top + 2*bottom")
         )
         )
-        grid0.addWidget(gaps_label, 3, 0)
+        grid0.addWidget(gaps_label, 4, 0)
         self.gaps_combo = FCComboBox()
         self.gaps_combo = FCComboBox()
-        grid0.addWidget(self.gaps_combo, 3, 1)
+        grid0.addWidget(self.gaps_combo, 4, 1)
 
 
         gaps_items = ['LR', 'TB', '4', '2LR', '2TB', '8']
         gaps_items = ['LR', 'TB', '4', '2LR', '2TB', '8']
         for it in gaps_items:
         for it in gaps_items:
@@ -5955,8 +5959,8 @@ class ToolsCutoutPrefGroupUI(OptionsGroupUI):
         self.convex_box_label.setToolTip(
         self.convex_box_label.setToolTip(
             _("Create a convex shape surrounding the entire PCB.")
             _("Create a convex shape surrounding the entire PCB.")
         )
         )
-        grid0.addWidget(self.convex_box_label, 4, 0)
-        grid0.addWidget(self.convex_box, 4, 1)
+        grid0.addWidget(self.convex_box_label, 5, 0)
+        grid0.addWidget(self.convex_box, 5, 1)
 
 
         self.layout.addStretch()
         self.layout.addStretch()
 
 

+ 5 - 8
flatcamGUI/GUIElements.py

@@ -220,7 +220,7 @@ class FloatEntry(QtWidgets.QLineEdit):
 
 
     def mousePressEvent(self, e, Parent=None):
     def mousePressEvent(self, e, Parent=None):
         super(FloatEntry, self).mousePressEvent(e)  # required to deselect on 2e click
         super(FloatEntry, self).mousePressEvent(e)  # required to deselect on 2e click
-        if self.readyToEdit:
+        if self.readyToEdit == True:
             self.selectAll()
             self.selectAll()
             self.readyToEdit = False
             self.readyToEdit = False
 
 
@@ -238,20 +238,18 @@ class FloatEntry(QtWidgets.QLineEdit):
 
 
     def get_value(self):
     def get_value(self):
         raw = str(self.text()).strip(' ')
         raw = str(self.text()).strip(' ')
-        evaled = 0.0
 
 
         try:
         try:
             evaled = eval(raw)
             evaled = eval(raw)
+            return float(evaled)
         except Exception as e:
         except Exception as e:
             if raw is not '':
             if raw is not '':
                 log.error("Could not evaluate val: %s, error: %s" % (str(raw), str(e)))
                 log.error("Could not evaluate val: %s, error: %s" % (str(raw), str(e)))
             return None
             return None
 
 
-        return float(evaled)
-
     def set_value(self, val):
     def set_value(self, val):
         if val is not None:
         if val is not None:
-            self.setText("%.4f" % val)
+            self.setText("%.4f" % float(val))
         else:
         else:
             self.setText("")
             self.setText("")
 
 
@@ -282,16 +280,15 @@ class FloatEntry2(QtWidgets.QLineEdit):
 
 
     def get_value(self):
     def get_value(self):
         raw = str(self.text()).strip(' ')
         raw = str(self.text()).strip(' ')
-        evaled = 0.0
+
         try:
         try:
             evaled = eval(raw)
             evaled = eval(raw)
+            return float(evaled)
         except Exception as e:
         except Exception as e:
             if raw is not '':
             if raw is not '':
                 log.error("Could not evaluate val: %s, error: %s" % (str(raw), str(e)))
                 log.error("Could not evaluate val: %s, error: %s" % (str(raw), str(e)))
             return None
             return None
 
 
-        return float(evaled)
-
     def set_value(self, val):
     def set_value(self, val):
         self.setText("%.4f" % val)
         self.setText("%.4f" % val)
 
 

+ 143 - 137
flatcamGUI/ObjectUI.py

@@ -1,15 +1,15 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Author: Juan Pablo Caram (c)                             #
 # Date: 2/5/2014                                           #
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
-# ########################################################## ##
+# ##########################################################
 # File Modified (major mod): Marius Adrian Stanciu         #
 # File Modified (major mod): Marius Adrian Stanciu         #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
-# ########################################################## ##
+# ##########################################################
 
 
 from PyQt5 import QtGui, QtCore, QtWidgets
 from PyQt5 import QtGui, QtCore, QtWidgets
 from PyQt5.QtCore import Qt
 from PyQt5.QtCore import Qt
@@ -17,9 +17,9 @@ from flatcamGUI.GUIElements import *
 
 
 import gettext
 import gettext
 import FlatCAMTranslation as fcTranslate
 import FlatCAMTranslation as fcTranslate
+import builtins
 
 
 fcTranslate.apply_language('strings')
 fcTranslate.apply_language('strings')
-import builtins
 if '_' not in builtins.__dict__:
 if '_' not in builtins.__dict__:
     _ = gettext.gettext
     _ = gettext.gettext
 
 
@@ -71,11 +71,11 @@ class ObjectUI(QtWidgets.QWidget):
         self.custom_box = QtWidgets.QVBoxLayout()
         self.custom_box = QtWidgets.QVBoxLayout()
         layout.addLayout(self.custom_box)
         layout.addLayout(self.custom_box)
 
 
-        ######################### ##
-        # ## Common to all objects # ##
-        ######################### ##
+        # ###########################
+        # ## Common to all objects ##
+        # ###########################
 
 
-        #### Scale ## ##
+        # ### Scale ####
         self.scale_label = QtWidgets.QLabel(_('<b>Scale:</b>'))
         self.scale_label = QtWidgets.QLabel(_('<b>Scale:</b>'))
         self.scale_label.setToolTip(
         self.scale_label.setToolTip(
             _("Change the size of the object.")
             _("Change the size of the object.")
@@ -89,7 +89,7 @@ class ObjectUI(QtWidgets.QWidget):
         faclabel = QtWidgets.QLabel(_('Factor:'))
         faclabel = QtWidgets.QLabel(_('Factor:'))
         faclabel.setToolTip(
         faclabel.setToolTip(
             _("Factor by which to multiply\n"
             _("Factor by which to multiply\n"
-            "geometric features of this object.")
+              "geometric features of this object.")
         )
         )
         self.scale_grid.addWidget(faclabel, 0, 0)
         self.scale_grid.addWidget(faclabel, 0, 0)
         self.scale_entry = FloatEntry2()
         self.scale_entry = FloatEntry2()
@@ -104,7 +104,7 @@ class ObjectUI(QtWidgets.QWidget):
         self.scale_button.setFixedWidth(70)
         self.scale_button.setFixedWidth(70)
         self.scale_grid.addWidget(self.scale_button, 0, 2)
         self.scale_grid.addWidget(self.scale_button, 0, 2)
 
 
-        #### Offset ## ##
+        # ### Offset ####
         self.offset_label = QtWidgets.QLabel(_('<b>Offset:</b>'))
         self.offset_label = QtWidgets.QLabel(_('<b>Offset:</b>'))
         self.offset_label.setToolTip(
         self.offset_label.setToolTip(
             _("Change the position of this object.")
             _("Change the position of this object.")
@@ -117,7 +117,7 @@ class ObjectUI(QtWidgets.QWidget):
         self.offset_vectorlabel = QtWidgets.QLabel(_('Vector:'))
         self.offset_vectorlabel = QtWidgets.QLabel(_('Vector:'))
         self.offset_vectorlabel.setToolTip(
         self.offset_vectorlabel.setToolTip(
             _("Amount by which to move the object\n"
             _("Amount by which to move the object\n"
-            "in the x and y axes in (x, y) format.")
+              "in the x and y axes in (x, y) format.")
         )
         )
         self.offset_grid.addWidget(self.offset_vectorlabel, 0, 0)
         self.offset_grid.addWidget(self.offset_vectorlabel, 0, 0)
         self.offsetvector_entry = EvalEntry2()
         self.offsetvector_entry = EvalEntry2()
@@ -188,7 +188,7 @@ class GerberObjectUI(ObjectUI):
         hlay_plot = QtWidgets.QHBoxLayout()
         hlay_plot = QtWidgets.QHBoxLayout()
         self.custom_box.addLayout(hlay_plot)
         self.custom_box.addLayout(hlay_plot)
 
 
-        #### Gerber Apertures ## ##
+        # ### Gerber Apertures ####
         self.apertures_table_label = QtWidgets.QLabel(_('<b>Apertures:</b>'))
         self.apertures_table_label = QtWidgets.QLabel(_('<b>Apertures:</b>'))
         self.apertures_table_label.setToolTip(
         self.apertures_table_label.setToolTip(
             _("Apertures Table for the Gerber Object.")
             _("Apertures Table for the Gerber Object.")
@@ -201,9 +201,8 @@ class GerberObjectUI(ObjectUI):
         self.aperture_table_visibility_cb = FCCheckBox()
         self.aperture_table_visibility_cb = FCCheckBox()
         self.aperture_table_visibility_cb.setToolTip(
         self.aperture_table_visibility_cb.setToolTip(
             _("Toggle the display of the Gerber Apertures Table.\n"
             _("Toggle the display of the Gerber Apertures Table.\n"
-            "When unchecked, it will delete all mark shapes\n"
-            "that are drawn on canvas.")
-
+              "When unchecked, it will delete all mark shapes\n"
+              "that are drawn on canvas.")
         )
         )
         # self.aperture_table_visibility_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
         # self.aperture_table_visibility_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
         hlay_plot.addWidget(self.aperture_table_visibility_cb)
         hlay_plot.addWidget(self.aperture_table_visibility_cb)
@@ -214,8 +213,8 @@ class GerberObjectUI(ObjectUI):
         self.mark_all_cb = FCCheckBox(_('Mark All'))
         self.mark_all_cb = FCCheckBox(_('Mark All'))
         self.mark_all_cb.setToolTip(
         self.mark_all_cb.setToolTip(
             _("When checked it will display all the apertures.\n"
             _("When checked it will display all the apertures.\n"
-            "When unchecked, it will delete all mark shapes\n"
-            "that are drawn on canvas.")
+              "When unchecked, it will delete all mark shapes\n"
+              "that are drawn on canvas.")
 
 
         )
         )
         self.mark_all_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
         self.mark_all_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
@@ -238,8 +237,8 @@ class GerberObjectUI(ObjectUI):
             _("Aperture Size:"))
             _("Aperture Size:"))
         self.apertures_table.horizontalHeaderItem(4).setToolTip(
         self.apertures_table.horizontalHeaderItem(4).setToolTip(
             _("Aperture Dimensions:\n"
             _("Aperture Dimensions:\n"
-            " - (width, height) for R, O type.\n"
-            " - (dia, nVertices) for P type"))
+              " - (width, height) for R, O type.\n"
+              " - (dia, nVertices) for P type"))
         self.apertures_table.horizontalHeaderItem(5).setToolTip(
         self.apertures_table.horizontalHeaderItem(5).setToolTip(
             _("Mark the aperture instances on canvas."))
             _("Mark the aperture instances on canvas."))
         # self.apertures_table.setColumnHidden(5, True)
         # self.apertures_table.setColumnHidden(5, True)
@@ -251,7 +250,7 @@ class GerberObjectUI(ObjectUI):
         self.isolation_routing_label = QtWidgets.QLabel(_("<b>Isolation Routing:</b>"))
         self.isolation_routing_label = QtWidgets.QLabel(_("<b>Isolation Routing:</b>"))
         self.isolation_routing_label.setToolTip(
         self.isolation_routing_label.setToolTip(
             _("Create a Geometry object with\n"
             _("Create a Geometry object with\n"
-            "toolpaths to cut outside polygons.")
+              "toolpaths to cut outside polygons.")
         )
         )
         self.custom_box.addWidget(self.isolation_routing_label)
         self.custom_box.addWidget(self.isolation_routing_label)
 
 
@@ -260,10 +259,10 @@ class GerberObjectUI(ObjectUI):
         tdlabel = QtWidgets.QLabel(_('Tool dia:'))
         tdlabel = QtWidgets.QLabel(_('Tool dia:'))
         tdlabel.setToolTip(
         tdlabel.setToolTip(
             _("Diameter of the cutting tool.\n"
             _("Diameter of the cutting tool.\n"
-            "If you want to have an isolation path\n"
-            "inside the actual shape of the Gerber\n"
-            "feature, use a negative value for\n"
-            "this parameter.")
+              "If you want to have an isolation path\n"
+              "inside the actual shape of the Gerber\n"
+              "feature, use a negative value for\n"
+              "this parameter.")
         )
         )
         tdlabel.setFixedWidth(90)
         tdlabel.setFixedWidth(90)
         grid1.addWidget(tdlabel, 0, 0)
         grid1.addWidget(tdlabel, 0, 0)
@@ -273,7 +272,7 @@ class GerberObjectUI(ObjectUI):
         passlabel = QtWidgets.QLabel(_('Passes:'))
         passlabel = QtWidgets.QLabel(_('Passes:'))
         passlabel.setToolTip(
         passlabel.setToolTip(
             _("Width of the isolation gap in\n"
             _("Width of the isolation gap in\n"
-            "number (integer) of tool widths.")
+              "number (integer) of tool widths.")
         )
         )
         passlabel.setFixedWidth(90)
         passlabel.setFixedWidth(90)
         grid1.addWidget(passlabel, 1, 0)
         grid1.addWidget(passlabel, 1, 0)
@@ -283,8 +282,8 @@ class GerberObjectUI(ObjectUI):
         overlabel = QtWidgets.QLabel(_('Pass overlap:'))
         overlabel = QtWidgets.QLabel(_('Pass overlap:'))
         overlabel.setToolTip(
         overlabel.setToolTip(
             _("How much (fraction) of the tool width to overlap each tool pass.\n"
             _("How much (fraction) of the tool width to overlap each tool pass.\n"
-            "Example:\n"
-            "A value here of 0.25 means an overlap of 25% from the tool diameter found above.")
+              "Example:\n"
+              "A value here of 0.25 means an overlap of 25% from the tool diameter found above.")
         )
         )
         overlabel.setFixedWidth(90)
         overlabel.setFixedWidth(90)
         grid1.addWidget(overlabel, 2, 0)
         grid1.addWidget(overlabel, 2, 0)
@@ -295,8 +294,8 @@ class GerberObjectUI(ObjectUI):
         self.milling_type_label = QtWidgets.QLabel(_('Milling Type:'))
         self.milling_type_label = QtWidgets.QLabel(_('Milling Type:'))
         self.milling_type_label.setToolTip(
         self.milling_type_label.setToolTip(
             _("Milling type:\n"
             _("Milling type:\n"
-            "- climb / best for precision milling and to reduce tool usage\n"
-            "- conventional / useful when there is no backlash compensation")
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
         )
         )
         grid1.addWidget(self.milling_type_label, 3, 0)
         grid1.addWidget(self.milling_type_label, 3, 0)
         self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
         self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
@@ -313,9 +312,9 @@ class GerberObjectUI(ObjectUI):
         # generate follow
         # generate follow
         self.follow_cb = FCCheckBox(label=_('"Follow"'))
         self.follow_cb = FCCheckBox(label=_('"Follow"'))
         self.follow_cb.setToolTip(
         self.follow_cb.setToolTip(
-           _( "Generate a 'Follow' geometry.\n"
-            "This means that it will cut through\n"
-            "the middle of the trace.")
+           _("Generate a 'Follow' geometry.\n"
+             "This means that it will cut through\n"
+             "the middle of the trace.")
 
 
         )
         )
         grid1.addWidget(self.follow_cb, 4, 1)
         grid1.addWidget(self.follow_cb, 4, 1)
@@ -323,14 +322,14 @@ class GerberObjectUI(ObjectUI):
         self.gen_iso_label = QtWidgets.QLabel(_("<b>Generate Isolation Geometry:</b>"))
         self.gen_iso_label = QtWidgets.QLabel(_("<b>Generate Isolation Geometry:</b>"))
         self.gen_iso_label.setToolTip(
         self.gen_iso_label.setToolTip(
             _("Create a Geometry object with toolpaths to cut \n"
             _("Create a Geometry object with toolpaths to cut \n"
-            "isolation outside, inside or on both sides of the\n"
-            "object. For a Gerber object outside means outside\n"
-            "of the Gerber feature and inside means inside of\n"
-            "the Gerber feature, if possible at all. This means\n"
-            "that only if the Gerber feature has openings inside, they\n"
-            "will be isolated. If what is wanted is to cut isolation\n"
-            "inside the actual Gerber feature, use a negative tool\n"
-            "diameter above.")
+              "isolation outside, inside or on both sides of the\n"
+              "object. For a Gerber object outside means outside\n"
+              "of the Gerber feature and inside means inside of\n"
+              "the Gerber feature, if possible at all. This means\n"
+              "that only if the Gerber feature has openings inside, they\n"
+              "will be isolated. If what is wanted is to cut isolation\n"
+              "inside the actual Gerber feature, use a negative tool\n"
+              "diameter above.")
         )
         )
         self.custom_box.addWidget(self.gen_iso_label)
         self.custom_box.addWidget(self.gen_iso_label)
 
 
@@ -344,8 +343,8 @@ class GerberObjectUI(ObjectUI):
         self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo'))
         self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo'))
         self.generate_iso_button.setToolTip(
         self.generate_iso_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
-            "for isolation routing. It contains both\n"
-            "the interiors and exteriors geometry.")
+              "for isolation routing. It contains both\n"
+              "the interiors and exteriors geometry.")
         )
         )
         self.generate_iso_button.setFixedWidth(90)
         self.generate_iso_button.setFixedWidth(90)
         hlay_1.addWidget(self.generate_iso_button, alignment=Qt.AlignLeft)
         hlay_1.addWidget(self.generate_iso_button, alignment=Qt.AlignLeft)
@@ -355,8 +354,8 @@ class GerberObjectUI(ObjectUI):
         self.generate_ext_iso_button = QtWidgets.QPushButton(_('Ext Geo'))
         self.generate_ext_iso_button = QtWidgets.QPushButton(_('Ext Geo'))
         self.generate_ext_iso_button.setToolTip(
         self.generate_ext_iso_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
-            "for isolation routing containing\n"
-            "only the exteriors geometry.")
+              "for isolation routing containing\n"
+              "only the exteriors geometry.")
         )
         )
         # self.generate_ext_iso_button.setFixedWidth(100)
         # self.generate_ext_iso_button.setFixedWidth(100)
         hlay_1.addWidget(self.generate_ext_iso_button)
         hlay_1.addWidget(self.generate_ext_iso_button)
@@ -364,8 +363,8 @@ class GerberObjectUI(ObjectUI):
         self.generate_int_iso_button = QtWidgets.QPushButton(_('Int Geo'))
         self.generate_int_iso_button = QtWidgets.QPushButton(_('Int Geo'))
         self.generate_int_iso_button.setToolTip(
         self.generate_int_iso_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
-            "for isolation routing containing\n"
-            "only the interiors geometry.")
+              "for isolation routing containing\n"
+              "only the interiors geometry.")
         )
         )
         # self.generate_ext_iso_button.setFixedWidth(90)
         # self.generate_ext_iso_button.setFixedWidth(90)
         hlay_1.addWidget(self.generate_int_iso_button)
         hlay_1.addWidget(self.generate_int_iso_button)
@@ -375,8 +374,6 @@ class GerberObjectUI(ObjectUI):
         self.ois_iso = OptionalInputSection(self.follow_cb,
         self.ois_iso = OptionalInputSection(self.follow_cb,
                                             [self.generate_int_iso_button, self.generate_ext_iso_button], logic=False)
                                             [self.generate_int_iso_button, self.generate_ext_iso_button], logic=False)
 
 
-
-
         grid2 = QtWidgets.QGridLayout()
         grid2 = QtWidgets.QGridLayout()
         self.custom_box.addLayout(grid2)
         self.custom_box.addLayout(grid2)
 
 
@@ -384,7 +381,7 @@ class GerberObjectUI(ObjectUI):
         self.clearcopper_label = QtWidgets.QLabel(_("<b>Clear N-copper:</b>"))
         self.clearcopper_label = QtWidgets.QLabel(_("<b>Clear N-copper:</b>"))
         self.clearcopper_label.setToolTip(
         self.clearcopper_label.setToolTip(
             _("Create a Geometry object with\n"
             _("Create a Geometry object with\n"
-            "toolpaths to cut all non-copper regions.")
+              "toolpaths to cut all non-copper regions.")
         )
         )
         self.clearcopper_label.setFixedWidth(90)
         self.clearcopper_label.setFixedWidth(90)
         grid2.addWidget(self.clearcopper_label, 0, 0)
         grid2.addWidget(self.clearcopper_label, 0, 0)
@@ -392,7 +389,7 @@ class GerberObjectUI(ObjectUI):
         self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool'))
         self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool'))
         self.generate_ncc_button.setToolTip(
         self.generate_ncc_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
-            "for non-copper routing.")
+              "for non-copper routing.")
         )
         )
         grid2.addWidget(self.generate_ncc_button, 0, 1)
         grid2.addWidget(self.generate_ncc_button, 0, 1)
 
 
@@ -400,15 +397,15 @@ class GerberObjectUI(ObjectUI):
         self.board_cutout_label = QtWidgets.QLabel(_("<b>Board cutout:</b>"))
         self.board_cutout_label = QtWidgets.QLabel(_("<b>Board cutout:</b>"))
         self.board_cutout_label.setToolTip(
         self.board_cutout_label.setToolTip(
             _("Create toolpaths to cut around\n"
             _("Create toolpaths to cut around\n"
-            "the PCB and separate it from\n"
-            "the original board.")
+              "the PCB and separate it from\n"
+              "the original board.")
         )
         )
         grid2.addWidget(self.board_cutout_label, 1, 0)
         grid2.addWidget(self.board_cutout_label, 1, 0)
 
 
         self.generate_cutout_button = QtWidgets.QPushButton(_('Cutout Tool'))
         self.generate_cutout_button = QtWidgets.QPushButton(_('Cutout Tool'))
         self.generate_cutout_button.setToolTip(
         self.generate_cutout_button.setToolTip(
             _("Generate the geometry for\n"
             _("Generate the geometry for\n"
-            "the board cutout.")
+              "the board cutout.")
         )
         )
         grid2.addWidget(self.generate_cutout_button, 1, 1)
         grid2.addWidget(self.generate_cutout_button, 1, 1)
 
 
@@ -416,10 +413,10 @@ class GerberObjectUI(ObjectUI):
         self.noncopper_label = QtWidgets.QLabel(_("<b>Non-copper regions:</b>"))
         self.noncopper_label = QtWidgets.QLabel(_("<b>Non-copper regions:</b>"))
         self.noncopper_label.setToolTip(
         self.noncopper_label.setToolTip(
             _("Create polygons covering the\n"
             _("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.")
+              "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.custom_box.addWidget(self.noncopper_label)
         self.custom_box.addWidget(self.noncopper_label)
 
 
@@ -430,9 +427,9 @@ class GerberObjectUI(ObjectUI):
         bmlabel = QtWidgets.QLabel(_('Boundary Margin:'))
         bmlabel = QtWidgets.QLabel(_('Boundary Margin:'))
         bmlabel.setToolTip(
         bmlabel.setToolTip(
             _("Specify the edge of the PCB\n"
             _("Specify the edge of the PCB\n"
-            "by drawing a box around all\n"
-            "objects with this minimum\n"
-            "distance.")
+              "by drawing a box around all\n"
+              "objects with this minimum\n"
+              "distance.")
         )
         )
         bmlabel.setFixedWidth(90)
         bmlabel.setFixedWidth(90)
         grid4.addWidget(bmlabel, 0, 0)
         grid4.addWidget(bmlabel, 0, 0)
@@ -454,7 +451,7 @@ class GerberObjectUI(ObjectUI):
         self.boundingbox_label = QtWidgets.QLabel(_('<b>Bounding Box:</b>'))
         self.boundingbox_label = QtWidgets.QLabel(_('<b>Bounding Box:</b>'))
         self.boundingbox_label.setToolTip(
         self.boundingbox_label.setToolTip(
             _("Create a geometry surrounding the Gerber object.\n"
             _("Create a geometry surrounding the Gerber object.\n"
-            "Square shape.")
+              "Square shape.")
         )
         )
         self.custom_box.addWidget(self.boundingbox_label)
         self.custom_box.addWidget(self.boundingbox_label)
 
 
@@ -464,7 +461,7 @@ class GerberObjectUI(ObjectUI):
         bbmargin = QtWidgets.QLabel(_('Boundary Margin:'))
         bbmargin = QtWidgets.QLabel(_('Boundary Margin:'))
         bbmargin.setToolTip(
         bbmargin.setToolTip(
             _("Distance of the edges of the box\n"
             _("Distance of the edges of the box\n"
-            "to the nearest polygon.")
+              "to the nearest polygon.")
         )
         )
         bbmargin.setFixedWidth(90)
         bbmargin.setFixedWidth(90)
         grid5.addWidget(bbmargin, 0, 0)
         grid5.addWidget(bbmargin, 0, 0)
@@ -474,9 +471,9 @@ class GerberObjectUI(ObjectUI):
         self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
         self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
         self.bbrounded_cb.setToolTip(
         self.bbrounded_cb.setToolTip(
             _("If the bounding box is \n"
             _("If the bounding box is \n"
-            "to have rounded corners\n"
-            "their radius is equal to\n"
-            "the margin.")
+              "to have rounded corners\n"
+              "their radius is equal to\n"
+              "the margin.")
         )
         )
         self.bbrounded_cb.setFixedWidth(90)
         self.bbrounded_cb.setFixedWidth(90)
         grid5.addWidget(self.bbrounded_cb, 1, 0)
         grid5.addWidget(self.bbrounded_cb, 1, 0)
@@ -498,7 +495,7 @@ class ExcellonObjectUI(ObjectUI):
                           icon_file='share/drill32.png',
                           icon_file='share/drill32.png',
                           parent=parent)
                           parent=parent)
 
 
-        #### Plot options ## ##
+        # ### Plot options ####
         hlay_plot = QtWidgets.QHBoxLayout()
         hlay_plot = QtWidgets.QHBoxLayout()
         self.custom_box.addLayout(hlay_plot)
         self.custom_box.addLayout(hlay_plot)
 
 
@@ -532,11 +529,11 @@ class ExcellonObjectUI(ObjectUI):
         hlay_plot = QtWidgets.QHBoxLayout()
         hlay_plot = QtWidgets.QHBoxLayout()
         self.tools_box.addLayout(hlay_plot)
         self.tools_box.addLayout(hlay_plot)
 
 
-        #### Tools Drills ## ##
+        # ### Tools Drills ####
         self.tools_table_label = QtWidgets.QLabel(_('<b>Tools Table</b>'))
         self.tools_table_label = QtWidgets.QLabel(_('<b>Tools Table</b>'))
         self.tools_table_label.setToolTip(
         self.tools_table_label.setToolTip(
             _("Tools in this Excellon object\n"
             _("Tools in this Excellon object\n"
-            "when are used for drilling.")
+              "when are used for drilling.")
         )
         )
         hlay_plot.addWidget(self.tools_table_label)
         hlay_plot.addWidget(self.tools_table_label)
 
 
@@ -559,32 +556,32 @@ class ExcellonObjectUI(ObjectUI):
 
 
         self.tools_table.horizontalHeaderItem(0).setToolTip(
         self.tools_table.horizontalHeaderItem(0).setToolTip(
             _("This is the Tool Number.\n"
             _("This is the Tool Number.\n"
-            "When ToolChange is checked, on toolchange event this value\n"
-            "will be showed as a T1, T2 ... Tn in the Machine Code."))
+              "When ToolChange is checked, on toolchange event this value\n"
+              "will be showed as a T1, T2 ... Tn in the Machine Code."))
         self.tools_table.horizontalHeaderItem(1).setToolTip(
         self.tools_table.horizontalHeaderItem(1).setToolTip(
             _("Tool Diameter. It's value (in current FlatCAM units) \n"
             _("Tool Diameter. It's value (in current FlatCAM units) \n"
-            "is the cut width into the material."))
+              "is the cut width into the material."))
         self.tools_table.horizontalHeaderItem(2).setToolTip(
         self.tools_table.horizontalHeaderItem(2).setToolTip(
             _("The number of Drill holes. Holes that are drilled with\n"
             _("The number of Drill holes. Holes that are drilled with\n"
-            "a drill bit."))
+              "a drill bit."))
         self.tools_table.horizontalHeaderItem(3).setToolTip(
         self.tools_table.horizontalHeaderItem(3).setToolTip(
             _("The number of Slot holes. Holes that are created by\n"
             _("The number of Slot holes. Holes that are created by\n"
-            "milling them with an endmill bit."))
+              "milling them with an endmill bit."))
         self.tools_table.horizontalHeaderItem(4).setToolTip(
         self.tools_table.horizontalHeaderItem(4).setToolTip(
             _("Some drill bits (the larger ones) need to drill deeper\n"
             _("Some drill bits (the larger ones) need to drill deeper\n"
-            "to create the desired exit hole diameter due of the tip shape.\n"
-            "The value here can compensate the Cut Z parameter."))
+              "to create the desired exit hole diameter due of the tip shape.\n"
+              "The value here can compensate the Cut Z parameter."))
         self.tools_table.horizontalHeaderItem(5).setToolTip(
         self.tools_table.horizontalHeaderItem(5).setToolTip(
             _("Toggle display of the drills for the current tool."))
             _("Toggle display of the drills for the current tool."))
 
 
         self.empty_label = QtWidgets.QLabel('')
         self.empty_label = QtWidgets.QLabel('')
         self.tools_box.addWidget(self.empty_label)
         self.tools_box.addWidget(self.empty_label)
 
 
-        #### 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(
             _("Create a CNC Job object\n"
             _("Create a CNC Job object\n"
-            "for this drill object.")
+              "for this drill object.")
         )
         )
         self.tools_box.addWidget(self.cncjob_label)
         self.tools_box.addWidget(self.cncjob_label)
 
 
@@ -595,7 +592,7 @@ class ExcellonObjectUI(ObjectUI):
         cutzlabel = QtWidgets.QLabel(_('Cut Z:'))
         cutzlabel = QtWidgets.QLabel(_('Cut Z:'))
         cutzlabel.setToolTip(
         cutzlabel.setToolTip(
             _("Drill depth (negative)\n"
             _("Drill depth (negative)\n"
-            "below the copper surface.")
+              "below the copper surface.")
         )
         )
         grid1.addWidget(cutzlabel, 0, 0)
         grid1.addWidget(cutzlabel, 0, 0)
         self.cutz_entry = LengthEntry()
         self.cutz_entry = LengthEntry()
@@ -605,7 +602,7 @@ class ExcellonObjectUI(ObjectUI):
         travelzlabel = QtWidgets.QLabel(_('Travel Z:'))
         travelzlabel = QtWidgets.QLabel(_('Travel Z:'))
         travelzlabel.setToolTip(
         travelzlabel.setToolTip(
             _("Tool height when travelling\n"
             _("Tool height when travelling\n"
-            "across the XY plane.")
+              "across the XY plane.")
         )
         )
         grid1.addWidget(travelzlabel, 1, 0)
         grid1.addWidget(travelzlabel, 1, 0)
         self.travelz_entry = LengthEntry()
         self.travelz_entry = LengthEntry()
@@ -615,7 +612,7 @@ class ExcellonObjectUI(ObjectUI):
         self.toolchange_cb = FCCheckBox(_("Tool change"))
         self.toolchange_cb = FCCheckBox(_("Tool change"))
         self.toolchange_cb.setToolTip(
         self.toolchange_cb.setToolTip(
             _("Include tool-change sequence\n"
             _("Include tool-change sequence\n"
-            "in G-Code (Pause for tool change).")
+              "in G-Code (Pause for tool change).")
         )
         )
         grid1.addWidget(self.toolchange_cb, 2, 0)
         grid1.addWidget(self.toolchange_cb, 2, 0)
 
 
@@ -623,7 +620,7 @@ class ExcellonObjectUI(ObjectUI):
         toolchzlabel = QtWidgets.QLabel(_("Tool change Z:"))
         toolchzlabel = QtWidgets.QLabel(_("Tool change Z:"))
         toolchzlabel.setToolTip(
         toolchzlabel.setToolTip(
             _("Z-axis position (height) for\n"
             _("Z-axis position (height) for\n"
-            "tool change.")
+              "tool change.")
         )
         )
         grid1.addWidget(toolchzlabel, 3, 0)
         grid1.addWidget(toolchzlabel, 3, 0)
         self.toolchangez_entry = LengthEntry()
         self.toolchangez_entry = LengthEntry()
@@ -634,7 +631,7 @@ class ExcellonObjectUI(ObjectUI):
         self.estartz_label = QtWidgets.QLabel(_("Start move Z:"))
         self.estartz_label = QtWidgets.QLabel(_("Start move Z:"))
         self.estartz_label.setToolTip(
         self.estartz_label.setToolTip(
             _("Tool height just before starting the work.\n"
             _("Tool height just before starting the work.\n"
-            "Delete the value if you don't need this feature.")
+              "Delete the value if you don't need this feature.")
         )
         )
         grid1.addWidget(self.estartz_label, 4, 0)
         grid1.addWidget(self.estartz_label, 4, 0)
         self.estartz_entry = FloatEntry()
         self.estartz_entry = FloatEntry()
@@ -644,7 +641,7 @@ class ExcellonObjectUI(ObjectUI):
         self.eendz_label = QtWidgets.QLabel(_("End move Z:"))
         self.eendz_label = QtWidgets.QLabel(_("End move Z:"))
         self.eendz_label.setToolTip(
         self.eendz_label.setToolTip(
             _("Z-axis position (height) for\n"
             _("Z-axis position (height) for\n"
-            "the last move.")
+              "the last move.")
         )
         )
         grid1.addWidget(self.eendz_label, 5, 0)
         grid1.addWidget(self.eendz_label, 5, 0)
         self.eendz_entry = LengthEntry()
         self.eendz_entry = LengthEntry()
@@ -654,8 +651,8 @@ class ExcellonObjectUI(ObjectUI):
         frlabel = QtWidgets.QLabel(_('Feedrate (Plunge):'))
         frlabel = QtWidgets.QLabel(_('Feedrate (Plunge):'))
         frlabel.setToolTip(
         frlabel.setToolTip(
             _("Tool speed while drilling\n"
             _("Tool speed while drilling\n"
-            "(in units per minute).\n"
-            "This is for linear move G01.")
+              "(in units per minute).\n"
+              "This is for linear move G01.")
         )
         )
         grid1.addWidget(frlabel, 6, 0)
         grid1.addWidget(frlabel, 6, 0)
         self.feedrate_entry = LengthEntry()
         self.feedrate_entry = LengthEntry()
@@ -682,7 +679,7 @@ class ExcellonObjectUI(ObjectUI):
         spdlabel = QtWidgets.QLabel(_('Spindle speed:'))
         spdlabel = QtWidgets.QLabel(_('Spindle speed:'))
         spdlabel.setToolTip(
         spdlabel.setToolTip(
             _("Speed of the spindle\n"
             _("Speed of the spindle\n"
-            "in RPM (optional)")
+              "in RPM (optional)")
         )
         )
         grid1.addWidget(spdlabel, 8, 0)
         grid1.addWidget(spdlabel, 8, 0)
         self.spindlespeed_entry = IntEntry(allow_empty=True)
         self.spindlespeed_entry = IntEntry(allow_empty=True)
@@ -692,7 +689,7 @@ class ExcellonObjectUI(ObjectUI):
         self.dwell_cb = FCCheckBox(_('Dwell:'))
         self.dwell_cb = FCCheckBox(_('Dwell:'))
         self.dwell_cb.setToolTip(
         self.dwell_cb.setToolTip(
             _("Pause to allow the spindle to reach its\n"
             _("Pause to allow the spindle to reach its\n"
-            "speed before cutting.")
+              "speed before cutting.")
         )
         )
         self.dwelltime_entry = FCEntry()
         self.dwelltime_entry = FCEntry()
         self.dwelltime_entry.setToolTip(
         self.dwelltime_entry.setToolTip(
@@ -707,7 +704,7 @@ class ExcellonObjectUI(ObjectUI):
         pp_excellon_label = QtWidgets.QLabel(_("Postprocessor:"))
         pp_excellon_label = QtWidgets.QLabel(_("Postprocessor:"))
         pp_excellon_label.setToolTip(
         pp_excellon_label.setToolTip(
             _("The json file that dictates\n"
             _("The json file that dictates\n"
-            "gcode output.")
+              "gcode output.")
         )
         )
         self.pp_excellon_name_cb = FCComboBox()
         self.pp_excellon_name_cb = FCComboBox()
         self.pp_excellon_name_cb.setFocusPolicy(QtCore.Qt.StrongFocus)
         self.pp_excellon_name_cb.setFocusPolicy(QtCore.Qt.StrongFocus)
@@ -718,7 +715,7 @@ class ExcellonObjectUI(ObjectUI):
         self.pdepth_label = QtWidgets.QLabel(_("Probe Z depth:"))
         self.pdepth_label = QtWidgets.QLabel(_("Probe Z depth:"))
         self.pdepth_label.setToolTip(
         self.pdepth_label.setToolTip(
             _("The maximum depth that the probe is allowed\n"
             _("The maximum depth that the probe is allowed\n"
-            "to probe. Negative value, in current units.")
+              "to probe. Negative value, in current units.")
         )
         )
         grid1.addWidget(self.pdepth_label, 11, 0)
         grid1.addWidget(self.pdepth_label, 11, 0)
         self.pdepth_entry = FCEntry()
         self.pdepth_entry = FCEntry()
@@ -739,18 +736,18 @@ class ExcellonObjectUI(ObjectUI):
 
 
         choose_tools_label = QtWidgets.QLabel(
         choose_tools_label = QtWidgets.QLabel(
             _("Select from the Tools Table above\n"
             _("Select from the Tools Table above\n"
-            "the tools you want to include.")
+              "the tools you want to include.")
         )
         )
         self.tools_box.addWidget(choose_tools_label)
         self.tools_box.addWidget(choose_tools_label)
 
 
-        #### Choose what to use for Gcode creation: Drills, Slots or Both
+        # ### Choose what to use for Gcode creation: Drills, Slots or Both
         gcode_box = QtWidgets.QFormLayout()
         gcode_box = QtWidgets.QFormLayout()
         gcode_type_label = QtWidgets.QLabel(_('<b>Type:    </b>'))
         gcode_type_label = QtWidgets.QLabel(_('<b>Type:    </b>'))
         gcode_type_label.setToolTip(
         gcode_type_label.setToolTip(
             _("Choose what to use for GCode generation:\n"
             _("Choose what to use for GCode generation:\n"
-            "'Drills', 'Slots' or 'Both'.\n"
-            "When choosing 'Slots' or 'Both', slots will be\n"
-            "converted to a series of drills.")
+              "'Drills', 'Slots' or 'Both'.\n"
+              "When choosing 'Slots' or 'Both', slots will be\n"
+              "converted to a series of drills.")
         )
         )
         self.excellon_gcode_type_radio = RadioSet([{'label': 'Drills', 'value': 'drills'},
         self.excellon_gcode_type_radio = RadioSet([{'label': 'Drills', 'value': 'drills'},
                                                    {'label': 'Slots', 'value': 'slots'},
                                                    {'label': 'Slots', 'value': 'slots'},
@@ -768,7 +765,7 @@ class ExcellonObjectUI(ObjectUI):
         )
         )
         self.tools_box.addWidget(self.generate_cnc_button)
         self.tools_box.addWidget(self.generate_cnc_button)
 
 
-        #### Milling Holes Drills## ##
+        # ### Milling Holes Drills ####
         self.mill_hole_label = QtWidgets.QLabel(_('<b>Mill Holes</b>'))
         self.mill_hole_label = QtWidgets.QLabel(_('<b>Mill Holes</b>'))
         self.mill_hole_label.setToolTip(
         self.mill_hole_label.setToolTip(
             _("Create Geometry for milling holes.")
             _("Create Geometry for milling holes.")
@@ -777,7 +774,7 @@ class ExcellonObjectUI(ObjectUI):
 
 
         self.choose_tools_label2 = QtWidgets.QLabel(
         self.choose_tools_label2 = QtWidgets.QLabel(
             _("Select from the Tools Table above\n"
             _("Select from the Tools Table above\n"
-            " the hole dias that are to be milled.")
+              " the hole dias that are to be milled.")
         )
         )
         self.tools_box.addWidget(self.choose_tools_label2)
         self.tools_box.addWidget(self.choose_tools_label2)
 
 
@@ -793,7 +790,7 @@ class ExcellonObjectUI(ObjectUI):
         self.generate_milling_button = QtWidgets.QPushButton(_('Mill Drills Geo'))
         self.generate_milling_button = QtWidgets.QPushButton(_('Mill Drills Geo'))
         self.generate_milling_button.setToolTip(
         self.generate_milling_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
-            "for milling DRILLS toolpaths.")
+              "for milling DRILLS toolpaths.")
         )
         )
         grid2.addWidget(self.generate_milling_button, 0, 2)
         grid2.addWidget(self.generate_milling_button, 0, 2)
 
 
@@ -809,7 +806,7 @@ class ExcellonObjectUI(ObjectUI):
         self.generate_milling_slots_button = QtWidgets.QPushButton(_('Mill Slots Geo'))
         self.generate_milling_slots_button = QtWidgets.QPushButton(_('Mill Slots Geo'))
         self.generate_milling_slots_button.setToolTip(
         self.generate_milling_slots_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
-            "for milling SLOTS toolpaths.")
+              "for milling SLOTS toolpaths.")
         )
         )
         grid3.addWidget(self.generate_milling_slots_button, 0, 2)
         grid3.addWidget(self.generate_milling_slots_button, 0, 2)
 
 
@@ -854,21 +851,21 @@ class GeometryObjectUI(ObjectUI):
         hlay_plot = QtWidgets.QHBoxLayout()
         hlay_plot = QtWidgets.QHBoxLayout()
         self.geo_tools_box.addLayout(hlay_plot)
         self.geo_tools_box.addLayout(hlay_plot)
 
 
-        #### Tools ## ##
+        # ### Tools ####
         self.tools_table_label = QtWidgets.QLabel(_('<b>Tools Table</b>'))
         self.tools_table_label = QtWidgets.QLabel(_('<b>Tools Table</b>'))
         self.tools_table_label.setToolTip(
         self.tools_table_label.setToolTip(
             _("Tools in this Geometry object used for cutting.\n"
             _("Tools in this Geometry object used for cutting.\n"
-            "The 'Offset' entry will set an offset for the cut.\n"
-            "'Offset' can be inside, outside, on path (none) and custom.\n"
-            "'Type' entry is only informative and it allow to know the \n"
-            "intent of using the current tool. \n"
-            "It can be Rough(ing), Finish(ing) or Iso(lation).\n"
-            "The 'Tool type'(TT) can be circular with 1 to 4 teeths(C1..C4),\n"
-            "ball(B), or V-Shaped(V). \n"
-            "When V-shaped is selected the 'Type' entry is automatically \n"
-            "set to Isolation, the CutZ parameter in the UI form is\n"
-            "grayed out and Cut Z is automatically calculated from the newly \n"
-            "showed UI form entries named V-Tip Dia and V-Tip Angle.")
+              "The 'Offset' entry will set an offset for the cut.\n"
+              "'Offset' can be inside, outside, on path (none) and custom.\n"
+              "'Type' entry is only informative and it allow to know the \n"
+              "intent of using the current tool. \n"
+              "It can be Rough(ing), Finish(ing) or Iso(lation).\n"
+              "The 'Tool type'(TT) can be circular with 1 to 4 teeths(C1..C4),\n"
+              "ball(B), or V-Shaped(V). \n"
+              "When V-shaped is selected the 'Type' entry is automatically \n"
+              "set to Isolation, the CutZ parameter in the UI form is\n"
+              "grayed out and Cut Z is automatically calculated from the newly \n"
+              "showed UI form entries named V-Tip Dia and V-Tip Angle.")
         )
         )
         hlay_plot.addWidget(self.tools_table_label)
         hlay_plot.addWidget(self.tools_table_label)
 
 
@@ -928,7 +925,8 @@ class GeometryObjectUI(ObjectUI):
                 "- Ball -> informative only and make reference to the Ball type endmill.\n"
                 "- Ball -> informative only and make reference to the Ball type endmill.\n"
                 "- V-Shape -> it will disable de Z-Cut parameter in the UI form and enable two additional UI form\n"
                 "- V-Shape -> it will disable de Z-Cut parameter in the UI form and enable two additional UI form\n"
                 "fields: V-Tip Dia and V-Tip Angle. Adjusting those two values will adjust the Z-Cut parameter such\n"
                 "fields: V-Tip Dia and V-Tip Angle. Adjusting those two values will adjust the Z-Cut parameter such\n"
-                "as the cut width into material will be equal with the value in the Tool Diameter column of this table.\n"
+                "as the cut width into material will be equal with the value in the Tool "
+                "Diameter column of this table.\n"
                 "Choosing the V-Shape Tool Type automatically will select the Operation Type as Isolation."
                 "Choosing the V-Shape Tool Type automatically will select the Operation Type as Isolation."
             ))
             ))
         self.geo_tools_table.horizontalHeaderItem(6).setToolTip(
         self.geo_tools_table.horizontalHeaderItem(6).setToolTip(
@@ -964,7 +962,7 @@ class GeometryObjectUI(ObjectUI):
         self.grid1.addWidget(self.tool_offset_entry, 0, 1)
         self.grid1.addWidget(self.tool_offset_entry, 0, 1)
         self.grid1.addWidget(spacer_lbl, 0, 2)
         self.grid1.addWidget(spacer_lbl, 0, 2)
 
 
-        #### Add a new Tool ## ##
+        # ### Add a new Tool ####
         hlay = QtWidgets.QHBoxLayout()
         hlay = QtWidgets.QHBoxLayout()
         self.geo_tools_box.addLayout(hlay)
         self.geo_tools_box.addLayout(hlay)
 
 
@@ -1014,15 +1012,15 @@ class GeometryObjectUI(ObjectUI):
 
 
         grid2.addWidget(self.addtool_btn, 0, 0)
         grid2.addWidget(self.addtool_btn, 0, 0)
         grid2.addWidget(self.copytool_btn, 0, 1)
         grid2.addWidget(self.copytool_btn, 0, 1)
-        grid2.addWidget(self.deltool_btn, 0,2)
+        grid2.addWidget(self.deltool_btn, 0, 2)
 
 
         self.empty_label = QtWidgets.QLabel('')
         self.empty_label = QtWidgets.QLabel('')
         self.geo_tools_box.addWidget(self.empty_label)
         self.geo_tools_box.addWidget(self.empty_label)
 
 
-        #-----------------------------------
-        # Create CNC Job
-        #-----------------------------------
-        #### Tools Data ## ##
+        # ##################
+        # Create CNC Job ###
+        # ##################
+        # ### Tools Data ## ##
         self.tool_data_label = QtWidgets.QLabel(_('<b>Tool Data</b>'))
         self.tool_data_label = QtWidgets.QLabel(_('<b>Tool Data</b>'))
         self.tool_data_label.setToolTip(
         self.tool_data_label.setToolTip(
             _(
             _(
@@ -1032,8 +1030,16 @@ class GeometryObjectUI(ObjectUI):
         )
         )
         self.geo_tools_box.addWidget(self.tool_data_label)
         self.geo_tools_box.addWidget(self.tool_data_label)
 
 
+        self.geo_param_frame = QtWidgets.QFrame()
+        self.geo_param_frame.setContentsMargins(0, 0, 0, 0)
+        self.geo_tools_box.addWidget(self.geo_param_frame)
+
+        self.geo_param_box = QtWidgets.QVBoxLayout()
+        self.geo_param_box.setContentsMargins(0, 0, 0, 0)
+        self.geo_param_frame.setLayout(self.geo_param_box)
+
         self.grid3 = QtWidgets.QGridLayout()
         self.grid3 = QtWidgets.QGridLayout()
-        self.geo_tools_box.addLayout(self.grid3)
+        self.geo_param_box.addLayout(self.grid3)
 
 
         # Tip Dia
         # Tip Dia
         self.tipdialabel = QtWidgets.QLabel(_('V-Tip Dia:'))
         self.tipdialabel = QtWidgets.QLabel(_('V-Tip Dia:'))
@@ -1067,7 +1073,7 @@ class GeometryObjectUI(ObjectUI):
             )
             )
         )
         )
         self.grid3.addWidget(cutzlabel, 3, 0)
         self.grid3.addWidget(cutzlabel, 3, 0)
-        self.cutz_entry = LengthEntry()
+        self.cutz_entry = FloatEntry()
         self.grid3.addWidget(self.cutz_entry, 3, 1)
         self.grid3.addWidget(self.cutz_entry, 3, 1)
 
 
         # Multi-pass
         # Multi-pass
@@ -1084,7 +1090,7 @@ class GeometryObjectUI(ObjectUI):
         )
         )
         self.grid3.addWidget(self.mpass_cb, 4, 0)
         self.grid3.addWidget(self.mpass_cb, 4, 0)
 
 
-        self.maxdepth_entry = LengthEntry()
+        self.maxdepth_entry = FloatEntry()
         self.maxdepth_entry.setToolTip(
         self.maxdepth_entry.setToolTip(
             _(
             _(
                 "Depth of each pass (positive)."
                 "Depth of each pass (positive)."
@@ -1103,7 +1109,7 @@ class GeometryObjectUI(ObjectUI):
             )
             )
         )
         )
         self.grid3.addWidget(travelzlabel, 5, 0)
         self.grid3.addWidget(travelzlabel, 5, 0)
-        self.travelz_entry = LengthEntry()
+        self.travelz_entry = FloatEntry()
         self.grid3.addWidget(self.travelz_entry, 5, 1)
         self.grid3.addWidget(self.travelz_entry, 5, 1)
 
 
         # Tool change:
         # Tool change:
@@ -1122,7 +1128,7 @@ class GeometryObjectUI(ObjectUI):
                 "in the Machine Code (Pause for tool change)."
                 "in the Machine Code (Pause for tool change)."
             )
             )
         )
         )
-        self.toolchangez_entry = LengthEntry()
+        self.toolchangez_entry = FloatEntry()
 
 
         self.grid3.addWidget(self.toolchangeg_cb, 6, 0)
         self.grid3.addWidget(self.toolchangeg_cb, 6, 0)
         self.grid3.addWidget(self.toolchzlabel, 7, 0)
         self.grid3.addWidget(self.toolchzlabel, 7, 0)
@@ -1149,7 +1155,7 @@ class GeometryObjectUI(ObjectUI):
             )
             )
         )
         )
         self.grid3.addWidget(self.endzlabel, 9, 0)
         self.grid3.addWidget(self.endzlabel, 9, 0)
-        self.gendz_entry = LengthEntry()
+        self.gendz_entry = FloatEntry()
         self.grid3.addWidget(self.gendz_entry, 9, 1)
         self.grid3.addWidget(self.gendz_entry, 9, 1)
 
 
         # Feedrate X-Y
         # Feedrate X-Y
@@ -1161,7 +1167,7 @@ class GeometryObjectUI(ObjectUI):
             )
             )
         )
         )
         self.grid3.addWidget(frlabel, 10, 0)
         self.grid3.addWidget(frlabel, 10, 0)
-        self.cncfeedrate_entry = LengthEntry()
+        self.cncfeedrate_entry = FloatEntry()
         self.grid3.addWidget(self.cncfeedrate_entry, 10, 1)
         self.grid3.addWidget(self.cncfeedrate_entry, 10, 1)
 
 
         # Feedrate Z (Plunge)
         # Feedrate Z (Plunge)
@@ -1173,7 +1179,7 @@ class GeometryObjectUI(ObjectUI):
             )
             )
         )
         )
         self.grid3.addWidget(frzlabel, 11, 0)
         self.grid3.addWidget(frzlabel, 11, 0)
-        self.cncplunge_entry = LengthEntry()
+        self.cncplunge_entry = FloatEntry()
         self.grid3.addWidget(self.cncplunge_entry, 11, 1)
         self.grid3.addWidget(self.cncplunge_entry, 11, 1)
 
 
         # Feedrate rapids
         # Feedrate rapids
@@ -1189,7 +1195,7 @@ class GeometryObjectUI(ObjectUI):
             )
             )
         )
         )
         self.grid3.addWidget(self.fr_rapidlabel, 12, 0)
         self.grid3.addWidget(self.fr_rapidlabel, 12, 0)
-        self.cncfeedrate_rapid_entry = LengthEntry()
+        self.cncfeedrate_rapid_entry = FloatEntry()
         self.grid3.addWidget(self.cncfeedrate_rapid_entry, 12, 1)
         self.grid3.addWidget(self.cncfeedrate_rapid_entry, 12, 1)
         # default values is to hide
         # default values is to hide
         self.fr_rapidlabel.hide()
         self.fr_rapidlabel.hide()
@@ -1228,7 +1234,7 @@ class GeometryObjectUI(ObjectUI):
                 "speed before cutting."
                 "speed before cutting."
             )
             )
         )
         )
-        self.dwelltime_entry = FCEntry()
+        self.dwelltime_entry = FloatEntry()
         self.dwelltime_entry.setToolTip(
         self.dwelltime_entry.setToolTip(
             _(
             _(
                 "Number of milliseconds for spindle to dwell."
                 "Number of milliseconds for spindle to dwell."
@@ -1294,11 +1300,11 @@ class GeometryObjectUI(ObjectUI):
                 "Generate the CNC Job object."
                 "Generate the CNC Job object."
             )
             )
         )
         )
-        self.geo_tools_box.addWidget(self.generate_cnc_button)
+        self.geo_param_box.addWidget(self.generate_cnc_button)
 
 
-        #------------------------------
-        # Paint area
-        #------------------------------
+        # ##############
+        # Paint area ##
+        # ##############
         self.paint_label = QtWidgets.QLabel(_('<b>Paint Area:</b>'))
         self.paint_label = QtWidgets.QLabel(_('<b>Paint Area:</b>'))
         self.paint_label.setToolTip(
         self.paint_label.setToolTip(
             _(
             _(
@@ -1340,7 +1346,6 @@ class CNCObjectUI(ObjectUI):
         self.scale_label.hide()
         self.scale_label.hide()
         self.scale_button.hide()
         self.scale_button.hide()
 
 
-
         for i in range(0, self.offset_grid.count()):
         for i in range(0, self.offset_grid.count()):
             self.offset_grid.itemAt(i).widget().hide()
             self.offset_grid.itemAt(i).widget().hide()
         self.offset_label.hide()
         self.offset_label.hide()
@@ -1475,9 +1480,9 @@ class CNCObjectUI(ObjectUI):
         )
         )
         self.custom_box.addWidget(self.updateplot_button)
         self.custom_box.addWidget(self.updateplot_button)
 
 
-        ################ ##
-        # ## Export G-Code
-        ################ ##
+        # ####################
+        # ## Export G-Code ##
+        # ####################
         self.export_gcode_label = QtWidgets.QLabel(_("<b>Export CNC Code:</b>"))
         self.export_gcode_label = QtWidgets.QLabel(_("<b>Export CNC Code:</b>"))
         self.export_gcode_label.setToolTip(
         self.export_gcode_label.setToolTip(
             _("Export and save G-Code to\n"
             _("Export and save G-Code to\n"
@@ -1575,7 +1580,8 @@ class CNCObjectUI(ObjectUI):
         self.tc_variable_combo.setItemData(8, _("z_move = height where to travel"), Qt.ToolTipRole)
         self.tc_variable_combo.setItemData(8, _("z_move = height where to travel"), Qt.ToolTipRole)
         self.tc_variable_combo.setItemData(9, _("z_depthpercut = the step value for multidepth cut"), Qt.ToolTipRole)
         self.tc_variable_combo.setItemData(9, _("z_depthpercut = the step value for multidepth cut"), Qt.ToolTipRole)
         self.tc_variable_combo.setItemData(10, _("spindlesspeed = the value for the spindle speed"), Qt.ToolTipRole)
         self.tc_variable_combo.setItemData(10, _("spindlesspeed = the value for the spindle speed"), Qt.ToolTipRole)
-        self.tc_variable_combo.setItemData(11, _("dwelltime = time to dwell to allow the spindle to reach it's set RPM"),
+        self.tc_variable_combo.setItemData(11, _("dwelltime = time to dwell to allow the "
+                                                 "spindle to reach it's set RPM"),
                                            Qt.ToolTipRole)
                                            Qt.ToolTipRole)
 
 
         cnclay.addWidget(self.toolchange_cb)
         cnclay.addWidget(self.toolchange_cb)

+ 2 - 2
flatcamGUI/PlotCanvas.py

@@ -132,7 +132,7 @@ class PlotCanvas(QtCore.QObject):
             self.r_line.parent = None
             self.r_line.parent = None
             self.t_line.parent = None
             self.t_line.parent = None
             self.l_line.parent = None
             self.l_line.parent = None
-        except:
+        except Exception as e:
             pass
             pass
 
 
     # redraw the workspace lines on the plot by readding them to the parent view.scene
     # redraw the workspace lines on the plot by readding them to the parent view.scene
@@ -142,7 +142,7 @@ class PlotCanvas(QtCore.QObject):
             self.r_line.parent = self.vispy_canvas.view.scene
             self.r_line.parent = self.vispy_canvas.view.scene
             self.t_line.parent = self.vispy_canvas.view.scene
             self.t_line.parent = self.vispy_canvas.view.scene
             self.l_line.parent = self.vispy_canvas.view.scene
             self.l_line.parent = self.vispy_canvas.view.scene
-        except:
+        except Exception as e:
             pass
             pass
 
 
     def vis_connect(self, event_name, callback):
     def vis_connect(self, event_name, callback):

+ 2 - 2
flatcamParsers/ParseFont.py

@@ -270,7 +270,7 @@ class ParseFont():
             else:
             else:
                 try:
                 try:
                     name = name.replace(" Regular", '')
                     name = name.replace(" Regular", '')
-                except:
+                except Exception as e:
                     pass
                     pass
                 self.regular_f.update({name: font})
                 self.regular_f.update({name: font})
         log.debug("Font parsing is finished.")
         log.debug("Font parsing is finished.")
@@ -313,7 +313,7 @@ class ParseFont():
                 if previous > 0 and glyph_index > 0:
                 if previous > 0 and glyph_index > 0:
                     delta = face.get_kerning(previous, glyph_index)
                     delta = face.get_kerning(previous, glyph_index)
                     pen_x += delta.x
                     pen_x += delta.x
-            except:
+            except Exception as e:
                 pass
                 pass
 
 
             face.load_glyph(glyph_index)
             face.load_glyph(glyph_index)

+ 200 - 127
flatcamTools/ToolCutOut.py

@@ -73,6 +73,20 @@ class CutOut(FlatCAMTool):
         )
         )
         form_layout.addRow(self.object_label, self.obj_combo)
         form_layout.addRow(self.object_label, self.obj_combo)
 
 
+        # Object kind
+        self.kindlabel = QtWidgets.QLabel(_('Obj kind:'))
+        self.kindlabel.setToolTip(
+            _("Choice of what kind the object we want to cutout is.<BR>"
+              "- <B>Single</B>: contain a single PCB Gerber outline object.<BR>"
+              "- <B>Panel</B>: a panel PCB Gerber object, which is made\n"
+              "out of many individual PCB outlines.")
+        )
+        self.obj_kind_combo = RadioSet([
+            {"label": _("Single"), "value": "single"},
+            {"label": _("Panel"), "value": "panel"},
+        ])
+        form_layout.addRow(self.kindlabel, self.obj_kind_combo)
+
         # Tool Diameter
         # Tool Diameter
         self.dia = FCEntry()
         self.dia = FCEntry()
         self.dia_label = QtWidgets.QLabel(_("Tool Dia:"))
         self.dia_label = QtWidgets.QLabel(_("Tool Dia:"))
@@ -320,6 +334,7 @@ class CutOut(FlatCAMTool):
         self.reset_fields()
         self.reset_fields()
 
 
         self.dia.set_value(float(self.app.defaults["tools_cutouttooldia"]))
         self.dia.set_value(float(self.app.defaults["tools_cutouttooldia"]))
+        self.obj_kind_combo.set_value(self.app.defaults["tools_cutoutkind"])
         self.margin.set_value(float(self.app.defaults["tools_cutoutmargin"]))
         self.margin.set_value(float(self.app.defaults["tools_cutoutmargin"]))
         self.gapsize.set_value(float(self.app.defaults["tools_cutoutgapsize"]))
         self.gapsize.set_value(float(self.app.defaults["tools_cutoutgapsize"]))
         self.gaps.set_value(self.app.defaults["tools_gaps_ff"])
         self.gaps.set_value(self.app.defaults["tools_gaps_ff"])
@@ -338,7 +353,8 @@ class CutOut(FlatCAMTool):
         # Get source object.
         # Get source object.
         try:
         try:
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
-        except:
+        except Exception as e:
+            log.debug("CutOut.on_freeform_cutout() --> %s" % str(e))
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
@@ -361,6 +377,11 @@ class CutOut(FlatCAMTool):
             self.app.inform.emit(_("[WARNING_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
             self.app.inform.emit(_("[WARNING_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
+        try:
+            kind = self.obj_kind_combo.get_value()
+        except ValueError:
+            return
+
         try:
         try:
             margin = float(self.margin.get_value())
             margin = float(self.margin.get_value())
         except ValueError:
         except ValueError:
@@ -415,71 +436,89 @@ class CutOut(FlatCAMTool):
             else:
             else:
                 object_geo = cutout_obj.solid_geometry
                 object_geo = cutout_obj.solid_geometry
 
 
-            # try:
-            #     __ = iter(object_geo)
-            # except TypeError:
-            #     object_geo = [object_geo]
+            def cutout_handler(geom):
+                # Get min and max data for each object as we just cut rectangles across X or Y
+                xmin, ymin, xmax, ymax = recursive_bounds(geom)
+
+                px = 0.5 * (xmin + xmax) + margin
+                py = 0.5 * (ymin + ymax) + margin
+                lenx = (xmax - xmin) + (margin * 2)
+                leny = (ymax - ymin) + (margin * 2)
+
+                proc_geometry = []
+
+                if gaps == '8' or gaps == '2LR':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       xmin - gapsize,  # botleft_x
+                                                       py - gapsize + leny / 4,  # botleft_y
+                                                       xmax + gapsize,  # topright_x
+                                                       py + gapsize + leny / 4)  # topright_y
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       xmin - gapsize,
+                                                       py - gapsize - leny / 4,
+                                                       xmax + gapsize,
+                                                       py + gapsize - leny / 4)
+
+                if gaps == '8' or gaps == '2TB':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       px - gapsize + lenx / 4,
+                                                       ymin - gapsize,
+                                                       px + gapsize + lenx / 4,
+                                                       ymax + gapsize)
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       px - gapsize - lenx / 4,
+                                                       ymin - gapsize,
+                                                       px + gapsize - lenx / 4,
+                                                       ymax + gapsize)
+
+                if gaps == '4' or gaps == 'LR':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       xmin - gapsize,
+                                                       py - gapsize,
+                                                       xmax + gapsize,
+                                                       py + gapsize)
+
+                if gaps == '4' or gaps == 'TB':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       px - gapsize,
+                                                       ymin - gapsize,
+                                                       px + gapsize,
+                                                       ymax + gapsize)
 
 
-            object_geo = unary_union(object_geo)
+                try:
+                    for g in geom:
+                        proc_geometry.append(g)
+                except TypeError:
+                    proc_geometry.append(geom)
 
 
-            # for geo in object_geo:
-            if isinstance(cutout_obj, FlatCAMGerber):
-                geo = object_geo.buffer(margin + abs(dia / 2))
-                geo = geo.exterior
+                return proc_geometry
+
+            if kind == 'single':
+                object_geo = unary_union(object_geo)
+
+                # for geo in object_geo:
+                if isinstance(cutout_obj, FlatCAMGerber):
+                    if isinstance(object_geo, MultiPolygon):
+                        x0, y0, x1, y1 = object_geo.bounds
+                        object_geo = box(x0, y0, x1, y1)
+
+                    geo_buf = object_geo.buffer(margin + abs(dia / 2))
+                    geo = geo_buf.exterior
+                else:
+                    geo = object_geo
+
+                solid_geo = cutout_handler(geom=geo)
             else:
             else:
-                geo = object_geo
-
-            # Get min and max data for each object as we just cut rectangles across X or Y
-            xmin, ymin, xmax, ymax = recursive_bounds(geo)
-
-            px = 0.5 * (xmin + xmax) + margin
-            py = 0.5 * (ymin + ymax) + margin
-            lenx = (xmax - xmin) + (margin * 2)
-            leny = (ymax - ymin) + (margin * 2)
-
-            if gaps == '8' or gaps == '2LR':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  xmin - gapsize,           # botleft_x
-                                                  py - gapsize + leny / 4,  # botleft_y
-                                                  xmax + gapsize,           # topright_x
-                                                  py + gapsize + leny / 4)  # topright_y
-                geo = self.subtract_poly_from_geo(geo,
-                                                  xmin - gapsize,
-                                                  py - gapsize - leny / 4,
-                                                  xmax + gapsize,
-                                                  py + gapsize - leny / 4)
-
-            if gaps == '8' or gaps == '2TB':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  px - gapsize + lenx / 4,
-                                                  ymin - gapsize,
-                                                  px + gapsize + lenx / 4,
-                                                  ymax + gapsize)
-                geo = self.subtract_poly_from_geo(geo,
-                                                  px - gapsize - lenx / 4,
-                                                  ymin - gapsize,
-                                                  px + gapsize - lenx / 4,
-                                                  ymax + gapsize)
-
-            if gaps == '4' or gaps == 'LR':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  xmin - gapsize,
-                                                  py - gapsize,
-                                                  xmax + gapsize,
-                                                  py + gapsize)
-
-            if gaps == '4' or gaps == 'TB':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  px - gapsize,
-                                                  ymin - gapsize,
-                                                  px + gapsize,
-                                                  ymax + gapsize)
+                try:
+                    __ = iter(object_geo)
+                except TypeError:
+                    object_geo = [object_geo]
 
 
-            try:
-                for g in geo:
-                    solid_geo.append(g)
-            except TypeError:
-                solid_geo.append(geo)
+                for geom_struct in object_geo:
+                    if isinstance(cutout_obj, FlatCAMGerber):
+                        geom_struct = (geom_struct.buffer(margin + abs(dia / 2))).exterior
+
+                    solid_geo += cutout_handler(geom=geom_struct)
 
 
             geo_obj.solid_geometry = deepcopy(solid_geo)
             geo_obj.solid_geometry = deepcopy(solid_geo)
             xmin, ymin, xmax, ymax = recursive_bounds(geo_obj.solid_geometry)
             xmin, ymin, xmax, ymax = recursive_bounds(geo_obj.solid_geometry)
@@ -508,7 +547,8 @@ class CutOut(FlatCAMTool):
         # Get source object.
         # Get source object.
         try:
         try:
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
-        except:
+        except Exception as e:
+            log.debug("CutOut.on_rectangular_cutout() --> %s" % str(e))
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
@@ -530,6 +570,11 @@ class CutOut(FlatCAMTool):
             self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
             self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
+        try:
+            kind = self.obj_kind_combo.get_value()
+        except ValueError:
+            return
+
         try:
         try:
             margin = float(self.margin.get_value())
             margin = float(self.margin.get_value())
         except ValueError:
         except ValueError:
@@ -577,68 +622,85 @@ class CutOut(FlatCAMTool):
             solid_geo = []
             solid_geo = []
             object_geo = cutout_obj.solid_geometry
             object_geo = cutout_obj.solid_geometry
 
 
-            try:
-                __ = iter(object_geo)
-            except TypeError:
-                object_geo = [object_geo]
+            def cutout_rect_handler(geom):
+                proc_geometry = []
+
+                px = 0.5 * (xmin + xmax) + margin
+                py = 0.5 * (ymin + ymax) + margin
+                lenx = (xmax - xmin) + (margin * 2)
+                leny = (ymax - ymin) + (margin * 2)
+
+                if gaps == '8' or gaps == '2LR':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       xmin - gapsize,  # botleft_x
+                                                       py - gapsize + leny / 4,  # botleft_y
+                                                       xmax + gapsize,  # topright_x
+                                                       py + gapsize + leny / 4)  # topright_y
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       xmin - gapsize,
+                                                       py - gapsize - leny / 4,
+                                                       xmax + gapsize,
+                                                       py + gapsize - leny / 4)
+
+                if gaps == '8' or gaps == '2TB':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       px - gapsize + lenx / 4,
+                                                       ymin - gapsize,
+                                                       px + gapsize + lenx / 4,
+                                                       ymax + gapsize)
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       px - gapsize - lenx / 4,
+                                                       ymin - gapsize,
+                                                       px + gapsize - lenx / 4,
+                                                       ymax + gapsize)
+
+                if gaps == '4' or gaps == 'LR':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       xmin - gapsize,
+                                                       py - gapsize,
+                                                       xmax + gapsize,
+                                                       py + gapsize)
+
+                if gaps == '4' or gaps == 'TB':
+                    geom = self.subtract_poly_from_geo(geom,
+                                                       px - gapsize,
+                                                       ymin - gapsize,
+                                                       px + gapsize,
+                                                       ymax + gapsize)
+                try:
+                    for g in geom:
+                        proc_geometry.append(g)
+                except TypeError:
+                    proc_geometry.append(geom)
+                return proc_geometry
 
 
-            object_geo = unary_union(object_geo)
+            if kind == 'single':
+                object_geo = unary_union(object_geo)
 
 
-            xmin, ymin, xmax, ymax = object_geo.bounds
-            geo = box(xmin, ymin, xmax, ymax)
+                xmin, ymin, xmax, ymax = object_geo.bounds
+                geo = box(xmin, ymin, xmax, ymax)
 
 
-            # if Gerber create a buffer at a distance
-            # if Geometry then cut through the geometry
-            if isinstance(cutout_obj, FlatCAMGerber):
-                geo = geo.buffer(margin + abs(dia / 2))
+                # if Gerber create a buffer at a distance
+                # if Geometry then cut through the geometry
+                if isinstance(cutout_obj, FlatCAMGerber):
+                    geo = geo.buffer(margin + abs(dia / 2))
 
 
-            px = 0.5 * (xmin + xmax) + margin
-            py = 0.5 * (ymin + ymax) + margin
-            lenx = (xmax - xmin) + (margin * 2)
-            leny = (ymax - ymin) + (margin * 2)
-
-            if gaps == '8' or gaps == '2LR':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  xmin - gapsize,  # botleft_x
-                                                  py - gapsize + leny / 4,  # botleft_y
-                                                  xmax + gapsize,  # topright_x
-                                                  py + gapsize + leny / 4)  # topright_y
-                geo = self.subtract_poly_from_geo(geo,
-                                                  xmin - gapsize,
-                                                  py - gapsize - leny / 4,
-                                                  xmax + gapsize,
-                                                  py + gapsize - leny / 4)
-
-            if gaps == '8' or gaps == '2TB':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  px - gapsize + lenx / 4,
-                                                  ymin - gapsize,
-                                                  px + gapsize + lenx / 4,
-                                                  ymax + gapsize)
-                geo = self.subtract_poly_from_geo(geo,
-                                                  px - gapsize - lenx / 4,
-                                                  ymin - gapsize,
-                                                  px + gapsize - lenx / 4,
-                                                  ymax + gapsize)
-
-            if gaps == '4' or gaps == 'LR':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  xmin - gapsize,
-                                                  py - gapsize,
-                                                  xmax + gapsize,
-                                                  py + gapsize)
-
-            if gaps == '4' or gaps == 'TB':
-                geo = self.subtract_poly_from_geo(geo,
-                                                  px - gapsize,
-                                                  ymin - gapsize,
-                                                  px + gapsize,
-                                                  ymax + gapsize)
-            try:
-                for g in geo:
-                    solid_geo.append(g)
-            except TypeError:
-                solid_geo.append(geo)
+                solid_geo = cutout_rect_handler(geom=geo)
+            else:
+                try:
+                    __ = iter(object_geo)
+                except TypeError:
+                    object_geo = [object_geo]
+
+                for geom_struct in object_geo:
+                    geom_struct = unary_union(geom_struct)
+                    xmin, ymin, xmax, ymax = geom_struct.bounds
+                    geom_struct = box(xmin, ymin, xmax, ymax)
+
+                    if isinstance(cutout_obj, FlatCAMGerber):
+                        geom_struct = geom_struct.buffer(margin + abs(dia / 2))
+
+                    solid_geo += cutout_rect_handler(geom=geom_struct)
 
 
             geo_obj.solid_geometry = deepcopy(solid_geo)
             geo_obj.solid_geometry = deepcopy(solid_geo)
             geo_obj.options['cnctooldia'] = str(dia)
             geo_obj.options['cnctooldia'] = str(dia)
@@ -715,7 +777,8 @@ class CutOut(FlatCAMTool):
         # Get source object.
         # Get source object.
         try:
         try:
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
-        except:
+        except Exception as e:
+            log.debug("CutOut.on_manual_cutout() --> %s" % str(e))
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Geometry object: %s") % name)
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Geometry object: %s") % name)
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
@@ -746,18 +809,19 @@ class CutOut(FlatCAMTool):
         # Get source object.
         # Get source object.
         try:
         try:
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
-        except:
+        except Exception as e:
+            log.debug("CutOut.on_manual_geo() --> %s" % str(e))
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Gerber object: %s") % name)
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Gerber object: %s") % name)
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         if cutout_obj is None:
         if cutout_obj is None:
             self.app.inform.emit(_("[ERROR_NOTCL] There is no Gerber object selected for Cutout.\n"
             self.app.inform.emit(_("[ERROR_NOTCL] There is no Gerber object selected for Cutout.\n"
-                                 "Select one and try again."))
+                                   "Select one and try again."))
             return
             return
 
 
         if not isinstance(cutout_obj, FlatCAMGerber):
         if not isinstance(cutout_obj, FlatCAMGerber):
             self.app.inform.emit(_("[ERROR_NOTCL] The selected object has to be of Gerber type.\n"
             self.app.inform.emit(_("[ERROR_NOTCL] The selected object has to be of Gerber type.\n"
-                                 "Select a Gerber file and try again."))
+                                   "Select a Gerber file and try again."))
             return
             return
 
 
         try:
         try:
@@ -768,13 +832,18 @@ class CutOut(FlatCAMTool):
                 dia = float(self.dia.get_value().replace(',', '.'))
                 dia = float(self.dia.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
                 self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
                 self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                     "Add it and retry."))
+                                       "Add it and retry."))
                 return
                 return
 
 
         if 0 in {dia}:
         if 0 in {dia}:
             self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
             self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
+        try:
+            kind = self.obj_kind_combo.get_value()
+        except ValueError:
+            return
+
         try:
         try:
             margin = float(self.margin.get_value())
             margin = float(self.margin.get_value())
         except ValueError:
         except ValueError:
@@ -783,7 +852,7 @@ class CutOut(FlatCAMTool):
                 margin = float(self.margin.get_value().replace(',', '.'))
                 margin = float(self.margin.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
                 self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
                 self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
-                                     "Add it and retry."))
+                                       "Add it and retry."))
                 return
                 return
 
 
         convex_box = self.convex_box.get_value()
         convex_box = self.convex_box.get_value()
@@ -794,6 +863,10 @@ class CutOut(FlatCAMTool):
             if convex_box:
             if convex_box:
                 geo = geo_union.convex_hull
                 geo = geo_union.convex_hull
                 geo_obj.solid_geometry = geo.buffer(margin + abs(dia / 2))
                 geo_obj.solid_geometry = geo.buffer(margin + abs(dia / 2))
+            elif kind == 'single':
+                x0, y0, x1, y1 = geo_union.bounds
+                geo = box(x0, y0, x1, y1)
+                geo_obj.solid_geometry = geo.buffer(margin + abs(dia / 2))
             else:
             else:
                 geo = geo_union
                 geo = geo_union
                 geo = geo.buffer(margin + abs(dia / 2))
                 geo = geo.buffer(margin + abs(dia / 2))

+ 5 - 5
flatcamTools/ToolMove.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMTool import FlatCAMTool
 from FlatCAMObj import *
 from FlatCAMObj import *
@@ -97,7 +97,7 @@ class ToolMove(FlatCAMTool):
                 pos_canvas = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
                 pos_canvas = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
 
 
                 # if GRID is active we need to get the snapped positions
                 # if GRID is active we need to get the snapped positions
-                if self.app.grid_status() is True:
+                if self.app.grid_status() == True:
                     pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
                     pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
                 else:
                 else:
                     pos = pos_canvas
                     pos = pos_canvas
@@ -117,7 +117,7 @@ class ToolMove(FlatCAMTool):
                     self.delete_shape()
                     self.delete_shape()
 
 
                     # if GRID is active we need to get the snapped positions
                     # if GRID is active we need to get the snapped positions
-                    if self.app.grid_status() is True:
+                    if self.app.grid_status() == True:
                         pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
                         pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
                     else:
                     else:
                         pos = pos_canvas
                         pos = pos_canvas
@@ -181,7 +181,7 @@ class ToolMove(FlatCAMTool):
         pos_canvas = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
         pos_canvas = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
 
 
         # if GRID is active we need to get the snapped positions
         # if GRID is active we need to get the snapped positions
-        if self.app.grid_status() is True:
+        if self.app.grid_status() == True:
             pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
             pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
         else:
         else:
             pos = pos_canvas
             pos = pos_canvas

+ 3 - 3
flatcamTools/ToolNonCopperClear.py

@@ -80,7 +80,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.tools_box.addWidget(self.tools_table)
         self.tools_box.addWidget(self.tools_table)
 
 
         self.tools_table.setColumnCount(4)
         self.tools_table.setColumnCount(4)
-        self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), 'TT', ''])
+        self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), _('TT'), ''])
         self.tools_table.setColumnHidden(3, True)
         self.tools_table.setColumnHidden(3, True)
         self.tools_table.setSortingEnabled(False)
         self.tools_table.setSortingEnabled(False)
         # self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
         # self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
@@ -461,7 +461,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             self.tools_table.itemChanged.disconnect(self.on_tool_edit)
             self.tools_table.itemChanged.disconnect(self.on_tool_edit)
-        except:
+        except TypeError:
             pass
             pass
 
 
     def on_tool_add(self, dia=None, muted=None):
     def on_tool_add(self, dia=None, muted=None):
@@ -861,7 +861,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                 for poly in cleared_by_last_tool:
                 for poly in cleared_by_last_tool:
                     try:
                     try:
                         area = area.difference(poly)
                         area = area.difference(poly)
-                    except:
+                    except Exception as e:
                         pass
                         pass
                 cleared_by_last_tool[:] = []
                 cleared_by_last_tool[:] = []
 
 

+ 2 - 2
flatcamTools/ToolPDF.py

@@ -360,13 +360,13 @@ class ToolPDF(FlatCAMTool):
 
 
         try:
         try:
             self.check_thread.stop()
             self.check_thread.stop()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         self.check_thread.setInterval(check_period)
         self.check_thread.setInterval(check_period)
         try:
         try:
             self.check_thread.timeout.disconnect(self.periodic_check_handler)
             self.check_thread.timeout.disconnect(self.periodic_check_handler)
-        except:
+        except TypeError:
             pass
             pass
 
 
         self.check_thread.timeout.connect(self.periodic_check_handler)
         self.check_thread.timeout.connect(self.periodic_check_handler)

+ 2 - 2
flatcamTools/ToolPaint.py

@@ -77,7 +77,7 @@ class ToolPaint(FlatCAMTool, Gerber):
         self.tools_box.addWidget(self.tools_table)
         self.tools_box.addWidget(self.tools_table)
 
 
         self.tools_table.setColumnCount(4)
         self.tools_table.setColumnCount(4)
-        self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), 'TT', ''])
+        self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), _('TT'), ''])
         self.tools_table.setColumnHidden(3, True)
         self.tools_table.setColumnHidden(3, True)
         # self.tools_table.setSortingEnabled(False)
         # self.tools_table.setSortingEnabled(False)
         # self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
         # self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
@@ -437,7 +437,7 @@ class ToolPaint(FlatCAMTool, Gerber):
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             self.tools_table.itemChanged.disconnect()
             self.tools_table.itemChanged.disconnect()
-        except:
+        except TypeError:
             pass
             pass
 
 
         # updated units
         # updated units

+ 9 - 7
flatcamTools/ToolPanelize.py

@@ -348,7 +348,8 @@ class Panelize(FlatCAMTool):
         # Get source object.
         # Get source object.
         try:
         try:
             obj = self.app.collection.get_by_name(str(name))
             obj = self.app.collection.get_by_name(str(name))
-        except:
+        except Exception as e:
+            log.debug("Panelize.on_panelize() --> %s" % str(e))
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
@@ -362,7 +363,8 @@ class Panelize(FlatCAMTool):
 
 
         try:
         try:
             box = self.app.collection.get_by_name(boxname)
             box = self.app.collection.get_by_name(boxname)
-        except:
+        except Exception as e:
+            log.debug("Panelize.on_panelize() --> %s" % str(e))
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % boxname)
             self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % boxname)
             return "Could not retrieve object: %s" % boxname
             return "Could not retrieve object: %s" % boxname
 
 
@@ -491,8 +493,8 @@ class Panelize(FlatCAMTool):
                         if option is not 'name':
                         if option is not 'name':
                             try:
                             try:
                                 obj_fin.options[option] = panel_obj.options[option]
                                 obj_fin.options[option] = panel_obj.options[option]
-                            except:
-                                log.warning("Failed to copy option.", option)
+                            except KeyError:
+                                log.warning("Failed to copy option. %s" % str(option))
 
 
                     for row in range(rows):
                     for row in range(rows):
                         currentx = 0.0
                         currentx = 0.0
@@ -534,7 +536,7 @@ class Panelize(FlatCAMTool):
                             for local_geom in geom:
                             for local_geom in geom:
                                 res_geo = translate_recursion(local_geom)
                                 res_geo = translate_recursion(local_geom)
                                 try:
                                 try:
-                                    geoms += (res_geo)
+                                    geoms += res_geo
                                 except TypeError:
                                 except TypeError:
                                     geoms.append(res_geo)
                                     geoms.append(res_geo)
                             return geoms
                             return geoms
@@ -638,9 +640,9 @@ class Panelize(FlatCAMTool):
             try:
             try:
                 panelize_2()
                 panelize_2()
                 self.app.inform.emit(_("[success] Panel created successfully."))
                 self.app.inform.emit(_("[success] Panel created successfully."))
-            except Exception as e:
+            except Exception as ee:
                 proc.done()
                 proc.done()
-                log.debug(str(e))
+                log.debug(str(ee))
                 return
                 return
             proc.done()
             proc.done()
 
 

+ 12 - 8
flatcamTools/ToolSolderPaste.py

@@ -642,22 +642,26 @@ class SolderPaste(FlatCAMTool):
     def ui_disconnect(self):
     def ui_disconnect(self):
         # if connected, disconnect the signal from the slot on item_changed as it creates issues
         # if connected, disconnect the signal from the slot on item_changed as it creates issues
 
 
-        try:
-            for i in range(self.gcode_form_layout.count()):
-                if isinstance(self.gcode_form_layout.itemAt(i).widget(), FCComboBox):
+        for i in range(self.gcode_form_layout.count()):
+            if isinstance(self.gcode_form_layout.itemAt(i).widget(), FCComboBox):
+                try:
                     self.gcode_form_layout.itemAt(i).widget().currentIndexChanged.disconnect()
                     self.gcode_form_layout.itemAt(i).widget().currentIndexChanged.disconnect()
-                if isinstance(self.gcode_form_layout.itemAt(i).widget(), FCEntry):
+                except TypeError:
+                    pass
+            if isinstance(self.gcode_form_layout.itemAt(i).widget(), FCEntry):
+                try:
                     self.gcode_form_layout.itemAt(i).widget().editingFinished.disconnect()
                     self.gcode_form_layout.itemAt(i).widget().editingFinished.disconnect()
-        except:
-            pass
+                except TypeError:
+                    pass
+
         try:
         try:
             self.tools_table.itemChanged.disconnect(self.on_tool_edit)
             self.tools_table.itemChanged.disconnect(self.on_tool_edit)
-        except:
+        except TypeError:
             pass
             pass
 
 
         try:
         try:
             self.tools_table.currentItemChanged.disconnect(self.on_row_selection_change)
             self.tools_table.currentItemChanged.disconnect(self.on_row_selection_change)
-        except:
+        except TypeError:
             pass
             pass
 
 
     def update_comboboxes(self, obj, status):
     def update_comboboxes(self, obj, status):

+ 6 - 6
flatcamTools/ToolSub.py

@@ -175,14 +175,14 @@ class ToolSub(FlatCAMTool):
 
 
         try:
         try:
             self.intersect_btn.clicked.disconnect(self.on_grb_intersection_click)
             self.intersect_btn.clicked.disconnect(self.on_grb_intersection_click)
-        except Exception as e:
-            log.debug("ToolSub.__init__() --> %s" % str(e))
+        except TypeError:
+            pass
         self.intersect_btn.clicked.connect(self.on_grb_intersection_click)
         self.intersect_btn.clicked.connect(self.on_grb_intersection_click)
 
 
         try:
         try:
             self.intersect_geo_btn.clicked.disconnect()
             self.intersect_geo_btn.clicked.disconnect()
-        except Exception as e:
-            log.debug("ToolSub.__init__() --> %s" % str(e))
+        except TypeError:
+            pass
         self.intersect_geo_btn.clicked.connect(self.on_geo_intersection_click)
         self.intersect_geo_btn.clicked.connect(self.on_geo_intersection_click)
 
 
     def install(self, icon=None, separator=None, **kwargs):
     def install(self, icon=None, separator=None, **kwargs):
@@ -569,14 +569,14 @@ class ToolSub(FlatCAMTool):
 
 
         try:
         try:
             self.check_thread.stop()
             self.check_thread.stop()
-        except Exception as e:
+        except TypeError:
             pass
             pass
 
 
         if reset:
         if reset:
             self.check_thread.setInterval(check_period)
             self.check_thread.setInterval(check_period)
             try:
             try:
                 self.check_thread.timeout.disconnect(self.periodic_check_handler)
                 self.check_thread.timeout.disconnect(self.periodic_check_handler)
-            except Exception as e:
+            except TypeError:
                 pass
                 pass
 
 
         self.check_thread.timeout.connect(self.periodic_check_handler)
         self.check_thread.timeout.connect(self.periodic_check_handler)

BIN
locale/de/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 194 - 194
locale/de/LC_MESSAGES/strings.po


BIN
locale/en/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 194 - 194
locale/en/LC_MESSAGES/strings.po


BIN
locale/es/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 196 - 196
locale/es/LC_MESSAGES/strings.po


BIN
locale/pt_BR/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 203 - 207
locale/pt_BR/LC_MESSAGES/strings.po


BIN
locale/ro/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 194 - 194
locale/ro/LC_MESSAGES/strings.po


BIN
locale/ru/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 193 - 193
locale/ru/LC_MESSAGES/strings.po


Разница между файлами не показана из-за своего большого размера
+ 220 - 221
locale_template/strings.pot


Некоторые файлы не были показаны из-за большого количества измененных файлов