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

Merged in marius_stanciu/flatcam_beta/Beta (pull request #190)

Beta
Marius Stanciu 6 лет назад
Родитель
Сommit
cc7e758cda

+ 2 - 2
FlatCAM.py

@@ -4,9 +4,10 @@ import os
 from PyQt5 import QtWidgets
 from PyQt5 import QtWidgets
 from PyQt5.QtCore import QSettings, Qt
 from PyQt5.QtCore import QSettings, Qt
 from FlatCAMApp import App
 from FlatCAMApp import App
-from multiprocessing import freeze_support
 from flatcamGUI import VisPyPatches
 from flatcamGUI import VisPyPatches
 
 
+from multiprocessing import freeze_support
+
 if sys.platform == "win32":
 if sys.platform == "win32":
     # cx_freeze 'module win32' workaround
     # cx_freeze 'module win32' workaround
     pass
     pass
@@ -58,5 +59,4 @@ if __name__ == '__main__':
         app.setAttribute(Qt.AA_EnableHighDpiScaling, False)
         app.setAttribute(Qt.AA_EnableHighDpiScaling, False)
 
 
     fc = App()
     fc = App()
-
     sys.exit(app.exec_())
     sys.exit(app.exec_())

Разница между файлами не показана из-за своего большого размера
+ 340 - 110
FlatCAMApp.py


Разница между файлами не показана из-за своего большого размера
+ 330 - 134
FlatCAMObj.py


+ 25 - 3
FlatCAMProcess.py

@@ -10,6 +10,13 @@ from flatcamGUI.FlatCAMGUI import FlatCAMActivityView
 from PyQt5 import QtCore
 from PyQt5 import QtCore
 import weakref
 import weakref
 
 
+import gettext
+import FlatCAMTranslation as fcTranslate
+import builtins
+
+fcTranslate.apply_language('strings')
+if '_' not in builtins.__dict__:
+    _ = gettext.gettext
 
 
 # import logging
 # import logging
 
 
@@ -121,6 +128,8 @@ class FCProcessContainer(object):
 
 
 class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer):
 class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer):
     something_changed = QtCore.pyqtSignal()
     something_changed = QtCore.pyqtSignal()
+    # this will signal that the application is IDLE
+    idle_flag = QtCore.pyqtSignal()
 
 
     def __init__(self, view):
     def __init__(self, view):
         assert isinstance(view, FlatCAMActivityView), \
         assert isinstance(view, FlatCAMActivityView), \
@@ -131,6 +140,9 @@ class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer):
 
 
         self.view = view
         self.view = view
 
 
+        self.text_to_display_in_activity = ''
+        self.new_text = ' '
+
         self.something_changed.connect(self.update_view)
         self.something_changed.connect(self.update_view)
 
 
     def on_done(self, proc):
     def on_done(self, proc):
@@ -143,14 +155,24 @@ class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer):
         # self.app.log.debug("FCVisibleProcessContainer.on_change()")
         # self.app.log.debug("FCVisibleProcessContainer.on_change()")
         super(FCVisibleProcessContainer, self).on_change(proc)
         super(FCVisibleProcessContainer, self).on_change(proc)
 
 
+        # whenever there is a change update the message on activity
+        self.text_to_display_in_activity = self.procs[0]().status_msg()
+
         self.something_changed.emit()
         self.something_changed.emit()
 
 
     def update_view(self):
     def update_view(self):
         if len(self.procs) == 0:
         if len(self.procs) == 0:
+            self.new_text = ''
             self.view.set_idle()
             self.view.set_idle()
+            self.idle_flag.emit()
 
 
         elif len(self.procs) == 1:
         elif len(self.procs) == 1:
-            self.view.set_busy(self.procs[0]().status_msg())
-
+            self.view.set_busy(self.text_to_display_in_activity + self.new_text)
         else:
         else:
-            self.view.set_busy("%d processes running." % len(self.procs))
+            self.view.set_busy("%d %s" % (len(self.procs), _("processes running.")))
+
+    def update_view_text(self, new_text):
+        # this has to be called after the method 'new' inherited by this class is called with a string text as param
+        self.new_text = new_text
+        if len(self.procs) == 1:
+            self.view.set_busy(self.text_to_display_in_activity + self.new_text, no_movie=True)

+ 1 - 1
FlatCAMWorkerStack.py

@@ -25,7 +25,7 @@ class WorkerStack(QtCore.QObject):
             thread.started.connect(worker.run)
             thread.started.connect(worker.run)
             worker.task_completed.connect(self.on_task_completed)
             worker.task_completed.connect(self.on_task_completed)
 
 
-            thread.start(QtCore.QThread.LowPriority)
+            thread.start(QtCore.QThread.HighPriority)
 
 
             self.workers.append(worker)
             self.workers.append(worker)
             self.threads.append(thread)
             self.threads.append(thread)

+ 2 - 1
ObjectCollection.py

@@ -762,7 +762,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
             try:
             try:
                 a_idx.build_ui()
                 a_idx.build_ui()
             except Exception as e:
             except Exception as e:
-                self.app.inform.emit(_("[ERROR] Cause of error: %s") % str(e))
+                self.app.inform.emit('[ERROR] %s: %s' %
+                                     (_("Cause of error"), str(e)))
                 raise
                 raise
 
 
     def get_list(self):
     def get_list(self):

+ 106 - 0
README.md

@@ -9,6 +9,112 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+9.09.2019
+
+- changed the triangulation type in VisPyVisuals for ShapeCollectionVisual class
+- added a setting in Preferences -> Gerber -> Gerber General named Buffering. If set to 'no' the Gerber objects load a lot more faster (perhaps 10 times faster than when set to 'full') but the visual look is not so great as all the aperture polygons can be seen
+- added for NCC Tool and Paint Tool a setting in the Preferences -> Tools --> (NCC Tool/ Paint Tool) that can set a progressive plotting (plot shapes as they are processed)
+- some fixes in Paint Tool when done over the Gerber objects in case that the progressive plotting is selected
+- some fixes in Gerber isolation in case that the progressive plotting is selected; added a 'Buffer solid geometry' button shown only when progressive plotting for Gerber object is selected. It will buffer the entire geometry of the object and plot it, in a threaded way.
+- modified FlatCAMObj.py file to the new string format that will allow easier translations
+- modified camlib.py, FlatCAMAPp.py and ObjectCollection.py files to the new string format that will allow easier translations
+- updated the POT file and the German language
+- fixed issue when loading unbuffered a Gerber file that has negative regions
+- fixed Panelize Tool to save the aperture geometries into the panel apertures. Also made the tool faster by removing the buffering at the end of the job
+- modified FlatCAMEditor's files to the new string format that will allow easier translations
+- updated POT file and the Romanian translation
+
+8.09.2019
+
+- added some documentation strings for methods in FlatCAMApp.App class
+- removed some @pyqtSlot() decorators as they interfere with the current way the program works
+
+7.09.2019
+
+- added a method to gracefully exit from threaded tasks and implemented it for the NCC Tool and for the Paint Tool
+- modified the on_about() function to reflect the reality in 2019 - FlatCAM it is an Open Source contributed software
+- remade the handlers for the Enable/Disable Project Tree context menu so they are threaded and activity is shown in the lower right corner of the main window
+- added to GUI new options for the Gerber object related to area subtraction
+- added new feature in the Gerber object isolation allowing for the isolation to avoid an area defined by another object (Gerber or Geometry)
+- all transformation functions show now the progress (rotate, mirror, scale, offset, skew)
+- made threaded the Offset and Scale operations found in the Selected tab of the object
+- corrected some issues and made Move Tool to show correctly when it is plotting and when it is offsetting the objects position
+- made Set Origin feature, threaded
+- updated German language translation files
+- separated the Plotting thread from the transformations threads
+
+6.09.2019
+
+- remade visibility threaded
+- reimplemented the thread listening for new FlatCAM process starting with args so it is no longer subclassed but using the moveToThread function
+- added percentage display for work done in NCC Tool
+- added percentage display for work done in Paint Tool
+- some fixes and prepared the activity monitor area to receive updated texts
+- added progress display in status bar for generating CNCJob from Excellon objects
+- added progress display in status bar for generating CNCJob from Geometry objects
+- modified all the FlatCAM tools strings to the new format in which the status is no longer included in the translated strings to make it easier for the future translations
+- more customization for the progress display in case of NCC Tool, Paint Tool and for the Gcode generation
+- updated POT file with the new strings
+- made the objects offset (therefore the Move Tool) show progress display
+
+5.09.2019
+
+- fixed issue with loading files at start-up
+- fixed issue with generating bounding box geometry for CNCJob objects
+- added some more infobar messages and log.debug
+- increased the priority for the worker tasks
+- hidden the configuration for G91 coordinates due of deciding to leave this development for another time; it require too much refactoring
+- added some messages for the G-code generation so the user know in which stage the process is
+
+4.09.2019
+
+- started to work on support for G91 in Gcode (relative coordinates)
+- added support for G91 coordinates
+- working in plotting the CNCjob generated with G91 coordinates
+
+3.09.2019
+
+- in NCC tool there is now a depth of cut parameter named 'Cut Z' which will dictate how deep the tool will enter into the PCB material
+- in NCC tool added possibility to choose between the type of tools to be used and when V-shape is used then the tool diameter is calculated from the desired depth of cut and from the V-tip parameters
+- small changes in NCC tool regarding the usage of the V-shape tool
+- fixed the isolation distance in NCC Tool for the tools with iso_op type
+- in NCC Tool now the Area adding is continuous until RMB is clicked (no key modifier is needed anymore)
+- fixed German language translation
+- in NCC Tool added a warning in case there are isolation tools and if those isolation's are interrupted by an area or a box
+- in Paint Tool made that the area selection is repeated until RMB click
+- in Paint Tool and NCC Tool fixed the RMB click detection when Area selection is used
+- finished the work on file extensions registration with FlatCAM. If the file extensions are deleted in the Preferences -> File Associations then those extensions are unregistered with FlatCAM
+- fixed bug in NCC Tools and in SolderPaste Tool if in Edit -> Preferences only one tool is entered
+- fixed bug in camblib.clear_polygon3() which caused that some copper clearing / paintings were not complete (some polygons were not processed) when the Straight Lines method was used
+- some changes in NCC Tools regarding of the clearing itself
+
+2.09.2019
+
+- fixed issue in NCC Tool when using area option
+- added formatting for some strings in the app strings, making the future translations easier
+- made changes in the Excellon Tools Table to make it more clear that the tools are selected in the # column and not in the Plot column
+- in Excellon and Gerber Selected tab made the Plot (mark) columns not selectable
+- some ToolTips were modified
+- in Properties Tool made threaded the calculation of convex_hull area and also made it to work for multi-geo objects
+- in NCC tool the type of tool that is used is transferred to the Geometry object
+- in NCC tool the type of isolation done with the tools selected as isolation tools can now be selected and it has also an Edit -> Preferences entry
+- in Properties Tool fixed the dimensions calculations (length, width, area) to work for multi-geo objects
+
+1.09.2019
+
+- fixed open handlers
+- fixed issue in NCC Tool where the tool table context menu could be installed multiple times
+- added new ability to create simple isolation's in the NCC Tool
+- fixed an issue when multi depth step is larger than the depth of cut
+
+27.08.2019
+
+- made FlatCAM so that whenever an associated file is double clicked, if there is an opened instance of FlatCAM, the file will be opened in the first instance without launching a new instance of FlatCAM. If FlatCAM is launched again it will spawn a new process (hopefully it will work when freezed).
+
+26.08.2019
+
+- added support for file associations with FlatCAM, for Windows
+
 25.08.2019
 25.08.2019
 
 
 - initial add of a new Tcl Command named CopperClear
 - initial add of a new Tcl Command named CopperClear

Разница между файлами не показана из-за своего большого размера
+ 433 - 73
camlib.py


+ 94 - 71
flatcamEditors/FlatCAMExcEditor.py

@@ -50,7 +50,8 @@ class FCDrillAdd(FCShapeTool):
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             self.draw_app.tools_table_exc.setCurrentItem(item)
             self.draw_app.tools_table_exc.setCurrentItem(item)
         except KeyError:
         except KeyError:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] To add a drill first select a tool"))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("To add a drill first select a tool"))
             self.draw_app.select_tool("drill_select")
             self.draw_app.select_tool("drill_select")
             return
             return
 
 
@@ -112,7 +113,8 @@ class FCDrillAdd(FCShapeTool):
         self.geometry = DrawToolShape(self.util_shape(self.points))
         self.geometry = DrawToolShape(self.util_shape(self.points))
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Drill added."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Drill added."))
 
 
 
 
 class FCDrillArray(FCShapeTool):
 class FCDrillArray(FCShapeTool):
@@ -154,7 +156,8 @@ class FCDrillArray(FCShapeTool):
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             self.draw_app.tools_table_exc.setCurrentItem(item)
             self.draw_app.tools_table_exc.setCurrentItem(item)
         except KeyError:
         except KeyError:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] To add an Drill Array first select a tool in Tool Table"))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("To add an Drill Array first select a tool in Tool Table"))
             return
             return
 
 
         try:
         try:
@@ -208,11 +211,12 @@ class FCDrillArray(FCShapeTool):
                 self.drill_linear_angle = float(self.draw_app.linear_angle_spinner.get_value())
                 self.drill_linear_angle = float(self.draw_app.linear_angle_spinner.get_value())
                 self.drill_angle = float(self.draw_app.drill_angle_entry.get_value())
                 self.drill_angle = float(self.draw_app.drill_angle_entry.get_value())
             except TypeError:
             except TypeError:
-                self.draw_app.app.inform.emit(
-                    _("[ERROR_NOTCL] The value is not Float. Check for comma instead of dot separator."))
+                self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                              _("The value is not Float. Check for comma instead of dot separator."))
                 return
                 return
         except Exception as e:
         except Exception as e:
-            self.draw_app.app.inform.emit(_("[ERROR_NOTCL] The value is mistyped. Check the value. %s") % str(e))
+            self.draw_app.app.inform.emit('[ERROR_NOTCL] %s. %s' %
+                                          (_("The value is mistyped. Check the value"), str(e)))
             return
             return
 
 
         if self.drill_array == 'Linear':
         if self.drill_array == 'Linear':
@@ -310,7 +314,8 @@ class FCDrillArray(FCShapeTool):
                 self.geometry.append(DrawToolShape(geo))
                 self.geometry.append(DrawToolShape(geo))
         else:
         else:
             if (self.drill_angle * self.drill_array_size) > 360:
             if (self.drill_angle * self.drill_array_size) > 360:
-                self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Too many drills for the selected spacing angle."))
+                self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                              _("Too many drills for the selected spacing angle."))
                 return
                 return
 
 
             radius = distance(self.destination, self.origin)
             radius = distance(self.destination, self.origin)
@@ -327,7 +332,8 @@ class FCDrillArray(FCShapeTool):
                 geo = self.util_shape((x, y))
                 geo = self.util_shape((x, y))
                 self.geometry.append(DrawToolShape(geo))
                 self.geometry.append(DrawToolShape(geo))
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Drill Array added."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Drill Array added."))
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.draw_app.array_frame.hide()
         self.draw_app.array_frame.hide()
         return
         return
@@ -355,7 +361,8 @@ class FCSlot(FCShapeTool):
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             self.draw_app.tools_table_exc.setCurrentItem(item)
             self.draw_app.tools_table_exc.setCurrentItem(item)
         except KeyError:
         except KeyError:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] To add a slot first select a tool"))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("To add a slot first select a tool"))
             self.draw_app.select_tool("drill_select")
             self.draw_app.select_tool("drill_select")
             return
             return
 
 
@@ -412,15 +419,15 @@ class FCSlot(FCShapeTool):
                 slot_length = float(self.draw_app.slot_length_entry.get_value().replace(',', '.'))
                 slot_length = float(self.draw_app.slot_length_entry.get_value().replace(',', '.'))
                 self.draw_app.slot_length_entry.set_value(slot_length)
                 self.draw_app.slot_length_entry.set_value(slot_length)
             except ValueError:
             except ValueError:
-                self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Value is missing or wrong format. "
-                                                "Add it and retry."))
+                self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                              _("Value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
             slot_angle = float(self.draw_app.slot_angle_spinner.get_value())
             slot_angle = float(self.draw_app.slot_angle_spinner.get_value())
         except ValueError:
         except ValueError:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Value is missing or wrong format. "
-                                            "Add it and retry."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("Value is missing or wrong format. Add it and retry."))
             return
             return
 
 
         if self.draw_app.slot_axis_radio.get_value() == 'X':
         if self.draw_app.slot_axis_radio.get_value() == 'X':
@@ -518,7 +525,8 @@ class FCSlot(FCShapeTool):
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Adding Slot completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Adding Slot completed."))
         self.draw_app.slot_frame.hide()
         self.draw_app.slot_frame.hide()
 
 
 
 
@@ -544,7 +552,8 @@ class FCSlotArray(FCShapeTool):
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
             self.draw_app.tools_table_exc.setCurrentItem(item)
             self.draw_app.tools_table_exc.setCurrentItem(item)
         except KeyError:
         except KeyError:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] To add an Slot Array first select a tool in Tool Table"))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("To add an Slot Array first select a tool in Tool Table"))
             return
             return
 
 
 
 
@@ -622,11 +631,12 @@ class FCSlotArray(FCShapeTool):
                 self.slot_linear_angle = float(self.draw_app.slot_array_linear_angle_spinner.get_value())
                 self.slot_linear_angle = float(self.draw_app.slot_array_linear_angle_spinner.get_value())
                 self.slot_angle = float(self.draw_app.slot_array_angle_entry.get_value())
                 self.slot_angle = float(self.draw_app.slot_array_angle_entry.get_value())
             except TypeError:
             except TypeError:
-                self.draw_app.app.inform.emit(
-                    _("[ERROR_NOTCL] The value is not Float. Check for comma instead of dot separator."))
+                self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                              _("The value is not Float. Check for comma instead of dot separator."))
                 return
                 return
         except Exception as e:
         except Exception as e:
-            self.draw_app.app.inform.emit(_("[ERROR_NOTCL] The value is mistyped. Check the value."))
+            self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                          _("The value is mistyped. Check the value."))
             return
             return
 
 
         if self.slot_array == 'Linear':
         if self.slot_array == 'Linear':
@@ -687,15 +697,15 @@ class FCSlotArray(FCShapeTool):
                 slot_length = float(self.draw_app.slot_length_entry.get_value().replace(',', '.'))
                 slot_length = float(self.draw_app.slot_length_entry.get_value().replace(',', '.'))
                 self.draw_app.slot_length_entry.set_value(slot_length)
                 self.draw_app.slot_length_entry.set_value(slot_length)
             except ValueError:
             except ValueError:
-                self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Value is missing or wrong format. "
-                                                "Add it and retry."))
+                self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                              _("Value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
             slot_angle = float(self.draw_app.slot_angle_spinner.get_value())
             slot_angle = float(self.draw_app.slot_angle_spinner.get_value())
         except ValueError:
         except ValueError:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Value is missing or wrong format. "
-                                            "Add it and retry."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("Value is missing or wrong format. Add it and retry."))
             return
             return
 
 
         if self.draw_app.slot_axis_radio.get_value() == 'X':
         if self.draw_app.slot_axis_radio.get_value() == 'X':
@@ -804,7 +814,8 @@ class FCSlotArray(FCShapeTool):
                 self.geometry.append(DrawToolShape(geo))
                 self.geometry.append(DrawToolShape(geo))
         else:
         else:
             if (self.slot_angle * self.slot_array_size) > 360:
             if (self.slot_angle * self.slot_array_size) > 360:
-                self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Too many Slots for the selected spacing angle."))
+                self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                              _("Too many Slots for the selected spacing angle."))
                 return
                 return
 
 
             radius = distance(self.destination, self.origin)
             radius = distance(self.destination, self.origin)
@@ -826,7 +837,8 @@ class FCSlotArray(FCShapeTool):
 
 
                 self.geometry.append(DrawToolShape(geo))
                 self.geometry.append(DrawToolShape(geo))
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Slot Array added."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Slot Array added."))
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.draw_app.slot_frame.hide()
         self.draw_app.slot_frame.hide()
         self.draw_app.slot_array_frame.hide()
         self.draw_app.slot_array_frame.hide()
@@ -872,9 +884,8 @@ class FCDrillResize(FCShapeTool):
         try:
         try:
             new_dia = self.draw_app.resdrill_entry.get_value()
             new_dia = self.draw_app.resdrill_entry.get_value()
         except:
         except:
-            self.draw_app.app.inform.emit(
-                _("[ERROR_NOTCL] Resize drill(s) failed. Please enter a diameter for resize.")
-            )
+            self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                          _("Resize drill(s) failed. Please enter a diameter for resize."))
             return
             return
 
 
         if new_dia not in self.draw_app.olddia_newdia:
         if new_dia not in self.draw_app.olddia_newdia:
@@ -963,7 +974,8 @@ class FCDrillResize(FCShapeTool):
                             self.geometry.append(DrawToolShape(new_poly))
                             self.geometry.append(DrawToolShape(new_poly))
                         else:
                         else:
                             # unexpected geometry so we cancel
                             # unexpected geometry so we cancel
-                            self.draw_app.app.inform.emit(_("[ERROR_NOTCL] Cancelled."))
+                            self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                                          _("Cancelled."))
                             return
                             return
 
 
                         # remove the geometry with the old size
                         # remove the geometry with the old size
@@ -1032,7 +1044,8 @@ class FCDrillResize(FCShapeTool):
                     except KeyError:
                     except KeyError:
                         # if the exception happen here then we are not dealing with slots neither
                         # if the exception happen here then we are not dealing with slots neither
                         # therefore something else is not OK so we return
                         # therefore something else is not OK so we return
-                        self.draw_app.app.inform.emit(_("[ERROR_NOTCL] Cancelled."))
+                        self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                                      _("Cancelled."))
                         return
                         return
 
 
             # this simple hack is used so we can delete form self.draw_app.selected but
             # this simple hack is used so we can delete form self.draw_app.selected but
@@ -1052,9 +1065,11 @@ class FCDrillResize(FCShapeTool):
             # we reactivate the signals after the after the tool editing
             # we reactivate the signals after the after the tool editing
             self.draw_app.tools_table_exc.itemChanged.connect(self.draw_app.on_tool_edit)
             self.draw_app.tools_table_exc.itemChanged.connect(self.draw_app.on_tool_edit)
 
 
-            self.draw_app.app.inform.emit(_("[success] Done. Drill/Slot Resize completed."))
+            self.draw_app.app.inform.emit('[success] Done. %s' %
+                                          _("Drill/Slot Resize completed."))
         else:
         else:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Cancelled. No drills/slots selected for resize ..."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("Cancelled. No drills/slots selected for resize ..."))
 
 
         # init this set() for another use perhaps
         # init this set() for another use perhaps
         self.selected_dia_set = set()
         self.selected_dia_set = set()
@@ -1137,7 +1152,8 @@ class FCDrillMove(FCShapeTool):
             sel_shapes_to_be_deleted = []
             sel_shapes_to_be_deleted = []
 
 
         self.draw_app.build_ui()
         self.draw_app.build_ui()
-        self.draw_app.app.inform.emit(_("[success] Done. Drill(s) Move completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Drill(s) Move completed."))
 
 
     def selection_bbox(self):
     def selection_bbox(self):
         geo_list = []
         geo_list = []
@@ -1234,7 +1250,8 @@ class FCDrillCopy(FCDrillMove):
             sel_shapes_to_be_deleted = []
             sel_shapes_to_be_deleted = []
 
 
         self.draw_app.build_ui()
         self.draw_app.build_ui()
-        self.draw_app.app.inform.emit(_("[success] Done. Drill(s) copied."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Drill(s) copied."))
 
 
 
 
 class FCDrillSelect(DrawTool):
 class FCDrillSelect(DrawTool):
@@ -1498,7 +1515,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         grid1 = QtWidgets.QGridLayout()
         grid1 = QtWidgets.QGridLayout()
         self.tools_box.addLayout(grid1)
         self.tools_box.addLayout(grid1)
 
 
-        addtool_entry_lbl = QtWidgets.QLabel(_('Tool Dia:'))
+        addtool_entry_lbl = QtWidgets.QLabel('%s:' % _('Tool Dia'))
         addtool_entry_lbl.setToolTip(
         addtool_entry_lbl.setToolTip(
             _("Diameter for the new tool")
             _("Diameter for the new tool")
         )
         )
@@ -1551,7 +1568,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         grid3 = QtWidgets.QGridLayout()
         grid3 = QtWidgets.QGridLayout()
         self.resize_box.addLayout(grid3)
         self.resize_box.addLayout(grid3)
 
 
-        res_entry_lbl = QtWidgets.QLabel(_('Resize Dia:'))
+        res_entry_lbl = QtWidgets.QLabel('%s:' % _('Resize Dia'))
         res_entry_lbl.setToolTip(
         res_entry_lbl.setToolTip(
            _("Diameter to resize to.")
            _("Diameter to resize to.")
         )
         )
@@ -1608,7 +1625,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.array_box.addLayout(self.array_form)
         self.array_box.addLayout(self.array_form)
 
 
         # Set the number of drill holes in the drill array
         # Set the number of drill holes in the drill array
-        self.drill_array_size_label = QtWidgets.QLabel(_('Nr of drills:'))
+        self.drill_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of drills'))
         self.drill_array_size_label.setToolTip(_("Specify how many drills to be in the array."))
         self.drill_array_size_label.setToolTip(_("Specify how many drills to be in the array."))
         self.drill_array_size_label.setMinimumWidth(100)
         self.drill_array_size_label.setMinimumWidth(100)
 
 
@@ -1626,7 +1643,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.linear_box.addLayout(self.linear_form)
         self.linear_box.addLayout(self.linear_form)
 
 
         # Linear Drill Array direction
         # Linear Drill Array direction
-        self.drill_axis_label = QtWidgets.QLabel(_('Direction:'))
+        self.drill_axis_label = QtWidgets.QLabel('%s:'% _('Direction'))
         self.drill_axis_label.setToolTip(
         self.drill_axis_label.setToolTip(
             _("Direction on which the linear array is oriented:\n"
             _("Direction on which the linear array is oriented:\n"
               "- 'X' - horizontal axis \n"
               "- 'X' - horizontal axis \n"
@@ -1641,7 +1658,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.linear_form.addRow(self.drill_axis_label, self.drill_axis_radio)
         self.linear_form.addRow(self.drill_axis_label, self.drill_axis_radio)
 
 
         # Linear Drill Array pitch distance
         # Linear Drill Array pitch distance
-        self.drill_pitch_label = QtWidgets.QLabel(_('Pitch:'))
+        self.drill_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch'))
         self.drill_pitch_label.setToolTip(
         self.drill_pitch_label.setToolTip(
             _("Pitch = Distance between elements of the array.")
             _("Pitch = Distance between elements of the array.")
         )
         )
@@ -1651,7 +1668,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.linear_form.addRow(self.drill_pitch_label, self.drill_pitch_entry)
         self.linear_form.addRow(self.drill_pitch_label, self.drill_pitch_entry)
 
 
         # Linear Drill Array angle
         # Linear Drill Array angle
-        self.linear_angle_label = QtWidgets.QLabel(_('Angle:'))
+        self.linear_angle_label = QtWidgets.QLabel('%s:' % _('Angle'))
         self.linear_angle_label.setToolTip(
         self.linear_angle_label.setToolTip(
            _("Angle at which the linear array is placed.\n"
            _("Angle at which the linear array is placed.\n"
              "The precision is of max 2 decimals.\n"
              "The precision is of max 2 decimals.\n"
@@ -1673,7 +1690,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.circular_box.setContentsMargins(0, 0, 0, 0)
         self.circular_box.setContentsMargins(0, 0, 0, 0)
         self.array_circular_frame.setLayout(self.circular_box)
         self.array_circular_frame.setLayout(self.circular_box)
 
 
-        self.drill_direction_label = QtWidgets.QLabel(_('Direction:'))
+        self.drill_direction_label = QtWidgets.QLabel('%s:' % _('Direction'))
         self.drill_direction_label.setToolTip(_("Direction for circular array."
         self.drill_direction_label.setToolTip(_("Direction for circular array."
                                                 "Can be CW = clockwise or CCW = counter clockwise."))
                                                 "Can be CW = clockwise or CCW = counter clockwise."))
         self.drill_direction_label.setMinimumWidth(100)
         self.drill_direction_label.setMinimumWidth(100)
@@ -1685,7 +1702,7 @@ class FlatCAMExcEditor(QtCore.QObject):
                                                {'label': _('CCW'), 'value': 'CCW'}])
                                                {'label': _('CCW'), 'value': 'CCW'}])
         self.circular_form.addRow(self.drill_direction_label, self.drill_direction_radio)
         self.circular_form.addRow(self.drill_direction_label, self.drill_direction_radio)
 
 
-        self.drill_angle_label = QtWidgets.QLabel(_('Angle:'))
+        self.drill_angle_label = QtWidgets.QLabel('%s:' % _('Angle'))
         self.drill_angle_label.setToolTip(_("Angle at which each element in circular array is placed."))
         self.drill_angle_label.setToolTip(_("Angle at which each element in circular array is placed."))
         self.drill_angle_label.setMinimumWidth(100)
         self.drill_angle_label.setMinimumWidth(100)
 
 
@@ -1727,7 +1744,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_box.addLayout(self.slot_form)
         self.slot_box.addLayout(self.slot_form)
 
 
         # Slot length
         # Slot length
-        self.slot_length_label = QtWidgets.QLabel(_('Length:'))
+        self.slot_length_label = QtWidgets.QLabel('%s:' % _('Length'))
         self.slot_length_label.setToolTip(
         self.slot_length_label.setToolTip(
             _("Length = The length of the slot.")
             _("Length = The length of the slot.")
         )
         )
@@ -1737,7 +1754,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_form.addRow(self.slot_length_label, self.slot_length_entry)
         self.slot_form.addRow(self.slot_length_label, self.slot_length_entry)
 
 
         # Slot direction
         # Slot direction
-        self.slot_axis_label = QtWidgets.QLabel(_('Direction:'))
+        self.slot_axis_label = QtWidgets.QLabel('%s:' % _('Direction'))
         self.slot_axis_label.setToolTip(
         self.slot_axis_label.setToolTip(
             _("Direction on which the slot is oriented:\n"
             _("Direction on which the slot is oriented:\n"
               "- 'X' - horizontal axis \n"
               "- 'X' - horizontal axis \n"
@@ -1752,7 +1769,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_form.addRow(self.slot_axis_label, self.slot_axis_radio)
         self.slot_form.addRow(self.slot_axis_label, self.slot_axis_radio)
 
 
         # Slot custom angle
         # Slot custom angle
-        self.slot_angle_label = QtWidgets.QLabel(_('Angle:'))
+        self.slot_angle_label = QtWidgets.QLabel('%s:' % _('Angle'))
         self.slot_angle_label.setToolTip(
         self.slot_angle_label.setToolTip(
            _("Angle at which the slot is placed.\n"
            _("Angle at which the slot is placed.\n"
              "The precision is of max 2 decimals.\n"
              "The precision is of max 2 decimals.\n"
@@ -1810,7 +1827,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_array_box.addLayout(self.slot_array_form)
         self.slot_array_box.addLayout(self.slot_array_form)
 
 
         # Set the number of slot holes in the slot array
         # Set the number of slot holes in the slot array
-        self.slot_array_size_label = QtWidgets.QLabel(_('Nr of slots:'))
+        self.slot_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of slots'))
         self.slot_array_size_label.setToolTip(_("Specify how many slots to be in the array."))
         self.slot_array_size_label.setToolTip(_("Specify how many slots to be in the array."))
         self.slot_array_size_label.setMinimumWidth(100)
         self.slot_array_size_label.setMinimumWidth(100)
 
 
@@ -1828,7 +1845,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_array_linear_box.addLayout(self.slot_array_linear_form)
         self.slot_array_linear_box.addLayout(self.slot_array_linear_form)
 
 
         # Linear Slot Array direction
         # Linear Slot Array direction
-        self.slot_array_axis_label = QtWidgets.QLabel(_('Direction:'))
+        self.slot_array_axis_label = QtWidgets.QLabel('%s:' % _('Direction'))
         self.slot_array_axis_label.setToolTip(
         self.slot_array_axis_label.setToolTip(
             _("Direction on which the linear array is oriented:\n"
             _("Direction on which the linear array is oriented:\n"
               "- 'X' - horizontal axis \n"
               "- 'X' - horizontal axis \n"
@@ -1843,7 +1860,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_array_linear_form.addRow(self.slot_array_axis_label, self.slot_array_axis_radio)
         self.slot_array_linear_form.addRow(self.slot_array_axis_label, self.slot_array_axis_radio)
 
 
         # Linear Slot Array pitch distance
         # Linear Slot Array pitch distance
-        self.slot_array_pitch_label = QtWidgets.QLabel(_('Pitch:'))
+        self.slot_array_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch'))
         self.slot_array_pitch_label.setToolTip(
         self.slot_array_pitch_label.setToolTip(
             _("Pitch = Distance between elements of the array.")
             _("Pitch = Distance between elements of the array.")
         )
         )
@@ -1853,7 +1870,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_array_linear_form.addRow(self.slot_array_pitch_label, self.slot_array_pitch_entry)
         self.slot_array_linear_form.addRow(self.slot_array_pitch_label, self.slot_array_pitch_entry)
 
 
         # Linear Slot Array angle
         # Linear Slot Array angle
-        self.slot_array_linear_angle_label = QtWidgets.QLabel(_('Angle:'))
+        self.slot_array_linear_angle_label = QtWidgets.QLabel('%s:' % _('Angle'))
         self.slot_array_linear_angle_label.setToolTip(
         self.slot_array_linear_angle_label.setToolTip(
             _("Angle at which the linear array is placed.\n"
             _("Angle at which the linear array is placed.\n"
               "The precision is of max 2 decimals.\n"
               "The precision is of max 2 decimals.\n"
@@ -1875,7 +1892,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.slot_array_circular_box.setContentsMargins(0, 0, 0, 0)
         self.slot_array_circular_box.setContentsMargins(0, 0, 0, 0)
         self.slot_array_circular_frame.setLayout(self.slot_array_circular_box)
         self.slot_array_circular_frame.setLayout(self.slot_array_circular_box)
 
 
-        self.slot_array_direction_label = QtWidgets.QLabel(_('Direction:'))
+        self.slot_array_direction_label = QtWidgets.QLabel('%s:' % _('Direction'))
         self.slot_array_direction_label.setToolTip(_("Direction for circular array."
         self.slot_array_direction_label.setToolTip(_("Direction for circular array."
                                                      "Can be CW = clockwise or CCW = counter clockwise."))
                                                      "Can be CW = clockwise or CCW = counter clockwise."))
         self.slot_array_direction_label.setMinimumWidth(100)
         self.slot_array_direction_label.setMinimumWidth(100)
@@ -1887,7 +1904,7 @@ class FlatCAMExcEditor(QtCore.QObject):
                                                     {'label': _('CCW'), 'value': 'CCW'}])
                                                     {'label': _('CCW'), 'value': 'CCW'}])
         self.slot_array_circular_form.addRow(self.slot_array_direction_label, self.slot_array_direction_radio)
         self.slot_array_circular_form.addRow(self.slot_array_direction_label, self.slot_array_direction_radio)
 
 
-        self.slot_array_angle_label = QtWidgets.QLabel(_('Angle:'))
+        self.slot_array_angle_label = QtWidgets.QLabel('%s:' % _('Angle'))
         self.slot_array_angle_label.setToolTip(_("Angle at which each element in circular array is placed."))
         self.slot_array_angle_label.setToolTip(_("Angle at which each element in circular array is placed."))
         self.slot_array_angle_label.setMinimumWidth(100)
         self.slot_array_angle_label.setMinimumWidth(100)
 
 
@@ -2395,9 +2412,8 @@ class FlatCAMExcEditor(QtCore.QObject):
                 try:
                 try:
                     tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
                     tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                         "use a number.")
-                                         )
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         if tool_dia not in self.olddia_newdia:
         if tool_dia not in self.olddia_newdia:
@@ -2408,17 +2424,17 @@ class FlatCAMExcEditor(QtCore.QObject):
             # each time a tool diameter is edited or added
             # each time a tool diameter is edited or added
             self.olddia_newdia[tool_dia] = tool_dia
             self.olddia_newdia[tool_dia] = tool_dia
         else:
         else:
-            self.app.inform.emit(_("[WARNING_NOTCL] Tool already in the original or actual tool list.\n"
-                                 "Save and reedit Excellon if you need to add this tool. ")
-                                 )
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Tool already in the original or actual tool list.\n"
+                                 "Save and reedit Excellon if you need to add this tool. "))
             return
             return
 
 
         # since we add a new tool, we update also the initial state of the tool_table through it's dictionary
         # since we add a new tool, we update also the initial state of the tool_table through it's dictionary
         # we add a new entry in the tool2tooldia dict
         # we add a new entry in the tool2tooldia dict
         self.tool2tooldia[len(self.olddia_newdia)] = tool_dia
         self.tool2tooldia[len(self.olddia_newdia)] = tool_dia
 
 
-        self.app.inform.emit(_("[success] Added new tool with dia: {dia} {units}").format(dia=str(tool_dia),
-                                                                                          units=str(self.units)))
+        self.app.inform.emit('[success] %s: %s %s' %
+                             (_("Added new tool with dia"), str(tool_dia), str(self.units)))
 
 
         self.build_ui()
         self.build_ui()
 
 
@@ -2449,7 +2465,8 @@ class FlatCAMExcEditor(QtCore.QObject):
                 else:
                 else:
                     deleted_tool_dia_list.append(float('%.4f' % dia))
                     deleted_tool_dia_list.append(float('%.4f' % dia))
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit(_("[WARNING_NOTCL] Select a tool in Tool Table"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Select a tool in Tool Table"))
             return
             return
 
 
         for deleted_tool_dia in deleted_tool_dia_list:
         for deleted_tool_dia in deleted_tool_dia_list:
@@ -2481,9 +2498,8 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
             self.olddia_newdia.pop(deleted_tool_dia, None)
             self.olddia_newdia.pop(deleted_tool_dia, None)
 
 
-            self.app.inform.emit(_("[success] Deleted tool with dia: {del_dia} {units}").format(
-                del_dia=str(deleted_tool_dia),
-                units=str(self.units)))
+            self.app.inform.emit('[success] %s: %s %s' %
+                                 (_("Deleted tool with diameter"), str(deleted_tool_dia), str(self.units)))
 
 
         self.replot()
         self.replot()
         # self.app.inform.emit("Could not delete selected tool")
         # self.app.inform.emit("Could not delete selected tool")
@@ -2632,7 +2648,8 @@ class FlatCAMExcEditor(QtCore.QObject):
         self.tools_table_exc.itemChanged.connect(self.on_tool_edit)
         self.tools_table_exc.itemChanged.connect(self.on_tool_edit)
         self.tools_table_exc.cellPressed.connect(self.on_row_selected)
         self.tools_table_exc.cellPressed.connect(self.on_row_selected)
 
 
-        self.app.inform.emit(_("[success] Done. Tool edit completed."))
+        self.app.inform.emit('[success] %s' %
+                             _("Done. Tool edit completed."))
 
 
         # self.tools_table_exc.selectionModel().currentChanged.connect(self.on_row_selected)
         # self.tools_table_exc.selectionModel().currentChanged.connect(self.on_row_selected)
 
 
@@ -3166,11 +3183,12 @@ class FlatCAMExcEditor(QtCore.QObject):
             try:
             try:
                 excellon_obj.create_geometry()
                 excellon_obj.create_geometry()
             except KeyError:
             except KeyError:
-                self.app.inform.emit(
-                   _("[ERROR_NOTCL] There are no Tools definitions in the file. Aborting Excellon creation.")
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("There are no Tools definitions in the file. Aborting Excellon creation.")
                 )
                 )
             except:
             except:
-                msg = _("[ERROR] An internal error has ocurred. See shell.\n")
+                msg = '[ERROR] %s' % \
+                      _("An internal error has ocurred. See Shell.\n")
                 msg += traceback.format_exc()
                 msg += traceback.format_exc()
                 app_obj.inform.emit(msg)
                 app_obj.inform.emit(msg)
                 raise
                 raise
@@ -3185,7 +3203,8 @@ class FlatCAMExcEditor(QtCore.QObject):
                 self.app.progress.emit(100)
                 self.app.progress.emit(100)
                 return
                 return
 
 
-            self.app.inform.emit(_("[success] Excellon editing finished."))
+            self.app.inform.emit('[success] %s' %
+                                 _("Excellon editing finished."))
             # self.progress.emit(100)
             # self.progress.emit(100)
 
 
     def on_tool_select(self, tool):
     def on_tool_select(self, tool):
@@ -3202,7 +3221,8 @@ class FlatCAMExcEditor(QtCore.QObject):
             # self.draw_app.select_tool('drill_select')
             # self.draw_app.select_tool('drill_select')
             self.complete = True
             self.complete = True
             current_tool = 'drill_select'
             current_tool = 'drill_select'
-            self.app.inform.emit(_("[WARNING_NOTCL] Cancelled. There is no Tool/Drill selected"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Cancelled. There is no Tool/Drill selected"))
 
 
         # This is to make the group behave as radio group
         # This is to make the group behave as radio group
         if current_tool in self.tools_exc:
         if current_tool in self.tools_exc:
@@ -3421,14 +3441,16 @@ class FlatCAMExcEditor(QtCore.QObject):
                         self.active_tool.complete = True
                         self.active_tool.complete = True
                         self.in_action = False
                         self.in_action = False
                         self.delete_utility_geometry()
                         self.delete_utility_geometry()
-                        self.app.inform.emit(_("[success] Done."))
+                        self.app.inform.emit('[success] %s' %
+                                             _("Done."))
                         self.select_tool('drill_select')
                         self.select_tool('drill_select')
                     else:
                     else:
                         if isinstance(self.active_tool, FCDrillAdd):
                         if isinstance(self.active_tool, FCDrillAdd):
                             self.active_tool.complete = True
                             self.active_tool.complete = True
                             self.in_action = False
                             self.in_action = False
                             self.delete_utility_geometry()
                             self.delete_utility_geometry()
-                            self.app.inform.emit(_("[success] Done."))
+                            self.app.inform.emit('[success] %s' %
+                                                 _("Done."))
                             self.select_tool('drill_select')
                             self.select_tool('drill_select')
 
 
                         self.app.cursor = QtGui.QCursor()
                         self.app.cursor = QtGui.QCursor()
@@ -3784,7 +3806,8 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         self.selected = []
         self.selected = []
         self.build_ui()
         self.build_ui()
-        self.app.inform.emit(_("[success] Done. Drill(s) deleted."))
+        self.app.inform.emit('[success] %s' %
+                             _("Done. Drill(s) deleted."))
 
 
     def delete_shape(self, del_shape):
     def delete_shape(self, del_shape):
         self.is_modified = True
         self.is_modified = True

+ 201 - 134
flatcamEditors/FlatCAMGeoEditor.py

@@ -137,8 +137,8 @@ class BufferSelectionTool(FlatCAMTool):
                 buffer_distance = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 buffer_distance = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buffer_distance_entry.set_value(buffer_distance)
                 self.buffer_distance_entry.set_value(buffer_distance)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
@@ -154,8 +154,8 @@ class BufferSelectionTool(FlatCAMTool):
                 buffer_distance = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 buffer_distance = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buffer_distance_entry.set_value(buffer_distance)
                 self.buffer_distance_entry.set_value(buffer_distance)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
@@ -171,8 +171,8 @@ class BufferSelectionTool(FlatCAMTool):
                 buffer_distance = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 buffer_distance = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buffer_distance_entry.set_value(buffer_distance)
                 self.buffer_distance_entry.set_value(buffer_distance)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
@@ -431,7 +431,7 @@ class PaintOptionsTool(FlatCAMTool):
         self.layout.addLayout(grid)
         self.layout.addLayout(grid)
 
 
         # Tool dia
         # Tool dia
-        ptdlabel = QtWidgets.QLabel(_('Tool dia:'))
+        ptdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
         ptdlabel.setToolTip(
         ptdlabel.setToolTip(
            _("Diameter of the tool to\n"
            _("Diameter of the tool to\n"
              "be used in the operation.")
              "be used in the operation.")
@@ -442,7 +442,7 @@ class PaintOptionsTool(FlatCAMTool):
         grid.addWidget(self.painttooldia_entry, 0, 1)
         grid.addWidget(self.painttooldia_entry, 0, 1)
 
 
         # Overlap
         # Overlap
-        ovlabel = QtWidgets.QLabel(_('Overlap Rate:'))
+        ovlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         ovlabel.setToolTip(
         ovlabel.setToolTip(
             _("How much (fraction) of the tool width to overlap each tool pass.\n"
             _("How much (fraction) of the tool width to overlap each tool pass.\n"
               "Example:\n"
               "Example:\n"
@@ -460,7 +460,7 @@ class PaintOptionsTool(FlatCAMTool):
         grid.addWidget(self.paintoverlap_entry, 1, 1)
         grid.addWidget(self.paintoverlap_entry, 1, 1)
 
 
         # Margin
         # Margin
-        marginlabel = QtWidgets.QLabel(_('Margin:'))
+        marginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         marginlabel.setToolTip(
         marginlabel.setToolTip(
            _("Distance by which to avoid\n"
            _("Distance by which to avoid\n"
              "the edges of the polygon to\n"
              "the edges of the polygon to\n"
@@ -471,7 +471,7 @@ class PaintOptionsTool(FlatCAMTool):
         grid.addWidget(self.paintmargin_entry, 2, 1)
         grid.addWidget(self.paintmargin_entry, 2, 1)
 
 
         # Method
         # Method
-        methodlabel = QtWidgets.QLabel(_('Method:'))
+        methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
         methodlabel.setToolTip(
         methodlabel.setToolTip(
             _("Algorithm to paint the polygon:<BR>"
             _("Algorithm to paint the polygon:<BR>"
               "<B>Standard</B>: Fixed step inwards.<BR>"
               "<B>Standard</B>: Fixed step inwards.<BR>"
@@ -562,7 +562,8 @@ class PaintOptionsTool(FlatCAMTool):
 
 
     def on_paint(self):
     def on_paint(self):
         if not self.fcdraw.selected:
         if not self.fcdraw.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Paint cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Paint cancelled. No shape selected."))
             return
             return
 
 
         try:
         try:
@@ -573,8 +574,8 @@ class PaintOptionsTool(FlatCAMTool):
                 tooldia = float(self.painttooldia_entry.get_value().replace(',', '.'))
                 tooldia = float(self.painttooldia_entry.get_value().replace(',', '.'))
                 self.painttooldia_entry.set_value(tooldia)
                 self.painttooldia_entry.set_value(tooldia)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Tool diameter value is missing or wrong format. Add it and retry."))
                 return
                 return
         try:
         try:
             overlap = float(self.paintoverlap_entry.get_value())
             overlap = float(self.paintoverlap_entry.get_value())
@@ -584,8 +585,8 @@ class PaintOptionsTool(FlatCAMTool):
                 overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
                 overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
                 self.paintoverlap_entry.set_value(overlap)
                 self.paintoverlap_entry.set_value(overlap)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Overlap value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Overlap value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
@@ -596,8 +597,8 @@ class PaintOptionsTool(FlatCAMTool):
                 margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
                 margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
                 self.paintmargin_entry.set_value(margin)
                 self.paintmargin_entry.set_value(margin)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Margin distance value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Margin distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         method = self.paintmethod_combo.get_value()
         method = self.paintmethod_combo.get_value()
         contour = self.paintcontour_cb.get_value()
         contour = self.paintcontour_cb.get_value()
@@ -1053,7 +1054,8 @@ class TransformEditorTool(FlatCAMTool):
 
 
     def template(self):
     def template(self):
         if not self.fcdraw.selected:
         if not self.fcdraw.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Transformation cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Transformation cancelled. No shape selected."))
             return
             return
 
 
 
 
@@ -1074,8 +1076,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.rotate_entry.get_value().replace(',', '.'))
                     value = float(self.rotate_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Rotate, "
-                                         "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
         self.app.worker_task.emit({'fcn': self.on_rotate_action,
         self.app.worker_task.emit({'fcn': self.on_rotate_action,
                                        'params': [value]})
                                        'params': [value]})
@@ -1111,8 +1113,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.skewx_entry.get_value().replace(',', '.'))
                     value = float(self.skewx_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Skew X, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_skew("X", value)
         # self.on_skew("X", value)
@@ -1132,8 +1134,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.skewy_entry.get_value().replace(',', '.'))
                     value = float(self.skewy_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Skew Y, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_skew("Y", value)
         # self.on_skew("Y", value)
@@ -1153,8 +1155,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     xvalue = float(self.scalex_entry.get_value().replace(',', '.'))
                     xvalue = float(self.scalex_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Scale X, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
@@ -1190,8 +1192,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     yvalue = float(self.scaley_entry.get_value().replace(',', '.'))
                     yvalue = float(self.scaley_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Scale Y, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
@@ -1222,8 +1224,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.offx_entry.get_value().replace(',', '.'))
                     value = float(self.offx_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Offset X, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_offset("X", value)
         # self.on_offset("X", value)
@@ -1243,8 +1245,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.offy_entry.get_value().replace(',', '.'))
                     value = float(self.offy_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Offset Y, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_offset("Y", value)
         # self.on_offset("Y", value)
@@ -1261,7 +1263,8 @@ class TransformEditorTool(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not shape_list:
         if not shape_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to rotate!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to rotate!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Appying Rotate")):
             with self.app.proc_container.new(_("Appying Rotate")):
@@ -1292,12 +1295,14 @@ class TransformEditorTool(FlatCAMTool):
 
 
                     # self.draw_app.transform_complete.emit()
                     # self.draw_app.transform_complete.emit()
 
 
-                    self.app.inform.emit(_("[success] Done. Rotate completed."))
+                    self.app.inform.emit('[success] %s' %
+                                         _("Done. Rotate completed."))
 
 
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, rotation movement was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Rotation action was not executed"),str(e)))
                     return
                     return
 
 
     def on_flip(self, axis):
     def on_flip(self, axis):
@@ -1308,7 +1313,8 @@ class TransformEditorTool(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not shape_list:
         if not shape_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to flip!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to flip!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Flip")):
             with self.app.proc_container.new(_("Applying Flip")):
@@ -1341,10 +1347,12 @@ class TransformEditorTool(FlatCAMTool):
                     for sha in shape_list:
                     for sha in shape_list:
                         if axis is 'X':
                         if axis is 'X':
                             sha.mirror('X', (px, py))
                             sha.mirror('X', (px, py))
-                            self.app.inform.emit(_('[success] Flip on the Y axis done ...'))
+                            self.app.inform.emit('[success] %s...' %
+                                                 _('Flip on the Y axis done'))
                         elif axis is 'Y':
                         elif axis is 'Y':
                             sha.mirror('Y', (px, py))
                             sha.mirror('Y', (px, py))
-                            self.app.inform.emit(_('[success] Flip on the X axis done ...'))
+                            self.app.inform.emit('[success] %s' %
+                                                 _('Flip on the X axis done'))
                         self.draw_app.replot()
                         self.draw_app.replot()
 
 
                     #     self.draw_app.add_shape(DrawToolShape(sha.geo))
                     #     self.draw_app.add_shape(DrawToolShape(sha.geo))
@@ -1354,7 +1362,8 @@ class TransformEditorTool(FlatCAMTool):
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Flip action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Flip action was not executed"), str(e)))
                     return
                     return
 
 
     def on_skew(self, axis, num):
     def on_skew(self, axis, num):
@@ -1363,7 +1372,8 @@ class TransformEditorTool(FlatCAMTool):
         yminlist = []
         yminlist = []
 
 
         if not shape_list:
         if not shape_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to shear/skew!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to shear/skew!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Skew")):
             with self.app.proc_container.new(_("Applying Skew")):
@@ -1390,12 +1400,17 @@ class TransformEditorTool(FlatCAMTool):
                     #     self.draw_app.add_shape(DrawToolShape(sha.geo))
                     #     self.draw_app.add_shape(DrawToolShape(sha.geo))
                     #
                     #
                     # self.draw_app.transform_complete.emit()
                     # self.draw_app.transform_complete.emit()
-
-                    self.app.inform.emit(_('[success] Skew on the %s axis done ...') % str(axis))
+                    if axis == 'X':
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Skew on the X axis done'))
+                    else:
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Skew on the Y axis done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Skew action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Skew action was not executed"), str(e)))
                     return
                     return
 
 
     def on_scale(self, axis, xfactor, yfactor, point=None):
     def on_scale(self, axis, xfactor, yfactor, point=None):
@@ -1406,7 +1421,8 @@ class TransformEditorTool(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not shape_list:
         if not shape_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to scale!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to scale!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Scale")):
             with self.app.proc_container.new(_("Applying Scale")):
@@ -1442,10 +1458,16 @@ class TransformEditorTool(FlatCAMTool):
                     #
                     #
                     # self.draw_app.transform_complete.emit()
                     # self.draw_app.transform_complete.emit()
 
 
-                    self.app.inform.emit(_('[success] Scale on the %s axis done ...') % str(axis))
+                    if str(axis) == 'X':
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Scale on the X axis done'))
+                    else:
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Scale on the Y axis done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Scale action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Scale action was not executed"), str(e)))
                     return
                     return
 
 
     def on_offset(self, axis, num):
     def on_offset(self, axis, num):
@@ -1454,7 +1476,8 @@ class TransformEditorTool(FlatCAMTool):
         yminlist = []
         yminlist = []
 
 
         if not shape_list:
         if not shape_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to offset!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to offset!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Offset")):
             with self.app.proc_container.new(_("Applying Offset")):
@@ -1468,16 +1491,22 @@ class TransformEditorTool(FlatCAMTool):
                             sha.offset((0, num))
                             sha.offset((0, num))
                         self.draw_app.replot()
                         self.draw_app.replot()
 
 
-                    self.app.inform.emit(_('[success] Offset on the %s axis done ...') % str(axis))
+                    if axis == 'X':
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Offset on the X axis done'))
+                    else:
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Offset on the Y axis done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Offset action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Offset action was not executed"), str(e)))
                     return
                     return
 
 
     def on_rotate_key(self):
     def on_rotate_key(self):
         val_box = FCInputDialog(title=_("Rotate ..."),
         val_box = FCInputDialog(title=_("Rotate ..."),
-                                text=_('Enter an Angle Value (degrees):'),
+                                text='%s:' % _('Enter an Angle Value (degrees)'),
                                 min=-359.9999, max=360.0000, decimals=4,
                                 min=-359.9999, max=360.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_rotate']))
                                 init_val=float(self.app.defaults['tools_transform_rotate']))
         val_box.setWindowIcon(QtGui.QIcon('share/rotate.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/rotate.png'))
@@ -1485,20 +1514,18 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_rotate(val=val)
             self.on_rotate(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape rotate done...")
-                )
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape rotate done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape rotate cancelled...")
-                )
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Geometry shape rotate cancelled"))
 
 
     def on_offx_key(self):
     def on_offx_key(self):
         units = self.app.ui.general_defaults_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 ..."),
         val_box = FCInputDialog(title=_("Offset on X axis ..."),
-                                text=(_('Enter a distance Value (%s):') % str(units)),
+                                text='%s: (%s)' % (_('Enter a distance Value'), str(units)),
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_offset_x']))
                                 init_val=float(self.app.defaults['tools_transform_offset_x']))
         val_box.setWindowIcon(QtGui.QIcon('share/offsetx32.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/offsetx32.png'))
@@ -1506,18 +1533,18 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_offx(val=val)
             self.on_offx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape offset on X axis done..."))
+            self.app.inform.emit('[success] %s' %
+                                 _("Geometry shape offset on X axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape offset X cancelled..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Geometry shape offset X cancelled"))
 
 
     def on_offy_key(self):
     def on_offy_key(self):
         units = self.app.ui.general_defaults_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 ..."),
         val_box = FCInputDialog(title=_("Offset on Y axis ..."),
-                                text=(_('Enter a distance Value (%s):') % str(units)),
+                                text='%s: (%s)' % (_('Enter a distance Value'), str(units)),
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_offset_y']))
                                 init_val=float(self.app.defaults['tools_transform_offset_y']))
         val_box.setWindowIcon(QtGui.QIcon('share/offsety32.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/offsety32.png'))
@@ -1525,16 +1552,16 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_offx(val=val)
             self.on_offx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape offset on Y axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape offset on Y axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape offset Y cancelled..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape offset on Y axis canceled"))
 
 
     def on_skewx_key(self):
     def on_skewx_key(self):
         val_box = FCInputDialog(title=_("Skew on X axis ..."),
         val_box = FCInputDialog(title=_("Skew on X axis ..."),
-                                text=_('Enter an Angle Value (degrees):'),
+                                text='%s:' % _('Enter an Angle Value (degrees)'),
                                 min=-359.9999, max=360.0000, decimals=4,
                                 min=-359.9999, max=360.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_skew_x']))
                                 init_val=float(self.app.defaults['tools_transform_skew_x']))
         val_box.setWindowIcon(QtGui.QIcon('share/skewX.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/skewX.png'))
@@ -1542,16 +1569,16 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_skewx(val=val)
             self.on_skewx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape skew on X axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape skew on X axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-               _("[WARNING_NOTCL] Geometry shape skew X cancelled..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape skew on X axis canceled"))
 
 
     def on_skewy_key(self):
     def on_skewy_key(self):
         val_box = FCInputDialog(title=_("Skew on Y axis ..."),
         val_box = FCInputDialog(title=_("Skew on Y axis ..."),
-                                text=_('Enter an Angle Value (degrees):'),
+                                text='%s:' % _('Enter an Angle Value (degrees)'),
                                 min=-359.9999, max=360.0000, decimals=4,
                                 min=-359.9999, max=360.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_skew_y']))
                                 init_val=float(self.app.defaults['tools_transform_skew_y']))
         val_box.setWindowIcon(QtGui.QIcon('share/skewY.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/skewY.png'))
@@ -1559,12 +1586,12 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_skewx(val=val)
             self.on_skewx(val=val)
-            self.app.inform.emit(
-               _("[success] Geometry shape skew on Y axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape skew on Y axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape skew Y cancelled..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape skew on Y axis canceled"))
 
 
 
 
 class DrawToolShape(object):
 class DrawToolShape(object):
@@ -1964,7 +1991,8 @@ class FCCircle(FCShapeTool):
         radius = distance(p1, p2)
         radius = distance(p1, p2)
         self.geometry = DrawToolShape(Point(p1).buffer(radius, int(self.steps_per_circ / 4)))
         self.geometry = DrawToolShape(Point(p1).buffer(radius, int(self.steps_per_circ / 4)))
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Adding Circle completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Adding Circle completed."))
 
 
 
 
 class FCArc(FCShapeTool):
 class FCArc(FCShapeTool):
@@ -2178,7 +2206,8 @@ class FCArc(FCShapeTool):
             self.geometry = DrawToolShape(LineString(arc(center, radius, startangle, stopangle,
             self.geometry = DrawToolShape(LineString(arc(center, radius, startangle, stopangle,
                                                          self.direction, self.steps_per_circ)))
                                                          self.direction, self.steps_per_circ)))
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Arc completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Arc completed."))
 
 
 
 
 class FCRectangle(FCShapeTool):
 class FCRectangle(FCShapeTool):
@@ -2231,7 +2260,8 @@ class FCRectangle(FCShapeTool):
         # self.geometry = LinearRing([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])])
         # self.geometry = LinearRing([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])])
         self.geometry = DrawToolShape(Polygon([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])]))
         self.geometry = DrawToolShape(Polygon([p1, (p2[0], p1[1]), p2, (p1[0], p2[1])]))
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Rectangle completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Rectangle completed."))
 
 
 
 
 class FCPolygon(FCShapeTool):
 class FCPolygon(FCShapeTool):
@@ -2285,7 +2315,8 @@ class FCPolygon(FCShapeTool):
         self.geometry = DrawToolShape(Polygon(self.points))
         self.geometry = DrawToolShape(Polygon(self.points))
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Polygon completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Polygon completed."))
 
 
     def on_key(self, key):
     def on_key(self, key):
         if key == 'Backspace' or key == QtCore.Qt.Key_Backspace:
         if key == 'Backspace' or key == QtCore.Qt.Key_Backspace:
@@ -2440,7 +2471,8 @@ class FCMove(FCShapeTool):
         self.selection_shape = self.selection_bbox()
         self.selection_shape = self.selection_bbox()
 
 
         if len(self.draw_app.get_selected()) == 0:
         if len(self.draw_app.get_selected()) == 0:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] MOVE: No shape selected. Select a shape to move ..."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                          _("MOVE: No shape selected. Select a shape to move"))
         else:
         else:
             self.draw_app.app.inform.emit(_(" MOVE: Click on reference point ..."))
             self.draw_app.app.inform.emit(_(" MOVE: Click on reference point ..."))
 
 
@@ -2479,7 +2511,8 @@ class FCMove(FCShapeTool):
             # Delete old
             # Delete old
             self.draw_app.delete_selected()
             self.draw_app.delete_selected()
             self.complete = True
             self.complete = True
-            self.draw_app.app.inform.emit(_("[success] Done. Geometry(s) Move completed."))
+            self.draw_app.app.inform.emit('[success] %s' %
+                                          _("Done. Geometry(s) Move completed."))
 
 
     def selection_bbox(self):
     def selection_bbox(self):
         geo_list = []
         geo_list = []
@@ -2599,7 +2632,8 @@ class FCCopy(FCMove):
         self.geometry = [DrawToolShape(affinity.translate(geom.geo, xoff=dx, yoff=dy))
         self.geometry = [DrawToolShape(affinity.translate(geom.geo, xoff=dx, yoff=dy))
                          for geom in self.draw_app.get_selected()]
                          for geom in self.draw_app.get_selected()]
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Geometry(s) Copy completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Geometry(s) Copy completed."))
 
 
 
 
 class FCText(FCShapeTool):
 class FCText(FCShapeTool):
@@ -2635,20 +2669,23 @@ class FCText(FCShapeTool):
                 self.geometry = DrawToolShape(affinity.translate(self.text_gui.text_path, xoff=dx, yoff=dy))
                 self.geometry = DrawToolShape(affinity.translate(self.text_gui.text_path, xoff=dx, yoff=dy))
             except Exception as e:
             except Exception as e:
                 log.debug("Font geometry is empty or incorrect: %s" % str(e))
                 log.debug("Font geometry is empty or incorrect: %s" % str(e))
-                self.draw_app.app.inform.emit(_("[ERROR]Font not supported. Only Regular, Bold, Italic and BoldItalic are "
-                                              "supported. Error: %s") % str(e))
+                self.draw_app.app.inform.emit('[ERROR] %s: %s' %
+                                              (_("Font not supported. Only Regular, Bold, Italic and BoldItalic are "
+                                              "supported. Error"), str(e)))
                 self.text_gui.text_path = []
                 self.text_gui.text_path = []
                 self.text_gui.hide_tool()
                 self.text_gui.hide_tool()
                 self.draw_app.select_tool('select')
                 self.draw_app.select_tool('select')
                 return
                 return
         else:
         else:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] No text to add."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("No text to add."))
             return
             return
 
 
         self.text_gui.text_path = []
         self.text_gui.text_path = []
         self.text_gui.hide_tool()
         self.text_gui.hide_tool()
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Adding Text completed."))
+        self.draw_app.app.inform.emit('[success]%s' %
+                                      _(" Done. Adding Text completed."))
 
 
     def utility_geometry(self, data=None):
     def utility_geometry(self, data=None):
         """
         """
@@ -2687,7 +2724,8 @@ class FCBuffer(FCShapeTool):
 
 
     def on_buffer(self):
     def on_buffer(self):
         if not self.draw_app.selected:
         if not self.draw_app.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Buffer cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Buffer cancelled. No shape selected."))
             return
             return
 
 
         try:
         try:
@@ -2698,8 +2736,8 @@ class FCBuffer(FCShapeTool):
                 buffer_distance = float(self.buff_tool.buffer_distance_entry.get_value().replace(',', '.'))
                 buffer_distance = float(self.buff_tool.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buff_tool.buffer_distance_entry.set_value(buffer_distance)
                 self.buff_tool.buffer_distance_entry.set_value(buffer_distance)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                     "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
@@ -2711,11 +2749,13 @@ class FCBuffer(FCShapeTool):
         self.disactivate()
         self.disactivate()
         if ret_val == 'fail':
         if ret_val == 'fail':
             return
             return
-        self.draw_app.app.inform.emit(_("[success] Done. Buffer Tool completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Buffer Tool completed."))
 
 
     def on_buffer_int(self):
     def on_buffer_int(self):
         if not self.draw_app.selected:
         if not self.draw_app.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Buffer cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Buffer cancelled. No shape selected."))
             return
             return
 
 
         try:
         try:
@@ -2726,8 +2766,8 @@ class FCBuffer(FCShapeTool):
                 buffer_distance = float(self.buff_tool.buffer_distance_entry.get_value().replace(',', '.'))
                 buffer_distance = float(self.buff_tool.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buff_tool.buffer_distance_entry.set_value(buffer_distance)
                 self.buff_tool.buffer_distance_entry.set_value(buffer_distance)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                     "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
@@ -2739,11 +2779,13 @@ class FCBuffer(FCShapeTool):
         self.disactivate()
         self.disactivate()
         if ret_val == 'fail':
         if ret_val == 'fail':
             return
             return
-        self.draw_app.app.inform.emit(_("[success] Done. Buffer Int Tool completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Buffer Int Tool completed."))
 
 
     def on_buffer_ext(self):
     def on_buffer_ext(self):
         if not self.draw_app.selected:
         if not self.draw_app.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Buffer cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Buffer cancelled. No shape selected."))
             return
             return
 
 
         try:
         try:
@@ -2754,8 +2796,8 @@ class FCBuffer(FCShapeTool):
                 buffer_distance = float(self.buff_tool.buffer_distance_entry.get_value().replace(',', '.'))
                 buffer_distance = float(self.buff_tool.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buff_tool.buffer_distance_entry.set_value(buffer_distance)
                 self.buff_tool.buffer_distance_entry.set_value(buffer_distance)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                     "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
@@ -2767,7 +2809,8 @@ class FCBuffer(FCShapeTool):
         self.disactivate()
         self.disactivate()
         if ret_val == 'fail':
         if ret_val == 'fail':
             return
             return
-        self.draw_app.app.inform.emit(_("[success] Done. Buffer Ext Tool completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Buffer Ext Tool completed."))
 
 
     def activate(self):
     def activate(self):
         self.buff_tool.buffer_button.clicked.disconnect()
         self.buff_tool.buffer_button.clicked.disconnect()
@@ -2862,7 +2905,8 @@ class FCEraser(FCShapeTool):
 
 
         self.draw_app.delete_utility_geometry()
         self.draw_app.delete_utility_geometry()
         self.draw_app.plot_all()
         self.draw_app.plot_all()
-        self.draw_app.app.inform.emit(_("[success] Done. Eraser tool action completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Eraser tool action completed."))
 
 
     def utility_geometry(self, data=None):
     def utility_geometry(self, data=None):
         """
         """
@@ -3497,8 +3541,13 @@ class FlatCAMGeoEditor(QtCore.QObject):
         if multigeo_tool:
         if multigeo_tool:
             self.multigeo_tool = multigeo_tool
             self.multigeo_tool = multigeo_tool
             geo_to_edit = fcgeometry.flatten(geometry=fcgeometry.tools[self.multigeo_tool]['solid_geometry'])
             geo_to_edit = fcgeometry.flatten(geometry=fcgeometry.tools[self.multigeo_tool]['solid_geometry'])
-            self.app.inform.emit(_("[WARNING_NOTCL] Editing MultiGeo Geometry, tool: {tool} with diameter: {dia}").
-                                 format(tool=self.multigeo_tool, dia=fcgeometry.tools[self.multigeo_tool]['tooldia']))
+            self.app.inform.emit('[WARNING_NOTCL] %s: %s %s: %s' %
+                                 (_("Editing MultiGeo Geometry, tool"),
+                                 str(self.multigeo_tool),
+                                 _("with diameter"),
+                                 str(fcgeometry.tools[self.multigeo_tool]['tooldia'])
+                                 )
+                                 )
         else:
         else:
             geo_to_edit = fcgeometry.flatten()
             geo_to_edit = fcgeometry.flatten()
 
 
@@ -3738,7 +3787,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
                             self.active_tool.complete = True
                             self.active_tool.complete = True
                             self.in_action = False
                             self.in_action = False
                             self.delete_utility_geometry()
                             self.delete_utility_geometry()
-                            self.app.inform.emit(_("[success] Done."))
+                            self.app.inform.emit('[success] %s' %
+                                                 _("Done."))
                             self.select_tool('select')
                             self.select_tool('select')
                         else:
                         else:
                             self.app.cursor = QtGui.QCursor()
                             self.app.cursor = QtGui.QCursor()
@@ -3752,7 +3802,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
                             self.active_tool.make()
                             self.active_tool.make()
                             if self.active_tool.complete:
                             if self.active_tool.complete:
                                 self.on_shape_complete()
                                 self.on_shape_complete()
-                                self.app.inform.emit(_("[success] Done."))
+                                self.app.inform.emit('[success] %s' %
+                                                     _("Done."))
                                 self.select_tool(self.active_tool.name)
                                 self.select_tool(self.active_tool.name)
         except Exception as e:
         except Exception as e:
             log.warning("Error: %s" % str(e))
             log.warning("Error: %s" % str(e))
@@ -3869,7 +3920,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
 
 
     def on_copy_click(self):
     def on_copy_click(self):
         if not self.selected:
         if not self.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Copy cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Copy cancelled. No shape selected."))
             return
             return
 
 
         self.app.ui.geo_copy_btn.setChecked(True)
         self.app.ui.geo_copy_btn.setChecked(True)
@@ -4119,8 +4171,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
             results = geo_shapes[0].geo
             results = geo_shapes[0].geo
         except Exception as e:
         except Exception as e:
             log.debug("FlatCAMGeoEditor.intersection() --> %s" % str(e))
             log.debug("FlatCAMGeoEditor.intersection() --> %s" % str(e))
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] A selection of at least 2 geo items is required to do Intersection."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("A selection of at least 2 geo items is required to do Intersection."))
             self.select_tool('select')
             self.select_tool('select')
             return
             return
 
 
@@ -4154,8 +4206,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
             intersector = geo_shapes[0].geo
             intersector = geo_shapes[0].geo
         except Exception as e:
         except Exception as e:
             log.debug("FlatCAMGeoEditor.intersection() --> %s" % str(e))
             log.debug("FlatCAMGeoEditor.intersection() --> %s" % str(e))
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] A selection of at least 2 geo items is required to do Intersection."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("A selection of at least 2 geo items is required to do Intersection."))
             self.select_tool('select')
             self.select_tool('select')
             return
             return
 
 
@@ -4240,9 +4292,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
         selected = self.get_selected()
         selected = self.get_selected()
 
 
         if buf_distance < 0:
         if buf_distance < 0:
-            self.app.inform.emit(
-               _("[ERROR_NOTCL] Negative buffer value is not accepted. "
-                 "Use Buffer interior to generate an 'inside' shape"))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Negative buffer value is not accepted. Use Buffer interior to generate an "
+                                   "'inside' shape"))
 
 
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
@@ -4250,11 +4302,13 @@ class FlatCAMGeoEditor(QtCore.QObject):
             return 'fail'
             return 'fail'
 
 
         if len(selected) == 0:
         if len(selected) == 0:
-            self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Nothing selected for buffering."))
             return 'fail'
             return 'fail'
 
 
         if not isinstance(buf_distance, float):
         if not isinstance(buf_distance, float):
-            self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Invalid distance for buffering."))
 
 
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
@@ -4277,7 +4331,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
                 )
                 )
 
 
         if not results:
         if not results:
-            self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a different buffer value."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Failed, the result is empty. Choose a different buffer value."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
@@ -4287,14 +4342,15 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.add_shape(DrawToolShape(sha))
             self.add_shape(DrawToolShape(sha))
 
 
         self.replot()
         self.replot()
-        self.app.inform.emit(_("[success] Full buffer geometry created."))
+        self.app.inform.emit('[success] %s' %
+                             _("Full buffer geometry created."))
 
 
     def buffer_int(self, buf_distance, join_style):
     def buffer_int(self, buf_distance, join_style):
         selected = self.get_selected()
         selected = self.get_selected()
 
 
         if buf_distance < 0:
         if buf_distance < 0:
-            self.app.inform.emit(
-                _("[ERROR_NOTCL] Negative buffer value is not accepted.")
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Negative buffer value is not accepted.")
             )
             )
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
@@ -4302,11 +4358,13 @@ class FlatCAMGeoEditor(QtCore.QObject):
             return 'fail'
             return 'fail'
 
 
         if len(selected) == 0:
         if len(selected) == 0:
-            self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Nothing selected for buffering."))
             return 'fail'
             return 'fail'
 
 
         if not isinstance(buf_distance, float):
         if not isinstance(buf_distance, float):
-            self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Invalid distance for buffering."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
@@ -4325,7 +4383,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
                 )
                 )
 
 
         if not results:
         if not results:
-            self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a smaller buffer value."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Failed, the result is empty. Choose a smaller buffer value."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
@@ -4335,25 +4394,29 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.add_shape(DrawToolShape(sha))
             self.add_shape(DrawToolShape(sha))
 
 
         self.replot()
         self.replot()
-        self.app.inform.emit(_("[success] Interior buffer geometry created."))
+        self.app.inform.emit('[success] %s' %
+                             _("Interior buffer geometry created."))
 
 
     def buffer_ext(self, buf_distance, join_style):
     def buffer_ext(self, buf_distance, join_style):
         selected = self.get_selected()
         selected = self.get_selected()
 
 
         if buf_distance < 0:
         if buf_distance < 0:
-            self.app.inform.emit(_("[ERROR_NOTCL] Negative buffer value is not accepted. "
-                                   "Use Buffer interior to generate an 'inside' shape"))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Negative buffer value is not accepted. Use Buffer interior to generate an "
+                                   "'inside' shape"))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
             return
             return
 
 
         if len(selected) == 0:
         if len(selected) == 0:
-            self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Nothing selected for buffering."))
             return
             return
 
 
         if not isinstance(buf_distance, float):
         if not isinstance(buf_distance, float):
-            self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Invalid distance for buffering."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
@@ -4372,7 +4435,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
                 )
                 )
 
 
         if not results:
         if not results:
-            self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a different buffer value."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Failed, the result is empty. Choose a different buffer value."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
@@ -4382,7 +4446,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.add_shape(DrawToolShape(sha))
             self.add_shape(DrawToolShape(sha))
 
 
         self.replot()
         self.replot()
-        self.app.inform.emit(_("[success] Exterior buffer geometry created."))
+        self.app.inform.emit('[success] %s' %
+                             _("Exterior buffer geometry created."))
 
 
     # def paint(self, tooldia, overlap, margin, method):
     # def paint(self, tooldia, overlap, margin, method):
     #     selected = self.get_selected()
     #     selected = self.get_selected()
@@ -4446,19 +4511,21 @@ class FlatCAMGeoEditor(QtCore.QObject):
         selected = self.get_selected()
         selected = self.get_selected()
 
 
         if len(selected) == 0:
         if len(selected) == 0:
-            self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for painting."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Nothing selected for painting."))
             return
             return
 
 
         for param in [tooldia, overlap, margin]:
         for param in [tooldia, overlap, margin]:
             if not isinstance(param, float):
             if not isinstance(param, float):
                 param_name = [k for k, v in locals().items() if v is param][0]
                 param_name = [k for k, v in locals().items() if v is param][0]
-                self.app.inform.emit(_("[WARNING] Invalid value for {}").format(param))
+                self.app.inform.emit('[WARNING] %s: %s' %
+                                     (_("Invalid value for"), str(param)))
 
 
         results = []
         results = []
 
 
         if overlap >= 1:
         if overlap >= 1:
-            self.app.inform.emit(
-                _("[ERROR_NOTCL] Could not do Paint. Overlap value has to be less than 1.00 (100%)."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Could not do Paint. Overlap value has to be less than 1.00 (100%%)."))
             return
             return
 
 
         def recurse(geometry, reset=True):
         def recurse(geometry, reset=True):
@@ -4516,8 +4583,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
                         local_results += list(cp.get_objects())
                         local_results += list(cp.get_objects())
                 except Exception as e:
                 except Exception as e:
                     log.debug("Could not Paint the polygons. %s" % str(e))
                     log.debug("Could not Paint the polygons. %s" % str(e))
-                    self.app.inform.emit(
-                        _("[ERROR] Could not do Paint. Try a different combination of parameters. "
+                    self.app.inform.emit('[ERROR] %s' %
+                                         _("Could not do Paint. Try a different combination of parameters. "
                           "Or a different method of Paint\n%s") % str(e))
                           "Or a different method of Paint\n%s") % str(e))
                     return
                     return
 
 

+ 182 - 123
flatcamEditors/FlatCAMGrbEditor.py

@@ -204,14 +204,15 @@ class FCPad(FCShapeTool):
         try:
         try:
             self.radius = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size']) / 2
             self.radius = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size']) / 2
         except KeyError:
         except KeyError:
-            self.draw_app.app.inform.emit(_(
-                "[WARNING_NOTCL] To add an Pad first select a aperture in Aperture Table"))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("To add an Pad first select a aperture in Aperture Table"))
             self.draw_app.in_action = False
             self.draw_app.in_action = False
             self.complete = True
             self.complete = True
             return
             return
 
 
         if self.radius == 0:
         if self.radius == 0:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Aperture size is zero. It needs to be greater than zero."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("Aperture size is zero. It needs to be greater than zero."))
             self.dont_execute = True
             self.dont_execute = True
             return
             return
         else:
         else:
@@ -374,7 +375,8 @@ class FCPad(FCShapeTool):
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Adding Pad completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Adding Pad completed."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -395,15 +397,16 @@ class FCPadArray(FCShapeTool):
         try:
         try:
             self.radius = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size']) / 2
             self.radius = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size']) / 2
         except KeyError:
         except KeyError:
-            self.draw_app.app.inform.emit(_(
-                "[WARNING_NOTCL] To add an Pad Array first select a aperture in Aperture Table"))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("To add an Pad Array first select a aperture in Aperture Table"))
             self.complete = True
             self.complete = True
             self.draw_app.in_action = False
             self.draw_app.in_action = False
             self.draw_app.array_frame.hide()
             self.draw_app.array_frame.hide()
             return
             return
 
 
         if self.radius == 0:
         if self.radius == 0:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Aperture size is zero. It needs to be greater than zero."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("Aperture size is zero. It needs to be greater than zero."))
             self.dont_execute = True
             self.dont_execute = True
             return
             return
         else:
         else:
@@ -498,11 +501,12 @@ class FCPadArray(FCShapeTool):
                 self.pad_linear_angle = float(self.draw_app.linear_angle_spinner.get_value())
                 self.pad_linear_angle = float(self.draw_app.linear_angle_spinner.get_value())
                 self.pad_angle = float(self.draw_app.pad_angle_entry.get_value())
                 self.pad_angle = float(self.draw_app.pad_angle_entry.get_value())
             except TypeError:
             except TypeError:
-                self.draw_app.app.inform.emit(
-                    _("[ERROR_NOTCL] The value is not Float. Check for comma instead of dot separator."))
+                self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                              _("The value is not Float. Check for comma instead of dot separator."))
                 return
                 return
         except Exception as e:
         except Exception as e:
-            self.draw_app.app.inform.emit(_("[ERROR_NOTCL] The value is mistyped. Check the value."))
+            self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                          _("The value is mistyped. Check the value."))
             return
             return
 
 
         if self.pad_array == 'Linear':
         if self.pad_array == 'Linear':
@@ -692,7 +696,8 @@ class FCPadArray(FCShapeTool):
                 self.geometry.append(DrawToolShape(geo))
                 self.geometry.append(DrawToolShape(geo))
         else:
         else:
             if (self.pad_angle * self.pad_array_size) > 360:
             if (self.pad_angle * self.pad_array_size) > 360:
-                self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Too many Pads for the selected spacing angle."))
+                self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                              _("Too many Pads for the selected spacing angle."))
                 return
                 return
 
 
             radius = distance(self.destination, self.origin)
             radius = distance(self.destination, self.origin)
@@ -714,7 +719,8 @@ class FCPadArray(FCShapeTool):
 
 
                 self.geometry.append(DrawToolShape(geo))
                 self.geometry.append(DrawToolShape(geo))
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Pad Array added."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Pad Array added."))
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.draw_app.array_frame.hide()
         self.draw_app.array_frame.hide()
         return
         return
@@ -746,7 +752,8 @@ class FCPoligonize(FCShapeTool):
         if not self.draw_app.selected:
         if not self.draw_app.selected:
             self.draw_app.in_action = False
             self.draw_app.in_action = False
             self.complete = True
             self.complete = True
-            self.draw_app.app.inform.emit(_("[ERROR_NOTCL] Failed. Nothing selected."))
+            self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' %
+                                          _("Failed. Nothing selected."))
             self.draw_app.select_tool("select")
             self.draw_app.select_tool("select")
             return
             return
 
 
@@ -761,8 +768,9 @@ class FCPoligonize(FCShapeTool):
         if len(apid_set) > 1:
         if len(apid_set) > 1:
             self.draw_app.in_action = False
             self.draw_app.in_action = False
             self.complete = True
             self.complete = True
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Failed. Poligonize works only on "
-                                            "geometries belonging to the same aperture."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
+                                          _("Failed. Poligonize works only on geometries belonging "
+                                            "to the same aperture."))
             self.draw_app.select_tool("select")
             self.draw_app.select_tool("select")
             return
             return
 
 
@@ -814,7 +822,8 @@ class FCPoligonize(FCShapeTool):
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done. Poligonize completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Poligonize completed."))
 
 
         # MS: always return to the Select Tool if modifier key is not pressed
         # MS: always return to the Select Tool if modifier key is not pressed
         # else return to the current tool
         # else return to the current tool
@@ -1054,7 +1063,8 @@ class FCRegion(FCShapeTool):
             self.geometry = DrawToolShape(new_geo_el)
             self.geometry = DrawToolShape(new_geo_el)
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -1157,7 +1167,8 @@ class FCTrack(FCRegion):
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -1430,7 +1441,8 @@ class FCDisc(FCShapeTool):
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -1687,7 +1699,8 @@ class FCSemiDisc(FCShapeTool):
 
 
         self.draw_app.in_action = False
         self.draw_app.in_action = False
         self.complete = True
         self.complete = True
-        self.draw_app.app.inform.emit(_("[success] Done."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -1835,7 +1848,8 @@ class FCApertureMove(FCShapeTool):
         self.selected_apertures = []
         self.selected_apertures = []
 
 
         if len(self.draw_app.get_selected()) == 0:
         if len(self.draw_app.get_selected()) == 0:
-            self.draw_app.app.inform.emit(_("[WARNING_NOTCL] Nothing selected to move ..."))
+            self.draw_app.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                          _("Nothing selected to move"))
             self.complete = True
             self.complete = True
             self.draw_app.select_tool("select")
             self.draw_app.select_tool("select")
             return
             return
@@ -1958,7 +1972,8 @@ class FCApertureMove(FCShapeTool):
 
 
         self.draw_app.plot_all()
         self.draw_app.plot_all()
         self.draw_app.build_ui()
         self.draw_app.build_ui()
-        self.draw_app.app.inform.emit(_("[success] Done. Apertures Move completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Apertures Move completed."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -2034,7 +2049,8 @@ class FCApertureCopy(FCApertureMove):
             sel_shapes_to_be_deleted = []
             sel_shapes_to_be_deleted = []
 
 
         self.draw_app.build_ui()
         self.draw_app.build_ui()
-        self.draw_app.app.inform.emit(_("[success] Done. Apertures copied."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Apertures copied."))
 
 
 
 
 class FCEraser(FCShapeTool):
 class FCEraser(FCShapeTool):
@@ -2141,7 +2157,8 @@ class FCEraser(FCShapeTool):
 
 
         self.draw_app.delete_utility_geometry()
         self.draw_app.delete_utility_geometry()
         self.draw_app.plot_all()
         self.draw_app.plot_all()
-        self.draw_app.app.inform.emit(_("[success] Done. Eraser tool action completed."))
+        self.draw_app.app.inform.emit('[success] %s' %
+                                      _("Done. Eraser tool action completed."))
 
 
     def clean_up(self):
     def clean_up(self):
         self.draw_app.selected = []
         self.draw_app.selected = []
@@ -2448,7 +2465,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
         self.apdim_entry = EvalEntry2()
         self.apdim_entry = EvalEntry2()
         grid1.addWidget(self.apdim_entry, 4, 1)
         grid1.addWidget(self.apdim_entry, 4, 1)
 
 
-        apadd_del_lbl = QtWidgets.QLabel('<b>%s</b>' % _('Add/Delete Aperture:'))
+        apadd_del_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Add/Delete Aperture'))
         apadd_del_lbl.setToolTip(
         apadd_del_lbl.setToolTip(
             _("Add/Delete an aperture in the aperture table")
             _("Add/Delete an aperture in the aperture table")
         )
         )
@@ -2481,7 +2498,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
         self.buffer_tool_frame.hide()
         self.buffer_tool_frame.hide()
 
 
         # Title
         # Title
-        buf_title_lbl = QtWidgets.QLabel('<b>%s</b>' % _('Buffer Aperture:'))
+        buf_title_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Buffer Aperture'))
         buf_title_lbl.setToolTip(
         buf_title_lbl.setToolTip(
             _("Buffer a aperture in the aperture list")
             _("Buffer a aperture in the aperture list")
         )
         )
@@ -3132,12 +3149,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
             try:
             try:
                 ap_id = str(self.apcode_entry.get_value())
                 ap_id = str(self.apcode_entry.get_value())
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Aperture code value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Aperture code value is missing or wrong format. Add it and retry."))
                 return
                 return
             if ap_id == '':
             if ap_id == '':
-                self.app.inform.emit(_("[WARNING_NOTCL] Aperture code value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Aperture code value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         if ap_id == '0':
         if ap_id == '0':
@@ -3172,7 +3189,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                     except Exception as e:
                     except Exception as e:
                         log.error("FlatCAMGrbEditor.on_aperture_add() --> the R or O aperture dims has to be in a "
                         log.error("FlatCAMGrbEditor.on_aperture_add() --> the R or O aperture dims has to be in a "
                                   "tuple format (x,y)\nError: %s" % str(e))
                                   "tuple format (x,y)\nError: %s" % str(e))
-                        self.app.inform.emit(_("[WARNING_NOTCL] Aperture dimensions value is missing or wrong format. "
+                        self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                             _("Aperture dimensions value is missing or wrong format. "
                                                "Add it in format (width, height) and retry."))
                                                "Add it in format (width, height) and retry."))
                         return
                         return
                 else:
                 else:
@@ -3184,8 +3202,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                             size_val = float(self.apsize_entry.get_value().replace(',', '.'))
                             size_val = float(self.apsize_entry.get_value().replace(',', '.'))
                             self.apsize_entry.set_value(size_val)
                             self.apsize_entry.set_value(size_val)
                         except ValueError:
                         except ValueError:
-                            self.app.inform.emit(_("[WARNING_NOTCL] Aperture size value is missing or wrong format. "
-                                                   "Add it and retry."))
+                            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                                 _("Aperture size value is missing or wrong format. Add it and retry."))
                             return
                             return
                 self.storage_dict[ap_id]['size'] = size_val
                 self.storage_dict[ap_id]['size'] = size_val
 
 
@@ -3195,14 +3213,16 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 # values  each time a aperture code is edited or added
                 # values  each time a aperture code is edited or added
                 self.olddia_newdia[ap_id] = ap_id
                 self.olddia_newdia[ap_id] = ap_id
             else:
             else:
-                self.app.inform.emit(_("[WARNING_NOTCL] Aperture already in the aperture table."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Aperture already in the aperture table."))
                 return
                 return
 
 
         # since we add a new tool, we update also the initial state of the tool_table through it's dictionary
         # since we add a new tool, we update also the initial state of the tool_table through it's dictionary
         # we add a new entry in the tool2tooldia dict
         # we add a new entry in the tool2tooldia dict
         self.tool2tooldia[len(self.olddia_newdia)] = int(ap_id)
         self.tool2tooldia[len(self.olddia_newdia)] = int(ap_id)
 
 
-        self.app.inform.emit(_("[success] Added new aperture with code: {apid}").format(apid=str(ap_id)))
+        self.app.inform.emit('[success] %s: %s' %
+                             (_("Added new aperture with code"), str(ap_id)))
 
 
         self.build_ui()
         self.build_ui()
 
 
@@ -3230,13 +3250,15 @@ class FlatCAMGrbEditor(QtCore.QObject):
             else:
             else:
                 # deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text())
                 # deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text())
                 if len(self.apertures_table.selectionModel().selectedRows()) == 0:
                 if len(self.apertures_table.selectionModel().selectedRows()) == 0:
-                    self.app.inform.emit(_("[WARNING_NOTCL] Select an aperture in Aperture Table"))
+                    self.app.inform.emit('[WARNING_NOTCL]%s' %
+                                         _(" Select an aperture in Aperture Table"))
                     return
                     return
                 for index in self.apertures_table.selectionModel().selectedRows():
                 for index in self.apertures_table.selectionModel().selectedRows():
                     row = index.row()
                     row = index.row()
                     deleted_apcode_list.append(self.apertures_table.item(row, 1).text())
                     deleted_apcode_list.append(self.apertures_table.item(row, 1).text())
         except Exception as exc:
         except Exception as exc:
-            self.app.inform.emit(_("[WARNING_NOTCL] Select an aperture in Aperture Table --> %s" % str(exc)))
+            self.app.inform.emit('[WARNING_NOTCL] %s %s' %
+                                 (_("Select an aperture in Aperture Table -->", str(exc))))
             return
             return
 
 
         if deleted_apcode_list:
         if deleted_apcode_list:
@@ -3259,8 +3281,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
 
 
                     self.olddia_newdia.pop(deleted_aperture, None)
                     self.olddia_newdia.pop(deleted_aperture, None)
 
 
-                    self.app.inform.emit(_("[success] Deleted aperture with code: {del_dia}").format(
-                        del_dia=str(deleted_aperture)))
+                    self.app.inform.emit('[success] %s: %s' %
+                                         (_("Deleted aperture with code"), str(deleted_aperture)))
 
 
         self.plot_all()
         self.plot_all()
         self.build_ui()
         self.build_ui()
@@ -3910,11 +3932,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
             try:
             try:
                 grb_obj.create_geometry()
                 grb_obj.create_geometry()
             except KeyError:
             except KeyError:
-                self.app.inform.emit(
-                   _("[ERROR_NOTCL] There are no Aperture definitions in the file. Aborting Gerber creation.")
-                )
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("There are no Aperture definitions in the file. Aborting Gerber creation."))
             except Exception as e:
             except Exception as e:
-                msg = _("[ERROR] An internal error has occurred. See shell.\n")
+                msg = '[ERROR] %s' % \
+                      _("An internal error has occurred. See shell.\n")
                 msg += traceback.format_exc()
                 msg += traceback.format_exc()
                 app_obj.inform.emit(msg)
                 app_obj.inform.emit(msg)
                 raise
                 raise
@@ -3927,7 +3949,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 self.app.progress.emit(100)
                 self.app.progress.emit(100)
                 return
                 return
 
 
-            self.app.inform.emit(_("[success] Gerber editing finished."))
+            self.app.inform.emit('[success] %s' %
+                                 _("Done. Gerber editing finished."))
 
 
     def on_tool_select(self, tool):
     def on_tool_select(self, tool):
         """
         """
@@ -3943,7 +3966,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
             # self.draw_app.select_tool('select')
             # self.draw_app.select_tool('select')
             self.complete = True
             self.complete = True
             current_tool = 'select'
             current_tool = 'select'
-            self.app.inform.emit(_("[WARNING_NOTCL] Cancelled. No aperture is selected"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Cancelled. No aperture is selected"))
 
 
         # This is to make the group behave as radio group
         # This is to make the group behave as radio group
         if current_tool in self.tools_gerber:
         if current_tool in self.tools_gerber:
@@ -4094,7 +4118,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                     self.app.clipboard.setText(
                     self.app.clipboard.setText(
                         self.app.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1])
                         self.app.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1])
                     )
                     )
-                    self.app.inform.emit(_("[success] Coordinates copied to clipboard."))
+                    self.app.inform.emit('[success] %s' %
+                                         _("Coordinates copied to clipboard."))
                     return
                     return
 
 
                 # Dispatch event to active_tool
                 # Dispatch event to active_tool
@@ -4153,7 +4178,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                             self.active_tool.complete = True
                             self.active_tool.complete = True
                             self.in_action = False
                             self.in_action = False
                             self.delete_utility_geometry()
                             self.delete_utility_geometry()
-                            self.app.inform.emit(_("[success] Done."))
+                            self.app.inform.emit('[success] %s' %
+                                                 _("Done."))
                             self.select_tool('select')
                             self.select_tool('select')
                         else:
                         else:
                             self.app.cursor = QtGui.QCursor()
                             self.app.cursor = QtGui.QCursor()
@@ -4167,7 +4193,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                             self.active_tool.make()
                             self.active_tool.make()
                             if self.active_tool.complete:
                             if self.active_tool.complete:
                                 self.on_grb_shape_complete()
                                 self.on_grb_shape_complete()
-                                self.app.inform.emit(_("[success] Done."))
+                                self.app.inform.emit('[success] %s' %
+                                                     _("Done."))
 
 
                                 # MS: always return to the Select Tool if modifier key is not pressed
                                 # MS: always return to the Select Tool if modifier key is not pressed
                                 # else return to the current tool but not for FCTrack
                                 # else return to the current tool but not for FCTrack
@@ -4474,7 +4501,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
         temp_ref = [s for s in self.selected]
         temp_ref = [s for s in self.selected]
 
 
         if len(temp_ref) == 0:
         if len(temp_ref) == 0:
-            self.app.inform.emit(_("[ERROR_NOTCL] Failed. No aperture geometry is selected."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Failed. No aperture geometry is selected."))
             return
             return
 
 
         for shape_sel in temp_ref:
         for shape_sel in temp_ref:
@@ -4482,7 +4510,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
 
 
         self.selected = []
         self.selected = []
         self.build_ui()
         self.build_ui()
-        self.app.inform.emit(_("[success] Done. Apertures geometry deleted."))
+        self.app.inform.emit('[success] %s' %
+                             _("Done. Apertures geometry deleted."))
 
 
     def delete_shape(self, geo_el):
     def delete_shape(self, geo_el):
         self.is_modified = True
         self.is_modified = True
@@ -4596,8 +4625,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 buff_value = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 buff_value = float(self.buffer_distance_entry.get_value().replace(',', '.'))
                 self.buffer_distance_entry.set_value(buff_value)
                 self.buffer_distance_entry.set_value(buff_value)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Buffer distance value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Buffer distance value is missing or wrong format. Add it and retry."))
                 return
                 return
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (which is really an INT)
@@ -4624,9 +4653,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                     return geom_el
                     return geom_el
 
 
         if not self.apertures_table.selectedItems():
         if not self.apertures_table.selectedItems():
-            self.app.inform.emit(_(
-                "[WARNING_NOTCL] No aperture to buffer. Select at least one aperture and try again."
-            ))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No aperture to buffer. Select at least one aperture and try again."))
             return
             return
 
 
         for x in self.apertures_table.selectedItems():
         for x in self.apertures_table.selectedItems():
@@ -4638,10 +4666,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 self.storage_dict[apid]['geometry'] = temp_storage
                 self.storage_dict[apid]['geometry'] = temp_storage
             except Exception as e:
             except Exception as e:
                 log.debug("FlatCAMGrbEditor.buffer() --> %s\n%s" % str(e))
                 log.debug("FlatCAMGrbEditor.buffer() --> %s\n%s" % str(e))
-                self.app.inform.emit(_("[ERROR_NOTCL] Failed.\n%s") % str(traceback.print_exc()))
+                self.app.inform.emit('[ERROR_NOTCL] %s\n%s' %
+                                     (_("Failed."), str(traceback.print_exc())))
                 return
                 return
         self.plot_all()
         self.plot_all()
-        self.app.inform.emit(_("[success] Done. Buffer Tool completed."))
+        self.app.inform.emit('[success] %s' %
+                             _("Done. Buffer Tool completed."))
 
 
     def on_scale(self):
     def on_scale(self):
         scale_factor = 1.0
         scale_factor = 1.0
@@ -4655,8 +4685,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 scale_factor = float(self.scale_factor_entry.get_value().replace(',', '.'))
                 scale_factor = float(self.scale_factor_entry.get_value().replace(',', '.'))
                 self.scale_factor_entry.set_value(scale_factor)
                 self.scale_factor_entry.set_value(scale_factor)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Scale factor value is missing or wrong format. "
-                                     "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Scale factor value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         def scale_recursion(geom_el, selection):
         def scale_recursion(geom_el, selection):
@@ -4687,9 +4717,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                     return geom_el
                     return geom_el
 
 
         if not self.apertures_table.selectedItems():
         if not self.apertures_table.selectedItems():
-            self.app.inform.emit(_(
-                "[WARNING_NOTCL] No aperture to scale. Select at least one aperture and try again."
-            ))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No aperture to scale. Select at least one aperture and try again."))
             return
             return
 
 
         for x in self.apertures_table.selectedItems():
         for x in self.apertures_table.selectedItems():
@@ -4704,7 +4733,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 log.debug("FlatCAMGrbEditor.on_scale() --> %s" % str(e))
                 log.debug("FlatCAMGrbEditor.on_scale() --> %s" % str(e))
 
 
         self.plot_all()
         self.plot_all()
-        self.app.inform.emit(_("[success] Done. Scale Tool completed."))
+        self.app.inform.emit('[success] %s' %
+                             _("Done. Scale Tool completed."))
 
 
     def on_markarea(self):
     def on_markarea(self):
         # clear previous marking
         # clear previous marking
@@ -4741,9 +4771,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
             self.ma_annotation.set(text=text, pos=position, visible=True,
             self.ma_annotation.set(text=text, pos=position, visible=True,
                                    font_size=self.app.defaults["cncjob_annotation_fontsize"],
                                    font_size=self.app.defaults["cncjob_annotation_fontsize"],
                                    color=self.app.defaults["global_sel_draw_color"])
                                    color=self.app.defaults["global_sel_draw_color"])
-            self.app.inform.emit(_("[success] Polygon areas marked."))
+            self.app.inform.emit('[success] %s' %
+                                 _("Polygon areas marked."))
         else:
         else:
-            self.app.inform.emit(_("[WARNING_NOTCL] There are no polygons to mark area."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("There are no polygons to mark area."))
 
 
     def on_eraser(self):
     def on_eraser(self):
         self.select_tool('eraser')
         self.select_tool('eraser')
@@ -5226,7 +5258,8 @@ class TransformEditorTool(FlatCAMTool):
 
 
     def template(self):
     def template(self):
         if not self.fcdraw.selected:
         if not self.fcdraw.selected:
-            self.app.inform.emit(_("[WARNING_NOTCL] Transformation cancelled. No shape selected."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Transformation cancelled. No shape selected."))
             return
             return
 
 
         self.draw_app.select_tool("select")
         self.draw_app.select_tool("select")
@@ -5246,8 +5279,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.rotate_entry.get_value().replace(',', '.'))
                     value = float(self.rotate_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Rotate, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
         self.app.worker_task.emit({'fcn': self.on_rotate_action,
         self.app.worker_task.emit({'fcn': self.on_rotate_action,
                                    'params': [value]})
                                    'params': [value]})
@@ -5289,8 +5322,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.skewx_entry.get_value().replace(',', '.'))
                     value = float(self.skewx_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Skew X, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_skew("X", value)
         # self.on_skew("X", value)
@@ -5316,8 +5349,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.skewy_entry.get_value().replace(',', '.'))
                     value = float(self.skewy_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Skew Y, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_skew("Y", value)
         # self.on_skew("Y", value)
@@ -5343,8 +5376,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     x_value = float(self.scalex_entry.get_value().replace(',', '.'))
                     x_value = float(self.scalex_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Scale X, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
@@ -5384,8 +5417,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     y_value = float(self.scaley_entry.get_value().replace(',', '.'))
                     y_value = float(self.scaley_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Scale Y, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
@@ -5422,8 +5455,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.offx_entry.get_value().replace(',', '.'))
                     value = float(self.offx_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Offset X, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_offset("X", value)
         # self.on_offset("X", value)
@@ -5448,8 +5481,8 @@ class TransformEditorTool(FlatCAMTool):
                 try:
                 try:
                     value = float(self.offy_entry.get_value().replace(',', '.'))
                     value = float(self.offy_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Offset Y, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
         # self.on_offset("Y", value)
         # self.on_offset("Y", value)
@@ -5471,7 +5504,8 @@ class TransformEditorTool(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not elem_list:
         if not elem_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to rotate!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to rotate!"))
             return
             return
 
 
         with self.app.proc_container.new(_("Appying Rotate")):
         with self.app.proc_container.new(_("Appying Rotate")):
@@ -5507,10 +5541,12 @@ class TransformEditorTool(FlatCAMTool):
                         sel_el['clear'] = affinity.rotate(sel_el['clear'], angle=-num, origin=(px, py))
                         sel_el['clear'] = affinity.rotate(sel_el['clear'], angle=-num, origin=(px, py))
                 self.draw_app.plot_all()
                 self.draw_app.plot_all()
 
 
-                self.app.inform.emit(_("[success] Done. Rotate completed."))
+                self.app.inform.emit('[success] %s' %
+                                     _("Done. Rotate completed."))
                 self.app.progress.emit(100)
                 self.app.progress.emit(100)
             except Exception as e:
             except Exception as e:
-                self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, rotation movement was not executed.") % str(e))
+                self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                     (_("Rotation action was not executed."), str(e)))
                 return
                 return
 
 
     def on_flip(self, axis):
     def on_flip(self, axis):
@@ -5526,7 +5562,8 @@ class TransformEditorTool(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not elem_list:
         if not elem_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to flip!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to flip!"))
             return
             return
 
 
         with self.app.proc_container.new(_("Applying Flip")):
         with self.app.proc_container.new(_("Applying Flip")):
@@ -5568,7 +5605,8 @@ class TransformEditorTool(FlatCAMTool):
                             sel_el['follow'] = affinity.scale(sel_el['follow'], xfact=1, yfact=-1, origin=(px, py))
                             sel_el['follow'] = affinity.scale(sel_el['follow'], xfact=1, yfact=-1, origin=(px, py))
                         if 'clear' in sel_el:
                         if 'clear' in sel_el:
                             sel_el['clear'] = affinity.scale(sel_el['clear'], xfact=1, yfact=-1, origin=(px, py))
                             sel_el['clear'] = affinity.scale(sel_el['clear'], xfact=1, yfact=-1, origin=(px, py))
-                        self.app.inform.emit(_('[success] Flip on the Y axis done ...'))
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Flip on the Y axis done'))
                     elif axis is 'Y':
                     elif axis is 'Y':
                         if 'solid' in sel_el:
                         if 'solid' in sel_el:
                             sel_el['solid'] = affinity.scale(sel_el['solid'], xfact=-1, yfact=1, origin=(px, py))
                             sel_el['solid'] = affinity.scale(sel_el['solid'], xfact=-1, yfact=1, origin=(px, py))
@@ -5576,12 +5614,14 @@ class TransformEditorTool(FlatCAMTool):
                             sel_el['follow'] = affinity.scale(sel_el['follow'], xfact=-1, yfact=1, origin=(px, py))
                             sel_el['follow'] = affinity.scale(sel_el['follow'], xfact=-1, yfact=1, origin=(px, py))
                         if 'clear' in sel_el:
                         if 'clear' in sel_el:
                             sel_el['clear'] = affinity.scale(sel_el['clear'], xfact=-1, yfact=1, origin=(px, py))
                             sel_el['clear'] = affinity.scale(sel_el['clear'], xfact=-1, yfact=1, origin=(px, py))
-                        self.app.inform.emit(_('[success] Flip on the X axis done ...'))
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Flip on the X axis done'))
                 self.draw_app.plot_all()
                 self.draw_app.plot_all()
                 self.app.progress.emit(100)
                 self.app.progress.emit(100)
 
 
             except Exception as e:
             except Exception as e:
-                self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Flip action was not executed.") % str(e))
+                self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                     (_("Flip action was not executed."), str(e)))
                 return
                 return
 
 
     def on_skew(self, axis, num):
     def on_skew(self, axis, num):
@@ -5596,7 +5636,8 @@ class TransformEditorTool(FlatCAMTool):
         yminlist = []
         yminlist = []
 
 
         if not elem_list:
         if not elem_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to shear/skew!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to shear/skew!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Skew")):
             with self.app.proc_container.new(_("Applying Skew")):
@@ -5634,11 +5675,17 @@ class TransformEditorTool(FlatCAMTool):
                                 sel_el['clear'] = affinity.skew(sel_el['clear'], 0, num, origin=(xminimal, yminimal))
                                 sel_el['clear'] = affinity.skew(sel_el['clear'], 0, num, origin=(xminimal, yminimal))
                     self.draw_app.plot_all()
                     self.draw_app.plot_all()
 
 
-                    self.app.inform.emit(_('[success] Skew on the %s axis done ...') % str(axis))
+                    if str(axis) == 'X':
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Skew on the X axis done'))
+                    else:
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Skew on the Y axis done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Skew action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Skew action was not executed."), str(e)))
                     return
                     return
 
 
     def on_scale(self, axis, xfactor, yfactor, point=None):
     def on_scale(self, axis, xfactor, yfactor, point=None):
@@ -5657,7 +5704,8 @@ class TransformEditorTool(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not elem_list:
         if not elem_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to scale!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to scale!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Scale")):
             with self.app.proc_container.new(_("Applying Scale")):
@@ -5698,10 +5746,16 @@ class TransformEditorTool(FlatCAMTool):
                             sel_el['clear'] = affinity.scale(sel_el['clear'], xfactor, yfactor, origin=(px, py))
                             sel_el['clear'] = affinity.scale(sel_el['clear'], xfactor, yfactor, origin=(px, py))
                     self.draw_app.plot_all()
                     self.draw_app.plot_all()
 
 
-                    self.app.inform.emit(_('[success] Scale on the %s axis done ...') % str(axis))
+                    if str(axis) == 'X':
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Scale on the X axis done'))
+                    else:
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Scale on the Y axis done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Scale action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Scale action was not executed."), str(e)))
                     return
                     return
 
 
     def on_offset(self, axis, num):
     def on_offset(self, axis, num):
@@ -5714,7 +5768,8 @@ class TransformEditorTool(FlatCAMTool):
         elem_list = self.draw_app.selected
         elem_list = self.draw_app.selected
 
 
         if not elem_list:
         if not elem_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No shape selected. Please Select a shape to offset!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No shape selected. Please Select a shape to offset!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Offset")):
             with self.app.proc_container.new(_("Applying Offset")):
@@ -5739,16 +5794,22 @@ class TransformEditorTool(FlatCAMTool):
                                 sel_el['clear'] = affinity.translate(sel_el['clear'], 0, num)
                                 sel_el['clear'] = affinity.translate(sel_el['clear'], 0, num)
                         self.draw_app.plot_all()
                         self.draw_app.plot_all()
 
 
-                    self.app.inform.emit(_('[success] Offset on the %s axis done ...') % str(axis))
+                    if str(axis) == 'X':
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Offset on the X axis done'))
+                    else:
+                        self.app.inform.emit('[success] %s...' %
+                                             _('Offset on the Y axis done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Offset action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Offset action was not executed."), str(e)))
                     return
                     return
 
 
     def on_rotate_key(self):
     def on_rotate_key(self):
         val_box = FCInputDialog(title=_("Rotate ..."),
         val_box = FCInputDialog(title=_("Rotate ..."),
-                                text=_('Enter an Angle Value (degrees):'),
+                                text='%s:' % _('Enter an Angle Value (degrees)'),
                                 min=-359.9999, max=360.0000, decimals=4,
                                 min=-359.9999, max=360.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_rotate']))
                                 init_val=float(self.app.defaults['tools_transform_rotate']))
         val_box.setWindowIcon(QtGui.QIcon('share/rotate.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/rotate.png'))
@@ -5756,20 +5817,18 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_rotate(val=val)
             self.on_rotate(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape rotate done...")
-            )
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape rotate done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape rotate cancelled...")
-            )
+            self.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                 _("Geometry shape rotate cancelled"))
 
 
     def on_offx_key(self):
     def on_offx_key(self):
         units = self.app.ui.general_defaults_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 ..."),
         val_box = FCInputDialog(title=_("Offset on X axis ..."),
-                                text=(_('Enter a distance Value (%s):') % str(units)),
+                                text='%s: (%s)' % (_('Enter a distance Value'), str(units)),
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_offset_x']))
                                 init_val=float(self.app.defaults['tools_transform_offset_x']))
         val_box.setWindowIcon(QtGui.QIcon('share/offsetx32.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/offsetx32.png'))
@@ -5777,18 +5836,18 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_offx(val=val)
             self.on_offx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape offset on X axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape offset on X axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape offset X cancelled..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                 _("Geometry shape offset X cancelled"))
 
 
     def on_offy_key(self):
     def on_offy_key(self):
         units = self.app.ui.general_defaults_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 ..."),
         val_box = FCInputDialog(title=_("Offset on Y axis ..."),
-                                text=(_('Enter a distance Value (%s):') % str(units)),
+                                text='%s: (%s)' % (_('Enter a distance Value'), str(units)),
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 min=-9999.9999, max=10000.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_offset_y']))
                                 init_val=float(self.app.defaults['tools_transform_offset_y']))
         val_box.setWindowIcon(QtGui.QIcon('share/offsety32.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/offsety32.png'))
@@ -5796,16 +5855,16 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_offx(val=val)
             self.on_offx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape offset on Y axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape offset on Y axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape offset Y cancelled..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                 _("Geometry shape offset Y cancelled"))
 
 
     def on_skewx_key(self):
     def on_skewx_key(self):
         val_box = FCInputDialog(title=_("Skew on X axis ..."),
         val_box = FCInputDialog(title=_("Skew on X axis ..."),
-                                text=_('Enter an Angle Value (degrees):'),
+                                text='%s:' % _('Enter an Angle Value (degrees)'),
                                 min=-359.9999, max=360.0000, decimals=4,
                                 min=-359.9999, max=360.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_skew_x']))
                                 init_val=float(self.app.defaults['tools_transform_skew_x']))
         val_box.setWindowIcon(QtGui.QIcon('share/skewX.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/skewX.png'))
@@ -5813,16 +5872,16 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_skewx(val=val)
             self.on_skewx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape skew on X axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape skew on X axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape skew X cancelled..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                 _("Geometry shape skew X cancelled"))
 
 
     def on_skewy_key(self):
     def on_skewy_key(self):
         val_box = FCInputDialog(title=_("Skew on Y axis ..."),
         val_box = FCInputDialog(title=_("Skew on Y axis ..."),
-                                text=_('Enter an Angle Value (degrees):'),
+                                text='%s:' % _('Enter an Angle Value (degrees)'),
                                 min=-359.9999, max=360.0000, decimals=4,
                                 min=-359.9999, max=360.0000, decimals=4,
                                 init_val=float(self.app.defaults['tools_transform_skew_y']))
                                 init_val=float(self.app.defaults['tools_transform_skew_y']))
         val_box.setWindowIcon(QtGui.QIcon('share/skewY.png'))
         val_box.setWindowIcon(QtGui.QIcon('share/skewY.png'))
@@ -5830,12 +5889,12 @@ class TransformEditorTool(FlatCAMTool):
         val, ok = val_box.get_value()
         val, ok = val_box.get_value()
         if ok:
         if ok:
             self.on_skewx(val=val)
             self.on_skewx(val=val)
-            self.app.inform.emit(
-                _("[success] Geometry shape skew on Y axis done..."))
+            self.app.inform.emit('[success] %s...' %
+                                 _("Geometry shape skew on Y axis done"))
             return
             return
         else:
         else:
-            self.app.inform.emit(
-                _("[WARNING_NOTCL] Geometry shape skew Y cancelled..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s...' %
+                                 _("Geometry shape skew Y cancelled"))
 
 
 
 
 def get_shapely_list_bounds(geometry_list):
 def get_shapely_list_bounds(geometry_list):

+ 356 - 71
flatcamGUI/FlatCAMGUI.py

@@ -938,6 +938,16 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.tools_scroll_area = QtWidgets.QScrollArea()
         self.tools_scroll_area = QtWidgets.QScrollArea()
         self.tools_tab_lay.addWidget(self.tools_scroll_area)
         self.tools_tab_lay.addWidget(self.tools_scroll_area)
 
 
+        self.fa_tab = QtWidgets.QWidget()
+        self.fa_tab.setObjectName("fa_tab")
+        self.pref_tab_area.addTab(self.fa_tab, _("FILE ASSOCIATIONS"))
+        self.fa_tab_lay = QtWidgets.QVBoxLayout()
+        self.fa_tab_lay.setContentsMargins(2, 2, 2, 2)
+        self.fa_tab.setLayout(self.fa_tab_lay)
+
+        self.fa_scroll_area = QtWidgets.QScrollArea()
+        self.fa_tab_lay.addWidget(self.fa_scroll_area)
+
         self.pref_tab_bottom_layout = QtWidgets.QHBoxLayout()
         self.pref_tab_bottom_layout = QtWidgets.QHBoxLayout()
         self.pref_tab_bottom_layout.setAlignment(QtCore.Qt.AlignVCenter)
         self.pref_tab_bottom_layout.setAlignment(QtCore.Qt.AlignVCenter)
         self.pref_tab_layout.addLayout(self.pref_tab_bottom_layout)
         self.pref_tab_layout.addLayout(self.pref_tab_bottom_layout)
@@ -1243,7 +1253,15 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                     <tr height="20">
                     <tr height="20">
                         <td height="20"><strong>ALT+F10</strong></td>
                         <td height="20"><strong>ALT+F10</strong></td>
                         <td>&nbsp;Toggle Full Screen</td>
                         <td>&nbsp;Toggle Full Screen</td>
+                    </tr>                 
+                    <tr height="20">
+                        <td height="20">&nbsp;</td>
+                        <td>&nbsp;</td>
                     </tr>
                     </tr>
+                    <tr height="20">
+                        <td height="20"><strong>CTRL+ALT+X</strong></td>
+                        <td>&nbsp;Abort current task (gracefully)</td>
+                    </tr>                    
                     <tr height="20">
                     <tr height="20">
                         <td height="20">&nbsp;</td>
                         <td height="20">&nbsp;</td>
                         <td>&nbsp;</td>
                         <td>&nbsp;</td>
@@ -1798,6 +1816,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.activity_view = FlatCAMActivityView()
         self.activity_view = FlatCAMActivityView()
         self.infobar.addWidget(self.activity_view)
         self.infobar.addWidget(self.activity_view)
 
 
+        # ###########################################################################
+        # ####### Set the APP ICON and the WINDOW TITLE and GEOMETRY ################
+        # ###########################################################################
+
         self.app_icon = QtGui.QIcon()
         self.app_icon = QtGui.QIcon()
         self.app_icon.addFile('share/flatcam_icon16.png', QtCore.QSize(16, 16))
         self.app_icon.addFile('share/flatcam_icon16.png', QtCore.QSize(16, 16))
         self.app_icon.addFile('share/flatcam_icon24.png', QtCore.QSize(24, 24))
         self.app_icon.addFile('share/flatcam_icon24.png', QtCore.QSize(24, 24))
@@ -1848,6 +1870,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
         self.tools_defaults_form = ToolsPreferencesUI()
         self.tools_defaults_form = ToolsPreferencesUI()
+        self.fa_defaults_form = FAPreferencesUI()
 
 
         self.general_options_form = GeneralPreferencesUI()
         self.general_options_form = GeneralPreferencesUI()
         self.gerber_options_form = GerberPreferencesUI()
         self.gerber_options_form = GerberPreferencesUI()
@@ -1855,6 +1878,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_options_form = GeometryPreferencesUI()
         self.geometry_options_form = GeometryPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
         self.tools_options_form = ToolsPreferencesUI()
         self.tools_options_form = ToolsPreferencesUI()
+        self.fa_options_form = FAPreferencesUI()
 
 
         QtWidgets.qApp.installEventFilter(self)
         QtWidgets.qApp.installEventFilter(self)
 
 
@@ -1930,6 +1954,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.lock_action.triggered[bool].connect(self.lock_toolbar)
         self.lock_action.triggered[bool].connect(self.lock_toolbar)
 
 
     def eventFilter(self, obj, event):
     def eventFilter(self, obj, event):
+        # filter the ToolTips display based on a Preferences setting
         if self.general_defaults_form.general_app_group.toggle_tooltips_cb.get_value() is False:
         if self.general_defaults_form.general_app_group.toggle_tooltips_cb.get_value() is False:
             if event.type() == QtCore.QEvent.ToolTip:
             if event.type() == QtCore.QEvent.ToolTip:
                 return True
                 return True
@@ -2151,7 +2176,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
             key = event.key
             key = event.key
 
 
         if self.app.call_source == 'app':
         if self.app.call_source == 'app':
-            if modifiers == QtCore.Qt.ControlModifier:
+            if modifiers == QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier:
+                if key == QtCore.Qt.Key_X:
+                    self.app.abort_all_tasks()
+                    return
+
+            elif modifiers == QtCore.Qt.ControlModifier:
                 if key == QtCore.Qt.Key_A:
                 if key == QtCore.Qt.Key_A:
                     self.app.on_selectall()
                     self.app.on_selectall()
 
 
@@ -3123,7 +3153,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                     # ## Current application units in Upper Case
                     # ## Current application units in Upper Case
                     self.units = self.general_defaults_form.general_app_group.units_radio.get_value().upper()
                     self.units = self.general_defaults_form.general_app_group.units_radio.get_value().upper()
                     tool_add_popup = FCInputDialog(title=_("New Tool ..."),
                     tool_add_popup = FCInputDialog(title=_("New Tool ..."),
-                                                   text=_('Enter a Tool Diameter:'),
+                                                   text='%s:' % _('Enter a Tool Diameter'),
                                                    min=0.0000, max=99.9999, decimals=4)
                                                    min=0.0000, max=99.9999, decimals=4)
                     tool_add_popup.setWindowIcon(QtGui.QIcon('share/letter_t_32.png'))
                     tool_add_popup.setWindowIcon(QtGui.QIcon('share/letter_t_32.png'))
 
 
@@ -3436,7 +3466,6 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
         self.vlay = QtWidgets.QVBoxLayout()
         self.vlay = QtWidgets.QVBoxLayout()
         self.vlay.addWidget(self.tools_ncc_group)
         self.vlay.addWidget(self.tools_ncc_group)
         self.vlay.addWidget(self.tools_paint_group)
         self.vlay.addWidget(self.tools_paint_group)
-        self.vlay.addWidget(self.tools_film_group)
 
 
         self.vlay1 = QtWidgets.QVBoxLayout()
         self.vlay1 = QtWidgets.QVBoxLayout()
         self.vlay1.addWidget(self.tools_cutout_group)
         self.vlay1.addWidget(self.tools_cutout_group)
@@ -3450,6 +3479,7 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
         self.vlay3 = QtWidgets.QVBoxLayout()
         self.vlay3 = QtWidgets.QVBoxLayout()
         self.vlay3.addWidget(self.tools_solderpaste_group)
         self.vlay3.addWidget(self.tools_solderpaste_group)
         self.vlay3.addWidget(self.tools_sub_group)
         self.vlay3.addWidget(self.tools_sub_group)
+        self.vlay3.addWidget(self.tools_film_group)
 
 
         self.layout.addLayout(self.vlay)
         self.layout.addLayout(self.vlay)
         self.layout.addLayout(self.vlay1)
         self.layout.addLayout(self.vlay1)
@@ -3480,6 +3510,27 @@ class CNCJobPreferencesUI(QtWidgets.QWidget):
         self.layout.addStretch()
         self.layout.addStretch()
 
 
 
 
+class FAPreferencesUI(QtWidgets.QWidget):
+
+    def __init__(self, parent=None):
+        QtWidgets.QWidget.__init__(self, parent=parent)
+        self.layout = QtWidgets.QHBoxLayout()
+        self.setLayout(self.layout)
+
+        self.fa_excellon_group = FAExcPrefGroupUI()
+        self.fa_excellon_group.setMinimumWidth(260)
+        self.fa_gcode_group = FAGcoPrefGroupUI()
+        self.fa_gcode_group.setMinimumWidth(260)
+        self.fa_gerber_group = FAGrbPrefGroupUI()
+        self.fa_gerber_group.setMinimumWidth(260)
+
+        self.layout.addWidget(self.fa_excellon_group)
+        self.layout.addWidget(self.fa_gcode_group)
+        self.layout.addWidget(self.fa_gerber_group)
+
+        self.layout.addStretch()
+
+
 class OptionsGroupUI(QtWidgets.QGroupBox):
 class OptionsGroupUI(QtWidgets.QGroupBox):
     def __init__(self, title, parent=None):
     def __init__(self, title, parent=None):
         # QtGui.QGroupBox.__init__(self, title, parent=parent)
         # QtGui.QGroupBox.__init__(self, title, parent=parent)
@@ -3506,31 +3557,31 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box = QtWidgets.QFormLayout()
         self.form_box = QtWidgets.QFormLayout()
 
 
         # Grid X Entry
         # Grid X Entry
-        self.gridx_label = QtWidgets.QLabel(_('Grid X value:'))
+        self.gridx_label = QtWidgets.QLabel('%s:' % _('Grid X value'))
         self.gridx_label.setToolTip(
         self.gridx_label.setToolTip(
            _("This is the Grid snap value on X axis.")
            _("This is the Grid snap value on X axis.")
         )
         )
         self.gridx_entry = FCEntry3()
         self.gridx_entry = FCEntry3()
 
 
         # Grid Y Entry
         # Grid Y Entry
-        self.gridy_label = QtWidgets.QLabel(_('Grid Y value:'))
+        self.gridy_label = QtWidgets.QLabel('%s:' % _('Grid Y value'))
         self.gridy_label.setToolTip(
         self.gridy_label.setToolTip(
             _("This is the Grid snap value on Y axis.")
             _("This is the Grid snap value on Y axis.")
         )
         )
         self.gridy_entry = FCEntry3()
         self.gridy_entry = FCEntry3()
 
 
         # Snap Max Entry
         # Snap Max Entry
-        self.snap_max_label = QtWidgets.QLabel(_('Snap Max:'))
+        self.snap_max_label = QtWidgets.QLabel('%s:' % _('Snap Max'))
         self.snap_max_label.setToolTip(_("Max. magnet distance"))
         self.snap_max_label.setToolTip(_("Max. magnet distance"))
         self.snap_max_dist_entry = FCEntry()
         self.snap_max_dist_entry = FCEntry()
 
 
         # Workspace
         # Workspace
-        self.workspace_lbl = QtWidgets.QLabel(_('Workspace:'))
+        self.workspace_lbl = QtWidgets.QLabel('%s:' % _('Workspace'))
         self.workspace_lbl.setToolTip(
         self.workspace_lbl.setToolTip(
            _("Draw a delimiting rectangle on canvas.\n"
            _("Draw a delimiting rectangle on canvas.\n"
              "The purpose is to illustrate the limits for our work.")
              "The purpose is to illustrate the limits for our work.")
         )
         )
-        self.workspace_type_lbl = QtWidgets.QLabel(_('Wk. format:'))
+        self.workspace_type_lbl = QtWidgets.QLabel('%s:' % _('Wk. format'))
         self.workspace_type_lbl.setToolTip(
         self.workspace_type_lbl.setToolTip(
            _("Select the type of rectangle to be used on canvas,\n"
            _("Select the type of rectangle to be used on canvas,\n"
              "as valid workspace.")
              "as valid workspace.")
@@ -3545,7 +3596,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.wks = OptionalInputSection(self.workspace_cb, [self.workspace_type_lbl, self.wk_cb])
         self.wks = OptionalInputSection(self.workspace_cb, [self.workspace_type_lbl, self.wk_cb])
 
 
         # Plot Fill Color
         # Plot Fill Color
-        self.pf_color_label = QtWidgets.QLabel(_('Plot Fill:'))
+        self.pf_color_label = QtWidgets.QLabel('%s:' % _('Plot Fill'))
         self.pf_color_label.setToolTip(
         self.pf_color_label.setToolTip(
            _("Set the fill color for plotted objects.\n"
            _("Set the fill color for plotted objects.\n"
              "First 6 digits are the color and the last 2\n"
              "First 6 digits are the color and the last 2\n"
@@ -3561,7 +3612,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Plot Fill Transparency Level
         # Plot Fill Transparency Level
-        self.pf_alpha_label = QtWidgets.QLabel(_('Alpha Level:'))
+        self.pf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha Level'))
         self.pf_alpha_label.setToolTip(
         self.pf_alpha_label.setToolTip(
            _("Set the fill transparency for plotted objects.")
            _("Set the fill transparency for plotted objects.")
         )
         )
@@ -3580,7 +3631,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_2.addWidget(self.pf_color_alpha_spinner)
         self.form_box_child_2.addWidget(self.pf_color_alpha_spinner)
 
 
         # Plot Line Color
         # Plot Line Color
-        self.pl_color_label = QtWidgets.QLabel(_('Plot Line:'))
+        self.pl_color_label = QtWidgets.QLabel('%s:' % _('Plot Line'))
         self.pl_color_label.setToolTip(
         self.pl_color_label.setToolTip(
            _("Set the line color for plotted objects.")
            _("Set the line color for plotted objects.")
         )
         )
@@ -3594,7 +3645,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_3.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_3.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Plot Selection (left - right) Fill Color
         # Plot Selection (left - right) Fill Color
-        self.sf_color_label = QtWidgets.QLabel(_('Sel. Fill:'))
+        self.sf_color_label = QtWidgets.QLabel('%s:' % _('Sel. Fill'))
         self.sf_color_label.setToolTip(
         self.sf_color_label.setToolTip(
             _("Set the fill color for the selection box\n"
             _("Set the fill color for the selection box\n"
               "in case that the selection is done from left to right.\n"
               "in case that the selection is done from left to right.\n"
@@ -3611,7 +3662,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Plot Selection (left - right) Fill Transparency Level
         # Plot Selection (left - right) Fill Transparency Level
-        self.sf_alpha_label = QtWidgets.QLabel(_('Alpha Level:'))
+        self.sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha Level'))
         self.sf_alpha_label.setToolTip(
         self.sf_alpha_label.setToolTip(
             _("Set the fill transparency for the 'left to right' selection box.")
             _("Set the fill transparency for the 'left to right' selection box.")
         )
         )
@@ -3630,7 +3681,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_5.addWidget(self.sf_color_alpha_spinner)
         self.form_box_child_5.addWidget(self.sf_color_alpha_spinner)
 
 
         # Plot Selection (left - right) Line Color
         # Plot Selection (left - right) Line Color
-        self.sl_color_label = QtWidgets.QLabel(_('Sel. Line:'))
+        self.sl_color_label = QtWidgets.QLabel('%s:' % _('Sel. Line'))
         self.sl_color_label.setToolTip(
         self.sl_color_label.setToolTip(
             _("Set the line color for the 'left to right' selection box.")
             _("Set the line color for the 'left to right' selection box.")
         )
         )
@@ -3644,7 +3695,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_6.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_6.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Plot Selection (right - left) Fill Color
         # Plot Selection (right - left) Fill Color
-        self.alt_sf_color_label = QtWidgets.QLabel(_('Sel2. Fill:'))
+        self.alt_sf_color_label = QtWidgets.QLabel('%s:' % _('Sel2. Fill'))
         self.alt_sf_color_label.setToolTip(
         self.alt_sf_color_label.setToolTip(
             _("Set the fill color for the selection box\n"
             _("Set the fill color for the selection box\n"
               "in case that the selection is done from right to left.\n"
               "in case that the selection is done from right to left.\n"
@@ -3661,7 +3712,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_7.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_7.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Plot Selection (right - left) Fill Transparency Level
         # Plot Selection (right - left) Fill Transparency Level
-        self.alt_sf_alpha_label = QtWidgets.QLabel(_('Alpha Level:'))
+        self.alt_sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha Level'))
         self.alt_sf_alpha_label.setToolTip(
         self.alt_sf_alpha_label.setToolTip(
             _("Set the fill transparency for selection 'right to left' box.")
             _("Set the fill transparency for selection 'right to left' box.")
         )
         )
@@ -3680,7 +3731,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_8.addWidget(self.alt_sf_color_alpha_spinner)
         self.form_box_child_8.addWidget(self.alt_sf_color_alpha_spinner)
 
 
         # Plot Selection (right - left) Line Color
         # Plot Selection (right - left) Line Color
-        self.alt_sl_color_label = QtWidgets.QLabel(_('Sel2. Line:'))
+        self.alt_sl_color_label = QtWidgets.QLabel('%s:' % _('Sel2. Line'))
         self.alt_sl_color_label.setToolTip(
         self.alt_sl_color_label.setToolTip(
             _("Set the line color for the 'right to left' selection box.")
             _("Set the line color for the 'right to left' selection box.")
         )
         )
@@ -3694,7 +3745,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_9.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_9.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Editor Draw Color
         # Editor Draw Color
-        self.draw_color_label = QtWidgets.QLabel(_('Editor Draw:'))
+        self.draw_color_label = QtWidgets.QLabel('%s:' % _('Editor Draw'))
         self.alt_sf_color_label.setToolTip(
         self.alt_sf_color_label.setToolTip(
             _("Set the color for the shape.")
             _("Set the color for the shape.")
         )
         )
@@ -3708,7 +3759,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_10.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_10.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Editor Draw Selection Color
         # Editor Draw Selection Color
-        self.sel_draw_color_label = QtWidgets.QLabel(_('Editor Draw Sel.:'))
+        self.sel_draw_color_label = QtWidgets.QLabel('%s:' % _('Editor Draw Sel.'))
         self.sel_draw_color_label.setToolTip(
         self.sel_draw_color_label.setToolTip(
             _("Set the color of the shape when selected.")
             _("Set the color of the shape when selected.")
         )
         )
@@ -3722,7 +3773,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_11.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_11.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
         # Project Tab items color
         # Project Tab items color
-        self.proj_color_label = QtWidgets.QLabel(_('Project Items:'))
+        self.proj_color_label = QtWidgets.QLabel('%s:' % _('Project Items'))
         self.proj_color_label.setToolTip(
         self.proj_color_label.setToolTip(
             _("Set the color of the items in Project Tab Tree.")
             _("Set the color of the items in Project Tab Tree.")
         )
         )
@@ -3735,7 +3786,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
         self.form_box_child_12.addWidget(self.proj_color_button)
         self.form_box_child_12.addWidget(self.proj_color_button)
         self.form_box_child_12.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
         self.form_box_child_12.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
 
-        self.proj_color_dis_label = QtWidgets.QLabel(_('Proj. Dis. Items:'))
+        self.proj_color_dis_label = QtWidgets.QLabel('%s:' % _('Proj. Dis. Items'))
         self.proj_color_dis_label.setToolTip(
         self.proj_color_dis_label.setToolTip(
             _("Set the color of the items in Project Tab Tree,\n"
             _("Set the color of the items in Project Tab Tree,\n"
               "for the case when the items are disabled.")
               "for the case when the items are disabled.")
@@ -3794,7 +3845,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         self.form_box = QtWidgets.QFormLayout()
         self.form_box = QtWidgets.QFormLayout()
 
 
         # Layout selection
         # Layout selection
-        self.layout_label = QtWidgets.QLabel(_('Layout:'))
+        self.layout_label = QtWidgets.QLabel('%s:' % _('Layout'))
         self.layout_label.setToolTip(
         self.layout_label.setToolTip(
             _("Select an layout for FlatCAM.\n"
             _("Select an layout for FlatCAM.\n"
               "It is applied immediately.")
               "It is applied immediately.")
@@ -3812,7 +3863,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
             self.layout_combo.setCurrentIndex(idx)
             self.layout_combo.setCurrentIndex(idx)
 
 
         # Style selection
         # Style selection
-        self.style_label = QtWidgets.QLabel(_('Style:'))
+        self.style_label = QtWidgets.QLabel('%s:' % _('Style'))
         self.style_label.setToolTip(
         self.style_label.setToolTip(
             _("Select an style for FlatCAM.\n"
             _("Select an style for FlatCAM.\n"
               "It will be applied at the next app start.")
               "It will be applied at the next app start.")
@@ -3825,7 +3876,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         self.style_combo.activated[str].connect(self.handle_style)
         self.style_combo.activated[str].connect(self.handle_style)
 
 
         # Enable High DPI Support
         # Enable High DPI Support
-        self.hdpi_label = QtWidgets.QLabel(_('HDPI Support:'))
+        self.hdpi_label = QtWidgets.QLabel('%s:' % _('HDPI Support'))
         self.hdpi_label.setToolTip(
         self.hdpi_label.setToolTip(
             _("Enable High DPI support for FlatCAM.\n"
             _("Enable High DPI support for FlatCAM.\n"
               "It will be applied at the next app start.")
               "It will be applied at the next app start.")
@@ -3840,7 +3891,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         self.hdpi_cb.stateChanged.connect(self.handle_hdpi)
         self.hdpi_cb.stateChanged.connect(self.handle_hdpi)
 
 
         # Clear Settings
         # Clear Settings
-        self.clear_label = QtWidgets.QLabel(_('Clear GUI Settings:'))
+        self.clear_label = QtWidgets.QLabel('%s:' % _('Clear GUI Settings'))
         self.clear_label.setToolTip(
         self.clear_label.setToolTip(
             _("Clear the GUI settings for FlatCAM,\n"
             _("Clear the GUI settings for FlatCAM,\n"
               "such as: layout, gui state, style, hdpi support etc.")
               "such as: layout, gui state, style, hdpi support etc.")
@@ -3849,7 +3900,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         self.clear_btn.clicked.connect(self.handle_clear)
         self.clear_btn.clicked.connect(self.handle_clear)
 
 
         # Enable Hover box
         # Enable Hover box
-        self.hover_label = QtWidgets.QLabel(_('Hover Shape:'))
+        self.hover_label = QtWidgets.QLabel('%s:' % _('Hover Shape'))
         self.hover_label.setToolTip(
         self.hover_label.setToolTip(
             _("Enable display of a hover shape for FlatCAM objects.\n"
             _("Enable display of a hover shape for FlatCAM objects.\n"
               "It is displayed whenever the mouse cursor is hovering\n"
               "It is displayed whenever the mouse cursor is hovering\n"
@@ -3858,7 +3909,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         self.hover_cb = FCCheckBox()
         self.hover_cb = FCCheckBox()
 
 
         # Enable Selection box
         # Enable Selection box
-        self.selection_label = QtWidgets.QLabel(_('Sel. Shape:'))
+        self.selection_label = QtWidgets.QLabel('%s:' % _('Sel. Shape'))
         self.selection_label.setToolTip(
         self.selection_label.setToolTip(
             _("Enable the display of a selection shape for FlatCAM objects.\n"
             _("Enable the display of a selection shape for FlatCAM objects.\n"
               "It is displayed whenever the mouse selects an object\n"
               "It is displayed whenever the mouse selects an object\n"
@@ -3867,7 +3918,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         )
         )
         self.selection_cb = FCCheckBox()
         self.selection_cb = FCCheckBox()
 
 
-        self.notebook_font_size_label = QtWidgets.QLabel(_('NB Font Size:'))
+        self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('NB Font Size'))
         self.notebook_font_size_label.setToolTip(
         self.notebook_font_size_label.setToolTip(
             _("This sets the font size for the elements found in the Notebook.\n"
             _("This sets the font size for the elements found in the Notebook.\n"
               "The notebook is the collapsible area in the left side of the GUI,\n"
               "The notebook is the collapsible area in the left side of the GUI,\n"
@@ -3884,7 +3935,7 @@ class GeneralGUISetGroupUI(OptionsGroupUI):
         else:
         else:
             self.notebook_font_size_spinner.set_value(12)
             self.notebook_font_size_spinner.set_value(12)
 
 
-        self.axis_font_size_label = QtWidgets.QLabel(_('Axis Font Size:'))
+        self.axis_font_size_label = QtWidgets.QLabel('%s:' % _('Axis Font Size'))
         self.axis_font_size_label.setToolTip(
         self.axis_font_size_label.setToolTip(
             _("This sets the font size for canvas axis.")
             _("This sets the font size for canvas axis.")
         )
         )
@@ -4053,7 +4104,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
                                           {'label': _('RMB'), 'value': '2'}])
                                           {'label': _('RMB'), 'value': '2'}])
 
 
         # Multiple Selection Modifier Key
         # Multiple Selection Modifier Key
-        self.mselectlabel = QtWidgets.QLabel('<b>%s:</b>' % _('Multiple Sel:'))
+        self.mselectlabel = QtWidgets.QLabel('<b>%s:</b>' % _('Multiple Sel'))
         self.mselectlabel.setToolTip(_("Select the key used for multiple selection."))
         self.mselectlabel.setToolTip(_("Select the key used for multiple selection."))
         self.mselect_radio = RadioSet([{'label': _('CTRL'), 'value': 'Control'},
         self.mselect_radio = RadioSet([{'label': _('CTRL'), 'value': 'Control'},
                                        {'label': _('SHIFT'), 'value': 'Shift'}])
                                        {'label': _('SHIFT'), 'value': 'Shift'}])
@@ -4263,10 +4314,23 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
             _("The number of circle steps for Gerber \n"
             _("The number of circle steps for Gerber \n"
               "circular aperture linear approximation.")
               "circular aperture linear approximation.")
         )
         )
-        grid0.addWidget(self.circle_steps_label, 1, 0)
         self.circle_steps_entry = IntEntry()
         self.circle_steps_entry = IntEntry()
+        grid0.addWidget(self.circle_steps_label, 1, 0)
         grid0.addWidget(self.circle_steps_entry, 1, 1)
         grid0.addWidget(self.circle_steps_entry, 1, 1)
 
 
+        # Milling Type
+        buffering_label = QtWidgets.QLabel('%s:' % _('Buffering'))
+        buffering_label.setToolTip(
+            _("Buffering type:\n"
+              "- None --> best performance, fast file loading but no so good display\n"
+              "- Full --> slow file loading but good visuals. This is the default.\n"
+              "<<WARNING>>: Don't change this unless you know what you are doing !!!")
+        )
+        self.buffering_radio = RadioSet([{'label': _('None'), 'value': 'no'},
+                                          {'label': _('Full'), 'value': 'full'}])
+        grid0.addWidget(buffering_label, 2, 0)
+        grid0.addWidget(self.buffering_radio, 2, 1)
+
         self.layout.addStretch()
         self.layout.addStretch()
 
 
 
 
@@ -4319,6 +4383,7 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
         self.iso_overlap_entry = FloatEntry()
         self.iso_overlap_entry = FloatEntry()
         grid0.addWidget(self.iso_overlap_entry, 2, 1)
         grid0.addWidget(self.iso_overlap_entry, 2, 1)
 
 
+        # Milling Type
         milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
         milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
         milling_type_label.setToolTip(
         milling_type_label.setToolTip(
             _("Milling type:\n"
             _("Milling type:\n"
@@ -5055,7 +5120,7 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI):
         self.toolchangez_entry = LengthEntry()
         self.toolchangez_entry = LengthEntry()
         grid2.addWidget(self.toolchangez_entry, 3, 1)
         grid2.addWidget(self.toolchangez_entry, 3, 1)
 
 
-        frlabel = QtWidgets.QLabel('%s:' % _('Feedrate (Plunge):'))
+        frlabel = QtWidgets.QLabel('%s:' % _('Feedrate (Plunge)'))
         frlabel.setToolTip(
         frlabel.setToolTip(
             _("Tool speed while drilling\n"
             _("Tool speed while drilling\n"
               "(in units per minute).\n"
               "(in units per minute).\n"
@@ -5095,7 +5160,7 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI):
             _("Pause to allow the spindle to reach its\n"
             _("Pause to allow the spindle to reach its\n"
               "speed before cutting.")
               "speed before cutting.")
         )
         )
-        dwelltime = QtWidgets.QLabel(_('Duration:'))
+        dwelltime = QtWidgets.QLabel('%s:' % _('Duration'))
         dwelltime.setToolTip(
         dwelltime.setToolTip(
             _("Number of time units for spindle to dwell.")
             _("Number of time units for spindle to dwell.")
         )
         )
@@ -5260,7 +5325,7 @@ class ExcellonAdvOptPrefGroupUI(OptionsGroupUI):
         self.feedrate_probe_entry = FCEntry()
         self.feedrate_probe_entry = FCEntry()
         grid1.addWidget(self.feedrate_probe_entry, 6, 1)
         grid1.addWidget(self.feedrate_probe_entry, 6, 1)
 
 
-        fplungelabel = QtWidgets.QLabel(_('Fast Plunge:'))
+        fplungelabel = QtWidgets.QLabel('%s:' % _('Fast Plunge'))
         fplungelabel.setToolTip(
         fplungelabel.setToolTip(
             _("By checking this, the vertical move from\n"
             _("By checking this, the vertical move from\n"
               "Z_Toolchange to Z_move is done with G0,\n"
               "Z_Toolchange to Z_move is done with G0,\n"
@@ -5496,7 +5561,7 @@ class ExcellonEditorPrefGroupUI(OptionsGroupUI):
         grid0.addWidget(self.drill_array_linear_label, 3, 0, 1, 2)
         grid0.addWidget(self.drill_array_linear_label, 3, 0, 1, 2)
 
 
         # Linear Drill Array direction
         # Linear Drill Array direction
-        self.drill_axis_label = QtWidgets.QLabel(_('Linear Dir.:'))
+        self.drill_axis_label = QtWidgets.QLabel('%s:' % _('Linear Dir.'))
         self.drill_axis_label.setToolTip(
         self.drill_axis_label.setToolTip(
             _("Direction on which the linear array is oriented:\n"
             _("Direction on which the linear array is oriented:\n"
               "- 'X' - horizontal axis \n"
               "- 'X' - horizontal axis \n"
@@ -6086,8 +6151,8 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
 
 
         grid0 = QtWidgets.QGridLayout()
         grid0 = QtWidgets.QGridLayout()
         self.layout.addLayout(grid0)
         self.layout.addLayout(grid0)
-        grid0.setColumnStretch(1, 1)
-        grid0.setColumnStretch(2, 1)
+        # grid0.setColumnStretch(1, 1)
+        # grid0.setColumnStretch(2, 1)
 
 
         # Plot CB
         # Plot CB
         # self.plot_cb = QtWidgets.QCheckBox('Plot')
         # self.plot_cb = QtWidgets.QCheckBox('Plot')
@@ -6096,7 +6161,7 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
         grid0.addWidget(self.plot_cb, 0, 0)
         grid0.addWidget(self.plot_cb, 0, 0)
 
 
         # Plot Kind
         # Plot Kind
-        self.cncplot_method_label = QtWidgets.QLabel('%s:' % _("Plot kind:"))
+        self.cncplot_method_label = QtWidgets.QLabel('%s:' % _("Plot kind"))
         self.cncplot_method_label.setToolTip(
         self.cncplot_method_label.setToolTip(
             _("This selects the kind of geometries on the canvas to plot.\n"
             _("This selects the kind of geometries on the canvas to plot.\n"
               "Those can be either of type 'Travel' which means the moves\n"
               "Those can be either of type 'Travel' which means the moves\n"
@@ -6172,35 +6237,57 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
         grid0.addWidget(self.steps_per_circle_entry, 5, 1)
         grid0.addWidget(self.steps_per_circle_entry, 5, 1)
 
 
         # Tool dia for plot
         # Tool dia for plot
-        tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
+        tdlabel = QtWidgets.QLabel('%s:' % _('Travel dia'))
         tdlabel.setToolTip(
         tdlabel.setToolTip(
-            _("Diameter of the tool to be\n"
+            _("The width of the travel lines to be\n"
               "rendered in the plot.")
               "rendered in the plot.")
         )
         )
-        grid0.addWidget(tdlabel, 6, 0)
         self.tooldia_entry = LengthEntry()
         self.tooldia_entry = LengthEntry()
+        grid0.addWidget(tdlabel, 6, 0)
         grid0.addWidget(self.tooldia_entry, 6, 1)
         grid0.addWidget(self.tooldia_entry, 6, 1)
 
 
+        # add a space
+        grid0.addWidget(QtWidgets.QLabel(''), 7, 0)
+
         # Number of decimals to use in GCODE coordinates
         # Number of decimals to use in GCODE coordinates
-        cdeclabel = QtWidgets.QLabel('%s:' % _('Coords dec.'))
+        cdeclabel = QtWidgets.QLabel('%s:' % _('Coordinates decimals'))
         cdeclabel.setToolTip(
         cdeclabel.setToolTip(
             _("The number of decimals to be used for \n"
             _("The number of decimals to be used for \n"
               "the X, Y, Z coordinates in CNC code (GCODE, etc.)")
               "the X, Y, Z coordinates in CNC code (GCODE, etc.)")
         )
         )
-        grid0.addWidget(cdeclabel, 7, 0)
         self.coords_dec_entry = IntEntry()
         self.coords_dec_entry = IntEntry()
-        grid0.addWidget(self.coords_dec_entry, 7, 1)
+        grid0.addWidget(cdeclabel, 8, 0)
+        grid0.addWidget(self.coords_dec_entry, 8, 1)
 
 
         # Number of decimals to use in GCODE feedrate
         # Number of decimals to use in GCODE feedrate
-        frdeclabel = QtWidgets.QLabel('%s:' % _('Feedrate dec.'))
+        frdeclabel = QtWidgets.QLabel('%s:' % _('Feedrate decimals'))
         frdeclabel.setToolTip(
         frdeclabel.setToolTip(
             _("The number of decimals to be used for \n"
             _("The number of decimals to be used for \n"
               "the Feedrate parameter in CNC code (GCODE, etc.)")
               "the Feedrate parameter in CNC code (GCODE, etc.)")
         )
         )
-        grid0.addWidget(frdeclabel, 8, 0)
         self.fr_dec_entry = IntEntry()
         self.fr_dec_entry = IntEntry()
-        grid0.addWidget(self.fr_dec_entry, 8, 1)
+        grid0.addWidget(frdeclabel, 9, 0)
+        grid0.addWidget(self.fr_dec_entry, 9, 1)
+
+        # The type of coordinates used in the Gcode: Absolute or Incremental
+        coords_type_label = QtWidgets.QLabel('%s:' % _('Coordinates type'))
+        coords_type_label.setToolTip(
+            _("The type of coordinates to be used in Gcode.\n"
+              "Can be:\n"
+              "- Absolute G90 -> the reference is the origin x=0, y=0\n"
+              "- Incremental G91 -> the reference is the previous position")
+        )
+        self.coords_type_radio = RadioSet([
+            {"label": _("Absolute G90"), "value": "G90"},
+            {"label": _("Incremental G91"), "value": "G91"}
+        ], orientation='vertical', stretch=False)
+        grid0.addWidget(coords_type_label, 10, 0)
+        grid0.addWidget(self.coords_type_radio, 10, 1)
 
 
+        # hidden for the time being, until implemented
+        coords_type_label.hide()
+        self.coords_type_radio.hide()
+        
         self.layout.addStretch()
         self.layout.addStretch()
 
 
 
 
@@ -6361,6 +6448,64 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
         self.ncc_tool_dia_entry = FCEntry()
         self.ncc_tool_dia_entry = FCEntry()
         grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
         grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
 
 
+        # Tool Type Radio Button
+        self.tool_type_label = QtWidgets.QLabel('%s:' % _('Tool Type'))
+        self.tool_type_label.setToolTip(
+            _("Default tool type:\n"
+              "- 'V-shape'\n"
+              "- Circular")
+        )
+
+        self.tool_type_radio = RadioSet([{'label': _('V-shape'), 'value': 'V'},
+                                         {'label': _('Circular'), 'value': 'C1'}])
+        self.tool_type_radio.setToolTip(
+            _("Default tool type:\n"
+              "- 'V-shape'\n"
+              "- Circular")
+        )
+
+        grid0.addWidget(self.tool_type_label, 1, 0)
+        grid0.addWidget(self.tool_type_radio, 1, 1)
+
+        # Tip Dia
+        self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
+        self.tipdialabel.setToolTip(
+            _("The tip diameter for V-Shape Tool"))
+        self.tipdia_entry = LengthEntry()
+
+        grid0.addWidget(self.tipdialabel, 2, 0)
+        grid0.addWidget(self.tipdia_entry, 2, 1)
+
+        # Tip Angle
+        self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
+        self.tipanglelabel.setToolTip(
+            _("The tip angle for V-Shape Tool.\n"
+              "In degree."))
+        self.tipangle_entry = LengthEntry()
+
+        grid0.addWidget(self.tipanglelabel, 3, 0)
+        grid0.addWidget(self.tipangle_entry, 3, 1)
+
+        # Milling Type Radio Button
+        self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
+        self.milling_type_label.setToolTip(
+            _("Milling type when the selected tool is of type: 'iso_op':\n"
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
+        )
+
+        self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
+                                            {'label': _('Conv.'), 'value': 'cv'}])
+        self.milling_type_radio.setToolTip(
+            _("Milling type when the selected tool is of type: 'iso_op':\n"
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
+        )
+
+        grid0.addWidget(self.milling_type_label, 4, 0)
+        grid0.addWidget(self.milling_type_radio, 4, 1)
+
+        # Tool order Radio Button
         self.ncc_order_label = QtWidgets.QLabel('%s:' % _('Tool order'))
         self.ncc_order_label = QtWidgets.QLabel('%s:' % _('Tool order'))
         self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n"
         self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n"
                                           "'No' --> means that the used order is the one in the tool table\n"
                                           "'No' --> means that the used order is the one in the tool table\n"
@@ -6378,9 +6523,25 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
                                           "'Reverse' --> menas that the tools will ordered from big to small\n\n"
                                           "'Reverse' --> menas that the tools will ordered from big to small\n\n"
                                           "WARNING: using rest machining will automatically set the order\n"
                                           "WARNING: using rest machining will automatically set the order\n"
                                           "in reverse and disable this control."))
                                           "in reverse and disable this control."))
-        grid0.addWidget(self.ncc_order_label, 1, 0)
-        grid0.addWidget(self.ncc_order_radio, 1, 1)
+        grid0.addWidget(self.ncc_order_label, 5, 0)
+        grid0.addWidget(self.ncc_order_radio, 5, 1)
+
+        # Cut Z entry
+        cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
+        cutzlabel.setToolTip(
+           _("Depth of cut into material. Negative value.\n"
+             "In FlatCAM units.")
+        )
+        self.cutz_entry = FloatEntry()
+        self.cutz_entry.setToolTip(
+           _("Depth of cut into material. Negative value.\n"
+             "In FlatCAM units.")
+        )
+
+        grid0.addWidget(cutzlabel, 6, 0)
+        grid0.addWidget(self.cutz_entry, 6, 1)
 
 
+        # Overlap Entry
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel.setToolTip(
         nccoverlabel.setToolTip(
            _("How much (fraction) of the tool width to overlap each tool pass.\n"
            _("How much (fraction) of the tool width to overlap each tool pass.\n"
@@ -6393,17 +6554,18 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
              "Higher values = slow processing and slow execution on CNC\n"
              "Higher values = slow processing and slow execution on CNC\n"
              "due of too many paths.")
              "due of too many paths.")
         )
         )
-        grid0.addWidget(nccoverlabel, 2, 0)
+        grid0.addWidget(nccoverlabel, 7, 0)
         self.ncc_overlap_entry = FloatEntry()
         self.ncc_overlap_entry = FloatEntry()
-        grid0.addWidget(self.ncc_overlap_entry, 2, 1)
+        grid0.addWidget(self.ncc_overlap_entry, 7, 1)
 
 
+        # Margin entry
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel.setToolTip(
         nccmarginlabel.setToolTip(
             _("Bounding box margin.")
             _("Bounding box margin.")
         )
         )
-        grid0.addWidget(nccmarginlabel, 3, 0)
+        grid0.addWidget(nccmarginlabel, 8, 0)
         self.ncc_margin_entry = FloatEntry()
         self.ncc_margin_entry = FloatEntry()
-        grid0.addWidget(self.ncc_margin_entry, 3, 1)
+        grid0.addWidget(self.ncc_margin_entry, 8, 1)
 
 
         # Method
         # Method
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
@@ -6413,13 +6575,13 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Line-based</B>: Parallel lines.")
               "<B>Line-based</B>: Parallel lines.")
         )
         )
-        grid0.addWidget(methodlabel, 4, 0)
+        grid0.addWidget(methodlabel, 9, 0)
         self.ncc_method_radio = RadioSet([
         self.ncc_method_radio = RadioSet([
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Straight lines"), "value": "lines"}
             {"label": _("Straight lines"), "value": "lines"}
         ], orientation='vertical', stretch=False)
         ], orientation='vertical', stretch=False)
-        grid0.addWidget(self.ncc_method_radio, 4, 1)
+        grid0.addWidget(self.ncc_method_radio, 9, 1)
 
 
         # Connect lines
         # Connect lines
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
@@ -6427,19 +6589,21 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
             _("Draw lines between resulting\n"
             _("Draw lines between resulting\n"
               "segments to minimize tool lifts.")
               "segments to minimize tool lifts.")
         )
         )
-        grid0.addWidget(pathconnectlabel, 5, 0)
+        grid0.addWidget(pathconnectlabel, 10, 0)
         self.ncc_connect_cb = FCCheckBox()
         self.ncc_connect_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_connect_cb, 5, 1)
+        grid0.addWidget(self.ncc_connect_cb, 10, 1)
 
 
+        # Contour Checkbox
         contourlabel = QtWidgets.QLabel('%s:' % _("Contour"))
         contourlabel = QtWidgets.QLabel('%s:' % _("Contour"))
         contourlabel.setToolTip(
         contourlabel.setToolTip(
            _("Cut around the perimeter of the polygon\n"
            _("Cut around the perimeter of the polygon\n"
              "to trim rough edges.")
              "to trim rough edges.")
         )
         )
-        grid0.addWidget(contourlabel, 6, 0)
+        grid0.addWidget(contourlabel, 11, 0)
         self.ncc_contour_cb = FCCheckBox()
         self.ncc_contour_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_contour_cb, 6, 1)
+        grid0.addWidget(self.ncc_contour_cb, 11, 1)
 
 
+        # Rest machining CheckBox
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel.setToolTip(
         restlabel.setToolTip(
             _("If checked, use 'rest machining'.\n"
             _("If checked, use 'rest machining'.\n"
@@ -6450,9 +6614,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "no more copper to clear or there are no more tools.\n"
               "no more copper to clear or there are no more tools.\n"
               "If not checked, use the standard algorithm.")
               "If not checked, use the standard algorithm.")
         )
         )
-        grid0.addWidget(restlabel, 7, 0)
+        grid0.addWidget(restlabel, 12, 0)
         self.ncc_rest_cb = FCCheckBox()
         self.ncc_rest_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_rest_cb, 7, 1)
+        grid0.addWidget(self.ncc_rest_cb, 12, 1)
 
 
         # ## NCC Offset choice
         # ## NCC Offset choice
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
@@ -6462,9 +6626,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "from the copper features.\n"
               "from the copper features.\n"
               "The value can be between 0 and 10 FlatCAM units.")
               "The value can be between 0 and 10 FlatCAM units.")
         )
         )
-        grid0.addWidget(self.ncc_offset_choice_label, 8, 0)
+        grid0.addWidget(self.ncc_offset_choice_label, 13, 0)
         self.ncc_choice_offset_cb = FCCheckBox()
         self.ncc_choice_offset_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_choice_offset_cb, 8, 1)
+        grid0.addWidget(self.ncc_choice_offset_cb, 13, 1)
 
 
         # ## NCC Offset value
         # ## NCC Offset value
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
@@ -6474,14 +6638,14 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "from the copper features.\n"
               "from the copper features.\n"
               "The value can be between 0 and 10 FlatCAM units.")
               "The value can be between 0 and 10 FlatCAM units.")
         )
         )
-        grid0.addWidget(self.ncc_offset_label, 9, 0)
+        grid0.addWidget(self.ncc_offset_label, 14, 0)
         self.ncc_offset_spinner = FCDoubleSpinner()
         self.ncc_offset_spinner = FCDoubleSpinner()
         self.ncc_offset_spinner.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_precision(4)
         self.ncc_offset_spinner.set_precision(4)
         self.ncc_offset_spinner.setWrapping(True)
         self.ncc_offset_spinner.setWrapping(True)
         self.ncc_offset_spinner.setSingleStep(0.1)
         self.ncc_offset_spinner.setSingleStep(0.1)
 
 
-        grid0.addWidget(self.ncc_offset_spinner, 9, 1)
+        grid0.addWidget(self.ncc_offset_spinner, 14, 1)
 
 
         # ## Reference
         # ## Reference
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
@@ -6496,8 +6660,19 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "specified by another object.")
               "specified by another object.")
         )
         )
-        grid0.addWidget(reference_label, 10, 0)
-        grid0.addWidget(self.reference_radio, 10, 1)
+        grid0.addWidget(reference_label, 15, 0)
+        grid0.addWidget(self.reference_radio, 15, 1)
+
+        # ## Plotting type
+        self.ncc_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
+                                            {"label": _("Progressive"), "value": "progressive"}])
+        plotting_label = QtWidgets.QLabel('%s:' % _("NCC Plotting"))
+        plotting_label.setToolTip(
+            _("- 'Normal' -  normal plotting, done at the end of the NCC job\n"
+              "- 'Progressive' - after each shape is generated it will be plotted.")
+        )
+        grid0.addWidget(plotting_label, 16, 0)
+        grid0.addWidget(self.ncc_plotting_radio, 16, 1)
 
 
         self.layout.addStretch()
         self.layout.addStretch()
 
 
@@ -6785,15 +6960,26 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "specified by another object.")
               "specified by another object.")
         )
         )
-        grid0.addWidget(selectlabel, 7, 0)
         self.selectmethod_combo = RadioSet([
         self.selectmethod_combo = RadioSet([
             {"label": _("Single"), "value": "single"},
             {"label": _("Single"), "value": "single"},
             {"label": _("Area"), "value": "area"},
             {"label": _("Area"), "value": "area"},
             {"label": _("All"), "value": "all"},
             {"label": _("All"), "value": "all"},
             {"label": _("Ref."), "value": "ref"}
             {"label": _("Ref."), "value": "ref"}
         ])
         ])
+        grid0.addWidget(selectlabel, 7, 0)
         grid0.addWidget(self.selectmethod_combo, 7, 1)
         grid0.addWidget(self.selectmethod_combo, 7, 1)
 
 
+        # ## Plotting type
+        self.paint_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
+                                              {"label": _("Progressive"), "value": "progressive"}])
+        plotting_label = QtWidgets.QLabel('%s:' % _("Paint Plotting"))
+        plotting_label.setToolTip(
+            _("- 'Normal' -  normal plotting, done at the end of the Paint job\n"
+              "- 'Progressive' - after each shape is generated it will be plotted.")
+        )
+        grid0.addWidget(plotting_label, 8, 0)
+        grid0.addWidget(self.paint_plotting_radio, 8, 1)
+
         self.layout.addStretch()
         self.layout.addStretch()
 
 
 
 
@@ -6818,7 +7004,7 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
 
 
         self.film_type_radio = RadioSet([{'label': 'Pos', 'value': 'pos'},
         self.film_type_radio = RadioSet([{'label': 'Pos', 'value': 'pos'},
                                          {'label': 'Neg', 'value': 'neg'}])
                                          {'label': 'Neg', 'value': 'neg'}])
-        ftypelbl = QtWidgets.QLabel(_('Film Type:'))
+        ftypelbl = QtWidgets.QLabel('%s:' % _('Film Type'))
         ftypelbl.setToolTip(
         ftypelbl.setToolTip(
             _("Generate a Positive black film or a Negative film.\n"
             _("Generate a Positive black film or a Negative film.\n"
               "Positive means that it will print the features\n"
               "Positive means that it will print the features\n"
@@ -7384,6 +7570,104 @@ class ToolsSubPrefGroupUI(OptionsGroupUI):
         self.layout.addStretch()
         self.layout.addStretch()
 
 
 
 
+class FAExcPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+        # OptionsGroupUI.__init__(self, "Excellon File associations Preferences", parent=None)
+        super(FAExcPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str(_("Excellon File associations")))
+
+        # ## Export G-Code
+        self.exc_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
+        self.exc_list_label.setToolTip(
+            _("List of file extensions to be\n"
+              "associated with FlatCAM.")
+        )
+        self.layout.addWidget(self.exc_list_label)
+
+        self.exc_list_text = FCTextArea()
+        self.exc_list_text.sizeHint(custom_sizehint=150)
+        font = QtGui.QFont()
+        font.setPointSize(12)
+        self.exc_list_text.setFont(font)
+
+        self.layout.addWidget(self.exc_list_text)
+
+        self.exc_list_btn = FCButton("Apply")
+        self.exc_list_btn.setToolTip(_("Apply the file associations between\n"
+                                       "FlatCAM and the files with above extensions.\n"
+                                       "They will be active after next logon.\n"
+                                       "This work only in Windows."))
+        self.layout.addWidget(self.exc_list_btn)
+
+        # self.layout.addStretch()
+
+
+class FAGcoPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+        # OptionsGroupUI.__init__(self, "Gcode File associations Preferences", parent=None)
+        super(FAGcoPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str(_("GCode File associations")))
+
+        # ## Export G-Code
+        self.gco_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
+        self.gco_list_label.setToolTip(
+            _("List of file extensions to be\n"
+              "associated with FlatCAM.")
+        )
+        self.layout.addWidget(self.gco_list_label)
+
+        self.gco_list_text = FCTextArea()
+        self.gco_list_text.sizeHint(custom_sizehint=150)
+        font = QtGui.QFont()
+        font.setPointSize(12)
+        self.gco_list_text.setFont(font)
+
+        self.layout.addWidget(self.gco_list_text)
+
+        self.gco_list_btn = FCButton("Apply")
+        self.gco_list_btn.setToolTip(_("Apply the file associations between\n"
+                                       "FlatCAM and the files with above extensions.\n"
+                                       "They will be active after next logon.\n"
+                                       "This work only in Windows."))
+        self.layout.addWidget(self.gco_list_btn)
+
+        # self.layout.addStretch()
+
+
+class FAGrbPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+        # OptionsGroupUI.__init__(self, "Gerber File associations Preferences", parent=None)
+        super(FAGrbPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str(_("Gerber File associations")))
+
+        # ## Export G-Code
+        self.grb_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
+        self.grb_list_label.setToolTip(
+            _("List of file extensions to be\n"
+              "associated with FlatCAM.")
+        )
+        self.layout.addWidget(self.grb_list_label)
+
+        self.grb_list_text = FCTextArea()
+        self.grb_list_text.sizeHint(custom_sizehint=150)
+        self.layout.addWidget(self.grb_list_text)
+        font = QtGui.QFont()
+        font.setPointSize(12)
+        self.grb_list_text.setFont(font)
+
+        self.grb_list_btn = FCButton("Apply")
+        self.grb_list_btn.setToolTip(_("Apply the file associations between\n"
+                                       "FlatCAM and the files with above extensions.\n"
+                                       "They will be active after next logon.\n"
+                                       "This work only in Windows."))
+        self.layout.addWidget(self.grb_list_btn)
+
+        # self.layout.addStretch()
+
+
 class FlatCAMActivityView(QtWidgets.QWidget):
 class FlatCAMActivityView(QtWidgets.QWidget):
 
 
     def __init__(self, parent=None):
     def __init__(self, parent=None):
@@ -7412,8 +7696,9 @@ class FlatCAMActivityView(QtWidgets.QWidget):
         self.movie.stop()
         self.movie.stop()
         self.text.setText(_("Idle."))
         self.text.setText(_("Idle."))
 
 
-    def set_busy(self, msg):
-        self.movie.start()
+    def set_busy(self, msg, no_movie=None):
+        if no_movie is not True:
+            self.movie.start()
         self.text.setText(msg)
         self.text.setText(msg)
 
 
 
 

+ 46 - 3
flatcamGUI/GUIElements.py

@@ -531,9 +531,13 @@ class FCTextArea(QtWidgets.QPlainTextEdit):
     def get_value(self):
     def get_value(self):
         return str(self.toPlainText())
         return str(self.toPlainText())
 
 
-    def sizeHint(self):
+    def sizeHint(self, custom_sizehint=None):
         default_hint_size = super(FCTextArea, self).sizeHint()
         default_hint_size = super(FCTextArea, self).sizeHint()
-        return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height())
+
+        if custom_sizehint is None:
+            return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height())
+        else:
+            return QtCore.QSize(custom_sizehint, default_hint_size.height())
 
 
 
 
 class FCTextAreaRich(QtWidgets.QTextEdit):
 class FCTextAreaRich(QtWidgets.QTextEdit):
@@ -1520,6 +1524,45 @@ class OptionalInputSection:
                     widget.setEnabled(True)
                     widget.setEnabled(True)
 
 
 
 
+class OptionalHideInputSection:
+
+    def __init__(self, cb, optinputs, logic=True):
+        """
+        Associates the a checkbox with a set of inputs.
+
+        :param cb: Checkbox that enables the optional inputs.
+        :param optinputs: List of widgets that are optional.
+        :param logic: When True the logic is normal, when False the logic is in reverse
+        It means that for logic=True, when the checkbox is checked the widgets are Enabled, and
+        for logic=False, when the checkbox is checked the widgets are Disabled
+        :return:
+        """
+        assert isinstance(cb, FCCheckBox), \
+            "Expected an FCCheckBox, got %s" % type(cb)
+
+        self.cb = cb
+        self.optinputs = optinputs
+        self.logic = logic
+
+        self.on_cb_change()
+        self.cb.stateChanged.connect(self.on_cb_change)
+
+    def on_cb_change(self):
+
+        if self.cb.checkState():
+            for widget in self.optinputs:
+                if self.logic is True:
+                    widget.show()
+                else:
+                    widget.hide()
+        else:
+            for widget in self.optinputs:
+                if self.logic is True:
+                    widget.hide()
+                else:
+                    widget.show()
+
+
 class FCTable(QtWidgets.QTableWidget):
 class FCTable(QtWidgets.QTableWidget):
     def __init__(self, parent=None):
     def __init__(self, parent=None):
         super(FCTable, self).__init__(parent)
         super(FCTable, self).__init__(parent)
@@ -1739,7 +1782,7 @@ class _BrowserTextEdit(QTextEdit):
 
 
     def clear(self):
     def clear(self):
         QTextEdit.clear(self)
         QTextEdit.clear(self)
-        text = "FlatCAM %s (c)2014-2019 Juan Pablo Caram (Type help to get started)\n\n" % self.version
+        text = "FlatCAM %s - Open Source Software - Type help to get started\n\n" % self.version
         text = html.escape(text)
         text = html.escape(text)
         text = text.replace('\n', '<br/>')
         text = text.replace('\n', '<br/>')
         self.moveCursor(QTextCursor.End)
         self.moveCursor(QTextCursor.End)

+ 114 - 52
flatcamGUI/ObjectUI.py

@@ -254,8 +254,13 @@ class GerberObjectUI(ObjectUI):
         )
         )
         self.custom_box.addWidget(self.isolation_routing_label)
         self.custom_box.addWidget(self.isolation_routing_label)
 
 
+        # ###########################################
+        # ########## NEW GRID #######################
+        # ###########################################
+
         grid1 = QtWidgets.QGridLayout()
         grid1 = QtWidgets.QGridLayout()
         self.custom_box.addLayout(grid1)
         self.custom_box.addLayout(grid1)
+
         tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
         tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
         tdlabel.setToolTip(
         tdlabel.setToolTip(
             _("Diameter of the cutting tool.\n"
             _("Diameter of the cutting tool.\n"
@@ -265,9 +270,9 @@ class GerberObjectUI(ObjectUI):
               "this parameter.")
               "this parameter.")
         )
         )
         tdlabel.setMinimumWidth(90)
         tdlabel.setMinimumWidth(90)
-        grid1.addWidget(tdlabel, 0, 0)
         self.iso_tool_dia_entry = LengthEntry()
         self.iso_tool_dia_entry = LengthEntry()
-        grid1.addWidget(self.iso_tool_dia_entry, 0, 1)
+        grid1.addWidget(tdlabel, 0, 0)
+        grid1.addWidget(self.iso_tool_dia_entry, 0, 1, 1, 2)
 
 
         passlabel = QtWidgets.QLabel('%s:' % _('# Passes'))
         passlabel = QtWidgets.QLabel('%s:' % _('# Passes'))
         passlabel.setToolTip(
         passlabel.setToolTip(
@@ -275,10 +280,10 @@ class GerberObjectUI(ObjectUI):
               "number (integer) of tool widths.")
               "number (integer) of tool widths.")
         )
         )
         passlabel.setMinimumWidth(90)
         passlabel.setMinimumWidth(90)
-        grid1.addWidget(passlabel, 1, 0)
         self.iso_width_entry = FCSpinner()
         self.iso_width_entry = FCSpinner()
         self.iso_width_entry.setRange(1, 999)
         self.iso_width_entry.setRange(1, 999)
-        grid1.addWidget(self.iso_width_entry, 1, 1)
+        grid1.addWidget(passlabel, 1, 0)
+        grid1.addWidget(self.iso_width_entry, 1, 1, 1, 2)
 
 
         overlabel = QtWidgets.QLabel('%s:' % _('Pass overlap'))
         overlabel = QtWidgets.QLabel('%s:' % _('Pass overlap'))
         overlabel.setToolTip(
         overlabel.setToolTip(
@@ -287,9 +292,9 @@ class GerberObjectUI(ObjectUI):
               "A value here of 0.25 means an overlap of 25% from the tool diameter found above.")
               "A value here of 0.25 means an overlap of 25% from the tool diameter found above.")
         )
         )
         overlabel.setMinimumWidth(90)
         overlabel.setMinimumWidth(90)
-        grid1.addWidget(overlabel, 2, 0)
         self.iso_overlap_entry = FloatEntry()
         self.iso_overlap_entry = FloatEntry()
-        grid1.addWidget(self.iso_overlap_entry, 2, 1)
+        grid1.addWidget(overlabel, 2, 0)
+        grid1.addWidget(self.iso_overlap_entry, 2, 1, 1, 2)
 
 
         # Milling Type Radio Button
         # Milling Type Radio Button
         self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
         self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
@@ -298,27 +303,69 @@ class GerberObjectUI(ObjectUI):
               "- climb / best for precision milling and to reduce tool usage\n"
               "- climb / best for precision milling and to reduce tool usage\n"
               "- conventional / useful when there is no backlash compensation")
               "- conventional / useful when there is no backlash compensation")
         )
         )
-        grid1.addWidget(self.milling_type_label, 3, 0)
         self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
         self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
                                             {'label': _('Conv.'), 'value': 'cv'}])
                                             {'label': _('Conv.'), 'value': 'cv'}])
-        grid1.addWidget(self.milling_type_radio, 3, 1)
+        grid1.addWidget(self.milling_type_label, 3, 0)
+        grid1.addWidget(self.milling_type_radio, 3, 1, 1, 2)
 
 
         # combine all passes CB
         # combine all passes CB
         self.combine_passes_cb = FCCheckBox(label=_('Combine Passes'))
         self.combine_passes_cb = FCCheckBox(label=_('Combine Passes'))
         self.combine_passes_cb.setToolTip(
         self.combine_passes_cb.setToolTip(
             _("Combine all passes into one object")
             _("Combine all passes into one object")
         )
         )
-        grid1.addWidget(self.combine_passes_cb, 4, 0)
 
 
         # generate follow
         # generate follow
         self.follow_cb = FCCheckBox(label=_('"Follow"'))
         self.follow_cb = FCCheckBox(label=_('"Follow"'))
-        self.follow_cb.setToolTip(
-           _("Generate a 'Follow' geometry.\n"
-             "This means that it will cut through\n"
-             "the middle of the trace.")
+        self.follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
+                                    "This means that it will cut through\n"
+                                    "the middle of the trace."))
 
 
-        )
+        # avoid an area from isolation
+        self.except_cb = FCCheckBox(label=_('Except'))
+        self.except_cb.setToolTip(_("When the isolation geometry is generated,\n"
+                                    "by checking this, the area of the object bellow\n"
+                                    "will be subtracted from the isolation geometry."))
+
+        grid1.addWidget(self.combine_passes_cb, 4, 0)
         grid1.addWidget(self.follow_cb, 4, 1)
         grid1.addWidget(self.follow_cb, 4, 1)
+        grid1.addWidget(self.except_cb, 4, 2)
+
+        # ## Form Layout
+        form_layout = QtWidgets.QFormLayout()
+        grid1.addLayout(form_layout, 5, 0, 1, 3)
+
+        # ################################################
+        # ##### Type of object to be excepted ############
+        # ################################################
+        self.type_obj_combo = QtWidgets.QComboBox()
+        self.type_obj_combo.addItem("Gerber")
+        self.type_obj_combo.addItem("Excellon")
+        self.type_obj_combo.addItem("Geometry")
+
+        # we get rid of item1 ("Excellon") as it is not suitable
+        self.type_obj_combo.view().setRowHidden(1, True)
+        self.type_obj_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
+        self.type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
+
+        self.type_obj_combo_label = QtWidgets.QLabel('%s:' % _("Obj Type"))
+        self.type_obj_combo_label.setToolTip(
+            _("Specify the type of object to be excepted from isolation.\n"
+              "It can be of type: Gerber or Geometry.\n"
+              "What is selected here will dictate the kind\n"
+              "of objects that will populate the 'Object' combobox.")
+        )
+        # self.type_obj_combo_label.setMinimumWidth(60)
+        form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
+
+        # ################################################
+        # ##### The object to be excepted ################
+        # ################################################
+        self.obj_combo = QtWidgets.QComboBox()
+
+        self.obj_label = QtWidgets.QLabel('%s:' % _("Object"))
+        self.obj_label.setToolTip(_("Object whose area will be removed from isolation geometry."))
+
+        form_layout.addRow(self.obj_label, self.obj_combo)
 
 
         self.gen_iso_label = QtWidgets.QLabel("<b>%s:</b>" % _("Generate Isolation Geometry"))
         self.gen_iso_label = QtWidgets.QLabel("<b>%s:</b>" % _("Generate Isolation Geometry"))
         self.gen_iso_label.setToolTip(
         self.gen_iso_label.setToolTip(
@@ -332,14 +379,16 @@ class GerberObjectUI(ObjectUI):
               "inside the actual Gerber feature, use a negative tool\n"
               "inside the actual Gerber feature, use a negative tool\n"
               "diameter above.")
               "diameter above.")
         )
         )
-        self.custom_box.addWidget(self.gen_iso_label)
-
-        hlay_1 = QtWidgets.QHBoxLayout()
-        self.custom_box.addLayout(hlay_1)
+        grid1.addWidget(self.gen_iso_label, 6, 0, 1, 3)
 
 
-        self.padding_area_label = QtWidgets.QLabel('')
-        self.padding_area_label.setMinimumWidth(90)
-        hlay_1.addWidget(self.padding_area_label)
+        self.create_buffer_button = QtWidgets.QPushButton(_('Buffer Solid Geometry'))
+        self.create_buffer_button.setToolTip(
+            _("This button is shown only when the Gerber file\n"
+              "is loaded without buffering.\n"
+              "Clicking this will create the buffered geometry\n"
+              "required for isolation.")
+        )
+        grid1.addWidget(self.create_buffer_button, 7, 0, 1, 3)
 
 
         self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo'))
         self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo'))
         self.generate_iso_button.setToolTip(
         self.generate_iso_button.setToolTip(
@@ -347,10 +396,10 @@ class GerberObjectUI(ObjectUI):
               "for isolation routing. It contains both\n"
               "for isolation routing. It contains both\n"
               "the interiors and exteriors geometry.")
               "the interiors and exteriors geometry.")
         )
         )
-        self.generate_iso_button.setMinimumWidth(90)
-        hlay_1.addWidget(self.generate_iso_button, alignment=Qt.AlignLeft)
+        grid1.addWidget(self.generate_iso_button, 8, 0)
 
 
-        # hlay_1.addStretch()
+        hlay_1 = QtWidgets.QHBoxLayout()
+        grid1.addLayout(hlay_1, 8, 1, 1, 2)
 
 
         self.generate_ext_iso_button = QtWidgets.QPushButton(_('Ext Geo'))
         self.generate_ext_iso_button = QtWidgets.QPushButton(_('Ext Geo'))
         self.generate_ext_iso_button.setToolTip(
         self.generate_ext_iso_button.setToolTip(
@@ -370,14 +419,28 @@ class GerberObjectUI(ObjectUI):
         # self.generate_ext_iso_button.setMinimumWidth(90)
         # self.generate_ext_iso_button.setMinimumWidth(90)
         hlay_1.addWidget(self.generate_int_iso_button)
         hlay_1.addWidget(self.generate_int_iso_button)
 
 
+        self.ohis_iso = OptionalHideInputSection(
+            self.except_cb,
+            [self.type_obj_combo, self.type_obj_combo_label, self.obj_combo, self.obj_label],
+            logic=True
+        )
         # when the follow checkbox is checked then the exteriors and interiors isolation generation buttons
         # when the follow checkbox is checked then the exteriors and interiors isolation generation buttons
         # are disabled as is doesn't make sense to have them enabled due of the nature of "follow"
         # are disabled as is doesn't make sense to have them enabled due of the nature of "follow"
         self.ois_iso = OptionalInputSection(self.follow_cb,
         self.ois_iso = OptionalInputSection(self.follow_cb,
                                             [self.generate_int_iso_button, self.generate_ext_iso_button], logic=False)
                                             [self.generate_int_iso_button, self.generate_ext_iso_button], logic=False)
 
 
+        grid1.addWidget(QtWidgets.QLabel(''), 9, 0)
+
+        # ###########################################
+        # ########## NEW GRID #######################
+        # ###########################################
+
         grid2 = QtWidgets.QGridLayout()
         grid2 = QtWidgets.QGridLayout()
         self.custom_box.addLayout(grid2)
         self.custom_box.addLayout(grid2)
 
 
+        self.tool_lbl = QtWidgets.QLabel('<b>%s</b>:' % _("TOOLS"))
+        grid2.addWidget(self.tool_lbl, 0, 0, 1, 2)
+
         # ## Clear non-copper regions
         # ## Clear non-copper regions
         self.clearcopper_label = QtWidgets.QLabel("<b>%s:</b>" % _("Clear N-copper"))
         self.clearcopper_label = QtWidgets.QLabel("<b>%s:</b>" % _("Clear N-copper"))
         self.clearcopper_label.setToolTip(
         self.clearcopper_label.setToolTip(
@@ -385,14 +448,14 @@ class GerberObjectUI(ObjectUI):
               "toolpaths to cut all non-copper regions.")
               "toolpaths to cut all non-copper regions.")
         )
         )
         self.clearcopper_label.setMinimumWidth(90)
         self.clearcopper_label.setMinimumWidth(90)
-        grid2.addWidget(self.clearcopper_label, 0, 0)
 
 
         self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool'))
         self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool'))
         self.generate_ncc_button.setToolTip(
         self.generate_ncc_button.setToolTip(
             _("Create the Geometry Object\n"
             _("Create the Geometry Object\n"
               "for non-copper routing.")
               "for non-copper routing.")
         )
         )
-        grid2.addWidget(self.generate_ncc_button, 0, 1)
+        grid2.addWidget(self.clearcopper_label, 1, 0)
+        grid2.addWidget(self.generate_ncc_button, 1, 1)
 
 
         # ## Board cutout
         # ## Board cutout
         self.board_cutout_label = QtWidgets.QLabel("<b>%s:</b>" % _("Board cutout"))
         self.board_cutout_label = QtWidgets.QLabel("<b>%s:</b>" % _("Board cutout"))
@@ -401,14 +464,14 @@ class GerberObjectUI(ObjectUI):
               "the PCB and separate it from\n"
               "the PCB and separate it from\n"
               "the original board.")
               "the original board.")
         )
         )
-        grid2.addWidget(self.board_cutout_label, 1, 0)
 
 
         self.generate_cutout_button = QtWidgets.QPushButton(_('Cutout Tool'))
         self.generate_cutout_button = QtWidgets.QPushButton(_('Cutout Tool'))
         self.generate_cutout_button.setToolTip(
         self.generate_cutout_button.setToolTip(
             _("Generate the geometry for\n"
             _("Generate the geometry for\n"
               "the board cutout.")
               "the board cutout.")
         )
         )
-        grid2.addWidget(self.generate_cutout_button, 1, 1)
+        grid2.addWidget(self.board_cutout_label, 2, 0)
+        grid2.addWidget(self.generate_cutout_button, 2, 1)
 
 
         # ## Non-copper regions
         # ## Non-copper regions
         self.noncopper_label = QtWidgets.QLabel("<b>%s:</b>" % _("Non-copper regions"))
         self.noncopper_label = QtWidgets.QLabel("<b>%s:</b>" % _("Non-copper regions"))
@@ -419,10 +482,8 @@ class GerberObjectUI(ObjectUI):
               "object. Can be used to remove all\n"
               "object. Can be used to remove all\n"
               "copper from a specified region.")
               "copper from a specified region.")
         )
         )
-        self.custom_box.addWidget(self.noncopper_label)
 
 
-        grid4 = QtWidgets.QGridLayout()
-        self.custom_box.addLayout(grid4)
+        grid2.addWidget(self.noncopper_label, 3, 0, 1, 2)
 
 
         # Margin
         # Margin
         bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
         bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
@@ -433,9 +494,9 @@ class GerberObjectUI(ObjectUI):
               "distance.")
               "distance.")
         )
         )
         bmlabel.setMinimumWidth(90)
         bmlabel.setMinimumWidth(90)
-        grid4.addWidget(bmlabel, 0, 0)
         self.noncopper_margin_entry = LengthEntry()
         self.noncopper_margin_entry = LengthEntry()
-        grid4.addWidget(self.noncopper_margin_entry, 0, 1)
+        grid2.addWidget(bmlabel, 4, 0)
+        grid2.addWidget(self.noncopper_margin_entry, 4, 1)
 
 
         # Rounded corners
         # Rounded corners
         self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo"))
         self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo"))
@@ -443,10 +504,10 @@ class GerberObjectUI(ObjectUI):
             _("Resulting geometry will have rounded corners.")
             _("Resulting geometry will have rounded corners.")
         )
         )
         self.noncopper_rounded_cb.setMinimumWidth(90)
         self.noncopper_rounded_cb.setMinimumWidth(90)
-        grid4.addWidget(self.noncopper_rounded_cb, 1, 0)
 
 
         self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
         self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
-        grid4.addWidget(self.generate_noncopper_button, 1, 1)
+        grid2.addWidget(self.noncopper_rounded_cb, 5, 0)
+        grid2.addWidget(self.generate_noncopper_button, 5, 1)
 
 
         # ## Bounding box
         # ## Bounding box
         self.boundingbox_label = QtWidgets.QLabel('<b>%s:</b>' % _('Bounding Box'))
         self.boundingbox_label = QtWidgets.QLabel('<b>%s:</b>' % _('Bounding Box'))
@@ -454,10 +515,8 @@ class GerberObjectUI(ObjectUI):
             _("Create a geometry surrounding the Gerber object.\n"
             _("Create a geometry surrounding the Gerber object.\n"
               "Square shape.")
               "Square shape.")
         )
         )
-        self.custom_box.addWidget(self.boundingbox_label)
 
 
-        grid5 = QtWidgets.QGridLayout()
-        self.custom_box.addLayout(grid5)
+        grid2.addWidget(self.boundingbox_label, 6, 0, 1, 2)
 
 
         bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
         bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
         bbmargin.setToolTip(
         bbmargin.setToolTip(
@@ -465,9 +524,9 @@ class GerberObjectUI(ObjectUI):
               "to the nearest polygon.")
               "to the nearest polygon.")
         )
         )
         bbmargin.setMinimumWidth(90)
         bbmargin.setMinimumWidth(90)
-        grid5.addWidget(bbmargin, 0, 0)
         self.bbmargin_entry = LengthEntry()
         self.bbmargin_entry = LengthEntry()
-        grid5.addWidget(self.bbmargin_entry, 0, 1)
+        grid2.addWidget(bbmargin, 7, 0)
+        grid2.addWidget(self.bbmargin_entry, 7, 1)
 
 
         self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
         self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
         self.bbrounded_cb.setToolTip(
         self.bbrounded_cb.setToolTip(
@@ -477,13 +536,13 @@ class GerberObjectUI(ObjectUI):
               "the margin.")
               "the margin.")
         )
         )
         self.bbrounded_cb.setMinimumWidth(90)
         self.bbrounded_cb.setMinimumWidth(90)
