Ver código fonte

- 2Sided Tool - fixed newly introduced issues in the Alignment section
- 2Sided Tool - modified the UI such that some of the fields will allow only numbers and some special characters ([,],(,),/,*,,,+,-,%)
- Cutout Tool - working on adding mouse bites for the Freeform cutout
- updated the translation files to the current state of the app

Marius Stanciu 5 anos atrás
pai
commit
f73f6fb5da

+ 7 - 0
CHANGELOG.md

@@ -7,6 +7,13 @@ CHANGELOG for FlatCAM beta
 
 =================================================
 
+29.08.2020
+
+- 2Sided Tool - fixed newly introduced issues in the Alignment section
+- 2Sided Tool - modified the UI such that some of the fields will allow only numbers and some special characters ([,],(,),/,*,,,+,-,%)
+- Cutout Tool - working on adding mouse bites for the Freeform cutout
+- updated the translation files to the current state of the app
+
 28.08.2020
 
 - Paint Tool - upgraded the UI and added the functionality that now adding a new tool is done by first searching the Tools DB for a suitable tool and if fails then it adds an default tool

+ 11 - 13
appGUI/GUIElements.py

@@ -286,7 +286,7 @@ class LengthEntry(QtWidgets.QLineEdit):
         # Unit conversion table OUTPUT-INPUT
         self.scales = {
             'IN': {'IN': 1.0,
-                   'MM': 1/25.4},
+                   'MM': 1 / 25.4},
             'MM': {'IN': 25.4,
                    'MM': 1.0}
         }
@@ -668,6 +668,7 @@ class NumericalEvalEntry(FCEntry):
     """
     Will evaluate the input and return a value. Accepts only float numbers and formulas using the operators: /,*,+,-,%
     """
+
     def __init__(self, border_color=None):
         super().__init__(border_color=border_color)
 
@@ -691,10 +692,11 @@ class NumericalEvalTupleEntry(EvalEntry):
     """
     Will return a text value. Accepts only float numbers and formulas using the operators: /,*,+,-,%
     """
+
     def __init__(self, border_color=None):
         super().__init__(border_color=border_color)
 
-        regex = QtCore.QRegExp("[0-9\/\*\+\-\%\.\s\,\[\]]*")
+        regex = QtCore.QRegExp("[0-9\/\*\+\-\%\.\s\,\[\]\(\)]*")
         validator = QtGui.QRegExpValidator(regex, self)
         self.setValidator(validator)
 
@@ -802,7 +804,6 @@ class FCSliderWithSpinner(QtWidgets.QFrame):
 
 
 class FCSpinner(QtWidgets.QSpinBox):
-
     returnPressed = QtCore.pyqtSignal()
     confirmation_signal = QtCore.pyqtSignal(bool, float, float)
 
@@ -1040,7 +1041,6 @@ class FCSliderWithDoubleSpinner(QtWidgets.QFrame):
 
 
 class FCDoubleSpinner(QtWidgets.QDoubleSpinBox):
-
     returnPressed = QtCore.pyqtSignal()
     confirmation_signal = QtCore.pyqtSignal(bool, float, float)
 
@@ -1694,7 +1694,6 @@ class FCButton(QtWidgets.QPushButton):
 
 
 class FCLabel(QtWidgets.QLabel):
-
     clicked = QtCore.pyqtSignal(bool)
     right_clicked = QtCore.pyqtSignal(bool)
     middle_clicked = QtCore.pyqtSignal(bool)
@@ -2018,7 +2017,7 @@ class FCDetachableTab(QtWidgets.QTabWidget):
                     if str(tab_name) == str(self.tabText(index)):
                         self.protectTab(index)
 
-        # Make this tab the current tab
+            # Make this tab the current tab
             if index > -1:
                 self.setCurrentIndex(insert_index) if self.use_old_index else self.setCurrentIndex(index)
 
@@ -2101,7 +2100,6 @@ class FCDetachableTab(QtWidgets.QTabWidget):
                 # area to the side of the QTabBar) or there are not tabs
                 # currently attached...
                 if tabDropPos.y() < self.tabBar.height() or self.count() == 0:
-
                     # Close the detached tab and allow it to re-attach
                     # automatically
                     self.detachedTabs[name].close()
