Procházet zdrojové kódy

- minor UI changes for Gerber UI
- ~~after an object move, the apertures plotted shapes are deleted from canvas and the 'mark all' button is deselected~~
- after move tool action or any other transform (rotate, skew, scale, mirror, offset), the plotted apertures are kept plotted.
- changing units now will convert all the default values from one unit type to another
- prettified the selection shape and the moving shape
- initial work in object hovering shape

Marius Stanciu před 6 roky
rodič
revize
06fb48eb6a

+ 230 - 70
FlatCAMApp.py

@@ -562,9 +562,9 @@ class App(QtCore.QObject):
             "global_project_autohide": True,
             "global_app_level": 'b',
 
-            "global_gridx": 1.0,
-            "global_gridy": 1.0,
-            "global_snap_max": 0.05,
+            "global_gridx": 0.0393701,
+            "global_gridy": 0.0393701,
+            "global_snap_max": 0.001968504,
             "global_grid_context_menu": {
                 'in': [0.01, 0.02, 0.025, 0.05, 0.1],
                 'mm': [0.1, 0.2, 0.5, 1, 2.54]
@@ -658,7 +658,6 @@ class App(QtCore.QObject):
             "excellon_drillz": -0.1,
             "excellon_travelz": 0.1,
             "excellon_feedrate": 3.0,
-            "excellon_feedrate_probe": 3.0,
             "excellon_spindlespeed": None,
             "excellon_dwell": False,
             "excellon_dwelltime": 1,
@@ -676,6 +675,7 @@ class App(QtCore.QObject):
             "excellon_endz": 2.0,
             "excellon_feedrate_rapid": 3.0,
             "excellon_z_pdepth": -0.02,
+            "excellon_feedrate_probe": 3.0,
             "excellon_f_plunge": False,
             "excellon_f_retract": False,
 
@@ -733,17 +733,17 @@ class App(QtCore.QObject):
             "cncjob_toolchange_macro": "",
             "cncjob_toolchange_macro_enable": False,
 
-            "tools_ncctools": "1.0, 0.5",
-            "tools_nccoverlap": 0.4,
-            "tools_nccmargin": 0.1,
+            "tools_ncctools": "0.0393701, 0.019685",
+            "tools_nccoverlap": 0.015748,
+            "tools_nccmargin": 0.00393701,
             "tools_nccmethod": "seed",
             "tools_nccconnect": True,
             "tools_ncccontour": True,
             "tools_nccrest": False,
 
-            "tools_cutouttooldia": 0.1,
-            "tools_cutoutmargin": 0.1,
-            "tools_cutoutgapsize": 0.15,
+            "tools_cutouttooldia": 0.00393701,
+            "tools_cutoutmargin": 0.00393701,
+            "tools_cutoutgapsize": 0.005905512,
             "tools_gaps_rect": "4",
             "tools_gaps_ff": "8",
 
@@ -757,10 +757,10 @@ class App(QtCore.QObject):
 
             "tools_2sided_mirror_axis": "X",
             "tools_2sided_axis_loc": "point",
-            "tools_2sided_drilldia": 1,
+            "tools_2sided_drilldia": 0.0393701,
 
             "tools_film_type": 'neg',
-            "tools_film_boundary": 1,
+            "tools_film_boundary": 0.0393701,
             "tools_film_scale": 0,
 
             "tools_panelize_spacing_columns": 0,
@@ -792,17 +792,17 @@ class App(QtCore.QObject):
             "tools_transform_mirror_reference": False,
             "tools_transform_mirror_point": (0, 0),
 
-            "tools_solderpaste_tools": "1.0, 0.3",
-            "tools_solderpaste_new": 0.3,
-            "tools_solderpaste_z_start": 0.005,
-            "tools_solderpaste_z_dispense": 0.01,
-            "tools_solderpaste_z_stop": 0.005,
-            "tools_solderpaste_z_travel": 0.1,
-            "tools_solderpaste_z_toolchange": 1.0,
+            "tools_solderpaste_tools": "0.0393701, 0.011811",
+            "tools_solderpaste_new": 0.011811,
+            "tools_solderpaste_z_start": 0.00019685039,
+            "tools_solderpaste_z_dispense": 0.00393701,
+            "tools_solderpaste_z_stop": 0.00019685039,
+            "tools_solderpaste_z_travel": 0.00393701,
+            "tools_solderpaste_z_toolchange": 0.0393701,
             "tools_solderpaste_xy_toolchange": "0.0, 0.0",
             "tools_solderpaste_frxy": 3.0,
             "tools_solderpaste_frz": 3.0,
-            "tools_solderpaste_frz_dispense": 1.0,
+            "tools_solderpaste_frz_dispense": 0.0393701,
             "tools_solderpaste_speedfwd": 20,
             "tools_solderpaste_dwellfwd": 1,
             "tools_solderpaste_speedrev": 10,
@@ -1341,6 +1341,7 @@ class App(QtCore.QObject):
         ###############################
         self.ui.general_options_form.general_app_group.units_radio.group_toggle_fn = self.on_toggle_units
         self.ui.general_defaults_form.general_app_group.language_apply_btn.clicked.connect(self.on_language_apply)
+        self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect(self.on_toggle_units)
 
         ###############################
         ### GUI PREFERENCES SIGNALS ###
@@ -1583,6 +1584,11 @@ class App(QtCore.QObject):
         # flag for polygons not cleared
         self.poly_not_cleared = False
 
+        # VisPy visuals
+        self.hover_shapes = ShapeCollection(parent=self.plotcanvas.vispy_canvas.view.scene, layers=7)
+        self.isHovering = False
+        self.notHovering = True
+
         ### Save defaults to factory_defaults.FlatConfig file ###
         ### It's done only once after install #############
         factory_file = open(self.data_path + '/factory_defaults.FlatConfig')
@@ -1645,9 +1651,9 @@ class App(QtCore.QObject):
             except:
                 pass
 
-    def defaults_write_form(self):
+    def defaults_write_form(self, factor=None):
         for option in self.defaults:
-            self.defaults_write_form_field(option)
+            self.defaults_write_form_field(option, factor=factor)
             # try:
             #     self.defaults_form_fields[option].set_value(self.defaults[option])
             # except KeyError:
@@ -1655,9 +1661,13 @@ class App(QtCore.QObject):
             #     # TODO: Rethink this?
             #     pass
 
-    def defaults_write_form_field(self, field):
+    def defaults_write_form_field(self, field, factor=None):
         try:
-            self.defaults_form_fields[field].set_value(self.defaults[field])
+            if factor is None:
+                self.defaults_form_fields[field].set_value(self.defaults[field])
+            else:
+                self.defaults_form_fields[field].set_value(self.defaults[field] * factor)
+
         except KeyError:
             #self.log.debug("defaults_write_form(): No field for: %s" % option)
             # TODO: Rethink this?
@@ -2456,10 +2466,7 @@ class App(QtCore.QObject):
                 oname = option[len(kind) + 1:]
                 obj.options[oname] = self.options[option]
 
-        # if kind == 'geometry':
-        #     obj.tools = {}
-        # elif kind == 'cncjob':
-        #     obj.cnc_tools = {}
+        obj.isHovering = False
 
         # Initialize as per user request
         # User must take care to implement initialize
@@ -3034,8 +3041,11 @@ class App(QtCore.QObject):
     def on_defaults_dict_change(self, field):
         self.defaults_write_form_field(field)
 
+        if field == "units":
+            self.set_screen_units(self.defaults['units'])
+
     def set_screen_units(self, units):
-        self.ui.units_label.setText("[" + self.options["units"].lower() + "]")
+        self.ui.units_label.setText("[" + self.defaults["units"].lower() + "]")
 
     def on_toggle_units(self):
         """
@@ -3053,22 +3063,41 @@ class App(QtCore.QObject):
             return
 
         # If option is the same, then ignore
-        if self.ui.general_options_form.general_app_group.units_radio.get_value().upper() == self.options["units"].upper():
-            self.log.debug("on_toggle_units(): Same as options, so ignoring.")
+        if self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == \
+                self.defaults["units"].upper():
+            self.log.debug("on_toggle_units(): Same as defaults, so ignoring.")
             return
 
         # Options to scale
-        dimensions = ['gerber_isotooldia', 'tools_cutoutmargin', 'tools_cutoutgapsize',
-                      'gerber_noncoppermargin', 'gerber_bboxmargin','gerber_isooverlap','tools_nccoverlap',
-                      'tools_nccmargin','tools_cutouttooldia','tools_cutoutgapsize',
-                      'gerber_noncoppermargin','gerber_bboxmargin',
-                      'excellon_drillz', "excellon_toolchangexy",
-                      'excellon_travelz', 'excellon_feedrate', 'excellon_feedrate_rapid', 'excellon_toolchangez',
-                      'excellon_tooldia', 'excellon_endz', 'cncjob_tooldia',
-                      'geometry_cutz', 'geometry_travelz', 'geometry_feedrate', 'geometry_feedrate_rapid',
-                      'geometry_cnctooldia', 'tools_painttooldia', 'tools_paintoverlap', 'geometry_toolchangexy',
-                      'geometry_toolchangez',
-                      'tools_paintmargin', 'geometry_endz', 'geometry_depthperpass', 'global_gridx', 'global_gridy']
+        dimensions = ['gerber_isotooldia', 'gerber_noncoppermargin', 'gerber_bboxmargin',
+
+                      'excellon_drillz',  'excellon_travelz', "excellon_toolchangexy",
+                      'excellon_feedrate', 'excellon_feedrate_rapid', 'excellon_toolchangez',
+                      'excellon_tooldia', 'excellon_slot_tooldia', 'excellon_endz', "excellon_feedrate_probe",
+                      "excellon_z_pdepth",
+
+                      'geometry_cutz',  "geometry_depthperpass", 'geometry_travelz', 'geometry_feedrate',
+                      'geometry_feedrate_rapid', "geometry_toolchangez", "geometry_feedrate_z",
+                      "geometry_toolchangexy", 'geometry_cnctooldia', 'geometry_endz', "geometry_z_pdepth",
+                      "geometry_feedrate_probe",
+
+                      'cncjob_tooldia',
+
+                      'tools_paintmargin', 'tools_painttooldia', 'tools_paintoverlap',
+                      "tools_ncctools", "tools_nccoverlap", "tools_nccmargin",
+                      "tools_2sided_drilldia", "tools_film_boundary",
+                      "tools_cutouttooldia", 'tools_cutoutmargin', 'tools_cutoutgapsize',
+                      "tools_panelize_constrainx", "tools_panelize_constrainy",
+                      "tools_calc_vshape_tip_dia", "tools_calc_vshape_cut_z",
+                      "tools_transform_skew_x", "tools_transform_skew_y", "tools_transform_offset_x",
+                      "tools_transform_offset_y",
+
+                      "tools_solderpaste_tools", "tools_solderpaste_new", "tools_solderpaste_z_start",
+                      "tools_solderpaste_z_dispense", "tools_solderpaste_z_stop", "tools_solderpaste_z_travel",
+                      "tools_solderpaste_z_toolchange", "tools_solderpaste_xy_toolchange", "tools_solderpaste_frxy",
+                      "tools_solderpaste_frz", "tools_solderpaste_frz_dispense",
+
+                      'global_gridx', 'global_gridy', 'global_snap_max']
 
         def scale_options(sfactor):
             for dim in dimensions:
@@ -3082,15 +3111,65 @@ class App(QtCore.QObject):
                     coords_xy[0] *= sfactor
                     coords_xy[1] *= sfactor
                     self.options['geometry_toolchangexy'] = "%f, %f" % (coords_xy[0], coords_xy[1])
+                elif dim == 'tools_ncctools':
+                    ncctols = [float(eval(a)) for a in self.defaults["tools_ncctools"].split(",")]
+                    ncctols[0] *= sfactor
+                    ncctols[1] *= sfactor
+                    self.options['tools_ncctools'] = "%f, %f" % (ncctols[0], ncctols[1])
+                elif dim == 'tools_solderpaste_tools':
+                    sp_tools = [float(eval(a)) for a in self.defaults["tools_solderpaste_tools"].split(",")]
+                    sp_tools[0] *= sfactor
+                    sp_tools[1] *= sfactor
+                    self.options['tools_solderpaste_tools'] = "%f, %f" % (sp_tools[0], sp_tools[1])
+                elif dim == 'tools_solderpaste_xy_toolchange':
+                    sp_coords = [float(eval(a)) for a in self.defaults["tools_solderpaste_xy_toolchange"].split(",")]
+                    sp_coords[0] *= sfactor
+                    sp_coords[1] *= sfactor
+                    self.options['tools_solderpaste_xy_toolchange'] = "%f, %f" % (sp_coords[0], sp_coords[1])
+                else:
+                    try:
+                        self.options[dim] = float(self.options[dim]) * sfactor
+                    except Exception as e:
+                        log.debug('App.on_toggle_units().scale_options() --> %s' % str(e))
+
+        def scale_defaults(sfactor):
+            for dim in dimensions:
+                if dim == 'excellon_toolchangexy':
+                    coords_xy = [float(eval(a)) for a in self.defaults["excellon_toolchangexy"].split(",")]
+                    coords_xy[0] *= sfactor
+                    coords_xy[1] *= sfactor
+                    self.defaults['excellon_toolchangexy'] = "%.4f, %.4f" % (coords_xy[0], coords_xy[1])
+                elif dim == 'geometry_toolchangexy':
+                    coords_xy = [float(eval(a)) for a in self.defaults["geometry_toolchangexy"].split(",")]
+                    coords_xy[0] *= sfactor
+                    coords_xy[1] *= sfactor
+                    self.defaults['geometry_toolchangexy'] = "%.4f, %.4f" % (coords_xy[0], coords_xy[1])
+                elif dim == 'tools_ncctools':
+                    ncctols = [float(eval(a)) for a in self.defaults["tools_ncctools"].split(",")]
+                    ncctols[0] *= sfactor
+                    ncctols[1] *= sfactor
+                    self.defaults['tools_ncctools'] = "%.4f, %.4f" % (ncctols[0], ncctols[1])
+                elif dim == 'tools_solderpaste_tools':
+                    sp_tools = [float(eval(a)) for a in self.defaults["tools_solderpaste_tools"].split(",")]
+                    sp_tools[0] *= sfactor
+                    sp_tools[1] *= sfactor
+                    self.defaults['tools_solderpaste_tools'] = "%.4f, %.4f" % (sp_tools[0], sp_tools[1])
+                elif dim == 'tools_solderpaste_xy_toolchange':
+                    sp_coords = [float(eval(a)) for a in self.defaults["tools_solderpaste_xy_toolchange"].split(",")]
+                    sp_coords[0] *= sfactor
+                    sp_coords[1] *= sfactor
+                    self.defaults['tools_solderpaste_xy_toolchange'] = "%.4f, %.4f" % (sp_coords[0], sp_coords[1])
                 else:
-                    self.options[dim] *= sfactor
+                    try:
+                        self.defaults[dim] = float(self.defaults[dim]) * sfactor
+                    except Exception as e:
+                        log.debug('App.on_toggle_units().scale_defaults() --> %s' % str(e))
 
         # The scaling factor depending on choice of units.
         factor = 1/25.4
-        if self.ui.general_options_form.general_app_group.units_radio.get_value().upper() == 'MM':
+        if self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
             factor = 25.4
 
-
         # Changing project units. Warn user.
         msgbox = QtWidgets.QMessageBox()
         msgbox.setText("<B>Change project units ...</B>")
@@ -3106,6 +3185,10 @@ class App(QtCore.QObject):
             scale_options(factor)
             self.options_write_form()
 
+            self.defaults_read_form()
+            scale_defaults(factor)
+            self.defaults_write_form()
+
             self.should_we_save = True
 
             # change this only if the workspace is active
@@ -3117,7 +3200,7 @@ class App(QtCore.QObject):
             self.ui.grid_gap_y_entry.set_value(float(self.ui.grid_gap_y_entry.get_value()) * factor)
 
             for obj in self.collection.get_list():
-                units = self.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+                units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
                 obj.convert_units(units)
 
                 # make that the properties stored in the object are also updated
@@ -3131,26 +3214,27 @@ class App(QtCore.QObject):
                     current.to_form()
 
             self.plot_all()
-            self.inform.emit("[success]Converted units to %s" % self.options["units"])
+            self.inform.emit("[success]Converted units to %s" % self.defaults["units"])
             # self.ui.units_label.setText("[" + self.options["units"] + "]")
-            self.set_screen_units(self.options["units"])
+            self.set_screen_units(self.defaults["units"])
         else:
             # Undo toggling
             self.toggle_units_ignore = True
-            if self.ui.general_options_form.general_app_group.units_radio.get_value().upper() == 'MM':
-                self.ui.general_options_form.general_app_group.units_radio.set_value('IN')
+            if self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
+                self.ui.general_defaults_form.general_app_group.units_radio.set_value('IN')
             else:
-                self.ui.general_options_form.general_app_group.units_radio.set_value('MM')
+                self.ui.general_defaults_form.general_app_group.units_radio.set_value('MM')
             self.toggle_units_ignore = False
             self.inform.emit("[WARNING_NOTCL]Units conversion cancelled.")
 
         self.options_read_form()
+        self.defaults_read_form()
 
     def on_toggle_units_click(self):
         if self.options["units"] == 'MM':
-            self.ui.general_options_form.general_app_group.units_radio.set_value("IN")
+            self.ui.general_defaults_form.general_app_group.units_radio.set_value("IN")
         else:
-            self.ui.general_options_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()
 
     def on_language_apply(self):
@@ -3834,7 +3918,7 @@ class App(QtCore.QObject):
 
     def on_tool_add_keypress(self):
         ## Current application units in Upper Case
-        self.units = self.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         notebook_widget_name = self.ui.notebook.currentWidget().objectName()
 
@@ -4431,7 +4515,7 @@ class App(QtCore.QObject):
             return 0
 
     def populate_cmenu_grids(self):
-        units = self.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
         self.ui.cmenu_gridmenu.clear()
         sorted_list = sorted(self.defaults["global_grid_context_menu"][str(units)])
@@ -4452,7 +4536,7 @@ class App(QtCore.QObject):
 
     def on_grid_add(self):
         ## Current application units in lower Case
-        units = self.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
         grid_add_popup = FCInputDialog(title="New Grid ...",
                                        text='Enter a Grid VAlue:',
@@ -4479,7 +4563,7 @@ class App(QtCore.QObject):
 
     def on_grid_delete(self):
         ## Current application units in lower Case
-        units = self.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
         grid_del_popup = FCInputDialog(title="Delete Grid ...",
                                        text='Enter a Grid Value:',
@@ -4651,8 +4735,34 @@ class App(QtCore.QObject):
                         self.draw_moving_selection_shape(self.pos, pos)
                         self.selection_type = True
 
-                # delete the status message on mouse move
-                # self.inform.emit("")
+                # hover effect
+                for obj in self.collection.get_list():
+                    try:
+                        # select the object(s) only if it is enabled (plotted)
+                        if obj.options['plot']:
+                            if obj not in self.collection.get_selected():
+                                poly_obj = Polygon(
+                                    [(obj.options['xmin'], obj.options['ymin']),
+                                     (obj.options['xmax'], obj.options['ymin']),
+                                     (obj.options['xmax'], obj.options['ymax']),
+                                     (obj.options['xmin'], obj.options['ymax'])]
+                                )
+                                if Point(pos).within(poly_obj):
+                                    if self.isHovering is False:
+                                        self.isHovering = True
+                                        self.notHovering = True
+                                        # create the selection box around the selected object
+                                        self.draw_hover_shape(obj, color='#d1e0e0')
+                                else:
+                                    if self.notHovering is True:
+                                        self.notHovering = False
+                                        self.isHovering = False
+                                        self.delete_hover_shape()
+                    except:
+                        # the Exception here will happen if we try to select on screen and we have an newly (and empty)
+                        # just created Geometry or Excellon object that do not have the xmin, xmax, ymin, ymax options.
+                        # In this case poly_obj creation (see above) will fail
+                        pass
 
             except:
                 self.ui.position_label.setText("")
@@ -4700,6 +4810,7 @@ class App(QtCore.QObject):
 
                         # delete the selection shape(S) as it may be in the way
                         self.delete_selection_shape()
+                        self.delete_hover_shape()
 
                 else:
                     if self.selection_type is not None:
@@ -4715,11 +4826,13 @@ class App(QtCore.QObject):
                             # a object by checking the bounding limits against mouse click position
                             if self.command_active is None:
                                 self.select_objects(key='CTRL')
+                                self.delete_hover_shape()
                         else:
                             # If there is no active command (self.command_active is None) then we check if we clicked on a object by
                             # checking the bounding limits against mouse click position
                             if self.command_active is None:
                                 self.select_objects()
+                                self.delete_hover_shape()
 
         except Exception as e:
             log.warning("Error: %s" % str(e))
@@ -4886,11 +4999,47 @@ class App(QtCore.QObject):
             log.error("[ERROR] Something went bad. %s" % str(e))
             return
 
+    def delete_hover_shape(self):
+        self.hover_shapes.clear()
+        self.hover_shapes.redraw()
+
+    def draw_hover_shape(self, sel_obj, color=None):
+        """
+
+        :param sel_obj: the object for which the hover shape must be drawn
+        :return:
+        """
+
+        pt1 = (float(sel_obj.options['xmin']), float(sel_obj.options['ymin']))
+        pt2 = (float(sel_obj.options['xmax']), float(sel_obj.options['ymin']))
+        pt3 = (float(sel_obj.options['xmax']), float(sel_obj.options['ymax']))
+        pt4 = (float(sel_obj.options['xmin']), float(sel_obj.options['ymax']))
+
+        hover_rect = Polygon([pt1, pt2, pt3, pt4])
+        if self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
+            hover_rect = hover_rect.buffer(-0.1)
+            hover_rect = hover_rect.buffer(0.2)
+
+        else:
+            hover_rect = hover_rect.buffer(-0.00393)
+            hover_rect = hover_rect.buffer(0.00787)
+
+        if color:
+            face = Color(color)
+            face.alpha = 0.3
+            outline = Color(color, alpha=0.8)
+        else:
+            face = Color(self.defaults['global_sel_fill'])
+            face.alpha = 0.1
+            outline = self.defaults['global_sel_line']
+
+        self.hover_shapes.add(hover_rect, color=outline, face_color=face, update=True, layer=0, tolerance=None)
+
     def delete_selection_shape(self):
         self.move_tool.sel_shapes.clear()
         self.move_tool.sel_shapes.redraw()
 
-    def draw_selection_shape(self, sel_obj):
+    def draw_selection_shape(self, sel_obj, color=None):
         """
 
         :param sel_obj: the object for which the selection shape must be drawn
@@ -4901,13 +5050,24 @@ class App(QtCore.QObject):
         pt2 = (float(sel_obj.options['xmax']), float(sel_obj.options['ymin']))
         pt3 = (float(sel_obj.options['xmax']), float(sel_obj.options['ymax']))
         pt4 = (float(sel_obj.options['xmin']), float(sel_obj.options['ymax']))
+
         sel_rect = Polygon([pt1, pt2, pt3, pt4])
+        if self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
+            sel_rect = sel_rect.buffer(-0.1)
+            sel_rect = sel_rect.buffer(0.2)
+        else:
+            sel_rect = sel_rect.buffer(-0.00393)
+            sel_rect = sel_rect.buffer(0.00787)
+
+        if color:
+            face = Color(color, alpha=0.1)
+            outline = Color(color, alpha=0.8)
+        else:
+            face = Color(self.defaults['global_sel_fill'], alpha=0.1)
+            outline = Color(self.defaults['global_sel_line'], alpha=0.8)
 
-        #blue_t = Color('blue')
-        blue_t = Color(self.defaults['global_sel_fill'])
-        blue_t.alpha = 0.3
-        self.sel_objects_list.append(self.move_tool.sel_shapes.add(sel_rect, color=self.defaults['global_sel_line'],
-                                                               face_color=blue_t, update=True, layer=0, tolerance=None))
+        self.sel_objects_list.append(self.move_tool.sel_shapes.add(sel_rect, color=outline,
+                                                               face_color=face, update=True, layer=0, tolerance=None))
 
     def draw_moving_selection_shape(self, old_coords, coords, **kwargs):
         """
@@ -6000,7 +6160,7 @@ class App(QtCore.QObject):
         ezeros = self.defaults["excellon_exp_zeros"]
         eformat = self.defaults[ "excellon_exp_format"]
 
-        fc_units = self.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        fc_units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
         if fc_units == 'MM':
             factor = 1 if eunits == 'METRIC' else 0.03937
         else:
@@ -6118,7 +6278,7 @@ class App(QtCore.QObject):
             return "Could not retrieve object: %s" % obj_name
 
         # updated units
-        units = self.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
         if units == 'IN' or units == 'INCH':
             units = 'INCH'
         elif units == 'MM' or units == 'METIRC':
@@ -6172,7 +6332,7 @@ class App(QtCore.QObject):
                              "Only Geometry and Gerber are supported")
             return
 
-        units = self.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         def obj_init(geo_obj, app_obj):
             geo_obj.import_svg(filename, obj_type, units=units)
@@ -6214,7 +6374,7 @@ class App(QtCore.QObject):
                              "Only Geometry and Gerber are supported")
             return
 
-        units = self.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         def obj_init(geo_obj, app_obj):
             geo_obj.import_dxf(filename, obj_type, units=units)
@@ -6263,7 +6423,7 @@ class App(QtCore.QObject):
 
             # Object name
             name = outname or filename.split('/')[-1].split('\\')[-1]
-            units = self.ui.general_options_form.general_app_group.units_radio.get_value()
+            units = self.ui.general_defaults_form.general_app_group.units_radio.get_value()
 
             self.new_object(obj_type, name, obj_init)
             self.progress.emit(20)

+ 6 - 6
FlatCAMEditor.py

@@ -346,7 +346,7 @@ class TextInputTool(FlatCAMTool):
                     font_name=self.font_name,
                     font_size=font_to_geo_size,
                     font_type=font_to_geo_type,
-                    units=self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper())
+                    units=self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper())
 
     def font_family(self, font):
         self.text_input_entry.selectAll()
@@ -1483,7 +1483,7 @@ class TransformEditorTool(FlatCAMTool):
                 "[WARNING_NOTCL] Geometry shape rotate cancelled...")
 
     def on_offx_key(self):
-        units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
         val_box = FCInputDialog(title="Offset on X axis ...",
                                 text=('Enter a distance Value (%s):' % str(units)),
@@ -1502,7 +1502,7 @@ class TransformEditorTool(FlatCAMTool):
                 "[WARNING_NOTCL] Geometry shape offset X cancelled...")
 
     def on_offy_key(self):
-        units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
         val_box = FCInputDialog(title="Offset on Y axis ...",
                                 text=('Enter a distance Value (%s):' % str(units)),
@@ -4985,7 +4985,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.move_timer.setSingleShot(True)
 
         ## Current application units in Upper Case
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         self.key = None  # Currently pressed key
         self.modifiers = None
@@ -5059,7 +5059,7 @@ class FlatCAMExcEditor(QtCore.QObject):
 
     def set_ui(self):
         # updated units
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         self.olddia_newdia.clear()
         self.tool2tooldia.clear()
@@ -5099,7 +5099,7 @@ class FlatCAMExcEditor(QtCore.QObject):
             pass
 
         # updated units
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         # make a new name for the new Excellon object (the one with edited content)
         self.edited_obj_name = self.exc_obj.options['name']

+ 4 - 3
FlatCAMGUI.py

@@ -1952,10 +1952,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
                 # Change Units
                 if key == QtCore.Qt.Key_Q:
-                    if self.app.options["units"] == 'MM':
-                        self.app.ui.general_options_form.general_app_group.units_radio.set_value("IN")
+                    if self.app.defaults["units"] == 'MM':
+                        self.app.ui.general_defaults_form.general_app_group.units_radio.set_value("IN")
                     else:
-                        self.app.ui.general_options_form.general_app_group.units_radio.set_value("MM")
+                        self.app.ui.general_defaults_form.general_app_group.units_radio.set_value("MM")
                     self.app.on_toggle_units()
 
                 # Rotate Object by 90 degree CW
@@ -3096,6 +3096,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
             del settings
             self.app.inform.emit("[success] GUI settings deleted ...")
 
+
 class GeneralAppPrefGroupUI(OptionsGroupUI):
     def __init__(self, parent=None):
         super(GeneralAppPrefGroupUI, self).__init__(self)

+ 94 - 75
FlatCAMObj.py

@@ -79,6 +79,8 @@ class FlatCAMObj(QtCore.QObject):
 
         self._drawing_tolerance = 0.01
 
+        self.isHovering = False
+
         # assert isinstance(self.ui, ObjectUI)
         # self.ui.name_entry.returnPressed.connect(self.on_name_activate)
         # self.ui.offset_button.clicked.connect(self.on_offset_button_click)
@@ -459,14 +461,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         # store the source file here
         self.source_file = ""
 
-        # assert isinstance(self.ui, GerberObjectUI)
-        # self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
-        # self.ui.solid_cb.stateChanged.connect(self.on_solid_cb_click)
-        # self.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
-        # self.ui.generate_iso_button.clicked.connect(self.on_iso_button_click)
-        # self.ui.generate_cutout_button.clicked.connect(self.on_generatecutout_button_click)
-        # self.ui.generate_bb_button.clicked.connect(self.on_generatebb_button_click)
-        # self.ui.generate_noncopper_button.clicked.connect(self.on_generatenoncopper_button_click)
+        # list of rows with apertures plotted
+        self.marked_rows = []
 
         # Attributes to be included in serialization
         # Always append to it because it carries contents
@@ -485,7 +481,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         FlatCAMObj.set_ui(self, ui)
         FlatCAMApp.App.log.debug("FlatCAMGerber.set_ui()")
 
-        self.replotApertures.connect(self.on_replot_apertures)
+        self.replotApertures.connect(self.on_mark_cb_click_table)
 
         self.form_fields.update({
             "plot": self.ui.plot_cb,
@@ -648,7 +644,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             self.apertures_row += 1
 
         self.ui.apertures_table.selectColumn(0)
-        #
         self.ui.apertures_table.resizeColumnsToContents()
         self.ui.apertures_table.resizeRowsToContents()
 
@@ -675,6 +670,11 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         self.ui.apertures_table.setMinimumHeight(self.ui.apertures_table.getHeight())
         self.ui.apertures_table.setMaximumHeight(self.ui.apertures_table.getHeight())
 
+        # update the 'mark' checkboxes state according with what is stored in the self.marked_rows list
+        if self.marked_rows:
+            for row in range(self.ui.apertures_table.rowCount()):
+                self.ui.apertures_table.cellWidget(row, 5).set_value(self.marked_rows[row])
+
         self.ui_connect()
 
     def ui_connect(self):
@@ -695,60 +695,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         except:
             pass
 
-    def on_mark_cb_click_table(self):
-        self.ui_disconnect()
-        # cw = self.sender()
-        # cw_index = self.ui.apertures_table.indexAt(cw.pos())
-        # cw_row = cw_index.row()
-        check_row = 0
-
-        self.clear_plot_apertures()
-        for aperture in self.apertures:
-            # find the apertures_table row associated with the aperture
-            for row in range(self.ui.apertures_table.rowCount()):
-                if int(self.ui.apertures_table.item(row, 1).text()) == int(aperture):
-                    check_row = row
-                    break
-
-            if self.ui.apertures_table.cellWidget(check_row, 5).isChecked():
-                # self.plot_apertures(color='#2d4606bf', marked_aperture=aperture, visible=True)
-                self.plot_apertures(color='#FD6A02', marked_aperture=aperture, visible=True)
-
-        self.mark_shapes.redraw()
-
-        # make sure that the Mark All is disabled if one of the row mark's are disabled and
-        # if all the row mark's are enabled also enable the Mark All checkbox
-        cb_cnt = 0
-        total_row = self.ui.apertures_table.rowCount()
-        for row in range(total_row):
-            if self.ui.apertures_table.cellWidget(row, 5).isChecked():
-                cb_cnt += 1
-            else:
-                cb_cnt -= 1
-        if cb_cnt < total_row:
-            self.ui.mark_all_cb.setChecked(False)
-        else:
-            self.ui.mark_all_cb.setChecked(True)
-        self.ui_connect()
-
-    def on_mark_all_click(self, signal):
-        self.ui_disconnect()
-        mark_all = self.ui.mark_all_cb.isChecked()
-        for row in range(self.ui.apertures_table.rowCount()):
-            mark_cb = self.ui.apertures_table.cellWidget(row, 5)
-            if mark_all:
-                mark_cb.setChecked(True)
-            else:
-                mark_cb.setChecked(False)
-        for aperture in self.apertures:
-            if mark_all:
-                # self.plot_apertures(color='#2d4606bf', marked_aperture=aperture, visible=True)
-                self.plot_apertures(color='#FD6A02', marked_aperture=aperture, visible=True)
-            else:
-                self.clear_plot_apertures()
-
-        self.ui_connect()
-
     def on_generatenoncopper_button_click(self, *args):
         self.app.report_usage("gerber_on_generatenoncopper_button")
 
@@ -1303,18 +1249,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             self.app.progress.emit(30)
 
             def job_thread(app_obj):
-                geometry = {}
-                for ap in self.apertures:
-                    geometry[int(ap)] = self.apertures[ap]['solid_geometry']
-                    try:
-                        _ = iter(geometry[int(ap)])
-                    except TypeError:
-                        geometry[int(ap)] = [geometry[int(ap)]]
                 self.app.progress.emit(30)
 
                 try:
                     if aperture_to_plot_mark in self.apertures:
-                        for geo in geometry[int(aperture_to_plot_mark)]:
+                        if type(self.apertures[aperture_to_plot_mark]['solid_geometry']) is not list:
+                            self.apertures[aperture_to_plot_mark]['solid_geometry'] = \
+                                [self.apertures[aperture_to_plot_mark]['solid_geometry']]
+                        for geo in self.apertures[aperture_to_plot_mark]['solid_geometry']:
                             if type(geo) == Polygon or type(geo) == LineString:
                                 self.add_mark_shape(shape=geo, color=color, face_color=color, visible=visibility)
                             else:
@@ -1334,9 +1276,86 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
 
     def clear_mark_all(self):
         self.ui.mark_all_cb.set_value(False)
+        self.marked_rows[:] = []
 
-    def on_replot_apertures(self):
-        pass
+    def on_mark_cb_click_table(self):
+        self.ui_disconnect()
+        # cw = self.sender()
+        # cw_index = self.ui.apertures_table.indexAt(cw.pos())
+        # cw_row = cw_index.row()
+        check_row = 0
+
+        self.clear_plot_apertures()
+        self.marked_rows[:] = []
+
+        for row in range(self.ui.apertures_table.rowCount()):
+            if self.ui.apertures_table.cellWidget(row, 5).isChecked():
+                self.marked_rows.append(True)
+
+                aperture = self.ui.apertures_table.item(row, 1).text()
+                # self.plot_apertures(color='#2d4606bf', marked_aperture=aperture, visible=True)
+                self.plot_apertures(color='#FD6A02', marked_aperture=aperture, visible=True)
+            else:
+                self.marked_rows.append(False)
+
+        self.mark_shapes.redraw()
+
+        # make sure that the Mark All is disabled if one of the row mark's are disabled and
+        # if all the row mark's are enabled also enable the Mark All checkbox
+        cb_cnt = 0
+        total_row = self.ui.apertures_table.rowCount()
+        for row in range(total_row):
+            if self.ui.apertures_table.cellWidget(row, 5).isChecked():
+                cb_cnt += 1
+            else:
+                cb_cnt -= 1
+        if cb_cnt < total_row:
+            self.ui.mark_all_cb.setChecked(False)
+        else:
+            self.ui.mark_all_cb.setChecked(True)
+        self.ui_connect()
+
+    def on_mark_all_click(self, signal):
+        self.ui_disconnect()
+        mark_all = self.ui.mark_all_cb.isChecked()
+        for row in range(self.ui.apertures_table.rowCount()):
+            # update the mark_rows list
+            if mark_all:
+                self.marked_rows.append(True)
+            else:
+                self.marked_rows[:] = []
+
+            mark_cb = self.ui.apertures_table.cellWidget(row, 5)
+            mark_cb.setChecked(mark_all)
+
+        if mark_all:
+            for aperture in self.apertures:
+                # self.plot_apertures(color='#2d4606bf', marked_aperture=aperture, visible=True)
+                self.plot_apertures(color='#FD6A02', marked_aperture=aperture, visible=True)
+        else:
+            self.clear_plot_apertures()
+
+        self.ui_connect()
+
+    def mirror(self, axis, point):
+        Gerber.mirror(self, axis=axis, point=point)
+        self.replotApertures.emit()
+
+    def offset(self, vect):
+        Gerber.offset(self, vect=vect)
+        self.replotApertures.emit()
+
+    def rotate(self, angle, point):
+        Gerber.rotate(self, angle=angle, point=point)
+        self.replotApertures.emit()
+
+    def scale(self, xfactor, yfactor=None, point=None):
+        Gerber.scale(self, xfactor=xfactor, yfactor=yfactor, point=point)
+        self.replotApertures.emit()
+
+    def skew(self, angle_x, angle_y, point):
+        Gerber.skew(self, angle_x=angle_x, angle_y=angle_y, point=point)
+        self.replotApertures.emit()
 
     def serialize(self):
         return {
@@ -3802,7 +3821,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             self.ui.geo_tools_table.setCurrentItem(self.ui.geo_tools_table.item(row, 0))
 
     def export_dxf(self):
-        units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
         dwg = None
         try:
             dwg = ezdxf.new('R2010')

+ 6 - 3
GUIElements.py

@@ -229,7 +229,7 @@ class FloatEntry(QtWidgets.QLineEdit):
 
     def set_value(self, val):
         if val is not None:
-            self.setText("%.6f" % val)
+            self.setText("%.4f" % val)
         else:
             self.setText("")
 
@@ -267,7 +267,7 @@ class FloatEntry2(QtWidgets.QLineEdit):
         return float(evaled)
 
     def set_value(self, val):
-        self.setText("%.6f" % val)
+        self.setText("%.4f" % val)
 
     def sizeHint(self):
         default_hint_size = super(FloatEntry2, self).sizeHint()
@@ -337,7 +337,10 @@ class FCEntry(QtWidgets.QLineEdit):
         return str(self.text())
 
     def set_value(self, val):
-        self.setText(str(val))
+        if type(val) is float:
+            self.setText('%.4f' % val)
+        else:
+            self.setText(str(val))
 
     def sizeHint(self):
         default_hint_size = super(FCEntry, self).sizeHint()

+ 3 - 4
ObjectUI.py

@@ -244,7 +244,7 @@ class GerberObjectUI(ObjectUI):
         # Scale Button
         self.scale_aperture_button = QtWidgets.QPushButton('Scale')
         self.scale_aperture_button.setToolTip(
-            "Perform scaling operation."
+            "Perform scaling operation on the selected apertures."
         )
         self.scale_aperture_button.setFixedWidth(50)
         self.transform_aperture_grid.addWidget(self.scale_aperture_button, 0, 2)
@@ -265,7 +265,7 @@ class GerberObjectUI(ObjectUI):
         # Buffer Button
         self.buffer_aperture_button = QtWidgets.QPushButton('Buffer')
         self.buffer_aperture_button.setToolTip(
-            "Perform scaling operation."
+            "Perform buffer operation on the selected apertures."
         )
         self.buffer_aperture_button.setFixedWidth(50)
         self.transform_aperture_grid.addWidget(self.buffer_aperture_button, 1, 2)
@@ -275,8 +275,7 @@ class GerberObjectUI(ObjectUI):
 
         self.new_grb_label = QtWidgets.QLabel("<b>Generate new Gerber Object:</b>")
         self.new_grb_label.setToolTip(
-            "Will generate a new Gerber object from the changed apertures.\n"
-            "This new object can then be isolated etc."
+            "Will generate a new Gerber object from the changed apertures."
         )
         new_hlay.addWidget(self.new_grb_label)
 

+ 2 - 2
PlotCanvas.py

@@ -65,7 +65,7 @@ class PlotCanvas(QtCore.QObject):
         self.draw_workspace()
 
         # if self.app.defaults['global_workspace'] is True:
-        #     if self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper() == 'MM':
+        #     if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
         #         self.wkspace_t = Line(pos=)
 
         self.shape_collections = []
@@ -92,7 +92,7 @@ class PlotCanvas(QtCore.QObject):
         a3p_mm = np.array([(0, 0), (297, 0), (297, 420), (0, 420)])
         a3l_mm = np.array([(0, 0), (420, 0), (420, 297), (0, 297)])
 
-        if self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper() == 'MM':
+        if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
             if self.app.defaults['global_workspaceT'] == 'A4P':
                 a = a4p_mm
             elif self.app.defaults['global_workspaceT'] == 'A4L':

+ 5 - 1
README.md

@@ -12,7 +12,11 @@ CAD program, and create G-Code for Isolation routing.
 3.03.2019
 
 - minor UI changes for Gerber UI
-- after an object move, the apertures plotted shapes are deleted from canvas and the mark all button is deselected
+- ~~after an object move, the apertures plotted shapes are deleted from canvas and the 'mark all' button is deselected~~
+- after move tool action or any other transform (rotate, skew, scale, mirror, offset), the plotted apertures are kept plotted.
+- changing units now will convert all the default values from one unit type to another
+- prettified the selection shape and the moving shape
+- initial work in object hovering shape
 
 02.03.2019
 

+ 1 - 1
camlib.py

@@ -6492,7 +6492,7 @@ class CNCjob(Geometry):
             temp_gcode = ''
             header_start = False
             header_stop = False
-            units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+            units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
             lines = StringIO(g)
             for line in lines:

+ 1 - 1
flatcamTools/ToolCalculators.py

@@ -244,7 +244,7 @@ class ToolCalculator(FlatCAMTool):
         FlatCAMTool.install(self, icon, separator, shortcut='ALT+C', **kwargs)
 
     def set_tool_ui(self):
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         ## Initialize form
         self.mm_entry.set_value('0')

+ 3 - 3
flatcamTools/ToolMeasurement.py

@@ -12,7 +12,7 @@ class Measurement(FlatCAMTool):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
 
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
         ## Title
         title_label = QtWidgets.QLabel("<font size=4><b>%s</b></font><br>" % self.toolName)
@@ -173,7 +173,7 @@ class Measurement(FlatCAMTool):
 
         # Switch notebook to tool page
         self.app.ui.notebook.setCurrentWidget(self.app.ui.tool_tab)
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
         self.show()
 
     def toggle(self):
@@ -210,7 +210,7 @@ class Measurement(FlatCAMTool):
         else:
             # ENABLE the Measuring TOOL
             self.active = True
-            self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower()
+            self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
             # we disconnect the mouse/key handlers from wherever the measurement tool was called
             if self.app.call_source == 'app':

+ 7 - 2
flatcamTools/ToolMove.py

@@ -125,8 +125,7 @@ class ToolMove(FlatCAMTool):
                                     # offset
                                     sel_obj.offset((dx, dy))
                                     sel_obj.plot()
-                                    sel_obj.clear_plot_apertures()
-                                    sel_obj.clear_mark_all()
+                                    sel_obj.replotApertures.emit()
 
                                     # Update the object bounding box options
                                     a,b,c,d = sel_obj.bounds()
@@ -237,6 +236,12 @@ class ToolMove(FlatCAMTool):
 
     def draw_shape(self, coords):
         self.sel_rect = Polygon(coords)
+        if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
+            self.sel_rect = self.sel_rect.buffer(-0.1)
+            self.sel_rect = self.sel_rect.buffer(0.2)
+        else:
+            self.sel_rect = self.sel_rect.buffer(-0.00393)
+            self.sel_rect = self.sel_rect.buffer(0.00787)
 
         blue_t = Color('blue')
         blue_t.alpha = 0.2

+ 2 - 2
flatcamTools/ToolNonCopperClear.py

@@ -345,13 +345,13 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.obj_name = ""
         self.ncc_obj = None
         self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
     def build_ui(self):
         self.ui_disconnect()
 
         # updated units
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         if self.units == "IN":
             self.addtool_entry.set_value(0.039)

+ 2 - 2
flatcamTools/ToolPaint.py

@@ -353,7 +353,7 @@ class ToolPaint(FlatCAMTool, Gerber):
         self.paintoverlap_entry.set_value(self.default_data["paintoverlap"])
 
         # updated units
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         if self.units == "IN":
             self.addtool_entry.set_value(0.039)
@@ -421,7 +421,7 @@ class ToolPaint(FlatCAMTool, Gerber):
             pass
 
         # updated units
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         sorted_tools = []
         for k, v in self.paint_tools.items():

+ 4 - 4
flatcamTools/ToolProperties.py

@@ -126,10 +126,10 @@ class Properties(FlatCAMTool):
         width = abs(ymax - ymin)
 
         self.addChild(dims, ['Length:', '%.4f %s' % (
-            length, self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower())], True)
+            length, self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())], True)
         self.addChild(dims, ['Width:', '%.4f %s' % (
-            width, self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower())], True)
-        if self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower() == 'mm':
+            width, self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())], True)
+        if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
             area = (length * width) / 100
             self.addChild(dims, ['Box Area:', '%.4f %s' % (area, 'cm2')], True)
         else:
@@ -142,7 +142,7 @@ class Properties(FlatCAMTool):
                            'in': 'Inch',
                            'mm': 'Metric'
                        }
-                       [str(self.app.ui.general_options_form.general_app_group.units_radio.get_value().lower())]], True)
+                       [str(self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())]], True)
 
         for option in obj.options:
             if option is 'name':

+ 2 - 2
flatcamTools/ToolSolderPaste.py

@@ -484,7 +484,7 @@ class SolderPaste(FlatCAMTool):
         self.name = ""
         self.obj = None
 
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         for name in list(self.app.postprocessors.keys()):
             # populate only with postprocessor files that start with 'Paste_'
@@ -502,7 +502,7 @@ class SolderPaste(FlatCAMTool):
         self.ui_disconnect()
 
         # updated units
-        self.units = self.app.ui.general_options_form.general_app_group.units_radio.get_value().upper()
+        self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
 
         sorted_tools = []
         for k, v in self.tooltable_tools.items():