-        grid5.addWidget(self.bbrounded_cb, 1, 0)
 
 
         self.generate_bb_button = QtWidgets.QPushButton(_('Generate Geo'))
         self.generate_bb_button = QtWidgets.QPushButton(_('Generate Geo'))
         self.generate_bb_button.setToolTip(
         self.generate_bb_button.setToolTip(
             _("Generate the Geometry object.")
             _("Generate the Geometry object.")
         )
         )
-        grid5.addWidget(self.generate_bb_button, 1, 1)
+        grid2.addWidget(self.bbrounded_cb, 8, 0)
+        grid2.addWidget(self.generate_bb_button, 8, 1)
 
 
 
 
 class ExcellonObjectUI(ObjectUI):
 class ExcellonObjectUI(ObjectUI):
@@ -558,7 +617,8 @@ class ExcellonObjectUI(ObjectUI):
         self.tools_table.horizontalHeaderItem(0).setToolTip(
         self.tools_table.horizontalHeaderItem(0).setToolTip(
             _("This is the Tool Number.\n"
             _("This is the Tool Number.\n"
               "When ToolChange is checked, on toolchange event this value\n"
               "When ToolChange is checked, on toolchange event this value\n"
-              "will be showed as a T1, T2 ... Tn in the Machine Code."))
+              "will be showed as a T1, T2 ... Tn in the Machine Code.\n\n"
+              "Here the tools are selected for G-code generation."))
         self.tools_table.horizontalHeaderItem(1).setToolTip(
         self.tools_table.horizontalHeaderItem(1).setToolTip(
             _("Tool Diameter. It's value (in current FlatCAM units) \n"
             _("Tool Diameter. It's value (in current FlatCAM units) \n"
               "is the cut width into the material."))
               "is the cut width into the material."))
@@ -573,7 +633,8 @@ class ExcellonObjectUI(ObjectUI):
               "to create the desired exit hole diameter due of the tip shape.\n"
               "to create the desired exit hole diameter due of the tip shape.\n"
               "The value here can compensate the Cut Z parameter."))
               "The value here can compensate the Cut Z parameter."))
         self.tools_table.horizontalHeaderItem(5).setToolTip(
         self.tools_table.horizontalHeaderItem(5).setToolTip(
-            _("Toggle display of the drills for the current tool."))
+            _("Toggle display of the drills for the current tool.\n"
+              "This does not select the tools for G-code generation."))
 
 
         self.empty_label = QtWidgets.QLabel('')
         self.empty_label = QtWidgets.QLabel('')
         self.tools_box.addWidget(self.empty_label)
         self.tools_box.addWidget(self.empty_label)
@@ -649,7 +710,7 @@ class ExcellonObjectUI(ObjectUI):
         grid1.addWidget(self.eendz_entry, 5, 1)
         grid1.addWidget(self.eendz_entry, 5, 1)
 
 
         # Excellon Feedrate
         # Excellon Feedrate
-        frlabel = QtWidgets.QLabel('%s:' % _('Feedrate (Plunge):'))
+        frlabel = QtWidgets.QLabel('%s:' % _('Feedrate (Plunge)'))
         frlabel.setToolTip(
         frlabel.setToolTip(
             _("Tool speed while drilling\n"
             _("Tool speed while drilling\n"
               "(in units per minute).\n"
               "(in units per minute).\n"
@@ -736,7 +797,8 @@ class ExcellonObjectUI(ObjectUI):
 
 
         choose_tools_label = QtWidgets.QLabel(
         choose_tools_label = QtWidgets.QLabel(
             _("Select from the Tools Table above\n"
             _("Select from the Tools Table above\n"
-              "the tools you want to include.")
+              "the hole dias that are to be drilled.\n"
+              "Use the # column to make the selection.")
         )
         )
         self.tools_box.addWidget(choose_tools_label)
         self.tools_box.addWidget(choose_tools_label)
 
 
@@ -759,7 +821,7 @@ class ExcellonObjectUI(ObjectUI):
         self.excellon_gcode_type_radio.setVisible(False)
         self.excellon_gcode_type_radio.setVisible(False)
         gcode_type_label.hide()
         gcode_type_label.hide()
 
 
-        self.generate_cnc_button = QtWidgets.QPushButton(_('Create GCode'))
+        self.generate_cnc_button = QtWidgets.QPushButton(_('Create Drills GCode'))
         self.generate_cnc_button.setToolTip(
         self.generate_cnc_button.setToolTip(
             _("Generate the CNC Job.")
             _("Generate the CNC Job.")
         )
         )
@@ -774,7 +836,8 @@ class ExcellonObjectUI(ObjectUI):
 
 
         self.choose_tools_label2 = QtWidgets.QLabel(
         self.choose_tools_label2 = QtWidgets.QLabel(
             _("Select from the Tools Table above\n"
             _("Select from the Tools Table above\n"
-              " the hole dias that are to be milled.")
+              "the hole dias that are to be milled.\n"
+              "Use the # column to make the selection.")
         )
         )
         self.tools_box.addWidget(self.choose_tools_label2)
         self.tools_box.addWidget(self.choose_tools_label2)
 
 
@@ -912,7 +975,7 @@ class GeometryObjectUI(ObjectUI):
         self.geo_tools_table.horizontalHeaderItem(3).setToolTip(
         self.geo_tools_table.horizontalHeaderItem(3).setToolTip(
             _(
             _(
                 "The (Operation) Type has only informative value. Usually the UI form values \n"
                 "The (Operation) Type has only informative value. Usually the UI form values \n"
-                "are choosed based on the operation type and this will serve as a reminder.\n"
+                "are choose based on the operation type and this will serve as a reminder.\n"
                 "Can be 'Roughing', 'Finishing' or 'Isolation'.\n"
                 "Can be 'Roughing', 'Finishing' or 'Isolation'.\n"
                 "For Roughing we may choose a lower Feedrate and multiDepth cut.\n"
                 "For Roughing we may choose a lower Feedrate and multiDepth cut.\n"
                 "For Finishing we may choose a higher Feedrate, without multiDepth.\n"
                 "For Finishing we may choose a higher Feedrate, without multiDepth.\n"
@@ -1111,7 +1174,7 @@ class GeometryObjectUI(ObjectUI):
 
 
         # Tool change:
         # Tool change:
 
 
-        self.toolchzlabel = QtWidgets.QLabel('%s:' %_("Tool change Z"))
+        self.toolchzlabel = QtWidgets.QLabel('%s:' % _("Tool change Z"))
         self.toolchzlabel.setToolTip(
         self.toolchzlabel.setToolTip(
             _(
             _(
                 "Z-axis position (height) for\n"
                 "Z-axis position (height) for\n"
@@ -1350,8 +1413,7 @@ class CNCObjectUI(ObjectUI):
         self.annotation_label.setToolTip(
         self.annotation_label.setToolTip(
             _("This selects if to display text annotation on the plot.\n"
             _("This selects if to display text annotation on the plot.\n"
               "When checked it will display numbers in order for each end\n"
               "When checked it will display numbers in order for each end\n"
-              "of a travel line."
-            )
+              "of a travel line.")
         )
         )
         self.annotation_cb = FCCheckBox()
         self.annotation_cb = FCCheckBox()
 
 

+ 1 - 1
flatcamGUI/PlotCanvas.py

@@ -34,7 +34,7 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
         """
         """
 
 
         super(PlotCanvas, self).__init__()
         super(PlotCanvas, self).__init__()
-        VisPyCanvas.__init__(self)
+        # VisPyCanvas.__init__(self)
 
 
         # VisPyCanvas does not allow new attributes. Override.
         # VisPyCanvas does not allow new attributes. Override.
         self.unfreeze()
         self.unfreeze()

+ 1 - 1
flatcamGUI/VisPyVisuals.py

@@ -187,7 +187,7 @@ class ShapeGroup(object):
 
 
 class ShapeCollectionVisual(CompoundVisual):
 class ShapeCollectionVisual(CompoundVisual):
 
 
-    def __init__(self, line_width=1, triangulation='gpc', layers=3, pool=None, **kwargs):
+    def __init__(self, line_width=1, triangulation='vispy', layers=3, pool=None, **kwargs):
         """
         """
         Represents collection of shapes to draw on VisPy scene
         Represents collection of shapes to draw on VisPy scene
         :param line_width: float
         :param line_width: float

+ 8 - 1
flatcamParsers/ParseFont.py

@@ -23,6 +23,13 @@ import freetype as ft
 from fontTools import ttLib
 from fontTools import ttLib
 
 
 import logging
 import logging
+import gettext
+import FlatCAMTranslation as fcTranslate
+import builtins
+
+fcTranslate.apply_language('strings')
+if '_' not in builtins.__dict__:
+    _ = gettext.gettext
 
 
 log = logging.getLogger('base2')
 log = logging.getLogger('base2')
 
 
@@ -295,7 +302,7 @@ class ParseFont():
             elif font_type == 'regular':
             elif font_type == 'regular':
                 path_filename = regular_dict[font_name]
                 path_filename = regular_dict[font_name]
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit("[ERROR_NOTCL] Font not supported, try another one.")
+            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Font not supported, try another one."))
             log.debug("[ERROR_NOTCL] Font Loading: %s" % str(e))
             log.debug("[ERROR_NOTCL] Font Loading: %s" % str(e))
             return "flatcam font parse failed"
             return "flatcam font parse failed"
 
 

+ 18 - 18
flatcamTools/ToolCalculators.py

@@ -307,8 +307,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 tip_diameter = float(self.tipDia_entry.get_value().replace(',', '.'))
                 tip_diameter = float(self.tipDia_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         try:
         try:
@@ -318,8 +318,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 half_tip_angle = float(self.tipAngle_entry.get_value().replace(',', '.'))
                 half_tip_angle = float(self.tipAngle_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         half_tip_angle /= 2
         half_tip_angle /= 2
 
 
@@ -330,8 +330,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 cut_depth = float(self.cutDepth_entry.get_value().replace(',', '.'))
                 cut_depth = float(self.cutDepth_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         tool_diameter = tip_diameter + (2 * cut_depth * math.tan(math.radians(half_tip_angle)))
         tool_diameter = tip_diameter + (2 * cut_depth * math.tan(math.radians(half_tip_angle)))
@@ -345,8 +345,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 mm_val = float(self.mm_entry.get_value().replace(',', '.'))
                 mm_val = float(self.mm_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         self.inch_entry.set_value('%.6f' % (mm_val / 25.4))
         self.inch_entry.set_value('%.6f' % (mm_val / 25.4))
 
 
@@ -358,8 +358,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 inch_val = float(self.inch_entry.get_value().replace(',', '.'))
                 inch_val = float(self.inch_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         self.mm_entry.set_value('%.6f' % (inch_val * 25.4))
         self.mm_entry.set_value('%.6f' % (inch_val * 25.4))
 
 
@@ -372,8 +372,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 length = float(self.pcblength_entry.get_value().replace(',', '.'))
                 length = float(self.pcblength_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         try:
         try:
@@ -383,8 +383,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 width = float(self.pcbwidth_entry.get_value().replace(',', '.'))
                 width = float(self.pcbwidth_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         try:
         try:
@@ -394,8 +394,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 density = float(self.cdensity_entry.get_value().replace(',', '.'))
                 density = float(self.cdensity_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         try:
         try:
@@ -405,8 +405,8 @@ class ToolCalculator(FlatCAMTool):
             try:
             try:
                 copper = float(self.growth_entry.get_value().replace(',', '.'))
                 copper = float(self.growth_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         calculated_current = (length * width * density) * 0.0021527820833419
         calculated_current = (length * width * density) * 0.0021527820833419

+ 64 - 52
flatcamTools/ToolCutOut.py

@@ -368,11 +368,12 @@ class CutOut(FlatCAMTool):
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
         except Exception as e:
             log.debug("CutOut.on_freeform_cutout() --> %s" % str(e))
             log.debug("CutOut.on_freeform_cutout() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), name))
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         if cutout_obj is None:
         if cutout_obj is None:
-            self.app.inform.emit(_("[ERROR_NOTCL] There is no object selected for Cutout.\nSelect one and try again."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("There is no object selected for Cutout.\nSelect one and try again."))
             return
             return
 
 
         try:
         try:
@@ -382,12 +383,13 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 dia = float(self.dia.get_value().replace(',', '.'))
                 dia = float(self.dia.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Tool diameter value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         if 0 in {dia}:
         if 0 in {dia}:
-            self.app.inform.emit(_("[WARNING_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
         try:
         try:
@@ -402,8 +404,8 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 margin = float(self.margin.get_value().replace(',', '.'))
                 margin = float(self.margin.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Margin value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
@@ -413,26 +415,27 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 gapsize = float(self.gapsize.get_value().replace(',', '.'))
                 gapsize = float(self.gapsize.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Gap size value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Gap size value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
             gaps = self.gaps.get_value()
             gaps = self.gaps.get_value()
         except TypeError:
         except TypeError:
-            self.app.inform.emit(_("[WARNING_NOTCL] Number of gaps value is missing. Add it and retry."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Number of gaps value is missing. Add it and retry."))
             return
             return
 
 
         if gaps not in ['None', 'LR', 'TB', '2LR', '2TB', '4', '8']:
         if gaps not in ['None', 'LR', 'TB', '2LR', '2TB', '4', '8']:
-            self.app.inform.emit(_("[WARNING_NOTCL] Gaps value can be only one of: "
-                                   "'None', 'lr', 'tb', '2lr', '2tb', 4 or 8. "
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Gaps value can be only one of: 'None', 'lr', 'tb', '2lr', '2tb', 4 or 8. "
                                    "Fill in a correct value and retry. "))
                                    "Fill in a correct value and retry. "))
             return
             return
 
 
         if cutout_obj.multigeo is True:
         if cutout_obj.multigeo is True:
-            self.app.inform.emit(_("[ERROR]Cutout operation cannot be done on a multi-geo Geometry.\n"
-                                   "Optionally, this Multi-geo Geometry can be converted to Single-geo Geometry,\n"
-                                   "and after that perform Cutout."))
+            self.app.inform.emit('[ERROR] %s' % _("Cutout operation cannot be done on a multi-geo Geometry.\n"
+                                                  "Optionally, this Multi-geo Geometry can be converted to "
+                                                  "Single-geo Geometry,\n"
+                                                  "and after that perform Cutout."))
             return
             return
 
 
         convex_box = self.convex_box.get_value()
         convex_box = self.convex_box.get_value()
@@ -548,7 +551,7 @@ class CutOut(FlatCAMTool):
         self.app.new_object('geometry', outname, geo_init)
         self.app.new_object('geometry', outname, geo_init)
 
 
         cutout_obj.plot()
         cutout_obj.plot()
-        self.app.inform.emit(_("[success] Any form CutOut operation finished."))
+        self.app.inform.emit('[success] %s' % _("Any form CutOut operation finished."))
         self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
         self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
         self.app.should_we_save = True
         self.app.should_we_save = True
 
 
@@ -565,11 +568,11 @@ class CutOut(FlatCAMTool):
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
         except Exception as e:
             log.debug("CutOut.on_rectangular_cutout() --> %s" % str(e))
             log.debug("CutOut.on_rectangular_cutout() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), name))
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         if cutout_obj is None:
         if cutout_obj is None:
-            self.app.inform.emit(_("[ERROR_NOTCL] Object not found: %s") % cutout_obj)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found: %s"), cutout_obj))
 
 
         try:
         try:
             dia = float(self.dia.get_value())
             dia = float(self.dia.get_value())
@@ -578,12 +581,13 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 dia = float(self.dia.get_value().replace(',', '.'))
                 dia = float(self.dia.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Tool diameter value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         if 0 in {dia}:
         if 0 in {dia}:
-            self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
         try:
         try:
@@ -598,8 +602,8 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 margin = float(self.margin.get_value().replace(',', '.'))
                 margin = float(self.margin.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Margin value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
@@ -609,26 +613,28 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 gapsize = float(self.gapsize.get_value().replace(',', '.'))
                 gapsize = float(self.gapsize.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Gap size value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Gap size value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         try:
         try:
             gaps = self.gaps.get_value()
             gaps = self.gaps.get_value()
         except TypeError:
         except TypeError:
-            self.app.inform.emit(_("[WARNING_NOTCL] Number of gaps value is missing. Add it and retry."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Number of gaps value is missing. Add it and retry."))
             return
             return
 
 
         if gaps not in ['None', 'LR', 'TB', '2LR', '2TB', '4', '8']:
         if gaps not in ['None', 'LR', 'TB', '2LR', '2TB', '4', '8']:
-            self.app.inform.emit(_("[WARNING_NOTCL] Gaps value can be only one of: "
-                                   "'None', 'lr', 'tb', '2lr', '2tb', 4 or 8. "
-                                   "Fill in a correct value and retry. "))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Gaps value can be only one of: "
+                                                          "'None', 'lr', 'tb', '2lr', '2tb', 4 or 8. "
+                                                          "Fill in a correct value and retry. "))
             return
             return
 
 
         if cutout_obj.multigeo is True:
         if cutout_obj.multigeo is True:
-            self.app.inform.emit(_("[ERROR]Cutout operation cannot be done on a multi-geo Geometry.\n"
-                                   "Optionally, this Multi-geo Geometry can be converted to Single-geo Geometry,\n"
-                                   "and after that perform Cutout."))
+            self.app.inform.emit('[ERROR] %s' % _("Cutout operation cannot be done on a multi-geo Geometry.\n"
+                                                  "Optionally, this Multi-geo Geometry can be converted to "
+                                                  "Single-geo Geometry,\n"
+                                                  "and after that perform Cutout."))
             return
             return
 
 
         # Get min and max data for each object as we just cut rectangles across X or Y
         # Get min and max data for each object as we just cut rectangles across X or Y
@@ -729,7 +735,8 @@ class CutOut(FlatCAMTool):
         self.app.new_object('geometry', outname, geo_init)
         self.app.new_object('geometry', outname, geo_init)
 
 
         # cutout_obj.plot()
         # cutout_obj.plot()
-        self.app.inform.emit(_("[success] Any form CutOut operation finished."))
+        self.app.inform.emit('[success] %s' %
+                             _("Any form CutOut operation finished."))
         self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
         self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
         self.app.should_we_save = True
         self.app.should_we_save = True
 
 
@@ -744,12 +751,13 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 self.cutting_dia = float(self.dia.get_value().replace(',', '.'))
                 self.cutting_dia = float(self.dia.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                     "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Tool diameter value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         if 0 in {self.cutting_dia}:
         if 0 in {self.cutting_dia}:
-            self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
         try:
         try:
@@ -759,8 +767,8 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 self.cutting_gapsize = float(self.gapsize.get_value().replace(',', '.'))
                 self.cutting_gapsize = float(self.gapsize.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Gap size value is missing or wrong format. "
-                                     "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Gap size value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         name = self.man_object_combo.currentText()
         name = self.man_object_combo.currentText()
@@ -769,7 +777,7 @@ class CutOut(FlatCAMTool):
             self.man_cutout_obj = self.app.collection.get_by_name(str(name))
             self.man_cutout_obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
         except Exception as e:
             log.debug("CutOut.on_manual_cutout() --> %s" % str(e))
             log.debug("CutOut.on_manual_cutout() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Geometry object: %s") % name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve Geometry object"), name))
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent)
         self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent)
@@ -788,12 +796,12 @@ class CutOut(FlatCAMTool):
             self.man_cutout_obj = self.app.collection.get_by_name(str(name))
             self.man_cutout_obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
         except Exception as e:
             log.debug("CutOut.on_manual_cutout() --> %s" % str(e))
             log.debug("CutOut.on_manual_cutout() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Geometry object: %s") % name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve Geometry object"), name))
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         if self.man_cutout_obj is None:
         if self.man_cutout_obj is None:
-            self.app.inform.emit(
-                _("[ERROR_NOTCL] Geometry object for manual cutout not found: %s") % self.man_cutout_obj)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Geometry object for manual cutout not found"), self.man_cutout_obj))
             return
             return
 
 
         # use the snapped position as reference
         # use the snapped position as reference
@@ -803,7 +811,7 @@ class CutOut(FlatCAMTool):
         self.man_cutout_obj.subtract_polygon(cut_poly)
         self.man_cutout_obj.subtract_polygon(cut_poly)
 
 
         self.man_cutout_obj.plot()
         self.man_cutout_obj.plot()
-        self.app.inform.emit(_("[success] Added manual Bridge Gap."))
+        self.app.inform.emit('[success] %s' % _("Added manual Bridge Gap."))
 
 
         self.app.should_we_save = True
         self.app.should_we_save = True
 
 
@@ -815,16 +823,18 @@ class CutOut(FlatCAMTool):
             cutout_obj = self.app.collection.get_by_name(str(name))
             cutout_obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
         except Exception as e:
             log.debug("CutOut.on_manual_geo() --> %s" % str(e))
             log.debug("CutOut.on_manual_geo() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve Gerber object: %s") % name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve Gerber object"), name))
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         if cutout_obj is None:
         if cutout_obj is None:
-            self.app.inform.emit(_("[ERROR_NOTCL] There is no Gerber object selected for Cutout.\n"
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("There is no Gerber object selected for Cutout.\n"
                                    "Select one and try again."))
                                    "Select one and try again."))
             return
             return
 
 
         if not isinstance(cutout_obj, FlatCAMGerber):
         if not isinstance(cutout_obj, FlatCAMGerber):
-            self.app.inform.emit(_("[ERROR_NOTCL] The selected object has to be of Gerber type.\n"
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("The selected object has to be of Gerber type.\n"
                                    "Select a Gerber file and try again."))
                                    "Select a Gerber file and try again."))
             return
             return
 
 
@@ -835,12 +845,13 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 dia = float(self.dia.get_value().replace(',', '.'))
                 dia = float(self.dia.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Tool diameter value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         if 0 in {dia}:
         if 0 in {dia}:
-            self.app.inform.emit(_("[ERROR_NOTCL] Tool Diameter is zero value. Change it to a positive real number."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Tool Diameter is zero value. Change it to a positive real number."))
             return "Tool Diameter is zero value. Change it to a positive real number."
             return "Tool Diameter is zero value. Change it to a positive real number."
 
 
         try:
         try:
@@ -855,8 +866,8 @@ class CutOut(FlatCAMTool):
             try:
             try:
                 margin = float(self.margin.get_value().replace(',', '.'))
                 margin = float(self.margin.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Margin value is missing or wrong format. Add it and retry."))
                 return
                 return
 
 
         convex_box = self.convex_box.get_value()
         convex_box = self.convex_box.get_value()
@@ -877,7 +888,8 @@ class CutOut(FlatCAMTool):
                     geo = box(x0, y0, x1, y1)
                     geo = box(x0, y0, x1, y1)
                     geo_obj.solid_geometry = geo.buffer(margin + abs(dia / 2))
                     geo_obj.solid_geometry = geo.buffer(margin + abs(dia / 2))
                 else:
                 else:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Geometry not supported for cutout: %s") % type(geo_union))
+                    self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                         (_("Geometry not supported for cutout"), type(geo_union)))
                     return 'fail'
                     return 'fail'
             else:
             else:
                 geo = geo_union
                 geo = geo_union

+ 27 - 25
flatcamTools/ToolDblSided.py

@@ -328,8 +328,8 @@ class DblSidedTool(FlatCAMTool):
             try:
             try:
                 px, py = self.point_entry.get_value()
                 px, py = self.point_entry.get_value()
             except TypeError:
             except TypeError:
-                self.app.inform.emit(_("[WARNING_NOTCL] 'Point' reference is selected and 'Point' coordinates "
-                                       "are missing. Add them and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("'Point' reference is selected and 'Point' coordinates "
+                                                              "are missing. Add them and retry."))
                 return
                 return
         else:
         else:
             selection_index = self.box_combo.currentIndex()
             selection_index = self.box_combo.currentIndex()
@@ -347,7 +347,7 @@ class DblSidedTool(FlatCAMTool):
                         bb_obj = model_index.internalPointer().obj
                         bb_obj = model_index.internalPointer().obj
                     except AttributeError:
                     except AttributeError:
                         self.app.inform.emit(
                         self.app.inform.emit(
-                            _("[WARNING_NOTCL] There is no Box reference object loaded. Load one and retry."))
+                            '[WARNING_NOTCL] %s' % _("There is no Box reference object loaded. Load one and retry."))
                         return
                         return
 
 
             xmin, ymin, xmax, ymax = bb_obj.bounds()
             xmin, ymin, xmax, ymax = bb_obj.bounds()
@@ -364,20 +364,21 @@ class DblSidedTool(FlatCAMTool):
                 dia = float(self.drill_dia.get_value().replace(',', '.'))
                 dia = float(self.drill_dia.get_value().replace(',', '.'))
                 self.drill_dia.set_value(dia)
                 self.drill_dia.set_value(dia)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
-                                       "Add it and retry."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("Tool diameter value is missing or wrong format. "
+                                                              "Add it and retry."))
                 return
                 return
 
 
         if dia is '':
         if dia is '':
-            self.app.inform.emit(_("[WARNING_NOTCL] No value or wrong format in Drill Dia entry. Add it and retry."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No value or wrong format in Drill Dia entry. Add it and retry."))
             return
             return
         tools = {"1": {"C": dia}}
         tools = {"1": {"C": dia}}
 
 
         # holes = self.alignment_holes.get_value()
         # holes = self.alignment_holes.get_value()
         holes = eval('[{}]'.format(self.alignment_holes.text()))
         holes = eval('[{}]'.format(self.alignment_holes.text()))
         if not holes:
         if not holes:
-            self.app.inform.emit(_("[WARNING_NOTCL] There are no Alignment Drill Coordinates to use. "
-                                   "Add them and retry."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("There are no Alignment Drill Coordinates to use. "
+                                                          "Add them and retry."))
             return
             return
 
 
         drills = []
         drills = []
@@ -399,7 +400,7 @@ class DblSidedTool(FlatCAMTool):
 
 
         self.app.new_object("excellon", "Alignment Drills", obj_init)
         self.app.new_object("excellon", "Alignment Drills", obj_init)
         self.drill_values = ''
         self.drill_values = ''
-        self.app.inform.emit(_("[success] Excellon object with alignment drills created..."))
+        self.app.inform.emit('[success] %s' % _("Excellon object with alignment drills created..."))
 
 
     def on_mirror_gerber(self):
     def on_mirror_gerber(self):
         selection_index = self.gerber_object_combo.currentIndex()
         selection_index = self.gerber_object_combo.currentIndex()
@@ -408,11 +409,11 @@ class DblSidedTool(FlatCAMTool):
         try:
         try:
             fcobj = model_index.internalPointer().obj
             fcobj = model_index.internalPointer().obj
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit(_("[WARNING_NOTCL] There is no Gerber object loaded ..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
             return
             return
 
 
         if not isinstance(fcobj, FlatCAMGerber):
         if not isinstance(fcobj, FlatCAMGerber):
-            self.app.inform.emit(_("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber, Excellon and Geometry objects can be mirrored."))
             return
             return
 
 
         axis = self.mirror_axis.get_value()
         axis = self.mirror_axis.get_value()
@@ -422,8 +423,8 @@ class DblSidedTool(FlatCAMTool):
             try:
             try:
                 px, py = self.point_entry.get_value()
                 px, py = self.point_entry.get_value()
             except TypeError:
             except TypeError:
-                self.app.inform.emit(_("[WARNING_NOTCL] 'Point' coordinates missing. "
-                                       "Using Origin (0, 0) as mirroring reference."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("'Point' coordinates missing. "
+                                                              "Using Origin (0, 0) as mirroring reference."))
                 px, py = (0, 0)
                 px, py = (0, 0)
 
 
         else:
         else:
@@ -432,7 +433,7 @@ class DblSidedTool(FlatCAMTool):
             try:
             try:
                 bb_obj = model_index_box.internalPointer().obj
                 bb_obj = model_index_box.internalPointer().obj
             except Exception as e:
             except Exception as e:
-                self.app.inform.emit(_("[WARNING_NOTCL] There is no Box object loaded ..."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Box object loaded ..."))
                 return
                 return
 
 
             xmin, ymin, xmax, ymax = bb_obj.bounds()
             xmin, ymin, xmax, ymax = bb_obj.bounds()
@@ -442,7 +443,7 @@ class DblSidedTool(FlatCAMTool):
         fcobj.mirror(axis, [px, py])
         fcobj.mirror(axis, [px, py])
         self.app.object_changed.emit(fcobj)
         self.app.object_changed.emit(fcobj)
         fcobj.plot()
         fcobj.plot()
-        self.app.inform.emit(_("[success] Gerber %s was mirrored...") % str(fcobj.options['name']))
+        self.app.inform.emit('[success] Gerber %s %s...' % (str(fcobj.options['name']), _("was mirrored")))
 
 
     def on_mirror_exc(self):
     def on_mirror_exc(self):
         selection_index = self.exc_object_combo.currentIndex()
         selection_index = self.exc_object_combo.currentIndex()
@@ -451,11 +452,11 @@ class DblSidedTool(FlatCAMTool):
         try:
         try:
             fcobj = model_index.internalPointer().obj
             fcobj = model_index.internalPointer().obj
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit(_("[WARNING_NOTCL] There is no Excellon object loaded ..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Excellon object loaded ..."))
             return
             return
 
 
         if not isinstance(fcobj, FlatCAMExcellon):
         if not isinstance(fcobj, FlatCAMExcellon):
-            self.app.inform.emit(_("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber, Excellon and Geometry objects can be mirrored."))
             return
             return
 
 
         axis = self.mirror_axis.get_value()
         axis = self.mirror_axis.get_value()
@@ -466,8 +467,8 @@ class DblSidedTool(FlatCAMTool):
                 px, py = self.point_entry.get_value()
                 px, py = self.point_entry.get_value()
             except Exception as e:
             except Exception as e:
                 log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
                 log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
-                self.app.inform.emit(_("[WARNING_NOTCL] There are no Point coordinates in the Point field. "
-                                       "Add coords and try again ..."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("There are no Point coordinates in the Point field. "
+                                                              "Add coords and try again ..."))
                 return
                 return
         else:
         else:
             selection_index_box = self.box_combo.currentIndex()
             selection_index_box = self.box_combo.currentIndex()
@@ -476,7 +477,7 @@ class DblSidedTool(FlatCAMTool):
                 bb_obj = model_index_box.internalPointer().obj
                 bb_obj = model_index_box.internalPointer().obj
             except Exception as e:
             except Exception as e:
                 log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
                 log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
-                self.app.inform.emit(_("[WARNING_NOTCL] There is no Box object loaded ..."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Box object loaded ..."))
                 return
                 return
 
 
             xmin, ymin, xmax, ymax = bb_obj.bounds()
             xmin, ymin, xmax, ymax = bb_obj.bounds()
@@ -486,7 +487,7 @@ class DblSidedTool(FlatCAMTool):
         fcobj.mirror(axis, [px, py])
         fcobj.mirror(axis, [px, py])
         self.app.object_changed.emit(fcobj)
         self.app.object_changed.emit(fcobj)
         fcobj.plot()
         fcobj.plot()
-        self.app.inform.emit(_("[success] Excellon %s was mirrored...") % str(fcobj.options['name']))
+        self.app.inform.emit('[success] Excellon %s %s...' % (str(fcobj.options['name']), _("was mirrored")))
 
 
     def on_mirror_geo(self):
     def on_mirror_geo(self):
         selection_index = self.geo_object_combo.currentIndex()
         selection_index = self.geo_object_combo.currentIndex()
@@ -495,11 +496,11 @@ class DblSidedTool(FlatCAMTool):
         try:
         try:
             fcobj = model_index.internalPointer().obj
             fcobj = model_index.internalPointer().obj
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit(_("[WARNING_NOTCL] There is no Geometry object loaded ..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Geometry object loaded ..."))
             return
             return
 
 
         if not isinstance(fcobj, FlatCAMGeometry):
         if not isinstance(fcobj, FlatCAMGeometry):
-            self.app.inform.emit(_("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber, Excellon and Geometry objects can be mirrored."))
             return
             return
 
 
         axis = self.mirror_axis.get_value()
         axis = self.mirror_axis.get_value()
@@ -513,7 +514,7 @@ class DblSidedTool(FlatCAMTool):
             try:
             try:
                 bb_obj = model_index_box.internalPointer().obj
                 bb_obj = model_index_box.internalPointer().obj
             except Exception as e:
             except Exception as e:
-                self.app.inform.emit(_("[WARNING_NOTCL] There is no Box object loaded ..."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Box object loaded ..."))
                 return
                 return
 
 
             xmin, ymin, xmax, ymax = bb_obj.bounds()
             xmin, ymin, xmax, ymax = bb_obj.bounds()
@@ -523,7 +524,8 @@ class DblSidedTool(FlatCAMTool):
         fcobj.mirror(axis, [px, py])
         fcobj.mirror(axis, [px, py])
         self.app.object_changed.emit(fcobj)
         self.app.object_changed.emit(fcobj)
         fcobj.plot()
         fcobj.plot()
-        self.app.inform.emit(_("[success] Geometry %s was mirrored...") % str(fcobj.options['name']))
+        self.app.inform.emit('[success] Geometry %s %s...' % (str(fcobj.options['name']), _("was mirrored")))
+
 
 
     def on_point_add(self):
     def on_point_add(self):
         val = self.app.defaults["global_point_clipboard_format"] % (self.app.pos[0], self.app.pos[1])
         val = self.app.defaults["global_point_clipboard_format"] % (self.app.pos[0], self.app.pos[1])

+ 8 - 8
flatcamTools/ToolFilm.py

@@ -227,13 +227,15 @@ class Film(FlatCAMTool):
         try:
         try:
             name = self.tf_object_combo.currentText()
             name = self.tf_object_combo.currentText()
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit(_("[ERROR_NOTCL] No FlatCAM object selected. Load an object for Film and retry."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("No FlatCAM object selected. Load an object for Film and retry."))
             return
             return
 
 
         try:
         try:
             boxname = self.tf_box_combo.currentText()
             boxname = self.tf_box_combo.currentText()
         except Exception as e:
         except Exception as e:
-            self.app.inform.emit(_("[ERROR_NOTCL] No FlatCAM object selected. Load an object for Box and retry."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("No FlatCAM object selected. Load an object for Box and retry."))
             return
             return
 
 
         try:
         try:
@@ -243,15 +245,13 @@ class Film(FlatCAMTool):
             try:
             try:
                 border = float(self.boundary_entry.get_value().replace(',', '.'))
                 border = float(self.boundary_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         try:
         try:
             scale_stroke_width = int(self.film_scale_entry.get_value())
             scale_stroke_width = int(self.film_scale_entry.get_value())
         except ValueError:
         except ValueError:
-            self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                 "use a number."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
             return
             return
 
 
         if border is None:
         if border is None:
@@ -271,7 +271,7 @@ class Film(FlatCAMTool):
             filename = str(filename)
             filename = str(filename)
 
 
             if str(filename) == "":
             if str(filename) == "":
-                self.app.inform.emit(_("[WARNING_NOTCL] Export SVG positive cancelled."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG positive cancelled."))
                 return
                 return
             else:
             else:
                 self.app.export_svg_black(name, boxname, filename, scale_factor=scale_stroke_width)
                 self.app.export_svg_black(name, boxname, filename, scale_factor=scale_stroke_width)
@@ -287,7 +287,7 @@ class Film(FlatCAMTool):
             filename = str(filename)
             filename = str(filename)
 
 
             if str(filename) == "":
             if str(filename) == "":
-                self.app.inform.emit(_("[WARNING_NOTCL] Export SVG negative cancelled."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG negative cancelled."))
                 return
                 return
             else:
             else:
                 self.app.export_svg_negative(name, boxname, filename, border, scale_factor=scale_stroke_width)
                 self.app.export_svg_negative(name, boxname, filename, border, scale_factor=scale_stroke_width)

+ 34 - 21
flatcamTools/ToolMove.py

@@ -24,6 +24,7 @@ if '_' not in builtins.__dict__:
 class ToolMove(FlatCAMTool):
 class ToolMove(FlatCAMTool):
 
 
     toolName = _("Move")
     toolName = _("Move")
+    replot_signal = pyqtSignal(list)
 
 
     def __init__(self, app):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
         FlatCAMTool.__init__(self, app)
@@ -45,6 +46,8 @@ class ToolMove(FlatCAMTool):
         # VisPy visuals
         # VisPy visuals
         self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
         self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
 
 
+        self.replot_signal[list].connect(self.replot)
+
     def install(self, icon=None, separator=None, **kwargs):
     def install(self, icon=None, separator=None, **kwargs):
         FlatCAMTool.install(self, icon, separator, shortcut='M', **kwargs)
         FlatCAMTool.install(self, icon, separator, shortcut='M', **kwargs)
 
 
@@ -85,7 +88,7 @@ class ToolMove(FlatCAMTool):
                 self.setVisible(False)
                 self.setVisible(False)
                 # signal that there is no command active
                 # signal that there is no command active
                 self.app.command_active = None
                 self.app.command_active = None
-                self.app.inform.emit(_("[WARNING_NOTCL] MOVE action cancelled. No object(s) to move."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("MOVE action cancelled. No object(s) to move."))
 
 
     def on_left_click(self, event):
     def on_left_click(self, event):
         # mouse click will be accepted only if the left button is clicked
         # mouse click will be accepted only if the left button is clicked
@@ -125,21 +128,20 @@ class ToolMove(FlatCAMTool):
                     dx = pos[0] - self.point1[0]
                     dx = pos[0] - self.point1[0]
                     dy = pos[1] - self.point1[1]
                     dy = pos[1] - self.point1[1]
 
 
-                    proc = self.app.proc_container.new(_("Moving ..."))
+                    obj_list = self.app.collection.get_selected()
 
 
                     def job_move(app_obj):
                     def job_move(app_obj):
-                        obj_list = self.app.collection.get_selected()
+                        with self.app.proc_container.new(_("Moving...")) as proc:
+                            try:
+                                if not obj_list:
+                                    self.app.inform.emit('[WARNING_NOTCL] %s' % _("No object(s) selected."))
+                                    return "fail"
 
 
-                        try:
-                            if not obj_list:
-                                self.app.inform.emit(_("[WARNING_NOTCL] No object(s) selected."))
-                                return "fail"
-                            else:
                                 for sel_obj in obj_list:
                                 for sel_obj in obj_list:
 
 
                                     # offset solid_geometry
                                     # offset solid_geometry
                                     sel_obj.offset((dx, dy))
                                     sel_obj.offset((dx, dy))
-                                    sel_obj.plot()
+                                    # sel_obj.plot()
 
 
                                     try:
                                     try:
                                         sel_obj.replotApertures.emit()
                                         sel_obj.replotApertures.emit()
@@ -152,17 +154,19 @@ class ToolMove(FlatCAMTool):
                                     sel_obj.options['ymin'] = b
                                     sel_obj.options['ymin'] = b
                                     sel_obj.options['xmax'] = c
                                     sel_obj.options['xmax'] = c
                                     sel_obj.options['ymax'] = d
                                     sel_obj.options['ymax'] = d
-                                    # self.app.collection.set_active(sel_obj.options['name'])
-                        except Exception as e:
-                            proc.done()
-                            self.app.inform.emit(_('[ERROR_NOTCL] '
-                                                 'ToolMove.on_left_click() --> %s') % str(e))
-                            return "fail"
+
+                                # time to plot the moved objects
+                                self.replot_signal.emit(obj_list)
+                            except Exception as e:
+                                proc.done()
+                                self.app.inform.emit('[ERROR_NOTCL] %s --> %s' % (_('ToolMove.on_left_click()'), str(e)))
+                                return "fail"
+
                         proc.done()
                         proc.done()
                         # delete the selection bounding box
                         # delete the selection bounding box
                         self.delete_shape()
                         self.delete_shape()
-                        self.app.inform.emit(_('[success] %s object was moved ...') %
-                                             str(sel_obj.kind).capitalize())
+                        self.app.inform.emit('[success] %s %s' %
+                                             (str(sel_obj.kind).capitalize(), 'object was moved ...'))
 
 
                     self.app.worker_task.emit({'fcn': job_move, 'params': [self]})
                     self.app.worker_task.emit({'fcn': job_move, 'params': [self]})
 
 
@@ -171,12 +175,21 @@ class ToolMove(FlatCAMTool):
                     return
                     return
 
 
                 except TypeError:
                 except TypeError:
-                    self.app.inform.emit(_('[ERROR_NOTCL] '
-                                         'ToolMove.on_left_click() --> Error when mouse left click.'))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _('ToolMove.on_left_click() --> Error when mouse left click.'))
                     return
                     return
 
 
             self.clicked_move = 1
             self.clicked_move = 1
 
 
+    def replot(self, obj_list):
+
+        def worker_task():
+            with self.app.proc_container.new('%s...' % _("Plotting")):
+                for sel_obj in obj_list:
+                    sel_obj.plot()
+
+        self.app.worker_task.emit({'fcn': worker_task, 'params': []})
+
     def on_move(self, event):
     def on_move(self, event):
         pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
         pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
 
 
@@ -199,7 +212,7 @@ class ToolMove(FlatCAMTool):
     def on_key_press(self, event):
     def on_key_press(self, event):
         if event.key == 'escape':
         if event.key == 'escape':
             # abort the move action
             # abort the move action
-            self.app.inform.emit(_("[WARNING_NOTCL] Move action cancelled."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Move action cancelled."))
             self.toggle()
             self.toggle()
         return
         return
 
 
@@ -211,7 +224,7 @@ class ToolMove(FlatCAMTool):
 
 
         obj_list = self.app.collection.get_selected()
         obj_list = self.app.collection.get_selected()
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] Object(s) not selected"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Object(s) not selected"))
             self.toggle()
             self.toggle()
         else:
         else:
             # if we have an object selected then we can safely activate the mouse events
             # if we have an object selected then we can safely activate the mouse events

Разница между файлами не показана из-за своего большого размера
+ 444 - 209
flatcamTools/ToolNonCopperClear.py


+ 35 - 8
flatcamTools/ToolPDF.py

@@ -156,7 +156,7 @@ class ToolPDF(FlatCAMTool):
             filenames, _f = QtWidgets.QFileDialog.getOpenFileNames(caption=_("Open PDF"), filter=_filter_)
             filenames, _f = QtWidgets.QFileDialog.getOpenFileNames(caption=_("Open PDF"), filter=_filter_)
 
 
         if len(filenames) == 0:
         if len(filenames) == 0:
-            self.app.inform.emit(_("[WARNING_NOTCL] Open PDF cancelled."))
+            self.app.inform.emit('[WARNING_NOTCL] %s.' % _("Open PDF cancelled"))
         else:
         else:
             # start the parsing timer with a period of 1 second
             # start the parsing timer with a period of 1 second
             self.periodic_check(1000)
             self.periodic_check(1000)
@@ -183,12 +183,20 @@ class ToolPDF(FlatCAMTool):
             # 1 inch = 72 points => 1 point = 1 / 72 = 0.01388888888 inch
             # 1 inch = 72 points => 1 point = 1 / 72 = 0.01388888888 inch
             self.point_to_unit_factor = 1 / 72
             self.point_to_unit_factor = 1 / 72
 
 
+        if self.app.abort_flag:
+            # graceful abort requested by the user
+            raise FlatCAMApp.GracefulException
+
         with self.app.proc_container.new(_("Parsing PDF file ...")):
         with self.app.proc_container.new(_("Parsing PDF file ...")):
             with open(filename, "rb") as f:
             with open(filename, "rb") as f:
                 pdf = f.read()
                 pdf = f.read()
 
 
             stream_nr = 0
             stream_nr = 0
             for s in re.findall(self.stream_re, pdf):
             for s in re.findall(self.stream_re, pdf):
+                if self.app.abort_flag:
+                    # graceful abort requested by the user
+                    raise FlatCAMApp.GracefulException
+
                 stream_nr += 1
                 stream_nr += 1
                 log.debug(" PDF STREAM: %d\n" % stream_nr)
                 log.debug(" PDF STREAM: %d\n" % stream_nr)
                 s = s.strip(b'\r\n')
                 s = s.strip(b'\r\n')
@@ -241,8 +249,7 @@ class ToolPDF(FlatCAMTool):
                 name_tool += 1
                 name_tool += 1
 
 
                 # create tools dictionary
                 # create tools dictionary
-                spec = {"C": dia}
-                spec['solid_geometry'] = []
+                spec = {"C": dia, 'solid_geometry': []}
                 exc_obj.tools[str(name_tool)] = spec
                 exc_obj.tools[str(name_tool)] = spec
 
 
                 # create drill list of dictionaries
                 # create drill list of dictionaries
@@ -259,19 +266,22 @@ class ToolPDF(FlatCAMTool):
             for tool in exc_obj.tools:
             for tool in exc_obj.tools:
                 if exc_obj.tools[tool]['solid_geometry']:
                 if exc_obj.tools[tool]['solid_geometry']:
                     return
                     return
-            app_obj.inform.emit(_("[ERROR_NOTCL] No geometry found in file: %s") % outname)
+            app_obj.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                (_("No geometry found in file"), outname))
             return "fail"
             return "fail"
 
 
         with self.app.proc_container.new(_("Rendering PDF layer #%d ...") % int(layer_nr)):
         with self.app.proc_container.new(_("Rendering PDF layer #%d ...") % int(layer_nr)):
 
 
             ret_val = self.app.new_object("excellon", outname, obj_init, autoselected=False)
             ret_val = self.app.new_object("excellon", outname, obj_init, autoselected=False)
             if ret_val == 'fail':
             if ret_val == 'fail':
-                self.app.inform.emit(_('[ERROR_NOTCL] Open PDF file failed.'))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _('Open PDF file failed.'))
                 return
                 return
             # Register recent file
             # Register recent file
             self.app.file_opened.emit("excellon", filename)
             self.app.file_opened.emit("excellon", filename)
             # GUI feedback
             # GUI feedback
-            self.app.inform.emit(_("[success] Rendered: %s") % outname)
+            self.app.inform.emit('[success] %s: %s' %
+                                 (_("Rendered"),  outname))
 
 
     def layer_rendering_as_gerber(self, filename, ap_dict, layer_nr):
     def layer_rendering_as_gerber(self, filename, ap_dict, layer_nr):
         outname = filename.split('/')[-1].split('\\')[-1] + "_%s" % str(layer_nr)
         outname = filename.split('/')[-1].split('\\')[-1] + "_%s" % str(layer_nr)
@@ -339,12 +349,13 @@ class ToolPDF(FlatCAMTool):
 
 
             ret = self.app.new_object('gerber', outname, obj_init, autoselected=False)
             ret = self.app.new_object('gerber', outname, obj_init, autoselected=False)
             if ret == 'fail':
             if ret == 'fail':
-                self.app.inform.emit(_('[ERROR_NOTCL] Open PDF file failed.'))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _('Open PDF file failed.'))
                 return
                 return
             # Register recent file
             # Register recent file
             self.app.file_opened.emit('gerber', filename)
             self.app.file_opened.emit('gerber', filename)
             # GUI feedback
             # GUI feedback
-            self.app.inform.emit(_("[success] Rendered: %s") % outname)
+            self.app.inform.emit('[success] %s: %s' % (_("Rendered"), outname))
 
 
     def periodic_check(self, check_period):
     def periodic_check(self, check_period):
         """
         """
@@ -386,10 +397,18 @@ class ToolPDF(FlatCAMTool):
                 if self.pdf_parsed:
                 if self.pdf_parsed:
                     obj_to_delete = []
                     obj_to_delete = []
                     for object_name in self.pdf_parsed:
                     for object_name in self.pdf_parsed:
+                        if self.app.abort_flag:
+                            # graceful abort requested by the user
+                            raise FlatCAMApp.GracefulException
+
                         filename = deepcopy(self.pdf_parsed[object_name]['filename'])
                         filename = deepcopy(self.pdf_parsed[object_name]['filename'])
                         pdf_content = deepcopy(self.pdf_parsed[object_name]['pdf'])
                         pdf_content = deepcopy(self.pdf_parsed[object_name]['pdf'])
                         obj_to_delete.append(object_name)
                         obj_to_delete.append(object_name)
                         for k in pdf_content:
                         for k in pdf_content:
+                            if self.app.abort_flag:
+                                # graceful abort requested by the user
+                                raise FlatCAMApp.GracefulException
+
                             ap_dict = pdf_content[k]
                             ap_dict = pdf_content[k]
                             if ap_dict:
                             if ap_dict:
                                 layer_nr = k
                                 layer_nr = k
@@ -467,6 +486,10 @@ class ToolPDF(FlatCAMTool):
         lines = pdf_content.splitlines()
         lines = pdf_content.splitlines()
 
 
         for pline in lines:
         for pline in lines:
+            if self.app.abort_flag:
+                # graceful abort requested by the user
+                raise FlatCAMApp.GracefulException
+
             line_nr += 1
             line_nr += 1
             log.debug("line %d: %s" % (line_nr, pline))
             log.debug("line %d: %s" % (line_nr, pline))
 
 
@@ -1325,6 +1348,10 @@ class ToolPDF(FlatCAMTool):
             if x in object_dict:
             if x in object_dict:
                 object_dict.pop(x)
                 object_dict.pop(x)
 
 
+        if self.app.abort_flag:
+            # graceful abort requested by the user
+            raise FlatCAMApp.GracefulException
+
         return object_dict
         return object_dict
 
 
     def bezier_to_points(self, start, c1, c2, stop):
     def bezier_to_points(self, start, c1, c2, stop):

Разница между файлами не показана из-за своего большого размера
+ 384 - 143
flatcamTools/ToolPaint.py


+ 43 - 47
flatcamTools/ToolPanelize.py

@@ -355,13 +355,15 @@ class Panelize(FlatCAMTool):
             obj = self.app.collection.get_by_name(str(name))
             obj = self.app.collection.get_by_name(str(name))
         except Exception as e:
         except Exception as e:
             log.debug("Panelize.on_panelize() --> %s" % str(e))
             log.debug("Panelize.on_panelize() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Could not retrieve object"), name))
             return "Could not retrieve object: %s" % name
             return "Could not retrieve object: %s" % name
 
 
         panel_obj = obj
         panel_obj = obj
 
 
         if panel_obj is None:
         if panel_obj is None:
-            self.app.inform.emit(_("[ERROR_NOTCL] Object not found: %s") % panel_obj)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Object not found"), panel_obj))
             return "Object not found: %s" % panel_obj
             return "Object not found: %s" % panel_obj
 
 
         boxname = self.box_combo.currentText()
         boxname = self.box_combo.currentText()
@@ -370,11 +372,13 @@ class Panelize(FlatCAMTool):
             box = self.app.collection.get_by_name(boxname)
             box = self.app.collection.get_by_name(boxname)
         except Exception as e:
         except Exception as e:
             log.debug("Panelize.on_panelize() --> %s" % str(e))
             log.debug("Panelize.on_panelize() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % boxname)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Could not retrieve object"), boxname))
             return "Could not retrieve object: %s" % boxname
             return "Could not retrieve object: %s" % boxname
 
 
         if box is None:
         if box is None:
-            self.app.inform.emit(_("[WARNING_NOTCL]No object Box. Using instead %s") % panel_obj)
+            self.app.inform.emit('[WARNING_NOTCL]%s: %s' %
+                                 (_("No object Box. Using instead"), panel_obj))
             self.reference_radio.set_value('bbox')
             self.reference_radio.set_value('bbox')
 
 
         if self.reference_radio.get_value() == 'bbox':
         if self.reference_radio.get_value() == 'bbox':
@@ -389,8 +393,8 @@ class Panelize(FlatCAMTool):
             try:
             try:
                 spacing_columns = float(self.spacing_columns.get_value().replace(',', '.'))
                 spacing_columns = float(self.spacing_columns.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         spacing_columns = spacing_columns if spacing_columns is not None else 0
         spacing_columns = spacing_columns if spacing_columns is not None else 0
 
 
@@ -401,8 +405,8 @@ class Panelize(FlatCAMTool):
             try:
             try:
                 spacing_rows = float(self.spacing_rows.get_value().replace(',', '.'))
                 spacing_rows = float(self.spacing_rows.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         spacing_rows = spacing_rows if spacing_rows is not None else 0
         spacing_rows = spacing_rows if spacing_rows is not None else 0
 
 
@@ -414,8 +418,8 @@ class Panelize(FlatCAMTool):
                 rows = float(self.rows.get_value().replace(',', '.'))
                 rows = float(self.rows.get_value().replace(',', '.'))
                 rows = int(rows)
                 rows = int(rows)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         rows = rows if rows is not None else 1
         rows = rows if rows is not None else 1
 
 
@@ -427,8 +431,8 @@ class Panelize(FlatCAMTool):
                 columns = float(self.columns.get_value().replace(',', '.'))
                 columns = float(self.columns.get_value().replace(',', '.'))
                 columns = int(columns)
                 columns = int(columns)
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         columns = columns if columns is not None else 1
         columns = columns if columns is not None else 1
 
 
@@ -439,8 +443,8 @@ class Panelize(FlatCAMTool):
             try:
             try:
                 constrain_dx = float(self.x_width_entry.get_value().replace(',', '.'))
                 constrain_dx = float(self.x_width_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         try:
         try:
@@ -450,14 +454,15 @@ class Panelize(FlatCAMTool):
             try:
             try:
                 constrain_dy = float(self.y_height_entry.get_value().replace(',', '.'))
                 constrain_dy = float(self.y_height_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                     "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         panel_type = str(self.panel_type_radio.get_value())
         panel_type = str(self.panel_type_radio.get_value())
 
 
         if 0 in {columns, rows}:
         if 0 in {columns, rows}:
-            self.app.inform.emit(_("[ERROR_NOTCL] Columns or Rows are zero value. Change them to a positive integer."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Columns or Rows are zero value. Change them to a positive integer."))
             return "Columns or Rows are zero value. Change them to a positive integer."
             return "Columns or Rows are zero value. Change them to a positive integer."
 
 
         xmin, ymin, xmax, ymax = box.bounds()
         xmin, ymin, xmax, ymax = box.bounds()
@@ -560,12 +565,7 @@ class Panelize(FlatCAMTool):
                     if isinstance(panel_obj, FlatCAMGerber):
                     if isinstance(panel_obj, FlatCAMGerber):
                         obj_fin.apertures = deepcopy(panel_obj.apertures)
                         obj_fin.apertures = deepcopy(panel_obj.apertures)
                         for ap in obj_fin.apertures:
                         for ap in obj_fin.apertures:
-                            if 'solid_geometry' in obj_fin.apertures[ap]:
-                                obj_fin.apertures[ap]['solid_geometry'] = []
-                            if 'clear_geometry' in obj_fin.apertures[ap]:
-                                obj_fin.apertures[ap]['clear_geometry'] = []
-                            if 'follow_geometry' in obj_fin.apertures[ap]:
-                                obj_fin.apertures[ap]['follow_geometry'] = []
+                            obj_fin.apertures[ap]['geometry'] = list()
 
 
                     self.app.progress.emit(0)
                     self.app.progress.emit(0)
                     for row in range(rows):
                     for row in range(rows):
@@ -594,33 +594,29 @@ class Panelize(FlatCAMTool):
                                     obj_fin.solid_geometry.append(geo)
                                     obj_fin.solid_geometry.append(geo)
 
 
                                 for apid in panel_obj.apertures:
                                 for apid in panel_obj.apertures:
-                                    if 'solid_geometry' in panel_obj.apertures[apid]:
-                                        geo_aper = translate_recursion(panel_obj.apertures[apid]['solid_geometry'])
-                                        if isinstance(geo_aper, list):
-                                            obj_fin.apertures[apid]['solid_geometry'] += geo_aper
-                                        else:
-                                            obj_fin.apertures[apid]['solid_geometry'].append(geo_aper)
+                                    for el in panel_obj.apertures[apid]['geometry']:
+                                        new_el = dict()
+                                        if 'solid' in el:
+                                            geo_aper = translate_recursion(el['solid'])
+                                            new_el['solid'] = deepcopy(geo_aper)
 
 
-                                    if 'clear_geometry' in panel_obj.apertures[apid]:
-                                        geo_aper = translate_recursion(panel_obj.apertures[apid]['clear_geometry'])
-                                        if isinstance(geo_aper, list):
-                                            obj_fin.apertures[apid]['clear_geometry'] += geo_aper
-                                        else:
-                                            obj_fin.apertures[apid]['clear_geometry'].append(geo_aper)
+                                        if 'clear' in el:
+                                            geo_aper = translate_recursion(el['clear'])
+                                            new_el['clear'] = deepcopy(geo_aper)
 
 
-                                    if 'follow_geometry' in panel_obj.apertures[apid]:
-                                        geo_aper = translate_recursion(panel_obj.apertures[apid]['follow_geometry'])
-                                        if isinstance(geo_aper, list):
-                                            obj_fin.apertures[apid]['follow_geometry'] += geo_aper
-                                        else:
-                                            obj_fin.apertures[apid]['follow_geometry'].append(geo_aper)
+                                        if 'follow' in el:
+                                            geo_aper = translate_recursion(el['follow'])
+                                            new_el['follow'] = deepcopy(geo_aper)
+
+                                        obj_fin.apertures[apid]['geometry'].append(deepcopy(new_el))
 
 
                             currentx += lenghtx
                             currentx += lenghtx
                         currenty += lenghty
                         currenty += lenghty
 
 
                     app_obj.log.debug("Found %s geometries. Creating a panel geometry cascaded union ..." %
                     app_obj.log.debug("Found %s geometries. Creating a panel geometry cascaded union ..." %
                                       len(obj_fin.solid_geometry))
                                       len(obj_fin.solid_geometry))
-                    obj_fin.solid_geometry = cascaded_union(obj_fin.solid_geometry)
+
+                    # obj_fin.solid_geometry = cascaded_union(obj_fin.solid_geometry)
                     app_obj.log.debug("Finished creating a cascaded union for the panel.")
                     app_obj.log.debug("Finished creating a cascaded union for the panel.")
 
 
                 if isinstance(panel_obj, FlatCAMExcellon):
                 if isinstance(panel_obj, FlatCAMExcellon):
@@ -632,19 +628,19 @@ class Panelize(FlatCAMTool):
                                         plot=True, autoselected=True)
                                         plot=True, autoselected=True)
 
 
         if self.constrain_flag is False:
         if self.constrain_flag is False:
-            self.app.inform.emit(_("[success] Panel done..."))
+            self.app.inform.emit('[success] %s' % _("Panel done..."))
         else:
         else:
             self.constrain_flag = False
             self.constrain_flag = False
-            self.app.inform.emit(_("[WARNING] Too big for the constrain area. "
+            self.app.inform.emit(_("{text} Too big for the constrain area. "
                                    "Final panel has {col} columns and {row} rows").format(
                                    "Final panel has {col} columns and {row} rows").format(
-                col=columns, row=rows))
+                text='[WARNING] ', col=columns, row=rows))
 
 
-        proc = self.app.proc_container.new(_("Generating panel ... Please wait."))
+        proc = self.app.proc_container.new(_("Generating panel..."))
 
 
         def job_thread(app_obj):
         def job_thread(app_obj):
             try:
             try:
                 panelize_2()
                 panelize_2()
-                self.app.inform.emit(_("[success] Panel created successfully."))
+                self.app.inform.emit('[success] %s' % _("Panel created successfully."))
             except Exception as ee:
             except Exception as ee:
                 proc.done()
                 proc.done()
                 log.debug(str(ee))
                 log.debug(str(ee))

+ 20 - 11
flatcamTools/ToolPcbWizard.py

@@ -362,7 +362,8 @@ class PcbWizard(FlatCAMTool):
                 self.frac_entry.set_value(self.fractional)
                 self.frac_entry.set_value(self.fractional)
 
 
         if not self.tools_from_inf:
         if not self.tools_from_inf:
-            self.app.inform.emit(_("[ERROR] The INF file does not contain the tool table.\n"
+            self.app.inform.emit('[ERROR] %s' %
+                                 _("The INF file does not contain the tool table.\n"
                                    "Try to open the Excellon file from File -> Open -> Excellon\n"
                                    "Try to open the Excellon file from File -> Open -> Excellon\n"
                                    "and edit the drill diameters manually."))
                                    "and edit the drill diameters manually."))
             return "fail"
             return "fail"
@@ -382,11 +383,13 @@ class PcbWizard(FlatCAMTool):
         if signal == 'inf':
         if signal == 'inf':
             self.inf_loaded = True
             self.inf_loaded = True
             self.tools_table.setVisible(True)
             self.tools_table.setVisible(True)
-            self.app.inform.emit(_("[success] PcbWizard .INF file loaded."))
+            self.app.inform.emit('[success] %s' %
+                                 _("PcbWizard .INF file loaded."))
         elif signal == 'excellon':
         elif signal == 'excellon':
             self.excellon_loaded = True
             self.excellon_loaded = True
             self.outname = os.path.split(str(filename))[1]
             self.outname = os.path.split(str(filename))[1]
-            self.app.inform.emit(_("[success] Main PcbWizard Excellon file loaded."))
+            self.app.inform.emit('[success] %s' %
+                                 _("Main PcbWizard Excellon file loaded."))
 
 
         if self.excellon_loaded and self.inf_loaded:
         if self.excellon_loaded and self.inf_loaded:
             self.update_params()
             self.update_params()
@@ -420,16 +423,18 @@ class PcbWizard(FlatCAMTool):
                 ret = excellon_obj.parse_file(file_obj=excellon_fileobj)
                 ret = excellon_obj.parse_file(file_obj=excellon_fileobj)
                 if ret == "fail":
                 if ret == "fail":
                     app_obj.log.debug("Excellon parsing failed.")
                     app_obj.log.debug("Excellon parsing failed.")
-                    app_obj.inform.emit(_("[ERROR_NOTCL] This is not Excellon file."))
+                    app_obj.inform.emit('[ERROR_NOTCL] %s' %
+                                        _("This is not Excellon file."))
                     return "fail"
                     return "fail"
             except IOError:
             except IOError:
-                app_obj.inform.emit(_("[ERROR_NOTCL] Cannot parse file: %s") % self.outname)
+                app_obj.inform.emit('[ERROR_NOTCL] %s: %s' % (
+                        _("Cannot parse file"), self.outname))
                 app_obj.log.debug("Could not import Excellon object.")
                 app_obj.log.debug("Could not import Excellon object.")
                 app_obj.progress.emit(0)
                 app_obj.progress.emit(0)
                 return "fail"
                 return "fail"
             except Exception as e:
             except Exception as e:
                 app_obj.log.debug("PcbWizard.on_import_excellon().obj_init() %s" % str(e))
                 app_obj.log.debug("PcbWizard.on_import_excellon().obj_init() %s" % str(e))
-                msg = _("[ERROR_NOTCL] An internal error has occurred. See shell.\n")
+                msg = '[ERROR_NOTCL] %s' % _("An internal error has occurred. See shell.\n")
                 msg += app_obj.traceback.format_exc()
                 msg += app_obj.traceback.format_exc()
                 app_obj.inform.emit(msg)
                 app_obj.inform.emit(msg)
                 return "fail"
                 return "fail"
@@ -442,7 +447,8 @@ class PcbWizard(FlatCAMTool):
             for tool in excellon_obj.tools:
             for tool in excellon_obj.tools:
                 if excellon_obj.tools[tool]['solid_geometry']:
                 if excellon_obj.tools[tool]['solid_geometry']:
                     return
                     return
-            app_obj.inform.emit(_("[ERROR_NOTCL] No geometry found in file: %s") % name)
+            app_obj.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                (_("No geometry found in file"), name))
             return "fail"
             return "fail"
 
 
         if excellon_fileobj is not None and excellon_fileobj != '':
         if excellon_fileobj is not None and excellon_fileobj != '':
@@ -454,16 +460,19 @@ class PcbWizard(FlatCAMTool):
 
 
                     ret_val = self.app.new_object("excellon", name, obj_init, autoselected=False)
                     ret_val = self.app.new_object("excellon", name, obj_init, autoselected=False)
                     if ret_val == 'fail':
                     if ret_val == 'fail':
-                        self.app.inform.emit(_('[ERROR_NOTCL] Import Excellon file failed.'))
+                        self.app.inform.emit('[ERROR_NOTCL] %s' % _('Import Excellon file failed.'))
                         return
                         return
 
 
                         # Register recent file
                         # Register recent file
                     self.app.file_opened.emit("excellon", name)
                     self.app.file_opened.emit("excellon", name)
 
 
                     # GUI feedback
                     # GUI feedback
-                    self.app.inform.emit(_("[success] Imported: %s") % name)
+                    self.app.inform.emit('[success] %s: %s' %
+                                         (_("Imported"), name))
                     self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
                     self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
             else:
             else:
-                self.app.inform.emit(_('[WARNING_NOTCL] Excellon merging is in progress. Please wait...'))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _('Excellon merging is in progress. Please wait...'))
         else:
         else:
-            self.app.inform.emit(_('[ERROR_NOTCL] The imported Excellon file is None.'))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _('The imported Excellon file is None.'))

+ 105 - 38
flatcamTools/ToolProperties.py

@@ -21,9 +21,10 @@ if '_' not in builtins.__dict__:
 
 
 
 
 class Properties(FlatCAMTool):
 class Properties(FlatCAMTool):
-
     toolName = _("Properties")
     toolName = _("Properties")
 
 
+    calculations_finished = pyqtSignal(float, float, float, float, object)
+
     def __init__(self, app):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
         FlatCAMTool.__init__(self, app)
 
 
@@ -64,6 +65,8 @@ class Properties(FlatCAMTool):
         self.vlay.addWidget(self.treeWidget)
         self.vlay.addWidget(self.treeWidget)
         self.vlay.setStretch(0, 0)
         self.vlay.setStretch(0, 0)
 
 
+        self.calculations_finished.connect(self.show_area_chull)
+
     def run(self, toggle=True):
     def run(self, toggle=True):
         self.app.report_usage("ToolProperties()")
         self.app.report_usage("ToolProperties()")
 
 
@@ -105,14 +108,16 @@ class Properties(FlatCAMTool):
     def properties(self):
     def properties(self):
         obj_list = self.app.collection.get_selected()
         obj_list = self.app.collection.get_selected()
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[ERROR_NOTCL] Properties Tool was not displayed. No object selected."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Properties Tool was not displayed. No object selected."))
             self.app.ui.notebook.setTabText(2, _("Tools"))
             self.app.ui.notebook.setTabText(2, _("Tools"))
             self.properties_frame.hide()
             self.properties_frame.hide()
             self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
             self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
             return
             return
         for obj in obj_list:
         for obj in obj_list:
             self.addItems(obj)
             self.addItems(obj)
-            self.app.inform.emit(_("[success] Object Properties are displayed."))
+            self.app.inform.emit('[success] %s' %
+                                 _("Object Properties are displayed."))
         self.app.ui.notebook.setTabText(2, _("Properties Tool"))
         self.app.ui.notebook.setTabText(2, _("Properties Tool"))
 
 
     def addItems(self, obj):
     def addItems(self, obj):
@@ -146,49 +151,94 @@ class Properties(FlatCAMTool):
 
 
         self.addChild(obj_name, [obj.options['name']])
         self.addChild(obj_name, [obj.options['name']])
 
 
-        # calculate physical dimensions
-        try:
-            xmin, ymin, xmax, ymax = obj.bounds()
-        except Exception as e:
-            log.debug("PropertiesTool.addItems() --> %s" % str(e))
-            return
+        def job_thread(obj):
+            proc = self.app.proc_container.new(_("Calculating dimensions ... Please wait."))
 
 
-        length = abs(xmax - xmin)
-        width = abs(ymax - ymin)
+            length = 0.0
+            width = 0.0
+            area = 0.0
 
 
-        self.addChild(dims, ['%s:' % _('Length'), '%.4f %s' % (
-            length, self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())], True)
-        self.addChild(dims, ['%s:' % _('Width'), '%.4f %s' % (
-            width, self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())], True)
+            geo = obj.solid_geometry
+            if geo:
+                # calculate physical dimensions
+                try:
+                    xmin, ymin, xmax, ymax = obj.bounds()
 
 
-        # calculate and add box area
-        if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
-            area = (length * width) / 100
-            self.addChild(dims, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'cm2')], True)
-        else:
-            area = length * width
-            self.addChild(dims, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'in2')], True)
+                    length = abs(xmax - xmin)
+                    width = abs(ymax - ymin)
+                except Exception as e:
+                    log.debug("PropertiesTool.addItems() --> %s" % str(e))
 
 
-        if not isinstance(obj, FlatCAMCNCjob):
-            # calculate and add convex hull area
-            geo = obj.solid_geometry
-            if isinstance(geo, MultiPolygon):
-                env_obj = geo.convex_hull
-            elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
-                    (isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
-                env_obj = cascaded_union(obj.solid_geometry)
-                env_obj = env_obj.convex_hull
+                # calculate box area
+                if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
+                    area = (length * width) / 100
+                else:
+                    area = length * width
             else:
             else:
-                env_obj = cascaded_union(obj.solid_geometry)
-                env_obj = env_obj.convex_hull
+                xmin = []
+                ymin = []
+                xmax = []
+                ymax = []
+
+                for tool in obj.tools:
+                    try:
+                        x0, y0, x1, y1 = cascaded_union(obj.tools[tool]['solid_geometry']).bounds
+                        xmin.append(x0)
+                        ymin.append(y0)
+                        xmax.append(x1)
+                        ymax.append(y1)
+                    except Exception as ee:
+                        log.debug("PropertiesTool.addItems() --> %s" % str(ee))
+
+                try:
+                    xmin = min(xmin)
+                    ymin = min(ymin)
+                    xmax = max(xmax)
+                    ymax = max(ymax)
+
+                    length = abs(xmax - xmin)
+                    width = abs(ymax - ymin)
+
+                    # calculate box area
+                    if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
+                        area = (length * width) / 100
+                    else:
+                        area = length * width
+                except Exception as e:
+                    log.debug("Properties.addItems() --> %s" % str(e))
+
+            area_chull = 0.0
+            if not isinstance(obj, FlatCAMCNCjob):
+                # calculate and add convex hull area
+                if geo:
+                    if isinstance(geo, MultiPolygon):
+                        env_obj = geo.convex_hull
+                    elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
+                            (isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
+                        env_obj = cascaded_union(obj.solid_geometry)
+                        env_obj = env_obj.convex_hull
+                    else:
+                        env_obj = cascaded_union(obj.solid_geometry)
+                        env_obj = env_obj.convex_hull
+
+                    area_chull = env_obj.area
+                else:
+                    try:
+                        area_chull = []
+                        for tool in obj.tools:
+                            area_el = cascaded_union(obj.tools[tool]['solid_geometry']).convex_hull
+                            area_chull.append(area_el.area)
+                        area_chull = max(area_chull)
+                    except Exception as e:
+                        area_chull = None
+                        log.debug("Properties.addItems() --> %s" % str(e))
 
 
-            area_chull = env_obj.area
             if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
             if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
                 area_chull = area_chull / 100
                 area_chull = area_chull / 100
-                self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'cm2')], True)
-            else:
-                area_chull = area_chull
-                self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'in2')], True)
+
+            self.calculations_finished.emit(area, length, width, area_chull, dims)
+
+        self.app.worker_task.emit({'fcn': job_thread, 'params': [obj]})
 
 
         self.addChild(units,
         self.addChild(units,
                       ['FlatCAM units:',
                       ['FlatCAM units:',
@@ -294,4 +344,21 @@ class Properties(FlatCAMTool):
         if column1 is not None:
         if column1 is not None:
             item.setText(1, str(title[1]))
             item.setText(1, str(title[1]))
 
 
+    def show_area_chull(self, area, length, width, chull_area, location):
+
+        # add dimensions
+        self.addChild(location, ['%s:' % _('Length'), '%.4f %s' % (
+            length, self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())], True)
+        self.addChild(location, ['%s:' % _('Width'), '%.4f %s' % (
+            width, self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower())], True)
+
+        # add box area
+        if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
+            self.addChild(location, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'cm2')], True)
+            self.addChild(location, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (chull_area, 'cm2')], True)
+
+        else:
+            self.addChild(location, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'in2')], True)
+            self.addChild(location, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (chull_area, 'in2')], True)
+
 # end of file
 # end of file

+ 61 - 37
flatcamTools/ToolSolderPaste.py

@@ -760,17 +760,18 @@ class SolderPaste(FlatCAMTool):
                 try:
                 try:
                     tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
                     tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
             if tool_dia is None:
             if tool_dia is None:
                 self.build_ui()
                 self.build_ui()
-                self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Please enter a tool diameter to add, in Float format."))
                 return
                 return
 
 
         if tool_dia == 0:
         if tool_dia == 0:
-            self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, "
-                                   "in Float format."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Please enter a tool diameter with non-zero value, in Float format."))
             return
             return
 
 
         # construct a list of all 'tooluid' in the self.tooltable_tools
         # construct a list of all 'tooluid' in the self.tooltable_tools
@@ -794,12 +795,14 @@ class SolderPaste(FlatCAMTool):
 
 
         if float('%.4f' % tool_dia) in tool_dias:
         if float('%.4f' % tool_dia) in tool_dias:
             if muted is None:
             if muted is None:
-                self.app.inform.emit(_("[WARNING_NOTCL] Adding Nozzle tool cancelled. Tool already in Tool Table."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Adding Nozzle tool cancelled. Tool already in Tool Table."))
             self.tools_table.itemChanged.connect(self.on_tool_edit)
             self.tools_table.itemChanged.connect(self.on_tool_edit)
             return
             return
         else:
         else:
             if muted is None:
             if muted is None:
-                self.app.inform.emit(_("[success] New Nozzle tool added to Tool Table."))
+                self.app.inform.emit('[success] %s' %
+                                     _("New Nozzle tool added to Tool Table."))
             self.tooltable_tools.update({
             self.tooltable_tools.update({
                 int(self.tooluid): {
                 int(self.tooluid): {
                     'tooldia': float('%.4f' % tool_dia),
                     'tooldia': float('%.4f' % tool_dia),
@@ -832,8 +835,8 @@ class SolderPaste(FlatCAMTool):
                 try:
                 try:
                     new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
                     new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                           "use a number."))
+                    self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                         _("Wrong value format entered, use a number."))
                     return
                     return
 
 
             tooluid = int(self.tools_table.item(row, 2).text())
             tooluid = int(self.tools_table.item(row, 2).text())
@@ -841,7 +844,8 @@ class SolderPaste(FlatCAMTool):
             # identify the tool that was edited and get it's tooluid
             # identify the tool that was edited and get it's tooluid
             if new_tool_dia not in tool_dias:
             if new_tool_dia not in tool_dias:
                 self.tooltable_tools[tooluid]['tooldia'] = new_tool_dia
                 self.tooltable_tools[tooluid]['tooldia'] = new_tool_dia
-                self.app.inform.emit(_("[success] Nozzle tool from Tool Table was edited."))
+                self.app.inform.emit('[success] %s' %
+                                     _("Nozzle tool from Tool Table was edited."))
                 self.build_ui()
                 self.build_ui()
                 return
                 return
             else:
             else:
@@ -852,8 +856,8 @@ class SolderPaste(FlatCAMTool):
                         break
                         break
                 restore_dia_item = self.tools_table.item(row, 1)
                 restore_dia_item = self.tools_table.item(row, 1)
                 restore_dia_item.setText(str(old_tool_dia))
                 restore_dia_item.setText(str(old_tool_dia))
-                self.app.inform.emit(_("[WARNING_NOTCL] Edit cancelled. "
-                                       "New diameter value is already in the Tool Table."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("Edit cancelled. New diameter value is already in the Tool Table."))
         self.build_ui()
         self.build_ui()
 
 
     def on_tool_delete(self, rows_to_delete=None, all=None):
     def on_tool_delete(self, rows_to_delete=None, all=None):
@@ -898,12 +902,14 @@ class SolderPaste(FlatCAMTool):
                     self.tooltable_tools.pop(t, None)
                     self.tooltable_tools.pop(t, None)
 
 
         except AttributeError:
         except AttributeError:
-            self.app.inform.emit(_("[WARNING_NOTCL] Delete failed. Select a Nozzle tool to delete."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Delete failed. Select a Nozzle tool to delete."))
             return
             return
         except Exception as e:
         except Exception as e:
             log.debug(str(e))
             log.debug(str(e))
 
 
-        self.app.inform.emit(_("[success] Nozzle tool(s) deleted from Tool Table."))
+        self.app.inform.emit('[success] %s' %
+                             _("Nozzle tool(s) deleted from Tool Table."))
         self.build_ui()
         self.build_ui()
 
 
     def on_rmb_combo(self, pos, combo):
     def on_rmb_combo(self, pos, combo):
@@ -958,7 +964,8 @@ class SolderPaste(FlatCAMTool):
         """
         """
         name = self.obj_combo.currentText()
         name = self.obj_combo.currentText()
         if name == '':
         if name == '':
-            self.app.inform.emit(_("[WARNING_NOTCL] No SolderPaste mask Gerber object loaded."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No SolderPaste mask Gerber object loaded."))
             return
             return
 
 
         obj = self.app.collection.get_by_name(name)
         obj = self.app.collection.get_by_name(name)
@@ -988,7 +995,8 @@ class SolderPaste(FlatCAMTool):
         sorted_tools.sort(reverse=True)
         sorted_tools.sort(reverse=True)
 
 
         if not sorted_tools:
         if not sorted_tools:
-            self.app.inform.emit(_("[WARNING_NOTCL] No Nozzle tools in the tool table."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No Nozzle tools in the tool table."))
             return 'fail'
             return 'fail'
 
 
         def flatten(geometry=None, reset=True, pathonly=False):
         def flatten(geometry=None, reset=True, pathonly=False):
@@ -1114,17 +1122,20 @@ class SolderPaste(FlatCAMTool):
                         if not geo_obj.tools[tooluid_key]['solid_geometry']:
                         if not geo_obj.tools[tooluid_key]['solid_geometry']:
                             a += 1
                             a += 1
                     if a == len(geo_obj.tools):
                     if a == len(geo_obj.tools):
-                        self.app.inform.emit(_('[ERROR_NOTCL] Cancelled. Empty file, it has no geometry...'))
+                        self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                             _('Cancelled. Empty file, it has no geometry...'))
                         return 'fail'
                         return 'fail'
 
 
-                    app_obj.inform.emit(_("[success] Solder Paste geometry generated successfully..."))
+                    app_obj.inform.emit('[success] %s...' %
+                                        _("Solder Paste geometry generated successfully"))
                     return
                     return
 
 
             # if we still have geometry not processed at the end of the tools then we failed
             # if we still have geometry not processed at the end of the tools then we failed
             # some or all the pads are not covered with solder paste
             # some or all the pads are not covered with solder paste
             if work_geo:
             if work_geo:
-                app_obj.inform.emit(_("[WARNING_NOTCL] Some or all pads have no solder "
-                                    "due of inadequate nozzle diameters..."))
+                app_obj.inform.emit('[WARNING_NOTCL] %s' %
+                                    _("Some or all pads have no solder "
+                                      "due of inadequate nozzle diameters..."))
                 return 'fail'
                 return 'fail'
 
 
         if use_thread:
         if use_thread:
@@ -1157,11 +1168,13 @@ class SolderPaste(FlatCAMTool):
         obj = self.app.collection.get_by_name(name)
         obj = self.app.collection.get_by_name(name)
 
 
         if name == '':
         if name == '':
-            self.app.inform.emit(_("[WARNING_NOTCL] There is no Geometry object available."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("There is no Geometry object available."))
             return 'fail'
             return 'fail'
 
 
         if obj.special_group != 'solder_paste_tool':
         if obj.special_group != 'solder_paste_tool':
-            self.app.inform.emit(_("[WARNING_NOTCL] This Geometry can't be processed. "
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("This Geometry can't be processed. "
                                    "NOT a solder_paste_tool geometry."))
                                    "NOT a solder_paste_tool geometry."))
             return 'fail'
             return 'fail'
 
 
@@ -1170,7 +1183,8 @@ class SolderPaste(FlatCAMTool):
             if obj.tools[tooluid_key]['solid_geometry'] is None:
             if obj.tools[tooluid_key]['solid_geometry'] is None:
                 a += 1
                 a += 1
         if a == len(obj.tools):
         if a == len(obj.tools):
-            self.app.inform.emit(_('[ERROR_NOTCL] Cancelled. Empty file, it has no geometry...'))
+            self.app.inform.emit('[ERROR_NOTCL] %s...' %
+                                 _('Cancelled. Empty file, it has no geometry'))
             return 'fail'
             return 'fail'
 
 
         # use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
         # use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
@@ -1197,7 +1211,7 @@ class SolderPaste(FlatCAMTool):
             ymax = obj.options['ymax']
             ymax = obj.options['ymax']
         except Exception as e:
         except Exception as e:
             log.debug("FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s\n" % str(e))
             log.debug("FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s\n" % str(e))
-            msg = "[ERROR] An internal error has ocurred. See shell.\n"
+            msg = '[ERROR] %s' % _("An internal error has ocurred. See shell.\n")
             msg += 'FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s' % str(e)
             msg += 'FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s' % str(e)
             msg += traceback.format_exc()
             msg += traceback.format_exc()
             self.app.inform.emit(msg)
             self.app.inform.emit(msg)
@@ -1267,7 +1281,8 @@ class SolderPaste(FlatCAMTool):
             def job_thread(app_obj):
             def job_thread(app_obj):
                 with self.app.proc_container.new("Generating CNC Code"):
                 with self.app.proc_container.new("Generating CNC Code"):
                     if app_obj.new_object("cncjob", name, job_init) != 'fail':
                     if app_obj.new_object("cncjob", name, job_init) != 'fail':
-                        app_obj.inform.emit(_("[success] ToolSolderPaste CNCjob created: %s") % name)
+                        app_obj.inform.emit('[success] [success] %s: %s' %
+                                            (_("ToolSolderPaste CNCjob created"), name))
                         app_obj.progress.emit(100)
                         app_obj.progress.emit(100)
 
 
             # Create a promise with the name
             # Create a promise with the name
@@ -1299,12 +1314,14 @@ class SolderPaste(FlatCAMTool):
 
 
         try:
         try:
             if obj.special_group != 'solder_paste_tool':
             if obj.special_group != 'solder_paste_tool':
-                self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
-                                     "NOT a solder_paste_tool CNCJob object."))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("This CNCJob object can't be processed. "
+                                       "NOT a solder_paste_tool CNCJob object."))
                 return
                 return
         except AttributeError:
         except AttributeError:
-            self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
-                                 "NOT a solder_paste_tool CNCJob object."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("This CNCJob object can't be processed. "
+                                   "NOT a solder_paste_tool CNCJob object."))
             return
             return
 
 
         gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
         gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
@@ -1327,7 +1344,8 @@ class SolderPaste(FlatCAMTool):
             lines = StringIO(gcode)
             lines = StringIO(gcode)
         except Exception as e:
         except Exception as e:
             log.debug("ToolSolderpaste.on_view_gcode() --> %s" % str(e))
             log.debug("ToolSolderpaste.on_view_gcode() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] No Gcode in the object..."))
+            self.app.inform.emit('[ERROR_NOTCL] %s...' %
+                                 _("No Gcode in the object"))
             return
             return
 
 
         try:
         try:
@@ -1336,7 +1354,8 @@ class SolderPaste(FlatCAMTool):
                 self.app.ui.code_editor.append(proc_line)
                 self.app.ui.code_editor.append(proc_line)
         except Exception as e:
         except Exception as e:
             log.debug('ToolSolderPaste.on_view_gcode() -->%s' % str(e))
             log.debug('ToolSolderPaste.on_view_gcode() -->%s' % str(e))
-            self.app.inform.emit(_('[ERROR] ToolSolderPaste.on_view_gcode() -->%s') % str(e))
+            self.app.inform.emit('[ERROR] %s --> %s' %
+                                 (_('ToolSolderPaste.on_view_gcode()'), str(e)))
             return
             return
 
 
         self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
         self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
@@ -1355,8 +1374,9 @@ class SolderPaste(FlatCAMTool):
         obj = self.app.collection.get_by_name(name)
         obj = self.app.collection.get_by_name(name)
 
 
         if obj.special_group != 'solder_paste_tool':
         if obj.special_group != 'solder_paste_tool':
-            self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
-                                 "NOT a solder_paste_tool CNCJob object."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("This CNCJob object can't be processed. "
+                                   "NOT a solder_paste_tool CNCJob object."))
             return
             return
 
 
         _filter_ = "G-Code Files (*.nc);;G-Code Files (*.txt);;G-Code Files (*.tap);;G-Code Files (*.cnc);;" \
         _filter_ = "G-Code Files (*.nc);;G-Code Files (*.txt);;G-Code Files (*.tap);;G-Code Files (*.cnc);;" \
@@ -1373,7 +1393,8 @@ class SolderPaste(FlatCAMTool):
             filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export Machine Code ..."), filter=_filter_)
             filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export Machine Code ..."), filter=_filter_)
 
 
         if filename == '':
         if filename == '':
-            self.app.inform.emit(_("[WARNING_NOTCL] Export Machine Code cancelled ..."))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("Export Machine Code cancelled ..."))
             return
             return
 
 
         gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
         gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
@@ -1399,17 +1420,20 @@ class SolderPaste(FlatCAMTool):
                     for line in lines:
                     for line in lines:
                         f.write(line)
                         f.write(line)
             except FileNotFoundError:
             except FileNotFoundError:
-                self.app.inform.emit(_("[WARNING_NOTCL] No such file or directory"))
+                self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                     _("No such file or directory"))
                 return
                 return
             except PermissionError:
             except PermissionError:
-                self.app.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+                self.app.inform.emit('[WARNING] %s' %
+                                     _("Permission denied, saving not possible.\n"
                                        "Most likely another app is holding the file open and not accessible."))
                                        "Most likely another app is holding the file open and not accessible."))
                 return 'fail'
                 return 'fail'
 
 
         if self.app.defaults["global_open_style"] is False:
         if self.app.defaults["global_open_style"] is False:
             self.app.file_opened.emit("gcode", filename)
             self.app.file_opened.emit("gcode", filename)
         self.app.file_saved.emit("gcode", filename)
         self.app.file_saved.emit("gcode", filename)
-        self.app.inform.emit(_("[success] Solder paste dispenser GCode file saved to: %s") % filename)
+        self.app.inform.emit('[success] %s: %s' %
+                             (_("Solder paste dispenser GCode file saved to"), filename))
 
 
     def reset_fields(self):
     def reset_fields(self):
         self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
         self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

+ 28 - 14
flatcamTools/ToolSub.py

@@ -241,7 +241,8 @@ class ToolSub(FlatCAMTool):
 
 
         self.target_grb_obj_name = self.target_gerber_combo.currentText()
         self.target_grb_obj_name = self.target_gerber_combo.currentText()
         if self.target_grb_obj_name == '':
         if self.target_grb_obj_name == '':
-            self.app.inform.emit(_("[ERROR_NOTCL] No Target object loaded."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("No Target object loaded."))
             return
             return
 
 
         # Get target object.
         # Get target object.
@@ -249,12 +250,14 @@ class ToolSub(FlatCAMTool):
             self.target_grb_obj = self.app.collection.get_by_name(self.target_grb_obj_name)
             self.target_grb_obj = self.app.collection.get_by_name(self.target_grb_obj_name)
         except Exception as e:
         except Exception as e:
             log.debug("ToolSub.on_grb_intersection_click() --> %s" % str(e))
             log.debug("ToolSub.on_grb_intersection_click() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Could not retrieve object"), self.obj_name))
             return "Could not retrieve object: %s" % self.target_grb_obj_name
             return "Could not retrieve object: %s" % self.target_grb_obj_name
 
 
         self.sub_grb_obj_name = self.sub_gerber_combo.currentText()
         self.sub_grb_obj_name = self.sub_gerber_combo.currentText()
         if self.sub_grb_obj_name == '':
         if self.sub_grb_obj_name == '':
-            self.app.inform.emit(_("[ERROR_NOTCL] No Substractor object loaded."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("No Substractor object loaded."))
             return
             return
 
 
         # Get substractor object.
         # Get substractor object.
@@ -262,7 +265,8 @@ class ToolSub(FlatCAMTool):
             self.sub_grb_obj = self.app.collection.get_by_name(self.sub_grb_obj_name)
             self.sub_grb_obj = self.app.collection.get_by_name(self.sub_grb_obj_name)
         except Exception as e:
         except Exception as e:
             log.debug("ToolSub.on_grb_intersection_click() --> %s" % str(e))
             log.debug("ToolSub.on_grb_intersection_click() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Could not retrieve object"), self.obj_name))
             return "Could not retrieve object: %s" % self.sub_grb_obj_name
             return "Could not retrieve object: %s" % self.sub_grb_obj_name
 
 
         # crate the new_apertures dict structure
         # crate the new_apertures dict structure
@@ -412,11 +416,13 @@ class ToolSub(FlatCAMTool):
         with self.app.proc_container.new(_("Generating new object ...")):
         with self.app.proc_container.new(_("Generating new object ...")):
             ret = self.app.new_object('gerber', outname, obj_init, autoselected=False)
             ret = self.app.new_object('gerber', outname, obj_init, autoselected=False)
             if ret == 'fail':
             if ret == 'fail':
-                self.app.inform.emit(_('[ERROR_NOTCL] Generating new object failed.'))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _('Generating new object failed.'))
                 return
                 return
 
 
             # GUI feedback
             # GUI feedback
-            self.app.inform.emit(_("[success] Created: %s") % outname)
+            self.app.inform.emit('[success] %s: %s' %
+                                 (_("Created"), outname))
 
 
             # cleanup
             # cleanup
             self.new_apertures.clear()
             self.new_apertures.clear()
@@ -437,7 +443,8 @@ class ToolSub(FlatCAMTool):
 
 
         self.target_geo_obj_name = self.target_geo_combo.currentText()
         self.target_geo_obj_name = self.target_geo_combo.currentText()
         if self.target_geo_obj_name == '':
         if self.target_geo_obj_name == '':
-            self.app.inform.emit(_("[ERROR_NOTCL] No Target object loaded."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("No Target object loaded."))
             return
             return
 
 
         # Get target object.
         # Get target object.
@@ -445,12 +452,14 @@ class ToolSub(FlatCAMTool):
             self.target_geo_obj = self.app.collection.get_by_name(self.target_geo_obj_name)
             self.target_geo_obj = self.app.collection.get_by_name(self.target_geo_obj_name)
         except Exception as e:
         except Exception as e:
             log.debug("ToolSub.on_geo_intersection_click() --> %s" % str(e))
             log.debug("ToolSub.on_geo_intersection_click() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.target_geo_obj_name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Could not retrieve object"), self.target_geo_obj_name))
             return "Could not retrieve object: %s" % self.target_grb_obj_name
             return "Could not retrieve object: %s" % self.target_grb_obj_name
 
 
         self.sub_geo_obj_name = self.sub_geo_combo.currentText()
         self.sub_geo_obj_name = self.sub_geo_combo.currentText()
         if self.sub_geo_obj_name == '':
         if self.sub_geo_obj_name == '':
-            self.app.inform.emit(_("[ERROR_NOTCL] No Substractor object loaded."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("No Substractor object loaded."))
             return
             return
 
 
         # Get substractor object.
         # Get substractor object.
@@ -458,11 +467,13 @@ class ToolSub(FlatCAMTool):
             self.sub_geo_obj = self.app.collection.get_by_name(self.sub_geo_obj_name)
             self.sub_geo_obj = self.app.collection.get_by_name(self.sub_geo_obj_name)
         except Exception as e:
         except Exception as e:
             log.debug("ToolSub.on_geo_intersection_click() --> %s" % str(e))
             log.debug("ToolSub.on_geo_intersection_click() --> %s" % str(e))
-            self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.sub_geo_obj_name)
+            self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+                                 (_("Could not retrieve object"), self.sub_geo_obj_name))
             return "Could not retrieve object: %s" % self.sub_geo_obj_name
             return "Could not retrieve object: %s" % self.sub_geo_obj_name
 
 
         if self.sub_geo_obj.multigeo:
         if self.sub_geo_obj.multigeo:
-            self.app.inform.emit(_("[ERROR_NOTCL] Currently, the Substractor geometry cannot be of type Multigeo."))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _("Currently, the Substractor geometry cannot be of type Multigeo."))
             return
             return
 
 
         # create the target_options obj
         # create the target_options obj
@@ -608,12 +619,14 @@ class ToolSub(FlatCAMTool):
         with self.app.proc_container.new(_("Generating new object ...")):
         with self.app.proc_container.new(_("Generating new object ...")):
             ret = self.app.new_object('geometry', outname, obj_init, autoselected=False)
             ret = self.app.new_object('geometry', outname, obj_init, autoselected=False)
             if ret == 'fail':
             if ret == 'fail':
-                self.app.inform.emit(_('[ERROR_NOTCL] Generating new object failed.'))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _('Generating new object failed.'))
                 return
                 return
             # Register recent file
             # Register recent file
             self.app.file_opened.emit('geometry', outname)
             self.app.file_opened.emit('geometry', outname)
             # GUI feedback
             # GUI feedback
-            self.app.inform.emit(_("[success] Created: %s") % outname)
+            self.app.inform.emit('[success] %s: %s' %
+                                 (_("Created"), outname))
 
 
             # cleanup
             # cleanup
             self.new_tools.clear()
             self.new_tools.clear()
@@ -687,7 +700,8 @@ class ToolSub(FlatCAMTool):
                 self.app.worker_task.emit({'fcn': self.new_geo_object,
                 self.app.worker_task.emit({'fcn': self.new_geo_object,
                                            'params': [outname]})
                                            'params': [outname]})
         else:
         else:
-            self.app.inform.emit(_('[ERROR_NOTCL] Generating new object failed.'))
+            self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                 _('Generating new object failed.'))
 
 
     def reset_fields(self):
     def reset_fields(self):
         self.target_gerber_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
         self.target_gerber_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

+ 44 - 30
flatcamTools/ToolTransform.py

@@ -470,8 +470,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 value = float(self.rotate_entry.get_value().replace(',', '.'))
                 value = float(self.rotate_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Rotate, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
         self.app.worker_task.emit({'fcn': self.on_rotate_action,
         self.app.worker_task.emit({'fcn': self.on_rotate_action,
                                    'params': [value]})
                                    'params': [value]})
@@ -504,8 +504,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 value = float(self.skewx_entry.get_value().replace(',', '.'))
                 value = float(self.skewx_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Skew X, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         # self.on_skew("X", value)
         # self.on_skew("X", value)
@@ -522,8 +522,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 value = float(self.skewy_entry.get_value().replace(',', '.'))
                 value = float(self.skewy_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Skew Y, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         # self.on_skew("Y", value)
         # self.on_skew("Y", value)
@@ -540,8 +540,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 xvalue = float(self.scalex_entry.get_value().replace(',', '.'))
                 xvalue = float(self.scalex_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Scale X, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
@@ -574,8 +574,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 yvalue = float(self.scaley_entry.get_value().replace(',', '.'))
                 yvalue = float(self.scaley_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Scale Y, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
         # scaling to zero has no sense so we remove it, because scaling with 1 does nothing
@@ -603,8 +603,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 value = float(self.offx_entry.get_value().replace(',', '.'))
                 value = float(self.offx_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Offset X, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         # self.on_offset("X", value)
         # self.on_offset("X", value)
@@ -621,8 +621,8 @@ class ToolTransform(FlatCAMTool):
             try:
             try:
                 value = float(self.offy_entry.get_value().replace(',', '.'))
                 value = float(self.offy_entry.get_value().replace(',', '.'))
             except ValueError:
             except ValueError:
-                self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered for Offset Y, "
-                                       "use a number."))
+                self.app.inform.emit('[ERROR_NOTCL] %s' %
+                                     _("Wrong value format entered, use a number."))
                 return
                 return
 
 
         # self.on_offset("Y", value)
         # self.on_offset("Y", value)
@@ -639,7 +639,8 @@ class ToolTransform(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to rotate!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No object selected. Please Select an object to rotate!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Appying Rotate")):
             with self.app.proc_container.new(_("Appying Rotate")):
@@ -675,11 +676,12 @@ class ToolTransform(FlatCAMTool):
                         # add information to the object that it was changed and how much
                         # add information to the object that it was changed and how much
                         sel_obj.options['rotate'] = num
                         sel_obj.options['rotate'] = num
                         sel_obj.plot()
                         sel_obj.plot()
-                    self.app.inform.emit(_('[success] Rotate done ...'))
+                    self.app.inform.emit('[success] %s...' % _('Rotate done'))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, rotation movement was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
+                                         (_("Due of"), str(e), _("action was not executed.")))
                     return
                     return
 
 
     def on_flip(self, axis):
     def on_flip(self, axis):
@@ -690,7 +692,8 @@ class ToolTransform(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to flip!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s!' %
+                                 _("No object selected. Please Select an object to flip"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Flip")):
             with self.app.proc_container.new(_("Applying Flip")):
@@ -735,7 +738,8 @@ class ToolTransform(FlatCAMTool):
                                     sel_obj.options['mirror_y'] = not sel_obj.options['mirror_y']
                                     sel_obj.options['mirror_y'] = not sel_obj.options['mirror_y']
                                 else:
                                 else:
                                     sel_obj.options['mirror_y'] = True
                                     sel_obj.options['mirror_y'] = True
-                                self.app.inform.emit(_('[success] Flip on the Y axis done ...'))
+                                self.app.inform.emit('[success] %s...' %
+                                                     _('Flip on the Y axis done'))
                             elif axis is 'Y':
                             elif axis is 'Y':
                                 sel_obj.mirror('Y', (px, py))
                                 sel_obj.mirror('Y', (px, py))
                                 # add information to the object that it was changed and how much
                                 # add information to the object that it was changed and how much
@@ -744,13 +748,15 @@ class ToolTransform(FlatCAMTool):
                                     sel_obj.options['mirror_x'] = not sel_obj.options['mirror_x']
                                     sel_obj.options['mirror_x'] = not sel_obj.options['mirror_x']
                                 else:
                                 else:
                                     sel_obj.options['mirror_x'] = True
                                     sel_obj.options['mirror_x'] = True
-                                self.app.inform.emit(_('[success] Flip on the X axis done ...'))
+                                self.app.inform.emit('[success] %s...' %
+                                                     _('Flip on the X axis done'))
                             self.app.object_changed.emit(sel_obj)
                             self.app.object_changed.emit(sel_obj)
                         sel_obj.plot()
                         sel_obj.plot()
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Flip action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
+                                         (_("Due of"), str(e), _("action was not executed.")))
                     return
                     return
 
 
     def on_skew(self, axis, num):
     def on_skew(self, axis, num):
@@ -759,7 +765,8 @@ class ToolTransform(FlatCAMTool):
         yminlist = []
         yminlist = []
 
 
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to shear/skew!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No object selected. Please Select an object to shear/skew!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Skew")):
             with self.app.proc_container.new(_("Applying Skew")):
@@ -797,7 +804,8 @@ class ToolTransform(FlatCAMTool):
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Skew action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
+                                         (_("Due of"), str(e), _("action was not executed.")))
                     return
                     return
 
 
     def on_scale(self, axis, xfactor, yfactor, point=None):
     def on_scale(self, axis, xfactor, yfactor, point=None):
@@ -808,7 +816,8 @@ class ToolTransform(FlatCAMTool):
         ymaxlist = []
         ymaxlist = []
 
 
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to scale!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No object selected. Please Select an object to scale!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Scale")):
             with self.app.proc_container.new(_("Applying Scale")):
@@ -850,17 +859,20 @@ class ToolTransform(FlatCAMTool):
                             self.app.object_changed.emit(sel_obj)
                             self.app.object_changed.emit(sel_obj)
                         sel_obj.plot()
                         sel_obj.plot()
 
 
-                    self.app.inform.emit(_('[success] Scale on the %s axis done ...') % str(axis))
+                    self.app.inform.emit('[success] %s %s %s...' %
+                                         (_('Scale on the'), str(axis), _('axis done')))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Scale action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
+                                         (_("Due of"), str(e), _("action was not executed.")))
                     return
                     return
 
 
     def on_offset(self, axis, num):
     def on_offset(self, axis, num):
         obj_list = self.app.collection.get_selected()
         obj_list = self.app.collection.get_selected()
 
 
         if not obj_list:
         if not obj_list:
-            self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to offset!"))
+            self.app.inform.emit('[WARNING_NOTCL] %s' %
+                                 _("No object selected. Please Select an object to offset!"))
             return
             return
         else:
         else:
             with self.app.proc_container.new(_("Applying Offset")):
             with self.app.proc_container.new(_("Applying Offset")):
@@ -869,7 +881,7 @@ class ToolTransform(FlatCAMTool):
 
 
                     for sel_obj in obj_list:
                     for sel_obj in obj_list:
                         if isinstance(sel_obj, FlatCAMCNCjob):
                         if isinstance(sel_obj, FlatCAMCNCjob):
-                            self.app.inform.emit(_("CNCJob objects can't be offseted."))
+                            self.app.inform.emit(_("CNCJob objects can't be offset."))
                         else:
                         else:
                             if axis is 'X':
                             if axis is 'X':
                                 sel_obj.offset((num, 0))
                                 sel_obj.offset((num, 0))
@@ -882,11 +894,13 @@ class ToolTransform(FlatCAMTool):
                             self.app.object_changed.emit(sel_obj)
                             self.app.object_changed.emit(sel_obj)
                         sel_obj.plot()
                         sel_obj.plot()
 
 
-                    self.app.inform.emit(_('[success] Offset on the %s axis done ...') % str(axis))
+                    self.app.inform.emit('[success] %s %s %s...' %
+                                         (_('Offset on the'), str(axis), _('axis done')))
                     self.app.progress.emit(100)
                     self.app.progress.emit(100)
 
 
                 except Exception as e:
                 except Exception as e:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Offset action was not executed.") % str(e))
+                    self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
+                                         (_("Due of"), str(e),  _("action was not executed.")))
                     return
                     return
 
 
 # end of file
 # end of file

BIN
locale/de/LC_MESSAGES/strings.mo


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


BIN
locale/en/LC_MESSAGES/strings.mo


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


BIN
locale/ro/LC_MESSAGES/strings.mo


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


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


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