@@ -2422,6 +2420,7 @@ class VerticalScrollArea(QtWidgets.QScrollArea):
     scroll area that also expands horizontally to accommodate
     its contents.
     """
+
     def __init__(self, parent=None):
         QtWidgets.QScrollArea.__init__(self, parent=parent)
         self.setWidgetResizable(True)
@@ -2537,7 +2536,6 @@ class OptionalHideInputSection:
 
 
 class FCTable(QtWidgets.QTableWidget):
-
     drag_drop_sig = QtCore.pyqtSignal(object, int)
     lost_focus = QtCore.pyqtSignal()
 
@@ -3011,7 +3009,7 @@ class _BrowserTextEdit(QTextEdit):
             save_action.triggered.connect(lambda: self.save_log(app=self.app))
 
         clear_action = QAction(_("Clear"), self)
-        clear_action.setShortcut(QKeySequence(Qt.Key_Delete))   # it's not working, the shortcut
+        clear_action.setShortcut(QKeySequence(Qt.Key_Delete))  # it's not working, the shortcut
         self.menu.addAction(clear_action)
         clear_action.triggered.connect(self.clear)
 
@@ -3507,8 +3505,8 @@ class FCZeroAxes(QtWidgets.QFrame):
 
 
 class RotatedToolButton(QtWidgets.QToolButton):
-    def __init__(self, orientation = "east", *args, **kwargs):
-        super(RotatedToolButton,self).__init__(*args, **kwargs)
+    def __init__(self, orientation="east", *args, **kwargs):
+        super(RotatedToolButton, self).__init__(*args, **kwargs)
         self.orientation = orientation
 
     def paintEvent(self, event):
@@ -3560,8 +3558,8 @@ class RotatedToolButton(QtWidgets.QToolButton):
 
 
 class RotatedButton(QtWidgets.QPushButton):
-    def __init__(self, orientation = "west", *args, **kwargs):
-        super(RotatedButton,self).__init__(*args, **kwargs)
+    def __init__(self, orientation="west", *args, **kwargs):
+        super(RotatedButton, self).__init__(*args, **kwargs)
         self.orientation = orientation
 
     def paintEvent(self, event):

+ 359 - 310
appTools/ToolCutOut.py

@@ -10,7 +10,7 @@ from appTool import AppTool
 from appGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox, OptionalInputSection, FCButton, \
     FCLabel
 
-from shapely.geometry import box, MultiPolygon, Polygon, LineString, LinearRing, MultiLineString
+from shapely.geometry import box, MultiPolygon, Polygon, LineString, LinearRing, MultiLineString, Point
 from shapely.ops import cascaded_union, unary_union, linemerge
 import shapely.affinity as affinity
 
@@ -187,52 +187,52 @@ class CutOut(AppTool):
         self.ui.dia.set_value(float(self.app.defaults["tools_cutout_tooldia"]))
 
         self.default_data.update({
-            "plot":             True,
-
-            "cutz":             float(self.app.defaults["geometry_cutz"]),
-            "multidepth":       self.app.defaults["geometry_multidepth"],
-            "depthperpass":     float(self.app.defaults["geometry_depthperpass"]),
-
-            "vtipdia":          float(self.app.defaults["geometry_vtipdia"]),
-            "vtipangle":        float(self.app.defaults["geometry_vtipangle"]),
-            "travelz":          float(self.app.defaults["geometry_travelz"]),
-            "feedrate":         float(self.app.defaults["geometry_feedrate"]),
-            "feedrate_z":       float(self.app.defaults["geometry_feedrate_z"]),
-            "feedrate_rapid":   float(self.app.defaults["geometry_feedrate_rapid"]),
-            "spindlespeed":     self.app.defaults["geometry_spindlespeed"],
-            "dwell":            self.app.defaults["geometry_dwell"],
-            "dwelltime":        float(self.app.defaults["geometry_dwelltime"]),
-            "spindledir":       self.app.defaults["geometry_spindledir"],
-            "ppname_g":         self.app.defaults["geometry_ppname_g"],
-            "extracut":         self.app.defaults["geometry_extracut"],
-            "extracut_length":  float(self.app.defaults["geometry_extracut_length"]),
-            "toolchange":       self.app.defaults["geometry_toolchange"],
-            "toolchangexy":     self.app.defaults["geometry_toolchangexy"],
-            "toolchangez":      float(self.app.defaults["geometry_toolchangez"]),
-            "startz":           self.app.defaults["geometry_startz"],
-            "endz":             float(self.app.defaults["geometry_endz"]),
-            "area_exclusion":   self.app.defaults["geometry_area_exclusion"],
-            "area_shape":       self.app.defaults["geometry_area_shape"],
-            "area_strategy":    self.app.defaults["geometry_area_strategy"],
-            "area_overz":       float(self.app.defaults["geometry_area_overz"]),
-            "optimization_type":    self.app.defaults["geometry_optimization_type"],
+            "plot": True,
+
+            "cutz": float(self.app.defaults["geometry_cutz"]),
+            "multidepth": self.app.defaults["geometry_multidepth"],
+            "depthperpass": float(self.app.defaults["geometry_depthperpass"]),
+
+            "vtipdia": float(self.app.defaults["geometry_vtipdia"]),
+            "vtipangle": float(self.app.defaults["geometry_vtipangle"]),
+            "travelz": float(self.app.defaults["geometry_travelz"]),
+            "feedrate": float(self.app.defaults["geometry_feedrate"]),
+            "feedrate_z": float(self.app.defaults["geometry_feedrate_z"]),
+            "feedrate_rapid": float(self.app.defaults["geometry_feedrate_rapid"]),
+            "spindlespeed": self.app.defaults["geometry_spindlespeed"],
+            "dwell": self.app.defaults["geometry_dwell"],
+            "dwelltime": float(self.app.defaults["geometry_dwelltime"]),
+            "spindledir": self.app.defaults["geometry_spindledir"],
+            "ppname_g": self.app.defaults["geometry_ppname_g"],
+            "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": float(self.app.defaults["geometry_extracut_length"]),
+            "toolchange": self.app.defaults["geometry_toolchange"],
+            "toolchangexy": self.app.defaults["geometry_toolchangexy"],
+            "toolchangez": float(self.app.defaults["geometry_toolchangez"]),
+            "startz": self.app.defaults["geometry_startz"],
+            "endz": float(self.app.defaults["geometry_endz"]),
+            "area_exclusion": self.app.defaults["geometry_area_exclusion"],
+            "area_shape": self.app.defaults["geometry_area_shape"],
+            "area_strategy": self.app.defaults["geometry_area_strategy"],
+            "area_overz": float(self.app.defaults["geometry_area_overz"]),
+            "optimization_type": self.app.defaults["geometry_optimization_type"],
 
             # Cutout
-            "tools_cutout_tooldia":         self.app.defaults["tools_cutout_tooldia"],
-            "tools_cutout_kind":            self.app.defaults["tools_cutout_kind"],
-            "tools_cutout_margin":          float(self.app.defaults["tools_cutout_margin"]),
-            "tools_cutout_z":               float(self.app.defaults["tools_cutout_z"]),
-            "tools_cutout_depthperpass":    float(self.app.defaults["tools_cutout_depthperpass"]),
-            "tools_cutout_mdepth":          self.app.defaults["tools_cutout_mdepth"],
-            "tools_cutout_gapsize":         float(self.app.defaults["tools_cutout_gapsize"]),
-            "tools_cutout_gaps_ff":         self.app.defaults["tools_cutout_gaps_ff"],
-            "tools_cutout_convexshape":     self.app.defaults["tools_cutout_convexshape"],
-
-            "tools_cutout_big_cursor":      self.app.defaults["tools_cutout_big_cursor"],
-            "tools_cutout_gap_type":        self.app.defaults["tools_cutout_gap_type"],
-            "tools_cutout_gap_depth":       float(self.app.defaults["tools_cutout_gap_depth"]),
-            "tools_cutout_mb_dia":          float(self.app.defaults["tools_cutout_mb_dia"]),
-            "tools_cutout_mb_spacing":      float(self.app.defaults["tools_cutout_mb_spacing"]),
+            "tools_cutout_tooldia": self.app.defaults["tools_cutout_tooldia"],
+            "tools_cutout_kind": self.app.defaults["tools_cutout_kind"],
+            "tools_cutout_margin": float(self.app.defaults["tools_cutout_margin"]),
+            "tools_cutout_z": float(self.app.defaults["tools_cutout_z"]),
+            "tools_cutout_depthperpass": float(self.app.defaults["tools_cutout_depthperpass"]),
+            "tools_cutout_mdepth": self.app.defaults["tools_cutout_mdepth"],
+            "tools_cutout_gapsize": float(self.app.defaults["tools_cutout_gapsize"]),
+            "tools_cutout_gaps_ff": self.app.defaults["tools_cutout_gaps_ff"],
+            "tools_cutout_convexshape": self.app.defaults["tools_cutout_convexshape"],
+
+            "tools_cutout_big_cursor": self.app.defaults["tools_cutout_big_cursor"],
+            "tools_cutout_gap_type": self.app.defaults["tools_cutout_gap_type"],
+            "tools_cutout_gap_depth": float(self.app.defaults["tools_cutout_gap_depth"]),
+            "tools_cutout_mb_dia": float(self.app.defaults["tools_cutout_mb_dia"]),
+            "tools_cutout_mb_spacing": float(self.app.defaults["tools_cutout_mb_spacing"]),
 
         })
         tool_dia = float(self.app.defaults["tools_cutout_tooldia"])
@@ -366,14 +366,14 @@ class CutOut(AppTool):
 
         new_tdia = deepcopy(updated_tooldia) if updated_tooldia is not None else deepcopy(truncated_tooldia)
         self.cut_tool_dict.update({
-                'tooldia':          new_tdia,
-                'offset':           deepcopy(offset),
-                'offset_value':     deepcopy(offset_val),
-                'type':             deepcopy(typ),
-                'tool_type':        deepcopy(tool_type),
-                'data':             deepcopy(new_tools_dict),
-                'solid_geometry':   []
-            })
+            'tooldia': new_tdia,
+            'offset': deepcopy(offset),
+            'offset_value': deepcopy(offset_val),
+            'type': deepcopy(typ),
+            'tool_type': deepcopy(tool_type),
+            'data': deepcopy(new_tools_dict),
+            'solid_geometry': []
+        })
 
         self.update_ui(new_tools_dict)
 
@@ -381,65 +381,67 @@ class CutOut(AppTool):
         self.app.inform.emit('[success] %s' % _("Updated tool from Tools Database."))
 
     def on_tool_default_add(self, dia=None, muted=None):
+
+        dia = dia
         self.default_data.update({
-            "plot":             True,
-
-            "cutz":             float(self.app.defaults["geometry_cutz"]),
-            "multidepth":       self.app.defaults["geometry_multidepth"],
-            "depthperpass":     float(self.app.defaults["geometry_depthperpass"]),
-
-            "vtipdia":          float(self.app.defaults["geometry_vtipdia"]),
-            "vtipangle":        float(self.app.defaults["geometry_vtipangle"]),
-            "travelz":          float(self.app.defaults["geometry_travelz"]),
-            "feedrate":         float(self.app.defaults["geometry_feedrate"]),
-            "feedrate_z":       float(self.app.defaults["geometry_feedrate_z"]),
-            "feedrate_rapid":   float(self.app.defaults["geometry_feedrate_rapid"]),
-            "spindlespeed":     self.app.defaults["geometry_spindlespeed"],
-            "dwell":            self.app.defaults["geometry_dwell"],
-            "dwelltime":        float(self.app.defaults["geometry_dwelltime"]),
-            "spindledir":       self.app.defaults["geometry_spindledir"],
-            "ppname_g":         self.app.defaults["geometry_ppname_g"],
-            "extracut":         self.app.defaults["geometry_extracut"],
-            "extracut_length":  float(self.app.defaults["geometry_extracut_length"]),
-            "toolchange":       self.app.defaults["geometry_toolchange"],
-            "toolchangexy":     self.app.defaults["geometry_toolchangexy"],
-            "toolchangez":      float(self.app.defaults["geometry_toolchangez"]),
-            "startz":           self.app.defaults["geometry_startz"],
-            "endz":             float(self.app.defaults["geometry_endz"]),
-            "area_exclusion":   self.app.defaults["geometry_area_exclusion"],
-            "area_shape":       self.app.defaults["geometry_area_shape"],
-            "area_strategy":    self.app.defaults["geometry_area_strategy"],
-            "area_overz":       float(self.app.defaults["geometry_area_overz"]),
-            "optimization_type":    self.app.defaults["geometry_optimization_type"],
+            "plot": True,
+
+            "cutz": float(self.app.defaults["geometry_cutz"]),
+            "multidepth": self.app.defaults["geometry_multidepth"],
+            "depthperpass": float(self.app.defaults["geometry_depthperpass"]),
+
+            "vtipdia": float(self.app.defaults["geometry_vtipdia"]),
+            "vtipangle": float(self.app.defaults["geometry_vtipangle"]),
+            "travelz": float(self.app.defaults["geometry_travelz"]),
+            "feedrate": float(self.app.defaults["geometry_feedrate"]),
+            "feedrate_z": float(self.app.defaults["geometry_feedrate_z"]),
+            "feedrate_rapid": float(self.app.defaults["geometry_feedrate_rapid"]),
+            "spindlespeed": self.app.defaults["geometry_spindlespeed"],
+            "dwell": self.app.defaults["geometry_dwell"],
+            "dwelltime": float(self.app.defaults["geometry_dwelltime"]),
+            "spindledir": self.app.defaults["geometry_spindledir"],
+            "ppname_g": self.app.defaults["geometry_ppname_g"],
+            "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": float(self.app.defaults["geometry_extracut_length"]),
+            "toolchange": self.app.defaults["geometry_toolchange"],
+            "toolchangexy": self.app.defaults["geometry_toolchangexy"],
+            "toolchangez": float(self.app.defaults["geometry_toolchangez"]),
+            "startz": self.app.defaults["geometry_startz"],
+            "endz": float(self.app.defaults["geometry_endz"]),
+            "area_exclusion": self.app.defaults["geometry_area_exclusion"],
+            "area_shape": self.app.defaults["geometry_area_shape"],
+            "area_strategy": self.app.defaults["geometry_area_strategy"],
+            "area_overz": float(self.app.defaults["geometry_area_overz"]),
+            "optimization_type": self.app.defaults["geometry_optimization_type"],
 
             # Cutout
-            "tools_cutout_tooldia":         self.app.defaults["tools_cutout_tooldia"],
-            "tools_cutout_kind":            self.app.defaults["tools_cutout_kind"],
-            "tools_cutout_margin":          float(self.app.defaults["tools_cutout_margin"]),
-            "tools_cutout_z":               float(self.app.defaults["tools_cutout_z"]),
-            "tools_cutout_depthperpass":    float(self.app.defaults["tools_cutout_depthperpass"]),
-            "tools_cutout_mdepth":          self.app.defaults["tools_cutout_mdepth"],
-            "tools_cutout_gapsize":         float(self.app.defaults["tools_cutout_gapsize"]),
-            "tools_cutout_gaps_ff":         self.app.defaults["tools_cutout_gaps_ff"],
-            "tools_cutout_convexshape":     self.app.defaults["tools_cutout_convexshape"],
-
-            "tools_cutout_big_cursor":      self.app.defaults["tools_cutout_big_cursor"],
-            "tools_cutout_gap_type":        self.app.defaults["tools_cutout_gap_type"],
-            "tools_cutout_gap_depth":       float(self.app.defaults["tools_cutout_gap_depth"]),
-            "tools_cutout_mb_dia":          float(self.app.defaults["tools_cutout_mb_dia"]),
-            "tools_cutout_mb_spacing":      float(self.app.defaults["tools_cutout_mb_spacing"]),
+            "tools_cutout_tooldia": self.app.defaults["tools_cutout_tooldia"],
+            "tools_cutout_kind": self.app.defaults["tools_cutout_kind"],
+            "tools_cutout_margin": float(self.app.defaults["tools_cutout_margin"]),
+            "tools_cutout_z": float(self.app.defaults["tools_cutout_z"]),
+            "tools_cutout_depthperpass": float(self.app.defaults["tools_cutout_depthperpass"]),
+            "tools_cutout_mdepth": self.app.defaults["tools_cutout_mdepth"],
+            "tools_cutout_gapsize": float(self.app.defaults["tools_cutout_gapsize"]),
+            "tools_cutout_gaps_ff": self.app.defaults["tools_cutout_gaps_ff"],
+            "tools_cutout_convexshape": self.app.defaults["tools_cutout_convexshape"],
+
+            "tools_cutout_big_cursor": self.app.defaults["tools_cutout_big_cursor"],
+            "tools_cutout_gap_type": self.app.defaults["tools_cutout_gap_type"],
+            "tools_cutout_gap_depth": float(self.app.defaults["tools_cutout_gap_depth"]),
+            "tools_cutout_mb_dia": float(self.app.defaults["tools_cutout_mb_dia"]),
+            "tools_cutout_mb_spacing": float(self.app.defaults["tools_cutout_mb_spacing"]),
 
         })
 
         self.cut_tool_dict.update({
-                'tooldia':          str(self.app.defaults["tools_cutout_tooldia"]),
-                'offset':           'Path',
-                'offset_value':     0.0,
-                'type':             _('Rough'),
-                'tool_type':        'C1',
-                'data':             deepcopy(self.default_data),
-                'solid_geometry':   []
-            })
+            'tooldia': str(self.app.defaults["tools_cutout_tooldia"]),
+            'offset': 'Path',
+            'offset_value': 0.0,
+            'type': _('Rough'),
+            'tool_type': 'C1',
+            'data': deepcopy(self.default_data),
+            'solid_geometry': []
+        })
 
         self.update_ui(self.default_data)
 
@@ -490,13 +492,13 @@ class CutOut(AppTool):
         truncated_tooldia = self.app.dec_format(tooldia, self.decimals)
         self.cutout_tools.update({
             1: {
-                'tooldia':          truncated_tooldia,
-                'offset':           tool['offset'],
-                'offset_value':     tool['offset_value'],
-                'type':             tool['type'],
-                'tool_type':        tool['tool_type'],
-                'data':             deepcopy(tool['data']),
-                'solid_geometry':   []
+                'tooldia': truncated_tooldia,
+                'offset': tool['offset'],
+                'offset_value': tool['offset_value'],
+                'type': tool['type'],
+                'tool_type': tool['tool_type'],
+                'data': deepcopy(tool['data']),
+                'solid_geometry': []
             }
         })
         self.cutout_tools[1]['data']['name'] = '_cutout'
@@ -554,7 +556,6 @@ class CutOut(AppTool):
             return
 
         margin = float(self.ui.margin.get_value())
-        gapsize = float(self.ui.gapsize.get_value())
 
         try:
             gaps = self.ui.gaps.get_value()
@@ -575,225 +576,274 @@ class CutOut(AppTool):
                                                   "and after that perform Cutout."))
             return
 
-        convex_box = self.ui.convex_box_cb.get_value()
-
-        gapsize = gapsize / 2 + (dia / 2)
+        def cutout_handler(geom, gapsize):
+            proc_geometry = []
+            rest_geometry = []
+            r_temp_geo = []
+            initial_geo = deepcopy(geom)
 
-        def geo_init(geo_obj, app_obj):
-            solid_geo = []
-            gaps_solid_geo = None
+            # Get min and max data for each object as we just cut rectangles across X or Y
+            xxmin, yymin, xxmax, yymax = CutOut.recursive_bounds(geom)
 
-            if cutout_obj.kind == 'gerber':
-                if isinstance(cutout_obj.solid_geometry, list):
-                    cutout_obj.solid_geometry = MultiPolygon(cutout_obj.solid_geometry)
+            px = 0.5 * (xxmin + xxmax) + margin
+            py = 0.5 * (yymin + yymax) + margin
+            lenx = (xxmax - xxmin) + (margin * 2)
+            leny = (yymax - yymin) + (margin * 2)
 
-                try:
-                    if convex_box:
-                        object_geo = cutout_obj.solid_geometry.convex_hull
-                    else:
-                        object_geo = cutout_obj.solid_geometry
-                except Exception as err:
-                    log.debug("CutOut.on_freeform_cutout().geo_init() --> %s" % str(err))
-                    object_geo = cutout_obj.solid_geometry
+            if gaps == 'None':
+                pass
             else:
-                object_geo = cutout_obj.solid_geometry
-
-            def cutout_handler(geom):
-                proc_geometry = []
-                rest_geometry = []
-                r_temp_geo = []
-                initial_geo = deepcopy(geom)
+                if gaps == '8' or gaps == '2LR':
+                    points = (
+                        xxmin - gapsize,  # botleft_x
+                        py - gapsize + leny / 4,  # botleft_y
+                        xxmax + gapsize,  # topright_x
+                        py + gapsize + leny / 4  # topright_y
+                    )
+                    geom = self.subtract_poly_from_geo(geom, points)
+                    r_temp_geo.append(
+                        self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
+                    )
+
+                    points = (
+                        xxmin - gapsize,
+                        py - gapsize - leny / 4,
+                        xxmax + gapsize,
+                        py + gapsize - leny / 4
+                    )
+                    geom = self.subtract_poly_from_geo(geom, points)
+                    r_temp_geo.append(
+                        self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
+                    )
+
+                if gaps == '8' or gaps == '2TB':
+                    points = (
+                        px - gapsize + lenx / 4,
+                        yymin - gapsize,
+                        px + gapsize + lenx / 4,
+                        yymax + gapsize
+                    )
+                    geom = self.subtract_poly_from_geo(geom, points)
+                    r_temp_geo.append(
+                        self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
+                    )
+
+                    points = (
+                        px - gapsize - lenx / 4,
+                        yymin - gapsize,
+                        px + gapsize - lenx / 4,
+                        yymax + gapsize
+                    )
+                    geom = self.subtract_poly_from_geo(geom, points)
+                    r_temp_geo.append(
+                        self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
+                    )
+
+                if gaps == '4' or gaps == 'LR':
+                    points = (
+                        xxmin - gapsize,
+                        py - gapsize,
+                        xxmax + gapsize,
+                        py + gapsize
+                    )
+                    geom = self.subtract_poly_from_geo(geom, points)
+                    r_temp_geo.append(
+                        self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
+                    )
+
+                if gaps == '4' or gaps == 'TB':
+                    points = (
+                        px - gapsize,
+                        yymin - gapsize,
+                        px + gapsize,
+                        yymax + gapsize
+                    )
+                    geom = self.subtract_poly_from_geo(geom, points)
+                    r_temp_geo.append(
+                        self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
+                    )
 
-                # Get min and max data for each object as we just cut rectangles across X or Y
-                xxmin, yymin, xxmax, yymax = CutOut.recursive_bounds(geom)
-
-                px = 0.5 * (xxmin + xxmax) + margin
-                py = 0.5 * (yymin + yymax) + margin
-                lenx = (xxmax - xxmin) + (margin * 2)
-                leny = (yymax - yymin) + (margin * 2)
-
-                if gaps == 'None':
-                    pass
-                else:
-                    if gaps == '8' or gaps == '2LR':
-                        points = (
-                            xxmin - gapsize,  # botleft_x
-                            py - gapsize + leny / 4,  # botleft_y
-                            xxmax + gapsize,  # topright_x
-                            py + gapsize + leny / 4  # topright_y
-                        )
-                        geom = self.subtract_poly_from_geo(geom, points)
-                        r_temp_geo.append(
-                            self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
-                        )
+            try:
+                for g in geom:
+                    if g and not g.is_empty:
+                        proc_geometry.append(g)
+            except TypeError:
+                if geom and not geom.is_empty:
+                    proc_geometry.append(geom)
 
-                        points = (
-                            xxmin - gapsize,
-                            py - gapsize - leny / 4,
-                            xxmax + gapsize,
-                            py + gapsize - leny / 4
-                        )
-                        geom = self.subtract_poly_from_geo(geom, points)
-                        r_temp_geo.append(
-                            self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
-                        )
+            r_temp_geo = CutOut.flatten(r_temp_geo)
+            for g in r_temp_geo:
+                if g and not g.is_empty:
+                    rest_geometry.append(g)
 
-                    if gaps == '8' or gaps == '2TB':
-                        points = (
-                            px - gapsize + lenx / 4,
-                            yymin - gapsize,
-                            px + gapsize + lenx / 4,
-                            yymax + gapsize
-                        )
-                        geom = self.subtract_poly_from_geo(geom, points)
-                        r_temp_geo.append(
-                            self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
-                        )
+            return proc_geometry, rest_geometry
 
-                        points = (
-                            px - gapsize - lenx / 4,
-                            yymin - gapsize,
-                            px + gapsize - lenx / 4,
-                            yymax + gapsize
-                        )
-                        geom = self.subtract_poly_from_geo(geom, points)
-                        r_temp_geo.append(
-                            self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
-                        )
+        with self.app.proc_container.new("Generating Cutout ..."):
+            outname = cutout_obj.options["name"] + "_cutout"
+            self.app.collection.promise(outname)
 
-                    if gaps == '4' or gaps == 'LR':
-                        points = (
-                            xxmin - gapsize,
-                            py - gapsize,
-                            xxmax + gapsize,
-                            py + gapsize
-                        )
-                        geom = self.subtract_poly_from_geo(geom, points)
-                        r_temp_geo.append(
-                            self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
-                        )
+            outname_exc = cutout_obj.options["name"] + "_mouse_bites"
+            if self.ui.gaptype_radio.get_value() == 'mb':
+                self.app.collection.promise(outname_exc)
 
-                    if gaps == '4' or gaps == 'TB':
-                        points = (
-                            px - gapsize,
-                            yymin - gapsize,
-                            px + gapsize,
-                            yymax + gapsize
-                        )
-                        geom = self.subtract_poly_from_geo(geom, points)
-                        r_temp_geo.append(
-                            self.intersect_geo(initial_geo, box(points[0], points[1], points[2], points[3]))
-                        )
+            def job_thread(app_obj):
+                solid_geo = []
+                gaps_solid_geo = []
+                mouse_bites_geo = []
 
-                try:
-                    for g in geom:
-                        if g and not g.is_empty:
-                            proc_geometry.append(g)
-                except TypeError:
-                    if geom and not geom.is_empty:
-                        proc_geometry.append(geom)
+                convex_box = self.ui.convex_box_cb.get_value()
+                gapsize = self.ui.gapsize.get_value()
+                gapsize = gapsize / 2 + (dia / 2)
 
-                r_temp_geo = CutOut.flatten(r_temp_geo)
-                for g in r_temp_geo:
-                    if g and not g.is_empty:
-                        rest_geometry.append(g)
-
-                return proc_geometry, rest_geometry
-
-            if kind == 'single':
-                object_geo = unary_union(object_geo)
-
-                # for geo in object_geo:
                 if cutout_obj.kind == 'gerber':
-                    if isinstance(object_geo, MultiPolygon):
-                        x0, y0, x1, y1 = object_geo.bounds
-                        object_geo = box(x0, y0, x1, y1)
-                    if margin >= 0:
-                        geo_buf = object_geo.buffer(margin + abs(dia / 2))
-                    else:
-                        geo_buf = object_geo.buffer(margin - abs(dia / 2))
+                    if isinstance(cutout_obj.solid_geometry, list):
+                        cutout_obj.solid_geometry = MultiPolygon(cutout_obj.solid_geometry)
 
-                    geo = geo_buf.exterior
+                    try:
+                        if convex_box:
+                            object_geo = cutout_obj.solid_geometry.convex_hull
+                        else:
+                            object_geo = cutout_obj.solid_geometry
+                    except Exception as err:
+                        log.debug("CutOut.on_freeform_cutout().geo_init() --> %s" % str(err))
+                        object_geo = cutout_obj.solid_geometry
                 else:
-                    geo = object_geo
+                    object_geo = cutout_obj.solid_geometry
 
-                solid_geo, rest_geo = cutout_handler(geom=geo)
-                if self.ui.gaptype_radio.get_value() == 'bt' and self.ui.thin_depth_entry.get_value() > 0:
-                    gaps_solid_geo = rest_geo
-            else:
-                try:
-                    __ = iter(object_geo)
-                except TypeError:
-                    object_geo = [object_geo]
+                if kind == 'single':
+                    object_geo = unary_union(object_geo)
 
-                for geom_struct in object_geo:
+                    # for geo in object_geo:
                     if cutout_obj.kind == 'gerber':
+                        if isinstance(object_geo, MultiPolygon):
+                            x0, y0, x1, y1 = object_geo.bounds
+                            object_geo = box(x0, y0, x1, y1)
                         if margin >= 0:
-                            geom_struct = (geom_struct.buffer(margin + abs(dia / 2))).exterior
+                            geo_buf = object_geo.buffer(margin + abs(dia / 2))
                         else:
-                            geom_struct_buff = geom_struct.buffer(-margin + abs(dia / 2))
-                            geom_struct = geom_struct_buff.interiors
-
-                    c_geo, r_geo = cutout_handler(geom=geom_struct)
-                    solid_geo += c_geo
-                    if self.ui.gaptype_radio.get_value() == 'bt' and self.ui.thin_depth_entry.get_value() > 0:
-                        gaps_solid_geo += r_geo
-
-            if not solid_geo:
-                app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
-                return "fail"
-
-            solid_geo = linemerge(solid_geo)
-            geo_obj.solid_geometry = deepcopy(solid_geo)
-
-            xmin, ymin, xmax, ymax = CutOut.recursive_bounds(geo_obj.solid_geometry)
-            geo_obj.options['xmin'] = xmin
-            geo_obj.options['ymin'] = ymin
-            geo_obj.options['xmax'] = xmax
-            geo_obj.options['ymax'] = ymax
-            geo_obj.options['cnctooldia'] = str(dia)
-            geo_obj.options['cutz'] = self.ui.cutz_entry.get_value()
-            geo_obj.options['multidepth'] = self.ui.mpass_cb.get_value()
-            geo_obj.options['depthperpass'] = self.ui.maxdepth_entry.get_value()
+                            geo_buf = object_geo.buffer(margin - abs(dia / 2))
 
-            geo_obj.multigeo = True
+                        geo = geo_buf.exterior
+                    else:
+                        geo = object_geo
 
-            geo_obj.tools.update({
-                1: self.cut_tool_dict
-            })
-            geo_obj.tools[1]['tooldia'] = str(dia)
-            geo_obj.tools[1]['solid_geometry'] = geo_obj.solid_geometry
+                    solid_geo, rest_geo = cutout_handler(geom=geo, gapsize=gapsize)
+                    if self.ui.gaptype_radio.get_value() == 'bt' and self.ui.thin_depth_entry.get_value() > 0:
+                        gaps_solid_geo = rest_geo
+                    if self.ui.gaptype_radio.get_value() == 'mb':
+                        mouse_bites_geo = rest_geo
+                else:
+                    try:
+                        __ = iter(object_geo)
+                    except TypeError:
+                        object_geo = [object_geo]
 
-            geo_obj.tools[1]['data']['name'] = outname
-            geo_obj.tools[1]['data']['cutz'] = self.ui.cutz_entry.get_value()
-            geo_obj.tools[1]['data']['multidepth'] = self.ui.mpass_cb.get_value()
-            geo_obj.tools[1]['data']['depthperpass'] = self.ui.maxdepth_entry.get_value()
+                    for geom_struct in object_geo:
+                        if cutout_obj.kind == 'gerber':
+                            if margin >= 0:
+                                geom_struct = (geom_struct.buffer(margin + abs(dia / 2))).exterior
+                            else:
+                                geom_struct_buff = geom_struct.buffer(-margin + abs(dia / 2))
+                                geom_struct = geom_struct_buff.interiors
+
+                        c_geo, r_geo = cutout_handler(geom=geom_struct, gapsize=gapsize)
+                        solid_geo += c_geo
+                        if self.ui.gaptype_radio.get_value() == 'bt' and self.ui.thin_depth_entry.get_value() > 0:
+                            gaps_solid_geo += r_geo
+                        if self.ui.gaptype_radio.get_value() == 'mb':
+                            mouse_bites_geo += r_geo
+                if not solid_geo:
+                    self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
+                    return "fail"
 
-            if gaps_solid_geo is not None:
-                geo_obj.tools.update({
-                    9999: self.cut_tool_dict
-                })
-                geo_obj.tools[9999]['tooldia'] = str(dia)
-                geo_obj.tools[9999]['solid_geometry'] = gaps_solid_geo
+                solid_geo = linemerge(solid_geo)
 
-                geo_obj.tools[9999]['data']['name'] = outname
-                geo_obj.tools[9999]['data']['cutz'] = self.ui.thin_depth_entry.get_value()
-                geo_obj.tools[9999]['data']['multidepth'] = self.ui.mpass_cb.get_value()
-                geo_obj.tools[9999]['data']['depthperpass'] = self.ui.maxdepth_entry.get_value()
-                # plot this tool in a different color
-                geo_obj.tools[9999]['data']['override_color'] = "#29a3a3fa"
+                # list of Shapely Points to mark the drill points centers
+                holes = []
+                print(mouse_bites_geo)
 
-        outname = cutout_obj.options["name"] + "_cutout"
-        ret = self.app.app_obj.new_object('geometry', outname, geo_init)
+                def geo_init(geo_obj, app_object):
+                    geo_obj.solid_geometry = deepcopy(solid_geo)
 
-        if ret == 'fail':
-            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
-            return
+                    xmin, ymin, xmax, ymax = CutOut.recursive_bounds(geo_obj.solid_geometry)
+                    geo_obj.options['xmin'] = xmin
+                    geo_obj.options['ymin'] = ymin
+                    geo_obj.options['xmax'] = xmax
+                    geo_obj.options['ymax'] = ymax
+                    geo_obj.options['cnctooldia'] = str(dia)
+                    geo_obj.options['cutz'] = self.ui.cutz_entry.get_value()
+                    geo_obj.options['multidepth'] = self.ui.mpass_cb.get_value()
+                    geo_obj.options['depthperpass'] = self.ui.maxdepth_entry.get_value()
+
+                    geo_obj.multigeo = True
+
+                    geo_obj.tools.update({
+                        1: self.cut_tool_dict
+                    })
+                    geo_obj.tools[1]['tooldia'] = str(dia)
+                    geo_obj.tools[1]['solid_geometry'] = geo_obj.solid_geometry
+
+                    geo_obj.tools[1]['data']['name'] = outname
+                    geo_obj.tools[1]['data']['cutz'] = self.ui.cutz_entry.get_value()
+                    geo_obj.tools[1]['data']['multidepth'] = self.ui.mpass_cb.get_value()
+                    geo_obj.tools[1]['data']['depthperpass'] = self.ui.maxdepth_entry.get_value()
+
+                    if gaps_solid_geo:
+                        geo_obj.tools.update({
+                            9999: self.cut_tool_dict
+                        })
+                        geo_obj.tools[9999]['tooldia'] = str(dia)
+                        geo_obj.tools[9999]['solid_geometry'] = gaps_solid_geo
+
+                        geo_obj.tools[9999]['data']['name'] = outname
+                        geo_obj.tools[9999]['data']['cutz'] = self.ui.thin_depth_entry.get_value()
+                        geo_obj.tools[9999]['data']['multidepth'] = self.ui.mpass_cb.get_value()
+                        geo_obj.tools[9999]['data']['depthperpass'] = self.ui.maxdepth_entry.get_value()
+                        # plot this tool in a different color
+                        geo_obj.tools[9999]['data']['override_color'] = "#29a3a3fa"
+
+                def excellon_init(exc_obj, app_o):
+                    if not holes:
+                        return 'fail'
+                    mb_dia = self.ui.mb_dia_entry.get_value()
+
+                    tools = {}
+                    tools[1] = {}
+                    tools[1]["tooldia"] = mb_dia
+                    tools[1]['drills'] = holes
+                    tools[1]['solid_geometry'] = []
+
+                    exc_obj.tools = tools
+                    exc_obj.create_geometry()
+                    exc_obj.source_file = app_o.export_excellon(obj_name=exc_obj.options['name'], local_use=exc_obj,
+                                                                filename=None, use_thread=False)
+                    # calculate the bounds
+                    xmin, ymin, xmax, ymax = CutOut.recursive_bounds(exc_obj.solid_geometry)
+                    exc_obj.options['xmin'] = xmin
+                    exc_obj.options['ymin'] = ymin
+                    exc_obj.options['xmax'] = xmax
+                    exc_obj.options['ymax'] = ymax
 
-        # cutout_obj.plot(plot_tool=1)
-        self.app.inform.emit('[success] %s' % _("Any form CutOut operation finished."))
-        # self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
-        self.app.should_we_save = True
+                try:
+                    ret = app_obj.app_obj.new_object('geometry', outname, geo_init)
+                    if ret == 'fail':
+                        app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
+                        return
+
+                    if self.ui.gaptype_radio.get_value() == 'mb':
+                        ret = app_obj.app_obj.new_object('excellon', outname_exc, excellon_init)
+                        if ret == 'fail':
+                            app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Mouse bites failed."))
+                            return
+
+                    # cutout_obj.plot(plot_tool=1)
+                    app_obj.inform.emit('[success] %s' % _("Any form CutOut operation finished."))
+                    # self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
+                    app_obj.should_we_save = True
+                except Exception as ee:
+                    log.debug(str(ee))
+
+            self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
 
     def on_rectangular_cutout(self):
         log.debug("Cutout.on_rectangular_cutout() was launched ...")
@@ -875,7 +925,7 @@ class CutOut(AppTool):
                             xmin - gapsize,  # botleft_x
                             py - gapsize + leny / 4,  # botleft_y
                             xmax + gapsize,  # topright_x
-                            py + gapsize + leny / 4 # topright_y
+                            py + gapsize + leny / 4  # topright_y
                         )
                         geom = self.subtract_poly_from_geo(geom, points)
                         points = (
@@ -1660,14 +1710,13 @@ class CutOut(AppTool):
             if second_geo.intersects(geo):
                 results.append(second_geo.intersection(geo))
 
-        return  CutOut.flatten(results)
+        return CutOut.flatten(results)
 
     def reset_fields(self):
         self.ui.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
 
 
 class CutoutUI:
-
     toolName = _("Cutout PCB")
 
     def __init__(self, layout, app):
@@ -1898,9 +1947,9 @@ class CutoutUI:
 
         self.gaptype_radio = RadioSet(
             [
-                {'label': _('Bridge'),      'value': 'b'},
-                {'label': _('Thin'),        'value': 'bt'},
-                {'label': "M-Bites",        'value': 'mb'}
+                {'label': _('Bridge'), 'value': 'b'},
+                {'label': _('Thin'), 'value': 'bt'},
+                {'label': "M-Bites", 'value': 'mb'}
             ],
             stretch=True
         )

+ 17 - 25
appTools/ToolDblSided.py

@@ -2,7 +2,7 @@
 from PyQt5 import QtWidgets, QtCore, QtGui
 
 from appTool import AppTool
-from appGUI.GUIElements import RadioSet, FCDoubleSpinner, EvalEntry, FCEntry, FCButton, FCComboBox, FCCheckBox
+from appGUI.GUIElements import RadioSet, FCDoubleSpinner, FCButton, FCComboBox, NumericalEvalTupleEntry
 
 from numpy import Inf
 
@@ -156,27 +156,19 @@ class DblSidedTool(AppTool):
             try:
                 px, py = self.ui.point_entry.get_value()
             except TypeError:
-                self.app.inform.emit('[WARNING_NOTCL] %s' % _("'Point' reference is selected and 'Point' coordinates "
-                                                              "are missing. Add them and retry."))
+                msg = '[WARNING_NOTCL] %s' % \
+                      _("'Point' reference is selected and 'Point' coordinates are missing. Add them and retry.")
+                self.app.inform.emit(msg)
                 return
         else:
             selection_index = self.ui.box_combo.currentIndex()
-            model_index = self.app.collection.index(selection_index, 0, self.ui.gerber_object_combo.rootModelIndex())
+            model_index = self.app.collection.index(selection_index, 0, self.ui.object_combo.rootModelIndex())
             try:
                 bb_obj = model_index.internalPointer().obj
             except AttributeError:
-                model_index = self.app.collection.index(selection_index, 0, self.ui.exc_object_combo.rootModelIndex())
-                try:
-                    bb_obj = model_index.internalPointer().obj
-                except AttributeError:
-                    model_index = self.app.collection.index(selection_index, 0,
-                                                            self.ui.geo_object_combo.rootModelIndex())
-                    try:
-                        bb_obj = model_index.internalPointer().obj
-                    except AttributeError:
-                        self.app.inform.emit(
-                            '[WARNING_NOTCL] %s' % _("There is no Box reference object loaded. Load one and retry."))
-                        return
+                msg = '[WARNING_NOTCL] %s' % _("There is no Box reference object loaded. Load one and retry.")
+                self.app.inform.emit(msg)
+                return
 
             xmin, ymin, xmax, ymax = bb_obj.bounds()
             px = 0.5 * (xmin + xmax)
@@ -184,10 +176,10 @@ class DblSidedTool(AppTool):
 
         xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis]
 
-        dia = float(self.drill_dia.get_value())
+        dia = self.ui.drill_dia.get_value()
         if dia == '':
-            self.app.inform.emit('[WARNING_NOTCL] %s' %
-                                 _("No value or wrong format in Drill Dia entry. Add it and retry."))
+            msg = '[WARNING_NOTCL] %s' % _("No value or wrong format in Drill Dia entry. Add it and retry.")
+            self.app.inform.emit(msg)
             return
 
         tools = {}
@@ -198,8 +190,8 @@ class DblSidedTool(AppTool):
         # holes = self.alignment_holes.get_value()
         holes = eval('[{}]'.format(self.ui.alignment_holes.text()))
         if not holes:
-            self.app.inform.emit('[WARNING_NOTCL] %s' % _("There are no Alignment Drill Coordinates to use. "
-                                                          "Add them and retry."))
+            msg = '[WARNING_NOTCL] %s' % _("There are no Alignment Drill Coordinates to use. Add them and retry.")
+            self.app.inform.emit(msg)
             return
 
         for hole in holes:
@@ -629,7 +621,7 @@ class DsidedUI:
         grid0.addWidget(self.ymax_entry, 10, 1)
 
         # Center point value
-        self.center_entry = FCEntry()
+        self.center_entry = NumericalEvalTupleEntry(border_color='#0069A9')
         self.center_entry.setPlaceholderText(_("Center point coordinates"))
 
         self.center_btn = FCButton('%s:' % _("Centroid"))
@@ -714,7 +706,7 @@ class DsidedUI:
         grid1.addWidget(self.axis_location, 4, 1, 1, 2)
 
         # ## Point/Box
-        self.point_entry = EvalEntry()
+        self.point_entry = NumericalEvalTupleEntry(border_color='#0069A9')
         self.point_entry.setPlaceholderText(_("Point coordinates"))
 
         # Add a reference
@@ -876,7 +868,7 @@ class DsidedUI:
               "It can be modified in the Mirror Parameters -> Reference section")
         )
 
-        self.align_ref_label_val = EvalEntry()
+        self.align_ref_label_val = NumericalEvalTupleEntry(border_color='#0069A9')
         self.align_ref_label_val.setToolTip(
             _("The reference point used to create the second alignment drill\n"
               "from the first alignment drill, by doing mirror.\n"
@@ -900,7 +892,7 @@ class DsidedUI:
               "- one drill in mirror position over the axis selected above in the 'Align Axis'.")
         )
 
-        self.alignment_holes = EvalEntry()
+        self.alignment_holes = NumericalEvalTupleEntry(border_color='#0069A9')
         self.alignment_holes.setPlaceholderText(_("Drill coordinates"))
 
         grid5.addWidget(self.ah_label, 0, 0, 1, 2)

BIN
locale/de/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/de/LC_MESSAGES/strings.po


BIN
locale/en/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/en/LC_MESSAGES/strings.po


BIN
locale/es/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/es/LC_MESSAGES/strings.po


BIN
locale/fr/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/fr/LC_MESSAGES/strings.po


BIN
locale/hu/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 363 - 234
locale/hu/LC_MESSAGES/strings.po


BIN
locale/it/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/it/LC_MESSAGES/strings.po


BIN
locale/pt_BR/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/pt_BR/LC_MESSAGES/strings.po


BIN
locale/ro/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 347 - 201
locale/ro/LC_MESSAGES/strings.po


BIN
locale/ru/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 346 - 200
locale/ru/LC_MESSAGES/strings.po


BIN
locale/tr/LC_MESSAGES/strings.mo


Diferenças do arquivo suprimidas por serem muito extensas
+ 348 - 202
locale/tr/LC_MESSAGES/strings.po


Diferenças do arquivo suprimidas por serem muito extensas
+ 342 - 231
locale_template/strings.pot


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff