From 14fe5080ec9f1043467e9525af8b953d35766bc4 Mon Sep 17 00:00:00 2001
From: Marius Stanciu
Date: Mon, 9 Sep 2019 19:30:43 +0300
Subject: [PATCH] - 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
---
FlatCAMApp.py | 593 +++--
ObjectCollection.py | 3 +-
README.md | 2 +
camlib.py | 223 +-
locale/de/LC_MESSAGES/strings.mo | Bin 333692 -> 330077 bytes
locale/de/LC_MESSAGES/strings.po | 3893 ++++++++++++++++--------------
locale_template/strings.pot | 1299 +++++-----
7 files changed, 3213 insertions(+), 2800 deletions(-)
diff --git a/FlatCAMApp.py b/FlatCAMApp.py
index af61c8ea..ef3869b6 100644
--- a/FlatCAMApp.py
+++ b/FlatCAMApp.py
@@ -1109,7 +1109,8 @@ class App(QtCore.QObject):
ret_val = fcTranslate.apply_language('strings')
if ret_val == "no language":
- self.inform.emit(_("[ERROR] Could not find the Language files. The App strings are missing."))
+ self.inform.emit('[ERROR] %s' %
+ _("Could not find the Language files. The App strings are missing."))
log.debug("Could not find the Language files. The App strings are missing.")
else:
# make the current language the current selection on the language combobox
@@ -2647,7 +2648,8 @@ class App(QtCore.QObject):
isinstance(edited_object, FlatCAMExcellon):
pass
else:
- self.inform.emit(_("[WARNING_NOTCL] Select a Geometry, Gerber or Excellon Object to edit."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Select a Geometry, Gerber or Excellon Object to edit."))
return
if isinstance(edited_object, FlatCAMGeometry):
@@ -2660,7 +2662,8 @@ class App(QtCore.QObject):
if edited_object.multigeo is True:
edited_tools = [int(x.text()) for x in edited_object.ui.geo_tools_table.selectedItems()]
if len(edited_tools) > 1:
- self.inform.emit(_("[WARNING_NOTCL] Simultanoeus editing of tools geometry in a MultiGeo Geometry "
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Simultanoeus editing of tools geometry in a MultiGeo Geometry "
"is not possible.\n"
"Edit only one geometry at a time."))
@@ -2714,7 +2717,8 @@ class App(QtCore.QObject):
self.ui.plot_tab_area.setTabText(0, "EDITOR Area")
self.ui.plot_tab_area.protectTab(0)
- self.inform.emit(_("[WARNING_NOTCL] Editor is activated ..."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Editor is activated ..."))
self.should_we_save = True
@@ -2765,7 +2769,8 @@ class App(QtCore.QObject):
edited_obj.options['xmax'] = xmax
edited_obj.options['ymax'] = ymax
except AttributeError as e:
- self.inform.emit(_("[WARNING] Object empty after edit."))
+ self.inform.emit('[WARNING] %s' %
+ _("Object empty after edit."))
log.debug("App.editor2object() --> Geometry --> %s" % str(e))
elif isinstance(edited_obj, FlatCAMGerber):
obj_type = "Gerber"
@@ -2787,10 +2792,12 @@ class App(QtCore.QObject):
self.exc_editor.update_options(edited_obj)
self.exc_editor.deactivate()
else:
- self.inform.emit(_("[WARNING_NOTCL] Select a Gerber, Geometry or Excellon Object to update."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Select a Gerber, Geometry or Excellon Object to update."))
return
- self.inform.emit(_("[selected] %s is updated, returning to App...") % obj_type)
+ self.inform.emit('[selected] %s %s' %
+ (obj_type, _("is updated, returning to App...")))
elif response == bt_no:
# clean the Tools Tab
self.ui.tool_scroll_area.takeWidget()
@@ -2806,7 +2813,8 @@ class App(QtCore.QObject):
# set focus on the project tab
self.ui.notebook.setCurrentWidget(self.ui.project_tab)
else:
- self.inform.emit(_("[WARNING_NOTCL] Select a Gerber, Geometry or Excellon Object to update."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Select a Gerber, Geometry or Excellon Object to update."))
return
elif response == bt_cancel:
return
@@ -2818,7 +2826,8 @@ class App(QtCore.QObject):
elif isinstance(edited_obj, FlatCAMExcellon):
self.exc_editor.deactivate()
else:
- self.inform.emit(_("[WARNING_NOTCL] Select a Gerber, Geometry or Excellon Object to update."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Select a Gerber, Geometry or Excellon Object to update."))
return
# if notebook is hidden we show it
@@ -3173,7 +3182,8 @@ class App(QtCore.QObject):
f.close()
except IOError:
self.log.error("Could not load defaults file.")
- self.inform.emit(_("[ERROR] Could not load defaults file."))
+ self.inform.emit('[ERROR] %s' %
+ _("Could not load defaults file."))
# in case the defaults file can't be loaded, show all toolbars
self.defaults["global_toolbar_view"] = 511
return
@@ -3185,7 +3195,8 @@ class App(QtCore.QObject):
self.defaults["global_toolbar_view"] = 511
e = sys.exc_info()[0]
App.log.error(str(e))
- self.inform.emit(_("[ERROR] Failed to parse defaults file."))
+ self.inform.emit('[ERROR] %s' %
+ _("Failed to parse defaults file."))
return
self.defaults.update(defaults)
log.debug("FlatCAM defaults loaded from: %s" % filename)
@@ -3216,7 +3227,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] FlatCAM preferences import cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("FlatCAM preferences import cancelled."))
else:
try:
f = open(filename)
@@ -3224,7 +3236,8 @@ class App(QtCore.QObject):
f.close()
except IOError:
self.log.error("Could not load defaults file.")
- self.inform.emit(_("[ERROR_NOTCL] Could not load defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Could not load defaults file."))
return
try:
@@ -3232,11 +3245,13 @@ class App(QtCore.QObject):
except Exception as e:
e = sys.exc_info()[0]
App.log.error(str(e))
- self.inform.emit(_("[ERROR_NOTCL] Failed to parse defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to parse defaults file."))
return
self.defaults.update(defaults_from_file)
self.on_preferences_edited()
- self.inform.emit(_("[success] Imported Defaults from %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Imported Defaults from"), filename))
def on_export_preferences(self):
"""
@@ -3268,7 +3283,8 @@ class App(QtCore.QObject):
defaults_from_file = {}
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] FlatCAM preferences export cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("FlatCAM preferences export cancelled."))
return
else:
try:
@@ -3276,7 +3292,8 @@ class App(QtCore.QObject):
defaults_file_content = f.read()
f.close()
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return
except IOError:
@@ -3288,7 +3305,8 @@ class App(QtCore.QObject):
e = sys.exc_info()[0]
App.log.error("Could not load defaults file.")
App.log.error(str(e))
- self.inform.emit(_("[ERROR_NOTCL] Could not load defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Could not load preferences file."))
return
try:
@@ -3307,12 +3325,14 @@ class App(QtCore.QObject):
json.dump(defaults_from_file, f, default=to_dict, indent=2, sort_keys=True)
f.close()
except:
- self.inform.emit(_("[ERROR_NOTCL] Failed to write defaults to file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to write defaults to file."))
return
if self.defaults["global_open_style"] is False:
self.file_opened.emit("preferences", filename)
self.file_saved.emit("preferences", filename)
- self.inform.emit("[success] Exported Defaults to %s" % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Exported preferences to"), filename))
def on_preferences_open_folder(self):
"""
@@ -3328,7 +3348,8 @@ class App(QtCore.QObject):
os.system('open "%s"' % self.data_path)
else:
subprocess.Popen(['xdg-open', self.data_path])
- self.inform.emit("[success] FlatCAM Preferences Folder opened.")
+ self.inform.emit('[success] %s' %
+ _("FlatCAM Preferences Folder opened."))
def save_geometry(self, x, y, width, height, notebook_width):
"""
@@ -3400,7 +3421,8 @@ class App(QtCore.QObject):
f = open(self.data_path + '/recent.json', 'w')
except IOError:
App.log.error("Failed to open recent items file for writing.")
- self.inform.emit(_('[ERROR_NOTCL] Failed to open recent files file for writing.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Failed to open recent files file for writing.'))
return
json.dump(self.recent, f, default=to_dict, indent=2, sort_keys=True)
@@ -3410,7 +3432,8 @@ class App(QtCore.QObject):
fp = open(self.data_path + '/recent_projects.json', 'w')
except IOError:
App.log.error("Failed to open recent items file for writing.")
- self.inform.emit(_('[ERROR_NOTCL] Failed to open recent projects file for writing.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Failed to open recent projects file for writing.'))
return
json.dump(self.recent_projects, fp, default=to_dict, indent=2, sort_keys=True)
@@ -3492,7 +3515,8 @@ class App(QtCore.QObject):
try:
return_value = initialize(obj, self)
except Exception as e:
- msg = _("[ERROR_NOTCL] An internal error has ocurred. See shell.\n")
+ msg = '[ERROR_NOTCL] %s' % \
+ _("An internal error has ocurred. See shell.\n")
msg += _("Object ({kind}) failed because: {error} \n\n").format(kind=kind, error=str(e))
msg += traceback.format_exc()
self.inform.emit(msg)
@@ -3513,7 +3537,8 @@ class App(QtCore.QObject):
# Check units and convert if necessary
# This condition CAN be true because initialize() can change obj.units
if self.options["units"].upper() != obj.units.upper():
- self.inform.emit(_("Converting units to ") + self.options["units"] + ".")
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Converting units to "), self.options["units"]))
obj.convert_units(self.options["units"])
t3 = time.time()
self.log.debug("%f seconds converting units." % (t3 - t2))
@@ -3860,7 +3885,8 @@ class App(QtCore.QObject):
e = sys.exc_info()[0]
App.log.error("Could not load defaults file.")
App.log.error(str(e))
- self.inform.emit(_("[ERROR_NOTCL] Could not load defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Could not load defaults file."))
return
try:
@@ -3869,7 +3895,8 @@ class App(QtCore.QObject):
e = sys.exc_info()[0]
App.log.error("Failed to parse defaults file.")
App.log.error(str(e))
- self.inform.emit(_("[ERROR_NOTCL] Failed to parse defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to parse defaults file."))
return
# Update options
@@ -3914,11 +3941,13 @@ class App(QtCore.QObject):
json.dump(defaults, f, default=to_dict, indent=2, sort_keys=True)
f.close()
except:
- self.inform.emit(_("[ERROR_NOTCL] Failed to write defaults to file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to write defaults to file."))
return
if not silent:
- self.inform.emit(_("[success] Defaults saved."))
+ self.inform.emit('[success] %s' %
+ _("Preferences saved."))
def save_factory_defaults(self, silent=False, data_path=None):
"""
@@ -3945,7 +3974,8 @@ class App(QtCore.QObject):
e = sys.exc_info()[0]
App.log.error("Could not load factory defaults file.")
App.log.error(str(e))
- self.inform.emit(_("[ERROR_NOTCL] Could not load factory defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Could not load factory defaults file."))
return
try:
@@ -3954,7 +3984,8 @@ class App(QtCore.QObject):
e = sys.exc_info()[0]
App.log.error("Failed to parse factory defaults file.")
App.log.error(str(e))
- self.inform.emit(_("[ERROR_NOTCL] Failed to parse factory defaults file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to parse factory defaults file."))
return
# Update options
@@ -3968,7 +3999,8 @@ class App(QtCore.QObject):
json.dump(factory_defaults, f_f_def_s, default=to_dict, indent=2, sort_keys=True)
f_f_def_s.close()
except:
- self.inform.emit(_("[ERROR_NOTCL] Failed to write factory defaults to file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to write factory defaults to file."))
return
if silent is False:
@@ -3982,7 +4014,8 @@ class App(QtCore.QObject):
:return: None
"""
if self.save_in_progress:
- self.inform.emit(_("[WARNING_NOTCL] Application is saving the project. Please wait ..."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Application is saving the project. Please wait ..."))
return
if self.should_we_save and self.collection.get_list():
@@ -4222,7 +4255,8 @@ class App(QtCore.QObject):
for ext in gco_list:
new_ext = new_ext + ext + ', '
self.defaults["fa_gcode"] = new_ext
- self.inform.emit(_("[success] Selected GCode file extensions registered with FlatCAM."))
+ self.inform.emit('[success] %s' %
+ _("Selected GCode file extensions registered with FlatCAM."))
if obj_type is None or obj_type == 'gerber':
grb_list = self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.get_value().replace(' ', '').split(',')
@@ -4243,7 +4277,8 @@ class App(QtCore.QObject):
for ext in grb_list:
new_ext = new_ext + ext + ', '
self.defaults["fa_gerber"] = new_ext
- self.inform.emit(_("[success] Selected Gerber file extensions registered with FlatCAM."))
+ self.inform.emit('[success] %s' %
+ _("Selected Gerber file extensions registered with FlatCAM."))
def on_edit_join(self, name=None):
"""
@@ -4266,7 +4301,8 @@ class App(QtCore.QObject):
# if len(geo_type_list) == 1 means that all list elements are the same
if len(geo_type_list) != 1:
- self.inform.emit(_("[ERROR] Failed join. The Geometry objects are of different types.\n"
+ self.inform.emit('[ERROR] %s' %
+ _("Failed join. The Geometry objects are of different types.\n"
"At least one is MultiGeo type and the other is SingleGeo type. A possibility is to "
"convert from one to another and retry joining \n"
"but in the case of converting from MultiGeo to SingleGeo, informations may be lost and "
@@ -4307,7 +4343,8 @@ class App(QtCore.QObject):
for obj in objs:
if not isinstance(obj, FlatCAMExcellon):
- self.inform.emit(_("[ERROR_NOTCL] Failed. Excellon joining works only on Excellon objects."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Excellon joining works only on Excellon objects."))
return
def initialize(obj, app):
@@ -4329,7 +4366,8 @@ class App(QtCore.QObject):
for obj in objs:
if not isinstance(obj, FlatCAMGerber):
- self.inform.emit(_("[ERROR_NOTCL] Failed. Gerber joining works only on Gerber objects."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Gerber joining works only on Gerber objects."))
return
def initialize(obj, app):
@@ -4353,11 +4391,13 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[ERROR_NOTCL] Failed. Select a Geometry Object and try again."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Select a Geometry Object and try again."))
return
if not isinstance(obj, FlatCAMGeometry):
- self.inform.emit(_("[ERROR_NOTCL] Expected a FlatCAMGeometry, got %s") % type(obj))
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Expected a FlatCAMGeometry, got"), type(obj)))
return
obj.multigeo = True
@@ -4370,7 +4410,8 @@ class App(QtCore.QObject):
self.should_we_save = True
- self.inform.emit(_("[success] A Geometry object was converted to MultiGeo type."))
+ self.inform.emit('[success] %s' %
+ _("A Geometry object was converted to MultiGeo type."))
def on_convert_multigeo_to_singlegeo(self):
"""
@@ -4387,11 +4428,13 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[ERROR_NOTCL] Failed. Select a Geometry Object and try again."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Select a Geometry Object and try again."))
return
if not isinstance(obj, FlatCAMGeometry):
- self.inform.emit(_("[ERROR_NOTCL] Expected a FlatCAMGeometry, got %s") % type(obj))
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Expected a FlatCAMGeometry, got %s"), type(obj)))
return
obj.multigeo = False
@@ -4405,7 +4448,8 @@ class App(QtCore.QObject):
self.should_we_save = True
- self.inform.emit(_("[success] A Geometry object was converted to SingleGeo type."))
+ self.inform.emit('[success] %s' %
+ _("A Geometry object was converted to SingleGeo type."))
def on_options_dict_change(self, field):
"""
@@ -4719,7 +4763,8 @@ class App(QtCore.QObject):
current.to_form()
self.plot_all()
- self.inform.emit(_("[success] Converted units to %s") % new_units)
+ self.inform.emit('[success] %s: %s' %
+ (_("Converted units to %s"), new_units))
# self.ui.units_label.setText("[" + self.options["units"] + "]")
self.set_screen_units(new_units)
else:
@@ -4730,7 +4775,8 @@ class App(QtCore.QObject):
else:
self.ui.general_defaults_form.general_app_group.units_radio.set_value('MM')
self.toggle_units_ignore = False
- self.inform.emit(_("[WARNING_NOTCL] Units conversion cancelled."))
+ self.inform.emit('[WARNING_NOTCL]%s' %
+ _(" Units conversion cancelled."))
self.options_read_form()
self.defaults_read_form()
@@ -5467,7 +5513,8 @@ class App(QtCore.QObject):
filename = str(QtWidgets.QFileDialog.getSaveFileName(caption=_("Export G-Code ..."), filter=_filter_)[0])
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Export Code cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Export Code cancelled."))
return
else:
try:
@@ -5476,10 +5523,12 @@ class App(QtCore.QObject):
for line in my_gcode:
f.write(line)
except FileNotFoundError:
- self.inform.emit(_("[WARNING] No such file or directory"))
+ self.inform.emit('[WARNING] %s' %
+ _("No such file or directory"))
return
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return
@@ -5549,13 +5598,13 @@ class App(QtCore.QObject):
val, ok = tool_add_popup.get_value()
if ok:
if float(val) == 0:
- self.inform.emit(
- _("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Please enter a tool diameter with non-zero value, in Float format."))
return
self.collection.get_active().on_tool_add(dia=float(val))
else:
- self.inform.emit(
- _("[WARNING_NOTCL] Adding Tool cancelled ..."))
+ self.inform.emit('[WARNING_NOTCL] %s...' %
+ _("Adding Tool cancelled"))
else:
msgbox = QtWidgets.QMessageBox()
msgbox.setText(_("Adding Tool works only when Advanced is checked.\n"
@@ -5582,19 +5631,19 @@ class App(QtCore.QObject):
if tool_widget == self.ncclear_tool.toolName:
if ok:
if float(val) == 0:
- self.inform.emit(
- _("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Please enter a tool diameter with non-zero value, in Float format."))
return
self.ncclear_tool.on_tool_add(dia=float(val))
else:
- self.inform.emit(
- _("[WARNING_NOTCL] Adding Tool cancelled ..."))
+ self.inform.emit('[WARNING_NOTCL] %s...' %
+ _("Adding Tool cancelled"))
# and only if the tool is Paint Area Tool
elif tool_widget == self.paint_tool.toolName:
if ok:
if float(val) == 0:
- self.inform.emit(
- _("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Please enter a tool diameter with non-zero value, in Float format."))
return
self.paint_tool.on_tool_add(dia=float(val))
else:
@@ -5604,13 +5653,13 @@ class App(QtCore.QObject):
elif tool_widget == self.paste_tool.toolName:
if ok:
if float(val) == 0:
- self.inform.emit(
- _("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Please enter a tool diameter with non-zero value, in Float format."))
return
self.paste_tool.on_tool_add(dia=float(val))
else:
- self.inform.emit(
- _("[WARNING_NOTCL] Adding Tool cancelled ..."))
+ self.inform.emit('[WARNING_NOTCL] %s...' %
+ _("Adding Tool cancelled"))
# It's meant to delete tools in tool tables via a 'Delete' shortcut key but only if certain conditions are met
# See description bellow.
@@ -5694,7 +5743,8 @@ class App(QtCore.QObject):
pass
self.delete_first_selected()
- self.inform.emit(_("Object(s) deleted ..."))
+ self.inform.emit('%s...' %
+ _("Object(s) deleted"))
# make sure that the selection shape is deleted, too
self.delete_selection_shape()
else:
@@ -5717,7 +5767,8 @@ class App(QtCore.QObject):
# Clear form
self.setup_component_editor()
- self.inform.emit("Object deleted: %s" % name)
+ self.inform.emit('%s: %s' %
+ (_("Object deleted"), name))
def on_set_origin(self):
"""
@@ -5776,7 +5827,8 @@ class App(QtCore.QObject):
obj.options['ymin'] = b
obj.options['xmax'] = c
obj.options['ymax'] = d
- self.inform.emit(_('[success] Origin set ...'))
+ self.inform.emit('[success]%s...' %
+ _('Origin set'))
self.replot_signal.emit([])
self.worker_task.emit({'fcn': worker_task, 'params': []})
@@ -5817,7 +5869,8 @@ class App(QtCore.QObject):
jump_loc = self.plotcanvas.translate_coords_2((location[0], location[1]))
cursor.setPos(canvas_origin.x() + jump_loc[0], (canvas_origin.y() + jump_loc[1]))
- self.inform.emit(_("[success] Done."))
+ self.inform.emit('[success] %s' %
+ _("Done."))
return location
def on_copy_object(self):
@@ -5950,7 +6003,8 @@ class App(QtCore.QObject):
if not self.collection.get_selected():
log.warning("App.convert_any2geo --> No object selected")
- self.inform.emit(_("[WARNING_NOTCL] No object is selected. Select an object and try again."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object is selected. Select an object and try again."))
return
for obj in self.collection.get_selected():
@@ -6017,7 +6071,8 @@ class App(QtCore.QObject):
if not self.collection.get_selected():
log.warning("App.convert_any2gerber --> No object selected")
- self.inform.emit(_("[WARNING_NOTCL] No object is selected. Select an object and try again."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object is selected. Select an object and try again."))
return
for obj in self.collection.get_selected():
@@ -6126,7 +6181,8 @@ class App(QtCore.QObject):
pass
def on_preferences_edited(self):
- self.inform.emit(_("[WARNING_NOTCL] Preferences edited but not saved."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Preferences edited but not saved."))
self.preferences_changed_flag = True
def on_preferences_closed(self):
@@ -6174,7 +6230,8 @@ class App(QtCore.QObject):
if response == bt_yes:
self.on_save_button()
- self.inform.emit(_("[success] Preferences saved."))
+ self.inform.emit('[success] %s' %
+ _("Preferences saved."))
else:
self.preferences_changed_flag = False
return
@@ -6189,7 +6246,8 @@ class App(QtCore.QObject):
ymaxlist = []
if not obj_list:
- self.inform.emit(_("[WARNING_NOTCL] No object selected to Flip on Y axis."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected to Flip on Y axis."))
else:
try:
# first get a bounding box to fit all
@@ -6214,9 +6272,11 @@ class App(QtCore.QObject):
obj.mirror('X', [px, py])
obj.plot()
self.object_changed.emit(obj)
- self.inform.emit(_("[success] Flip on Y axis done."))
+ self.inform.emit('[success] %s' %
+ _("Flip on Y axis done."))
except Exception as e:
- self.inform.emit(_("[ERROR_NOTCL] Due of %s, Flip action was not executed.") % str(e))
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Flip action was not executed."), str(e)))
return
def on_flipx(self):
@@ -6229,7 +6289,8 @@ class App(QtCore.QObject):
ymaxlist = []
if not obj_list:
- self.inform.emit(_("[WARNING_NOTCL] No object selected to Flip on X axis."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected to Flip on X axis."))
else:
try:
# first get a bounding box to fit all
@@ -6254,9 +6315,11 @@ class App(QtCore.QObject):
obj.mirror('Y', [px, py])
obj.plot()
self.object_changed.emit(obj)
- self.inform.emit(_("[success] Flip on X axis done."))
+ self.inform.emit('[success] %s' %
+ _("Flip on X axis done."))
except Exception as e:
- self.inform.emit(_("[ERROR_NOTCL] Due of %s, Flip action was not executed.") % str(e))
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Flip action was not executed."), str(e)))
return
def on_rotate(self, silent=False, preset=None):
@@ -6269,7 +6332,8 @@ class App(QtCore.QObject):
ymaxlist = []
if not obj_list:
- self.inform.emit(_("[WARNING_NOTCL] No object selected to Rotate."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected to Rotate."))
else:
if silent is False:
rotatebox = FCInputDialog(title=_("Transform"), text=_("Enter the Angle value:"),
@@ -6302,9 +6366,11 @@ class App(QtCore.QObject):
sel_obj.rotate(-float(num), point=(px, py))
sel_obj.plot()
self.object_changed.emit(sel_obj)
- self.inform.emit(_("[success] Rotation done."))
+ self.inform.emit('[success] %s' %
+ _("Rotation done."))
except Exception as e:
- self.inform.emit(_("[ERROR_NOTCL] Due of %s, rotation movement was not executed.") % str(e))
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Rotation movement was not executed."), str(e)))
return
def on_skewx(self):
@@ -6315,7 +6381,8 @@ class App(QtCore.QObject):
yminlist = []
if not obj_list:
- self.inform.emit(_("[WARNING_NOTCL] No object selected to Skew/Shear on X axis."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected to Skew/Shear on X axis."))
else:
skewxbox = FCInputDialog(title=_("Transform"), text=_("Enter the Angle value:"),
min=-360, max=360, decimals=4,
@@ -6336,7 +6403,8 @@ class App(QtCore.QObject):
obj.skew(num, 0, point=(xminimal, yminimal))
obj.plot()
self.object_changed.emit(obj)
- self.inform.emit(_("[success] Skew on X axis done."))
+ self.inform.emit('[success] %s' %
+ _("Skew on X axis done."))
def on_skewy(self):
self.report_usage("on_skewy()")
@@ -6346,7 +6414,8 @@ class App(QtCore.QObject):
yminlist = []
if not obj_list:
- self.inform.emit(_("[WARNING_NOTCL] No object selected to Skew/Shear on Y axis."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected to Skew/Shear on Y axis."))
else:
skewybox = FCInputDialog(title=_("Transform"), text=_("Enter the Angle value:"),
min=-360, max=360, decimals=4,
@@ -6367,7 +6436,8 @@ class App(QtCore.QObject):
obj.skew(0, num, point=(xminimal, yminimal))
obj.plot()
self.object_changed.emit(obj)
- self.inform.emit(_("[success] Skew on Y axis done."))
+ self.inform.emit('[success] %s' %
+ _("Skew on Y axis done."))
def on_plots_updated(self):
"""
@@ -6453,20 +6523,20 @@ class App(QtCore.QObject):
val, ok = grid_add_popup.get_value()
if ok:
if float(val) == 0:
- self.inform.emit(
- _("[WARNING_NOTCL] Please enter a grid value with non-zero value, in Float format."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Please enter a grid value with non-zero value, in Float format."))
return
else:
if val not in self.defaults["global_grid_context_menu"][str(units)]:
self.defaults["global_grid_context_menu"][str(units)].append(val)
- self.inform.emit(
- _("[success] New Grid added ..."))
+ self.inform.emit('[success] %s...' %
+ _("New Grid added"))
else:
- self.inform.emit(
- _("[WARNING_NOTCL] Grid already exists ..."))
+ self.inform.emit('[WARNING_NOTCL] %s...' %
+ _("Grid already exists"))
else:
- self.inform.emit(
- _("[WARNING_NOTCL] Adding New Grid cancelled ..."))
+ self.inform.emit('[WARNING_NOTCL] %s...' %
+ _("Adding New Grid cancelled"))
def on_grid_delete(self):
# ## Current application units in lower Case
@@ -6480,21 +6550,21 @@ class App(QtCore.QObject):
val, ok = grid_del_popup.get_value()
if ok:
if float(val) == 0:
- self.inform.emit(
- _("[WARNING_NOTCL] Please enter a grid value with non-zero value, in Float format."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Please enter a grid value with non-zero value, in Float format."))
return
else:
try:
self.defaults["global_grid_context_menu"][str(units)].remove(val)
except ValueError:
- self.inform.emit(
- _("[ERROR_NOTCL] Grid Value does not exist ..."))
+ self.inform.emit('[ERROR_NOTCL]%s...' %
+ _(" Grid Value does not exist"))
return
- self.inform.emit(
- _("[success] Grid Value deleted ..."))
+ self.inform.emit('[success] %s...' %
+ _("Grid Value deleted"))
else:
- self.inform.emit(
- _("[WARNING_NOTCL] Delete Grid value cancelled ..."))
+ self.inform.emit('[WARNING_NOTCL] %s...' %
+ _("Delete Grid value cancelled"))
def on_shortcut_list(self):
self.report_usage("on_shortcut_list()")
@@ -6533,7 +6603,8 @@ class App(QtCore.QObject):
name = obj.options["name"]
except AttributeError:
log.debug("on_copy_name() --> No object selected to copy it's name")
- self.inform.emit(_("[WARNING_NOTCL] No object selected to copy it's name"))
+ self.inform.emit('[WARNING_NOTCL]%s' %
+ _(" No object selected to copy it's name"))
return
self.clipboard.setText(name)
@@ -6579,7 +6650,8 @@ class App(QtCore.QObject):
self.click_noproject = True
self.clipboard.setText(self.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1]))
- self.inform.emit(_("[success] Coordinates copied to clipboard."))
+ self.inform.emit('[success] %s' %
+ _("Coordinates copied to clipboard."))
return
self.on_mouse_move_over_plot(event, origin_click=True)
@@ -7069,7 +7141,8 @@ class App(QtCore.QObject):
self.on_file_new()
else:
self.on_file_new()
- self.inform.emit(_("[success] New Project created..."))
+ self.inform.emit('[success] %s...' %
+ _("New Project created"))
def on_file_new(self):
"""
@@ -7200,7 +7273,8 @@ class App(QtCore.QObject):
filenames = [name]
if len(filenames) == 0:
- self.inform.emit(_("[WARNING_NOTCL] Open Gerber cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open Gerber cancelled."))
else:
for filename in filenames:
if filename != '':
@@ -7230,7 +7304,8 @@ class App(QtCore.QObject):
filenames = [str(name)]
if len(filenames) == 0:
- self.inform.emit(_("[WARNING_NOTCL] Open Excellon cancelled."))
+ self.inform.emit('[WARNING_NOTCL]%s' %
+ _(" Open Excellon cancelled."))
else:
for filename in filenames:
if filename != '':
@@ -7264,7 +7339,8 @@ class App(QtCore.QObject):
filenames = [name]
if len(filenames) == 0:
- self.inform.emit(_("[WARNING_NOTCL] Open G-Code cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open G-Code cancelled."))
else:
for filename in filenames:
if filename != '':
@@ -7292,7 +7368,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Open Project cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open Project cancelled."))
else:
# self.worker_task.emit({'fcn': self.open_project,
# 'params': [filename]})
@@ -7318,7 +7395,8 @@ class App(QtCore.QObject):
filter=_filter_)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Open Config cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open Config cancelled."))
else:
self.open_config_file(filename)
@@ -7333,7 +7411,8 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected."))
msg = _("Please Select a Geometry object to export")
msgbox = QtWidgets.QMessageBox()
msgbox.setInformativeText(msg)
@@ -7347,7 +7426,8 @@ class App(QtCore.QObject):
and not isinstance(obj, FlatCAMGerber)
and not isinstance(obj, FlatCAMCNCjob)
and not isinstance(obj, FlatCAMExcellon)):
- msg = _("[ERROR_NOTCL] Only Geometry, Gerber and CNCJob objects can be used.")
+ msg = '[ERROR_NOTCL] %s' % \
+ _("Only Geometry, Gerber and CNCJob objects can be used.")
msgbox = QtWidgets.QMessageBox()
msgbox.setInformativeText(msg)
bt_ok = msgbox.addButton(_('Ok'), QtWidgets.QMessageBox.AcceptRole)
@@ -7369,7 +7449,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Export SVG cancelled."))
+ self.inform.emit('[WARNING_NOTCL]%s' %
+ _(" Export SVG cancelled."))
return
else:
self.export_svg(name, filename)
@@ -7388,7 +7469,8 @@ class App(QtCore.QObject):
image = _screenshot()
data = np.asarray(image)
if not data.ndim == 3 and data.shape[-1] in (3, 4):
- self.inform.emit(_('[[WARNING_NOTCL]] Data must be a 3D array with last dimension 3 or 4'))
+ self.inform.emit('[[WARNING_NOTCL]] %s' %
+ _('Data must be a 3D array with last dimension 3 or 4'))
return
filter_ = "PNG File (*.png);;All Files (*.*)"
@@ -7422,12 +7504,14 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected. Please select an Gerber object to export."))
+ self.inform.emit('[WARNING_NOTCL] %S' %
+ _("No object selected. Please select an Gerber object to export."))
return
# Check for more compatible types and add as required
if not isinstance(obj, FlatCAMGerber):
- self.inform.emit(_("[ERROR_NOTCL] Failed. Only Gerber objects can be saved as Gerber files..."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Only Gerber objects can be saved as Gerber files..."))
return
name = self.collection.get_active().options["name"]
@@ -7444,7 +7528,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Save Gerber source file cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Save Gerber source file cancelled."))
return
else:
self.save_source_file(name, filename)
@@ -7463,12 +7548,14 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected. Please select an Excellon object to export."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected. Please select an Excellon object to export."))
return
# Check for more compatible types and add as required
if not isinstance(obj, FlatCAMExcellon):
- self.inform.emit(_("[ERROR_NOTCL] Failed. Only Excellon objects can be saved as Excellon files..."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Only Excellon objects can be saved as Excellon files..."))
return
name = self.collection.get_active().options["name"]
@@ -7485,7 +7572,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Saving Excellon source file cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Saving Excellon source file cancelled."))
return
else:
self.save_source_file(name, filename)
@@ -7504,12 +7592,14 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an Excellon object to export."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected. Please Select an Excellon object to export."))
return
# Check for more compatible types and add as required
if not isinstance(obj, FlatCAMExcellon):
- self.inform.emit(_("[ERROR_NOTCL] Failed. Only Excellon objects can be saved as Excellon files..."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Only Excellon objects can be saved as Excellon files..."))
return
name = self.collection.get_active().options["name"]
@@ -7526,7 +7616,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Export Excellon cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Export Excellon cancelled."))
return
else:
self.export_excellon(name, filename)
@@ -7545,12 +7636,14 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an Gerber object to export."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected. Please Select an Gerber object to export."))
return
# Check for more compatible types and add as required
if not isinstance(obj, FlatCAMGerber):
- self.inform.emit(_("[ERROR_NOTCL] Failed. Only Gerber objects can be saved as Gerber files..."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed. Only Gerber objects can be saved as Gerber files..."))
return
name = self.collection.get_active().options["name"]
@@ -7567,7 +7660,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Export Gerber cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Export Gerber cancelled."))
return
else:
self.export_gerber(name, filename)
@@ -7586,7 +7680,8 @@ class App(QtCore.QObject):
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected."))
msg = _("Please Select a Geometry object to export")
msgbox = QtWidgets.QMessageBox()
msgbox.setInformativeText(msg)
@@ -7597,7 +7692,8 @@ class App(QtCore.QObject):
# Check for more compatible types and add as required
if not isinstance(obj, FlatCAMGeometry):
- msg = _("[ERROR_NOTCL] Only Geometry objects can be used.")
+ msg = '[ERROR_NOTCL] %s' % \
+ _("Only Geometry objects can be used.")
msgbox = QtWidgets.QMessageBox()
msgbox.setInformativeText(msg)
bt_ok = msgbox.addButton(_('Ok'), QtWidgets.QMessageBox.AcceptRole)
@@ -7621,7 +7717,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Export DXF cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Export DXF cancelled."))
return
else:
self.export_dxf(name, filename)
@@ -7653,7 +7750,8 @@ class App(QtCore.QObject):
filenames = [str(filename) for filename in filenames]
if len(filenames) == 0:
- self.inform.emit(_("[WARNING_NOTCL] Open SVG cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open SVG cancelled."))
else:
for filename in filenames:
if filename != '':
@@ -7685,7 +7783,8 @@ class App(QtCore.QObject):
filenames = [str(filename) for filename in filenames]
if len(filenames) == 0:
- self.inform.emit(_("[WARNING_NOTCL] Open DXF cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open DXF cancelled."))
else:
for filename in filenames:
if filename != '':
@@ -7723,14 +7822,16 @@ class App(QtCore.QObject):
try:
obj = self.collection.get_active()
except:
- self.inform.emit(_("[WARNING_NOTCL] Select an Gerber or Excellon file to view it's source file."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Select an Gerber or Excellon file to view it's source file."))
return 'fail'
# then append the text from GCode to the text editor
try:
file = StringIO(obj.source_file)
except AttributeError:
- self.inform.emit(_("[WARNING_NOTCL] There is no selected object for which to see it's source file code."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("There is no selected object for which to see it's source file code."))
return 'fail'
if obj.kind == 'gerber':
@@ -7748,7 +7849,8 @@ class App(QtCore.QObject):
self.ui.code_editor.append(proc_line)
except Exception as e:
log.debug('App.on_view_source() -->%s' % str(e))
- self.inform.emit(_('[ERROR]App.on_view_source() -->%s') % str(e))
+ self.inform.emit('[ERROR] %s %s' %
+ (_('App.on_view_source() -->'), str(e)))
return
self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
@@ -7809,7 +7911,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Open TCL script cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Open TCL script cancelled."))
else:
self.on_filenewscript()
@@ -7821,7 +7924,8 @@ class App(QtCore.QObject):
self.ui.code_editor.append(proc_line)
except Exception as e:
log.debug('App.on_fileopenscript() -->%s' % str(e))
- self.inform.emit(_('[ERROR]App.on_fileopenscript() -->%s') % str(e))
+ self.inform.emit('[ERROR] %s %s' %
+ (_('App.on_fileopenscript() -->'), str(e)))
return
self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
@@ -7858,7 +7962,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == "":
- self.inform.emit(_("[WARNING_NOTCL] Run TCL script cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Run TCL script cancelled."))
else:
try:
with open(filename, "r") as tcl_script:
@@ -7922,7 +8027,8 @@ class App(QtCore.QObject):
filename = str(filename)
if filename == '':
- self.inform.emit(_("[WARNING_NOTCL] Save Project cancelled."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Save Project cancelled."))
return
try:
@@ -8003,14 +8109,16 @@ class App(QtCore.QObject):
with open(filename, 'w') as fp:
fp.write(svgcode.toprettyxml())
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return 'fail'
if self.defaults["global_open_style"] is False:
self.file_opened.emit("SVG", filename)
self.file_saved.emit("SVG", filename)
- self.inform.emit(_("[success] SVG file exported to %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("SVG file exported to"), filename))
def export_svg_negative(self, obj_name, box_name, filename, boundary, scale_factor=0.00, use_thread=True):
"""
@@ -8044,7 +8152,8 @@ class App(QtCore.QObject):
return "Could not retrieve object: %s" % box_name
if box is None:
- self.inform.emit(_("[WARNING_NOTCL] No object Box. Using instead %s") % obj)
+ self.inform.emit('[WARNING_NOTCL] %s: %s' %
+ (_("No object Box. Using instead"), obj))
box = obj
def make_negative_film():
@@ -8116,7 +8225,8 @@ class App(QtCore.QObject):
with open(filename, 'w') as fp:
fp.write(doc.toprettyxml())
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return 'fail'
@@ -8124,7 +8234,8 @@ class App(QtCore.QObject):
if self.defaults["global_open_style"] is False:
self.file_opened.emit("SVG", filename)
self.file_saved.emit("SVG", filename)
- self.inform.emit(_("[success] SVG file exported to %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("SVG file exported to"), filename))
if use_thread is True:
proc = self.proc_container.new(_("Generating Film ... Please wait."))
@@ -8172,7 +8283,8 @@ class App(QtCore.QObject):
return "Could not retrieve object: %s" % box_name
if box is None:
- self.inform.emit(_("[WARNING_NOTCL] No object Box. Using instead %s") % obj)
+ self.inform.emit('[WARNING_NOTCL] %s: %s' %
+ (_("No object Box. Using instead"), obj))
box = obj
def make_black_film():
@@ -8239,7 +8351,8 @@ class App(QtCore.QObject):
with open(filename, 'w') as fp:
fp.write(doc.toprettyxml())
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return 'fail'
@@ -8247,7 +8360,8 @@ class App(QtCore.QObject):
if self.defaults["global_open_style"] is False:
self.file_opened.emit("SVG", filename)
self.file_saved.emit("SVG", filename)
- self.inform.emit(_("[success] SVG file exported to %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("SVG file exported to"), filename))
if use_thread is True:
proc = self.proc_container.new(_("Generating Film ... Please wait."))
@@ -8296,7 +8410,8 @@ class App(QtCore.QObject):
for line in file_string:
file.writelines(line)
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return 'fail'
@@ -8409,14 +8524,16 @@ class App(QtCore.QObject):
with open(filename, 'w') as fp:
fp.write(exported_excellon)
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return 'fail'
if self.defaults["global_open_style"] is False:
self.file_opened.emit("Excellon", filename)
self.file_saved.emit("Excellon", filename)
- self.inform.emit(_("[success] Excellon file exported to %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Excellon file exported to"), filename))
except Exception as e:
log.debug("App.export_excellon.make_excellon() --> %s" % str(e))
return 'fail'
@@ -8428,14 +8545,16 @@ class App(QtCore.QObject):
def job_thread_exc(app_obj):
ret = make_excellon()
if ret == 'fail':
- self.inform.emit(_('[ERROR_NOTCL] Could not export Excellon file.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Could not export Excellon file.'))
return
self.worker_task.emit({'fcn': job_thread_exc, 'params': [self]})
else:
ret = make_excellon()
if ret == 'fail':
- self.inform.emit(_('[ERROR_NOTCL] Could not export Excellon file.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Could not export Excellon file.'))
return
def export_gerber(self, obj_name, filename, use_thread=True):
@@ -8534,14 +8653,16 @@ class App(QtCore.QObject):
with open(filename, 'w') as fp:
fp.write(exported_gerber)
except PermissionError:
- self.inform.emit(_("[WARNING] Permission denied, saving not possible.\n"
+ self.inform.emit('[WARNING] %s' %
+ _("Permission denied, saving not possible.\n"
"Most likely another app is holding the file open and not accessible."))
return 'fail'
if self.defaults["global_open_style"] is False:
self.file_opened.emit("Gerber", filename)
self.file_saved.emit("Gerber", filename)
- self.inform.emit(_("[success] Gerber file exported to %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Gerber file exported to"), filename))
except Exception as e:
log.debug("App.export_gerber.make_gerber() --> %s" % str(e))
return 'fail'
@@ -8553,14 +8674,16 @@ class App(QtCore.QObject):
def job_thread_exc(app_obj):
ret = make_gerber()
if ret == 'fail':
- self.inform.emit(_('[ERROR_NOTCL] Could not export Gerber file.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Could not export Gerber file.'))
return
self.worker_task.emit({'fcn': job_thread_exc, 'params': [self]})
else:
ret = make_gerber()
if ret == 'fail':
- self.inform.emit(_('[ERROR_NOTCL] Could not export Gerber file.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Could not export Gerber file.'))
return
def export_dxf(self, obj_name, filename, use_thread=True):
@@ -8602,7 +8725,8 @@ class App(QtCore.QObject):
if self.defaults["global_open_style"] is False:
self.file_opened.emit("DXF", filename)
self.file_saved.emit("DXF", filename)
- self.inform.emit(_("[success] DXF file exported to %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("DXF file exported to"), filename))
except:
return 'fail'
@@ -8613,14 +8737,16 @@ class App(QtCore.QObject):
def job_thread_exc(app_obj):
ret = make_dxf()
if ret == 'fail':
- app_obj.inform.emit(_('[[WARNING_NOTCL]] Could not export DXF file.'))
+ app_obj.inform.emit('[WARNING_NOTCL] %s' %
+ _('Could not export DXF file.'))
return
self.worker_task.emit({'fcn': job_thread_exc, 'params': [self]})
else:
ret = make_dxf()
if ret == 'fail':
- self.inform.emit(_('[[WARNING_NOTCL]] Could not export DXF file.'))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _('Could not export DXF file.'))
return
def import_svg(self, filename, geo_type='geometry', outname=None):
@@ -8640,7 +8766,8 @@ class App(QtCore.QObject):
elif geo_type == "gerber":
obj_type = geo_type
else:
- self.inform.emit(_("[ERROR_NOTCL] Not supported type is picked as parameter. "
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Not supported type is picked as parameter. "
"Only Geometry and Gerber are supported"))
return
@@ -8661,7 +8788,8 @@ class App(QtCore.QObject):
self.file_opened.emit("svg", filename)
# GUI feedback
- self.inform.emit(_("[success] Opened: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Opened"), filename))
self.progress.emit(100)
def import_dxf(self, filename, geo_type='geometry', outname=None):
@@ -8682,7 +8810,8 @@ class App(QtCore.QObject):
elif geo_type == "gerber":
obj_type = geo_type
else:
- self.inform.emit(_("[ERROR_NOTCL] Not supported type is picked as parameter. "
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Not supported type is picked as parameter. "
"Only Geometry and Gerber are supported"))
return
@@ -8703,7 +8832,8 @@ class App(QtCore.QObject):
self.file_opened.emit("dxf", filename)
# GUI feedback
- self.inform.emit(_("[success] Opened: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Opened"), filename))
self.progress.emit(100)
def import_image(self, filename, o_type='gerber', dpi=96, mode='black', mask=[250, 250, 250, 250], outname=None):
@@ -8726,7 +8856,8 @@ class App(QtCore.QObject):
elif o_type == "gerber":
obj_type = o_type
else:
- self.inform.emit(_("[ERROR_NOTCL] Not supported type is picked as parameter. "
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Not supported type is picked as parameter. "
"Only Geometry and Gerber are supported"))
return
@@ -8746,7 +8877,8 @@ class App(QtCore.QObject):
self.file_opened.emit("image", filename)
# GUI feedback
- self.inform.emit(_("[success] Opened: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Opened"), filename))
self.progress.emit(100)
def open_gerber(self, filename, outname=None):
@@ -8775,19 +8907,22 @@ class App(QtCore.QObject):
try:
gerber_obj.parse_file(filename)
except IOError:
- app_obj.inform.emit(_("[ERROR_NOTCL] Failed to open file: %s") % filename)
+ app_obj.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Failed to open file"), filename))
app_obj.progress.emit(0)
- self.inform.emit(_('[ERROR_NOTCL] Failed to open file: %s') % filename)
return "fail"
except ParseError as err:
- app_obj.inform.emit(_("[ERROR_NOTCL] Failed to parse file: {name}. {error}").format(name=filename,
- error=str(err)))
+ app_obj.inform.emit(_("{e_code} Failed to parse file: {name}. {error}").format(
+ e_code=_("[ERROR_NOTCL]"),
+ name=filename,
+ error=str(err)))
app_obj.progress.emit(0)
self.log.error(str(err))
return "fail"
except Exception as e:
log.debug("App.open_gerber() --> %s" % str(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()
app_obj.inform.emit(msg)
return "fail"
@@ -8796,7 +8931,8 @@ class App(QtCore.QObject):
# app_obj.inform.emit("[ERROR] No geometry found in file: " + filename)
# self.collection.set_active(gerber_obj.options["name"])
# self.collection.delete_active()
- self.inform.emit(_("[ERROR_NOTCL] Object is not Gerber file or empty. Aborting object creation."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Object is not Gerber file or empty. Aborting object creation."))
return "fail"
# Further parsing
@@ -8814,7 +8950,8 @@ class App(QtCore.QObject):
# # ## Object creation # ##
ret = self.new_object("gerber", name, obj_init, autoselected=False)
if ret == 'fail':
- self.inform.emit(_('[ERROR_NOTCL] Open Gerber failed. Probable not a Gerber file.'))
+ self.inform.emit('[ERROR_NOTCL]%s' %
+ _(' Open Gerber failed. Probable not a Gerber file.'))
return
# Register recent file
@@ -8823,7 +8960,8 @@ class App(QtCore.QObject):
self.progress.emit(100)
# GUI feedback
- self.inform.emit(_("[success] Opened: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Opened"), filename))
def open_excellon(self, filename, outname=None):
"""
@@ -8847,15 +8985,18 @@ class App(QtCore.QObject):
ret = excellon_obj.parse_file(filename=filename)
if ret == "fail":
log.debug("Excellon parsing failed.")
- self.inform.emit(_("[ERROR_NOTCL] This is not Excellon file."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("This is not Excellon file."))
return "fail"
except IOError:
- app_obj.inform.emit(_("[ERROR_NOTCL] Cannot open file: %s") % filename)
+ app_obj.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Cannot open file"), filename))
log.debug("Could not open Excellon object.")
self.progress.emit(0) # TODO: self and app_bjj mixed
return "fail"
except:
- msg = _("[ERROR_NOTCL] An internal error has occurred. See shell.\n")
+ msg = '[ERROR_NOTCL] %s' % \
+ _("An internal error has occurred. See shell.\n")
msg += traceback.format_exc()
app_obj.inform.emit(msg)
return "fail"
@@ -8868,7 +9009,8 @@ class App(QtCore.QObject):
for tool in excellon_obj.tools:
if excellon_obj.tools[tool]['solid_geometry']:
return
- app_obj.inform.emit(_("[ERROR_NOTCL] No geometry found in file: %s") % filename)
+ app_obj.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("No geometry found in file"), filename))
return "fail"
with self.proc_container.new(_("Opening Excellon.")):
@@ -8877,14 +9019,16 @@ class App(QtCore.QObject):
name = outname or filename.split('/')[-1].split('\\')[-1]
ret_val = self.new_object("excellon", name, obj_init, autoselected=False)
if ret_val == 'fail':
- self.inform.emit(_('[ERROR_NOTCL] Open Excellon file failed. Probable not an Excellon file.'))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _('Open Excellon file failed. Probable not an Excellon file.'))
return
# Register recent file
self.file_opened.emit("excellon", filename)
# GUI feedback
- self.inform.emit(_("[success] Opened: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Opened"), filename))
def open_gcode(self, filename, outname=None):
"""
@@ -8914,7 +9058,8 @@ class App(QtCore.QObject):
gcode = f.read()
f.close()
except IOError:
- app_obj_.inform.emit(_("[ERROR_NOTCL] Failed to open %s") % filename)
+ app_obj_.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Failed to open"), filename))
self.progress.emit(0)
return "fail"
@@ -8924,7 +9069,8 @@ class App(QtCore.QObject):
ret = job_obj.gcode_parse()
if ret == "fail":
- self.inform.emit(_("[ERROR_NOTCL] This is not GCODE"))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("This is not GCODE"))
return "fail"
self.progress.emit(60)
@@ -8938,7 +9084,8 @@ class App(QtCore.QObject):
# New object creation and file processing
ret = self.new_object("cncjob", name, obj_init, autoselected=False)
if ret == 'fail':
- self.inform.emit(_("[ERROR_NOTCL] Failed to create CNCJob Object. Probable not a GCode file.\n "
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to create CNCJob Object. Probable not a GCode file.\n "
"Attempting to create a FlatCAM CNCJob Object from "
"G-Code file failed during processing"))
return "fail"
@@ -8947,7 +9094,8 @@ class App(QtCore.QObject):
self.file_opened.emit("cncjob", filename)
# GUI feedback
- self.inform.emit(_("[success] Opened: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Opened"), filename))
self.progress.emit(100)
def open_config_file(self, filename, run_from_arg=None):
@@ -8978,7 +9126,8 @@ class App(QtCore.QObject):
f.close()
except IOError:
App.log.error("Failed to open config file: %s" % filename)
- self.inform.emit(_("[ERROR_NOTCL] Failed to open config file: %s") % filename)
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Failed to open config file"), filename))
return
def open_project(self, filename, run_from_arg=None):
@@ -9006,7 +9155,8 @@ class App(QtCore.QObject):
f = open(filename, 'r')
except IOError:
App.log.error("Failed to open project file: %s" % filename)
- self.inform.emit(_("[ERROR_NOTCL] Failed to open project file: %s") % filename)
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Failed to open project file"), filename))
return
try:
@@ -9024,7 +9174,8 @@ class App(QtCore.QObject):
except Exception as e:
App.log.error("Failed to open project file: %s with error: %s" % (filename, str(e)))
- self.inform.emit(_("[ERROR_NOTCL] Failed to open project file: %s") % filename)
+ self.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_("Failed to open project file"), filename))
return
# Clear the current project
@@ -9048,12 +9199,17 @@ class App(QtCore.QObject):
App.log.debug("Recreating from opened project an %s object: %s" %
(obj['kind'].capitalize(), obj['options']['name']))
- self.set_ui_title(name="{} {}: {}".format(_("Loading Project ... restoring"), obj['kind'].upper(), obj['options']['name']))
+ self.set_ui_title(name="{} {}: {}".format(_("Loading Project ... restoring"),
+ obj['kind'].upper(),
+ obj['options']['name']
+ )
+ )
self.new_object(obj['kind'], obj['options']['name'], obj_init, active=False, fit=False, plot=True)
# self.plot_all()
- self.inform.emit(_("[success] Project loaded from: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Project loaded from"), filename))
self.should_we_save = False
self.file_opened.emit("project", filename)
@@ -9368,14 +9524,16 @@ class App(QtCore.QObject):
f = open(self.data_path + '/recent.json')
except IOError:
App.log.error("Failed to load recent item list.")
- self.inform.emit(_("[ERROR_NOTCL] Failed to load recent item list."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to load recent item list."))
return
try:
self.recent = json.load(f)
except json.scanner.JSONDecodeError:
App.log.error("Failed to parse recent item list.")
- self.inform.emit(_("[ERROR_NOTCL] Failed to parse recent item list."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to parse recent item list."))
f.close()
return
f.close()
@@ -9385,14 +9543,16 @@ class App(QtCore.QObject):
fp = open(self.data_path + '/recent_projects.json')
except IOError:
App.log.error("Failed to load recent project item list.")
- self.inform.emit(_("[ERROR_NOTCL] Failed to load recent projects item list."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to load recent projects item list."))
return
try:
self.recent_projects = json.load(fp)
except json.scanner.JSONDecodeError:
App.log.error("Failed to parse recent project item list.")
- self.inform.emit(_("[ERROR_NOTCL] Failed to parse recent project item list."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to parse recent project item list."))
fp.close()
return
fp.close()
@@ -9581,14 +9741,16 @@ The normal flow when working in FlatCAM is the following:
except:
# App.log.warning("Failed checking for latest version. Could not connect.")
self.log.warning("Failed checking for latest version. Could not connect.")
- self.inform.emit(_("[WARNING_NOTCL] Failed checking for latest version. Could not connect."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("Failed checking for latest version. Could not connect."))
return
try:
data = json.load(f)
except Exception as e:
App.log.error("Could not parse information about latest version.")
- self.inform.emit(_("[ERROR_NOTCL] Could not parse information about latest version."))
+ self.inform.emit('[ERROR_NOTCL] %s' %
+ _("Could not parse information about latest version."))
App.log.debug("json.load(): %s" % str(e))
f.close()
return
@@ -9598,7 +9760,8 @@ The normal flow when working in FlatCAM is the following:
# ## Latest version?
if self.version >= data["version"]:
App.log.debug("FlatCAM is up to date!")
- self.inform.emit(_("[success] FlatCAM is up to date!"))
+ self.inform.emit('[success] %s' %
+ _("FlatCAM is up to date!"))
return
App.log.debug("Newer version available.")
@@ -9660,25 +9823,29 @@ The normal flow when working in FlatCAM is the following:
self.report_usage("disable_all_plots()")
self.disable_plots(self.collection.get_list())
- self.inform.emit(_("[success] All plots disabled."))
+ self.inform.emit('[success] %s' %
+ _("All plots disabled."))
def disable_other_plots(self):
self.report_usage("disable_other_plots()")
self.disable_plots(self.collection.get_non_selected())
- self.inform.emit(_("[success] All non selected plots disabled."))
+ self.inform.emit('[success] %s' %
+ _("All non selected plots disabled."))
def enable_all_plots(self):
self.report_usage("enable_all_plots()")
self.enable_plots(self.collection.get_list())
- self.inform.emit(_("[success] All plots enabled."))
+ self.inform.emit('[success] %s' %
+ _("All plots enabled."))
def on_enable_sel_plots(self):
log.debug("App.on_enable_sel_plot()")
object_list = self.collection.get_selected()
self.enable_plots(objects=object_list)
- self.inform.emit(_("[success] Selected plots enabled..."))
+ self.inform.emit('[success] %s' %
+ _("Selected plots enabled..."))
def on_disable_sel_plots(self):
log.debug("App.on_disable_sel_plot()")
@@ -9686,7 +9853,8 @@ The normal flow when working in FlatCAM is the following:
# self.inform.emit(_("Disabling plots ..."))
object_list = self.collection.get_selected()
self.disable_plots(objects=object_list)
- self.inform.emit(_("[success] Selected plots disabled..."))
+ self.inform.emit('[success] %s' %
+ _("Selected plots disabled..."))
def enable_plots(self, objects):
"""
@@ -9819,7 +9987,8 @@ The normal flow when working in FlatCAM is the following:
g = json.dumps(d, default=to_dict, indent=2, sort_keys=True).encode('utf-8')
# # Write
f.write(g)
- self.inform.emit(_("[success] Project saved to: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Project saved to"), filename))
else:
# Open file
try:
@@ -9837,22 +10006,28 @@ The normal flow when working in FlatCAM is the following:
try:
saved_f = open(filename, 'r')
except IOError:
- self.inform.emit(_("[ERROR_NOTCL] Failed to verify project file: %s. Retry to save it.") % filename)
+ self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
+ (_("Failed to verify project file"), filename, _("Retry to save it."))
+ )
return
try:
saved_d = json.load(saved_f, object_hook=dict2obj)
except:
- self.inform.emit(
- _("[ERROR_NOTCL] Failed to parse saved project file: %s. Retry to save it.") % filename)
+ self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
+ (_("Failed to parse saved project file"), filename, _("Retry to save it."))
+ )
f.close()
return
saved_f.close()
if 'version' in saved_d:
- self.inform.emit(_("[success] Project saved to: %s") % filename)
+ self.inform.emit('[success] %s: %s' %
+ (_("Project saved to"), filename))
else:
- self.inform.emit(_("[ERROR_NOTCL] Failed to save project file: %s. Retry to save it.") % filename)
+ self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
+ (_("Failed to parse saved project file"), filename, _("Retry to save it."))
+ )
settings = QSettings("Open Source", "FlatCAM")
lock_state = self.ui.lock_action.isChecked()
@@ -9938,7 +10113,8 @@ The normal flow when working in FlatCAM is the following:
self.options_read_form()
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected."))
return
for option in self.options:
if option.find(obj.kind + "_") == 0:
@@ -9958,7 +10134,8 @@ The normal flow when working in FlatCAM is the following:
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected."))
return
obj.read_form()
for option in obj.options:
@@ -9979,7 +10156,8 @@ The normal flow when working in FlatCAM is the following:
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected."))
return
obj.read_form()
for option in obj.options:
@@ -10001,7 +10179,8 @@ The normal flow when working in FlatCAM is the following:
self.defaults_read_form()
obj = self.collection.get_active()
if obj is None:
- self.inform.emit(_("[WARNING_NOTCL] No object selected."))
+ self.inform.emit('[WARNING_NOTCL] %s' %
+ _("No object selected."))
return
for option in self.defaults:
if option.find(obj.kind + "_") == 0:
diff --git a/ObjectCollection.py b/ObjectCollection.py
index 3721db2b..9fe589e1 100644
--- a/ObjectCollection.py
+++ b/ObjectCollection.py
@@ -762,7 +762,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
try:
a_idx.build_ui()
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
def get_list(self):
diff --git a/README.md b/README.md
index 0c257283..1674667d 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,8 @@ CAD program, and create G-Code for Isolation routing.
- 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
8.09.2019
diff --git a/camlib.py b/camlib.py
index 048711ac..9b7a1f1c 100644
--- a/camlib.py
+++ b/camlib.py
@@ -211,7 +211,8 @@ class Geometry(object):
if isinstance(self.solid_geometry, list):
return len(self.solid_geometry) == 0
- self.app.inform.emit(_("[ERROR_NOTCL] self.solid_geometry is neither BaseGeometry or list."))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("self.solid_geometry is neither BaseGeometry or list."))
return
def subtract_polygon(self, points):
@@ -1517,9 +1518,11 @@ class Geometry(object):
self.el_count = 0
self.solid_geometry = mirror_geom(self.solid_geometry)
- self.app.inform.emit(_('[success] Object was mirrored ...'))
+ self.app.inform.emit('[success] %s...' %
+ _('Object was mirrored'))
except AttributeError:
- self.app.inform.emit(_("[ERROR_NOTCL] Failed to mirror. No object selected"))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to mirror. No object selected"))
self.app.proc_container.new_text = ''
@@ -1587,9 +1590,11 @@ class Geometry(object):
self.el_count = 0
self.solid_geometry = rotate_geom(self.solid_geometry)
- self.app.inform.emit(_('[success] Object was rotated ...'))
+ self.app.inform.emit('[success] %s...' %
+ _('Object was rotated'))
except AttributeError:
- self.app.inform.emit(_("[ERROR_NOTCL] Failed to rotate. No object selected"))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to rotate. No object selected"))
self.app.proc_container.new_text = ''
@@ -1656,9 +1661,11 @@ class Geometry(object):
self.el_count = 0
self.solid_geometry = skew_geom(self.solid_geometry)
- self.app.inform.emit(_('[success] Object was skewed ...'))
+ self.app.inform.emit('[success] %s...' %
+ _('Object was skewed'))
except AttributeError:
- self.app.inform.emit(_("[ERROR_NOTCL] Failed to skew. No object selected"))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Failed to skew. No object selected"))
self.app.proc_container.new_text = ''
@@ -2931,8 +2938,10 @@ class Gerber (Geometry):
self.apertures['0']['geometry'] = []
last_path_aperture = '0'
else:
- self.app.inform.emit(_("[WARNING] Coordinates missing, line ignored: %s") % str(gline))
- self.app.inform.emit(_("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!"))
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("Coordinates missing, line ignored"), str(gline)))
+ self.app.inform.emit('[WARNING_NOTCL] %s' %
+ _("GERBER file might be CORRUPT. Check the file !!!"))
elif current_operation_code == 2:
if len(path) > 1:
@@ -2981,9 +2990,10 @@ class Gerber (Geometry):
geo_s = Polygon(path)
except ValueError:
log.warning("Problem %s %s" % (gline, line_num))
- self.app.inform.emit(_("[ERROR] Region does not have enough points. "
- "File will be processed but there are parser errors. "
- "Line number: %s") % str(line_num))
+ self.app.inform.emit('[ERROR] %s: %s' %
+ (_("Region does not have enough points. "
+ "File will be processed but there are parser errors. "
+ "Line number"), str(line_num)))
else:
if last_path_aperture is None:
log.warning("No aperture defined for curent path. (%d)" % line_num)
@@ -3016,8 +3026,10 @@ class Gerber (Geometry):
if linear_x is not None and linear_y is not None:
path = [[linear_x, linear_y]] # Start new path
else:
- self.app.inform.emit(_("[WARNING] Coordinates missing, line ignored: %s") % str(gline))
- self.app.inform.emit(_("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!"))
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("Coordinates missing, line ignored"), str(gline)))
+ self.app.inform.emit('[WARNING_NOTCL] %s' %
+ _("GERBER file might be CORRUPT. Check the file !!!"))
# Flash
# Not allowed in region mode.
@@ -3376,7 +3388,8 @@ class Gerber (Geometry):
log.error("Gerber PARSING FAILED. Line %d: %s" % (line_num, gline))
loc = '%s #%d %s: %s\n' % (_("Gerber Line"), line_num, _("Gerber Line Content"), gline) + repr(err)
- self.app.inform.emit('[ERROR] %s\n%s:' % (_("Gerber Parser ERROR"), loc))
+ self.app.inform.emit('[ERROR] %s\n%s:' %
+ (_("Gerber Parser ERROR"), loc))
@staticmethod
def create_flash_geometry(location, aperture, steps_per_circle=None):
@@ -3623,7 +3636,8 @@ class Gerber (Geometry):
log.debug('camlib.Gerber.scale() Exception --> %s' % str(e))
return 'fail'
- self.app.inform.emit('[success] %s' % _("Gerber Scale done."))
+ self.app.inform.emit('[success] %s' %
+ _("Gerber Scale done."))
self.app.proc_container.new_text = ''
# ## solid_geometry ???
@@ -3712,7 +3726,8 @@ class Gerber (Geometry):
log.debug('camlib.Gerber.offset() Exception --> %s' % str(e))
return 'fail'
- self.app.inform.emit('[success] %s' % _("Gerber Offset done."))
+ self.app.inform.emit('[success] %s' %
+ _("Gerber Offset done."))
self.app.proc_container.new_text = ''
def mirror(self, axis, point):
@@ -3788,7 +3803,8 @@ class Gerber (Geometry):
log.debug('camlib.Gerber.mirror() Exception --> %s' % str(e))
return 'fail'
- self.app.inform.emit('[success] %s' % _("Gerber Mirror done."))
+ self.app.inform.emit('[success] %s' %
+ _("Gerber Mirror done."))
self.app.proc_container.new_text = ''
def skew(self, angle_x, angle_y, point):
@@ -3856,7 +3872,8 @@ class Gerber (Geometry):
log.debug('camlib.Gerber.skew() Exception --> %s' % str(e))
return 'fail'
- self.app.inform.emit('[success] %s' % _("Gerber Skew done."))
+ self.app.inform.emit('[success] %s' %
+ _("Gerber Skew done."))
self.app.proc_container.new_text = ''
def rotate(self, angle, point):
@@ -3916,7 +3933,8 @@ class Gerber (Geometry):
except Exception as e:
log.debug('camlib.Gerber.rotate() Exception --> %s' % str(e))
return 'fail'
- self.app.inform.emit('[success] %s' % _("Gerber Rotate done."))
+ self.app.inform.emit('[success] %s' %
+ _("Gerber Rotate done."))
self.app.proc_container.new_text = ''
@@ -4202,7 +4220,8 @@ class Excellon(Geometry):
# and we need to exit from here
if self.detect_gcode_re.search(eline):
log.warning("This is GCODE mark: %s" % eline)
- self.app.inform.emit(_('[ERROR_NOTCL] This is GCODE mark: %s') % eline)
+ self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
+ (_('This is GCODE mark'), eline))
return
# Header Begin (M48) #
@@ -4317,13 +4336,18 @@ class Excellon(Geometry):
# the bellow construction is so each tool will have a slightly different diameter
# starting with a default value, to allow Excellon editing after that
self.diameterless = True
- self.app.inform.emit(_("[WARNING] No tool diameter info's. See shell.\n"
- "A tool change event: T%s was found but the Excellon file "
- "have no informations regarding the tool "
- "diameters therefore the application will try to load it by "
- "using some 'fake' diameters.\nThe user needs to edit the "
- "resulting Excellon object and change the diameters to "
- "reflect the real diameters.") % current_tool)
+ self.app.inform.emit('[WARNING] %s%s %s' %
+ (_("No tool diameter info's. See shell.\n"
+ "A tool change event: T"),
+ str(current_tool),
+ _("was found but the Excellon file "
+ "have no informations regarding the tool "
+ "diameters therefore the application will try to load it "
+ "by using some 'fake' diameters.\n"
+ "The user needs to edit the resulting Excellon object and "
+ "change the diameters to reflect the real diameters.")
+ )
+ )
if self.excellon_units == 'MM':
diam = self.toolless_diam + (int(current_tool) - 1) / 100
@@ -4769,9 +4793,12 @@ class Excellon(Geometry):
log.info("Zeros: %s, Units %s." % (self.zeros, self.units))
except Exception as e:
log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline))
- msg = _("[ERROR_NOTCL] An internal error has ocurred. See shell.\n")
- msg += _('[ERROR] Excellon Parser error.\nParsing Failed. Line {l_nr}: {line}\n').format(l_nr=line_num,
- line=eline)
+ msg = '[ERROR_NOTCL] %s' % \
+ _("An internal error has ocurred. See shell.\n")
+ msg += _('{e_code} Excellon Parser error.\nParsing Failed. Line {l_nr}: {line}\n').format(
+ e_code='[ERROR]',
+ l_nr=line_num,
+ line=eline)
msg += traceback.format_exc()
self.app.inform.emit(msg)
@@ -4850,7 +4877,8 @@ class Excellon(Geometry):
for drill in self.drills:
# poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
if drill['tool'] is '':
- self.app.inform.emit(_("[WARNING] Excellon.create_geometry() -> a drill location was skipped "
+ self.app.inform.emit('[WARNING] %s' %
+ _("Excellon.create_geometry() -> a drill location was skipped "
"due of not having a tool associated.\n"
"Check the resulting GCode."))
log.debug("Excellon.create_geometry() -> a drill location was skipped "
@@ -5523,7 +5551,8 @@ class CNCjob(Geometry):
try:
value = getattr(self, command)
except AttributeError:
- self.app.inform.emit(_("[ERROR] There is no such parameter: %s") % str(match))
+ self.app.inform.emit('[ERROR] %s: %s' %
+ (_("There is no such parameter"), str(match)))
log.debug("CNCJob.parse_custom_toolchange_code() --> AttributeError ")
return 'fail'
text = text.replace(match, str(value))
@@ -5593,15 +5622,17 @@ class CNCjob(Geometry):
self.exc_tools = deepcopy(exobj.tools)
if drillz > 0:
- self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
+ self.app.inform.emit('[WARNING] %s' %
+ _("The Cut Z parameter has positive value. "
"It is the depth value to drill into material.\n"
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
"therefore the app will convert the value to negative. "
"Check the resulting CNC code (Gcode etc)."))
self.z_cut = -drillz
elif drillz == 0:
- self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
- "There will be no cut, skipping %s file") % exobj.options['name'])
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("The Cut Z parameter is zero. There will be no cut, skipping file"),
+ exobj.options['name']))
return 'fail'
else:
self.z_cut = drillz
@@ -5614,7 +5645,8 @@ class CNCjob(Geometry):
else:
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
if len(self.xy_toolchange) < 2:
- self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
+ self.app.inform.emit('[ERROR]%s' %
+ _("The Toolchange X,Y field in Edit -> Preferences has to be "
"in the format (x, y) \nbut now there is only one value, not two. "))
return 'fail'
except Exception as e:
@@ -5733,7 +5765,8 @@ class CNCjob(Geometry):
measured_up_to_zero_distance = 0.0
measured_lift_distance = 0.0
- self.app.inform.emit('%s...' % _("Starting G-Code"))
+ self.app.inform.emit('%s...' %
+ _("Starting G-Code"))
current_platform = platform.architecture()[0]
if current_platform == '64bit':
if excellon_optimization_type == 'M':
@@ -5885,12 +5918,14 @@ class CNCjob(Geometry):
old_disp_number = disp_number
else:
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' %
+ _('G91 coordinates not implemented'))
return 'fail'
else:
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
"The loaded Excellon file has no drills ...")
- self.app.inform.emit(_('[ERROR_NOTCL] The loaded Excellon file has no drills ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' %
+ _('The loaded Excellon file has no drills'))
return 'fail'
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
@@ -6029,17 +6064,20 @@ class CNCjob(Geometry):
old_disp_number = disp_number
else:
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' %
+ _('G91 coordinates not implemented'))
return 'fail'
else:
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
"The loaded Excellon file has no drills ...")
- self.app.inform.emit(_('[ERROR_NOTCL] The loaded Excellon file has no drills ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' %
+ _('The loaded Excellon file has no drills'))
return 'fail'
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
else:
- self.app.inform.emit(_("[ERROR_NOTCL] Wrong optimization type selected."))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Wrong optimization type selected."))
return 'fail'
else:
log.debug("Using Travelling Salesman drill path optimization.")
@@ -6133,12 +6171,14 @@ class CNCjob(Geometry):
self.app.proc_container.update_view_text(' %d%%' % disp_number)
old_disp_number = disp_number
else:
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' %
+ _('G91 coordinates not implemented'))
return 'fail'
else:
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
"The loaded Excellon file has no drills ...")
- self.app.inform.emit(_('[ERROR_NOTCL] The loaded Excellon file has no drills ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' %
+ _('The loaded Excellon file has no drills'))
return 'fail'
log.debug("The total travel distance with Travelling Salesman Algorithm is: %s" % str(measured_distance))
@@ -6249,20 +6289,23 @@ class CNCjob(Geometry):
self.f_plunge = self.app.defaults["geometry_f_plunge"]
if self.z_cut is None:
- self.app.inform.emit(_("[ERROR_NOTCL] Cut_Z parameter is None or zero. Most likely a bad combinations of "
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Cut_Z parameter is None or zero. Most likely a bad combinations of "
"other parameters."))
return 'fail'
if self.z_cut > 0:
- self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
+ self.app.inform.emit('[WARNING] %s' %
+ _("The Cut Z parameter has positive value. "
"It is the depth value to cut into material.\n"
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
"therefore the app will convert the value to negative."
"Check the resulting CNC code (Gcode etc)."))
self.z_cut = -self.z_cut
elif self.z_cut == 0:
- self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
- "There will be no cut, skipping %s file") % self.options['name'])
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("The Cut Z parameter is zero. There will be no cut, skipping file"),
+ self.options['name']))
return 'fail'
# made sure that depth_per_cut is no more then the z_cut
@@ -6270,19 +6313,22 @@ class CNCjob(Geometry):
self.z_depthpercut = abs(self.z_cut)
if self.z_move is None:
- self.app.inform.emit(_("[ERROR_NOTCL] Travel Z parameter is None or zero."))
+ self.app.inform.emit('[ERROR_NOTCL] %S' %
+ _("Travel Z parameter is None or zero."))
return 'fail'
if self.z_move < 0:
- self.app.inform.emit(_("[WARNING] The Travel Z parameter has negative value. "
+ self.app.inform.emit('[WARNING] %s' %
+ _("The Travel Z parameter has negative value. "
"It is the height value to travel between cuts.\n"
"The Z Travel parameter needs to have a positive value, assuming it is a typo "
"therefore the app will convert the value to positive."
"Check the resulting CNC code (Gcode etc)."))
self.z_move = -self.z_move
elif self.z_move == 0:
- self.app.inform.emit(_("[WARNING] The Z Travel parameter is zero. "
- "This is dangerous, skipping %s file") % self.options['name'])
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("The Z Travel parameter is zero. This is dangerous, skipping file"),
+ self.options['name']))
return 'fail'
# ## Index first and last points in paths
@@ -6436,7 +6482,12 @@ class CNCjob(Geometry):
self.gcode += self.doformat(p.spindle_stop_code)
self.gcode += self.doformat(p.lift_code, x=current_pt[0], y=current_pt[1])
self.gcode += self.doformat(p.end_code, x=0, y=0)
- self.app.inform.emit(_("Finished G-Code generation... %s paths traced.") % str(path_count))
+ self.app.inform.emit('%s... %s %s.' %
+ (_("Finished G-Code generation"),
+ str(path_count),
+ _("paths traced")
+ )
+ )
return self.gcode
def generate_from_geometry_2(self, geometry, append=True,
@@ -6468,13 +6519,15 @@ class CNCjob(Geometry):
"""
if not isinstance(geometry, Geometry):
- self.app.inform.emit(_("[ERROR]Expected a Geometry, got %s") % type(geometry))
+ self.app.inform.emit('[ERROR] %s: %s' %
+ (_("Expected a Geometry, got"), type(geometry)))
return 'fail'
log.debug("Generate_from_geometry_2()")
# if solid_geometry is empty raise an exception
if not geometry.solid_geometry:
- self.app.inform.emit(_("[ERROR_NOTCL] Trying to generate a CNC Job "
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Trying to generate a CNC Job "
"from a Geometry object without solid_geometry."))
temp_solid_geometry = []
@@ -6513,7 +6566,8 @@ class CNCjob(Geometry):
# if the offset is less than half of the total length or less than half of the total width of the
# solid geometry it's obvious we can't do the offset
if -offset > ((c - a) / 2) or -offset > ((d - b) / 2):
- self.app.inform.emit(_("[ERROR_NOTCL] The Tool Offset value is too negative to use "
+ self.app.inform.emit(_('[ERROR_NOTCL] %s' %
+ "The Tool Offset value is too negative to use "
"for the current_geometry.\n"
"Raise the value (in module) and try again."))
return 'fail'
@@ -6565,7 +6619,8 @@ class CNCjob(Geometry):
else:
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
if len(self.xy_toolchange) < 2:
- self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
+ self.app.inform.emit('[ERROR] %s' %
+ _("The Toolchange X,Y field in Edit -> Preferences has to be "
"in the format (x, y) \nbut now there is only one value, not two. "))
return 'fail'
except Exception as e:
@@ -6576,36 +6631,42 @@ class CNCjob(Geometry):
self.f_plunge = self.app.defaults["geometry_f_plunge"]
if self.z_cut is None:
- self.app.inform.emit(_("[ERROR_NOTCL] Cut_Z parameter is None or zero. Most likely a bad combinations of "
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Cut_Z parameter is None or zero. Most likely a bad combinations of "
"other parameters."))
return 'fail'
if self.z_cut > 0:
- self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
+ self.app.inform.emit('[WARNING] %s' %
+ _("The Cut Z parameter has positive value. "
"It is the depth value to cut into material.\n"
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
"therefore the app will convert the value to negative."
"Check the resulting CNC code (Gcode etc)."))
self.z_cut = -self.z_cut
elif self.z_cut == 0:
- self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
- "There will be no cut, skipping %s file") % geometry.options['name'])
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("The Cut Z parameter is zero. There will be no cut, skipping file"),
+ geometry.options['name']))
return 'fail'
if self.z_move is None:
- self.app.inform.emit(_("[ERROR_NOTCL] Travel Z parameter is None or zero."))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("Travel Z parameter is None or zero."))
return 'fail'
if self.z_move < 0:
- self.app.inform.emit(_("[WARNING] The Travel Z parameter has negative value. "
+ self.app.inform.emit('[WARNING] %s' %
+ _("The Travel Z parameter has negative value. "
"It is the height value to travel between cuts.\n"
"The Z Travel parameter needs to have a positive value, assuming it is a typo "
"therefore the app will convert the value to positive."
"Check the resulting CNC code (Gcode etc)."))
self.z_move = -self.z_move
elif self.z_move == 0:
- self.app.inform.emit(_("[WARNING] The Z Travel parameter is zero. "
- "This is dangerous, skipping %s file") % self.options['name'])
+ self.app.inform.emit('[WARNING] %s: %s' %
+ (_("The Z Travel parameter is zero. "
+ "This is dangerous, skipping file"), self.options['name']))
return 'fail'
# made sure that depth_per_cut is no more then the z_cut
@@ -6763,7 +6824,12 @@ class CNCjob(Geometry):
self.gcode += self.doformat(p.spindle_stop_code)
self.gcode += self.doformat(p.lift_code, x=current_pt[0], y=current_pt[1])
self.gcode += self.doformat(p.end_code, x=0, y=0)
- self.app.inform.emit(_("Finished G-Code generation... %s paths traced.") % str(path_count))
+ self.app.inform.emit('%s... %s %s' %
+ (_("Finished G-Code generation"),
+ str(path_count),
+ _(" paths traced.")
+ )
+ )
return self.gcode
@@ -6789,7 +6855,8 @@ class CNCjob(Geometry):
if not kwargs:
log.debug("camlib.generate_from_solderpaste_geo() --> No tool in the solderpaste geometry.")
- self.app.inform.emit(_("[ERROR_NOTCL] There is no tool data in the SolderPaste geometry."))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _("There is no tool data in the SolderPaste geometry."))
# this is the tool diameter, it is used as such to accommodate the postprocessor who need the tool diameter
@@ -6875,7 +6942,13 @@ class CNCjob(Geometry):
pass
log.debug("Finishing SolderPste G-Code... %s paths traced." % path_count)
- self.app.inform.emit(_("Finished SolderPste G-Code generation... %s paths traced.") % str(path_count))
+ self.app.inform.emit('%s... %s %s' %
+ (_("Finished SolderPste G-Code generation"),
+ str(path_count),
+ _("paths traced.")
+ )
+ )
+
# Finish
self.gcode += self.doformat(p.lift_code)
@@ -7344,7 +7417,8 @@ class CNCjob(Geometry):
visible=visible, layer=1)
else:
# For Incremental coordinates type G91
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _('G91 coordinates not implemented ...'))
for geo in gcode_parsed:
if geo['kind'][0] == 'T':
current_position = geo['geom'].coords[0]
@@ -7621,7 +7695,8 @@ class CNCjob(Geometry):
# For Incremental coordinates type G91
# next_x = pt[0] - prev_x
# next_y = pt[1] - prev_y
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _('G91 coordinates not implemented ...'))
next_x = pt[0]
next_y = pt[1]
@@ -7723,7 +7798,8 @@ class CNCjob(Geometry):
# For Incremental coordinates type G91
# next_x = pt[0] - prev_x
# next_y = pt[1] - prev_y
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _('G91 coordinates not implemented ...'))
next_x = pt[0]
next_y = pt[1]
@@ -7769,7 +7845,8 @@ class CNCjob(Geometry):
# For Incremental coordinates type G91
# first_x = path[0][0] - old_point[0]
# first_y = path[0][1] - old_point[1]
- self.app.inform.emit(_('[ERROR_NOTCL] G91 coordinates not implemented ...'))
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
+ _('G91 coordinates not implemented ...'))
first_x = path[0][0]
first_y = path[0][1]
diff --git a/locale/de/LC_MESSAGES/strings.mo b/locale/de/LC_MESSAGES/strings.mo
index 91f2fd886219dc1e9d1d18c52ff316a4fc5197fd..208040922f7e5943dcbc0b7e5575a2982a51d1cb 100644
GIT binary patch
delta 54290
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 jZd&5}KtfU*Zbn$2
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 |