Merge pull request #5262 from sliptonic/bug/translation
[PATH] Bug/translation
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -30,8 +30,7 @@ import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
import math
|
||||
import numpy
|
||||
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
# lazily loaded modules
|
||||
from lazy_loader.lazy_loader import LazyLoader
|
||||
@@ -39,6 +38,7 @@ from lazy_loader.lazy_loader import LazyLoader
|
||||
Part = LazyLoader("Part", globals(), "Part")
|
||||
DraftGeomUtils = LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
__title__ = "Path Profile Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
@@ -55,11 +55,6 @@ else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
|
||||
# Qt translation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"""Proxy object for Profile operations based on faces."""
|
||||
|
||||
@@ -79,23 +74,21 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"""initAreaOpProperties(obj) ... create operation specific properties"""
|
||||
self.addNewProps = []
|
||||
|
||||
for (prtyp, nm, grp, tt) in self.areaOpProperties():
|
||||
if not hasattr(obj, nm):
|
||||
obj.addProperty(prtyp, nm, grp, tt)
|
||||
self.addNewProps.append(nm)
|
||||
for (propertytype, propertyname, grp, tt) in self.areaOpProperties():
|
||||
if not hasattr(obj, propertyname):
|
||||
obj.addProperty(propertytype, propertyname, grp, tt)
|
||||
self.addNewProps.append(propertyname)
|
||||
|
||||
if len(self.addNewProps) > 0:
|
||||
# Set enumeration lists for enumeration properties
|
||||
ENUMS = self.areaOpPropertyEnumerations()
|
||||
for n in ENUMS:
|
||||
if n in self.addNewProps:
|
||||
setattr(obj, n, ENUMS[n])
|
||||
if n[0] in self.addNewProps:
|
||||
setattr(obj, n[0], n[1])
|
||||
if warn:
|
||||
newPropMsg = translate("PathProfile", "New property added to")
|
||||
newPropMsg = "New property added to"
|
||||
newPropMsg += ' "{}": {}'.format(obj.Label, self.addNewProps) + ". "
|
||||
newPropMsg += (
|
||||
translate("PathProfile", "Check its default value.") + "\n"
|
||||
)
|
||||
newPropMsg += "Check its default value." + "\n"
|
||||
FreeCAD.Console.PrintWarning(newPropMsg)
|
||||
|
||||
self.propertiesReady = True
|
||||
@@ -109,7 +102,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyEnumeration",
|
||||
"Direction",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"The direction that the toolpath should go around the part ClockWise (CW) or CounterClockWise (CCW)",
|
||||
),
|
||||
@@ -118,8 +111,8 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyEnumeration",
|
||||
"HandleMultipleFeatures",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
"PathPocket",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Choose how to process multiple Base Geometry features.",
|
||||
),
|
||||
),
|
||||
@@ -127,7 +120,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyEnumeration",
|
||||
"JoinType",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Controls how tool moves around corners. Default=Round",
|
||||
),
|
||||
@@ -136,7 +129,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyFloat",
|
||||
"MiterLimit",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Maximum distance before a miter join is truncated"
|
||||
),
|
||||
),
|
||||
@@ -144,7 +137,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyDistance",
|
||||
"OffsetExtra",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Extra value to stay away from final profile- good for roughing toolpath",
|
||||
),
|
||||
@@ -153,7 +146,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyBool",
|
||||
"processHoles",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Profile holes as well as the outline"
|
||||
),
|
||||
),
|
||||
@@ -161,50 +154,78 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"App::PropertyBool",
|
||||
"processPerimeter",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile the outline"),
|
||||
QT_TRANSLATE_NOOP("App::Property", "Profile the outline"),
|
||||
),
|
||||
(
|
||||
"App::PropertyBool",
|
||||
"processCircles",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile round holes"),
|
||||
QT_TRANSLATE_NOOP("App::Property", "Profile round holes"),
|
||||
),
|
||||
(
|
||||
"App::PropertyEnumeration",
|
||||
"Side",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Side of edge that tool should cut"
|
||||
),
|
||||
QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut"),
|
||||
),
|
||||
(
|
||||
"App::PropertyBool",
|
||||
"UseComp",
|
||||
"Profile",
|
||||
QtCore.QT_TRANSLATE_NOOP(
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Make True, if using Cutter Radius Compensation"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
def areaOpPropertyEnumerations(self):
|
||||
"""areaOpPropertyEnumerations() ... returns a dictionary of enumeration lists
|
||||
for the operation's enumeration type properties."""
|
||||
@classmethod
|
||||
def areaOpPropertyEnumerations(self, dataType="data"):
|
||||
|
||||
"""opPropertyEnumerations(dataType="data")... return property enumeration lists of specified dataType.
|
||||
Args:
|
||||
dataType = 'data', 'raw', 'translated'
|
||||
Notes:
|
||||
'data' is list of internal string literals used in code
|
||||
'raw' is list of (translated_text, data_string) tuples
|
||||
'translated' is list of translated string literals
|
||||
"""
|
||||
|
||||
# Enumeration lists for App::PropertyEnumeration properties
|
||||
return {
|
||||
"Direction": ["CW", "CCW"], # this is the direction that the profile runs
|
||||
"HandleMultipleFeatures": ["Collectively", "Individually"],
|
||||
enums = {
|
||||
"Direction": [
|
||||
(translate("PathProfile", "CW"), "CW"),
|
||||
(translate("PathProfile", "CCW"), "CCW"),
|
||||
], # this is the direction that the profile runs
|
||||
"HandleMultipleFeatures": [
|
||||
(translate("PathProfile", "Collectively"), "Collectively"),
|
||||
(translate("PathProfile", "Individually"), "Individually"),
|
||||
],
|
||||
"JoinType": [
|
||||
"Round",
|
||||
"Square",
|
||||
"Miter",
|
||||
(translate("PathProfile", "Round"), "Round"),
|
||||
(translate("PathProfile", "Square"), "Square"),
|
||||
(translate("PathProfile", "Miter"), "Miter"),
|
||||
], # this is the direction that the Profile runs
|
||||
"Side": [
|
||||
"Outside",
|
||||
"Inside",
|
||||
(translate("PathProfile", "Outside"), "Outside"),
|
||||
(translate("PathProfile", "Inside"), "Inside"),
|
||||
], # side of profile that cutter is on in relation to direction of profile
|
||||
}
|
||||
|
||||
if dataType == "raw":
|
||||
return enums
|
||||
|
||||
data = list()
|
||||
idx = 0 if dataType == "translated" else 1
|
||||
|
||||
PathLog.debug(enums)
|
||||
|
||||
for k, v in enumerate(enums):
|
||||
# data[k] = [tup[idx] for tup in v]
|
||||
data.append((v, [tup[idx] for tup in enums[v]]))
|
||||
PathLog.debug(data)
|
||||
|
||||
return data
|
||||
|
||||
def areaOpPropertyDefaults(self, obj, job):
|
||||
"""areaOpPropertyDefaults(obj, job) ... returns a dictionary of default values
|
||||
for the operation's properties."""
|
||||
@@ -350,8 +371,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
shapes = []
|
||||
remainingObjBaseFeatures = []
|
||||
self.isDebug = True if PathLog.getLevel(PathLog.thisModule()) == 4 else False
|
||||
self.inaccessibleMsg = translate(
|
||||
"PathProfile",
|
||||
self.inaccessibleMsg = translate("PathProfile",
|
||||
"The selected edge(s) are inaccessible. If multiple, re-ordering selection might work.",
|
||||
)
|
||||
self.offsetExtra = obj.OffsetExtra.Value
|
||||
@@ -418,10 +438,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
else:
|
||||
PathLog.track()
|
||||
ignoreSub = base.Name + "." + sub
|
||||
msg = translate(
|
||||
"PathProfile",
|
||||
"Found a selected object which is not a face. Ignoring:",
|
||||
)
|
||||
msg = "Found a selected object which is not a face. Ignoring:"
|
||||
PathLog.warning(msg + " {}".format(ignoreSub))
|
||||
|
||||
for baseShape, wire in holes:
|
||||
@@ -458,9 +475,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
)
|
||||
except Exception as ee: # pylint: disable=broad-except
|
||||
# PathUtils.getEnvelope() failed to return an object.
|
||||
msg = translate(
|
||||
"Path", "Unable to create path for face(s)."
|
||||
)
|
||||
msg = translate("PathProfile", "Unable to create path for face(s).")
|
||||
PathLog.error(msg + "\n{}".format(ee))
|
||||
cont = False
|
||||
|
||||
@@ -569,10 +584,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
# Attempt open-edges profile
|
||||
if self.JOB.GeometryTolerance.Value == 0.0:
|
||||
msg = self.JOB.Label + ".GeometryTolerance = 0.0. "
|
||||
msg += translate(
|
||||
"PathProfile",
|
||||
"Please set to an acceptable value greater than zero.",
|
||||
)
|
||||
msg += "Please set to an acceptable value greater than zero."
|
||||
PathLog.error(msg)
|
||||
else:
|
||||
flattened = self._flattenWire(obj, wire, obj.FinalDepth.Value)
|
||||
@@ -606,10 +618,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
shapes.append(tup)
|
||||
else:
|
||||
if zDiff < self.JOB.GeometryTolerance.Value:
|
||||
msg = translate(
|
||||
"PathProfile",
|
||||
"Check edge selection and Final Depth requirements for profiling open edge(s).",
|
||||
)
|
||||
msg = translate("PathProfile", "Check edge selection and Final Depth requirements for profiling open edge(s).")
|
||||
PathLog.error(msg)
|
||||
else:
|
||||
PathLog.error(self.inaccessibleMsg)
|
||||
@@ -667,9 +676,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
fdv = obj.FinalDepth.Value
|
||||
extLenFwd = sdv - fdv
|
||||
if extLenFwd <= 0.0:
|
||||
msg = translate(
|
||||
"PathProfile", "For open edges, verify Final Depth for this operation."
|
||||
)
|
||||
msg = "For open edges, verify Final Depth for this operation."
|
||||
FreeCAD.Console.PrintError(msg + "\n")
|
||||
# return False
|
||||
extLenFwd = 0.1
|
||||
|
||||
@@ -22,12 +22,11 @@
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import PathGui as PGui # ensure Path/Gui/Resources are loaded
|
||||
import PathGui as PGui # ensure Path/Gui/Resources are loaded
|
||||
import PathScripts.PathGui as PathGui
|
||||
import PathScripts.PathOpGui as PathOpGui
|
||||
import PathScripts.PathProfile as PathProfile
|
||||
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
|
||||
__title__ = "Path Profile Operation UI"
|
||||
@@ -36,47 +35,48 @@ __url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Profile operation page controller and command implementation."
|
||||
|
||||
|
||||
FeatureSide = 0x01
|
||||
FeatureSide = 0x01
|
||||
FeatureProcessing = 0x02
|
||||
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''Base class for profile operation page controllers. Two sub features are supported:
|
||||
FeatureSide ... Is the Side property exposed in the UI
|
||||
FeatureProcessing ... Are the processing check boxes supported by the operation
|
||||
'''
|
||||
"""Base class for profile operation page controllers. Two sub features are supported:
|
||||
FeatureSide ... Is the Side property exposed in the UI
|
||||
FeatureProcessing ... Are the processing check boxes supported by the operation
|
||||
"""
|
||||
|
||||
def initPage(self, obj):
|
||||
self.setTitle("Profile - " + obj.Label)
|
||||
self.updateVisibility()
|
||||
|
||||
def profileFeatures(self):
|
||||
'''profileFeatures() ... return which of the optional profile features are supported.
|
||||
"""profileFeatures() ... return which of the optional profile features are supported.
|
||||
Currently two features are supported and returned:
|
||||
FeatureSide ... Is the Side property exposed in the UI
|
||||
FeatureProcessing ... Are the processing check boxes supported by the operation
|
||||
.'''
|
||||
."""
|
||||
return FeatureSide | FeatureProcessing
|
||||
|
||||
def getForm(self):
|
||||
'''getForm() ... returns UI customized according to profileFeatures()'''
|
||||
"""getForm() ... returns UI customized according to profileFeatures()"""
|
||||
form = FreeCADGui.PySideUic.loadUi(":/panels/PageOpProfileFullEdit.ui")
|
||||
|
||||
comboToPropertyMap = [("cutSide", "Side"), ("direction", "Direction")]
|
||||
enumTups = PathProfile.ObjectProfile.areaOpPropertyEnumerations(dataType="raw")
|
||||
|
||||
self.populateCombobox(form, enumTups, comboToPropertyMap)
|
||||
return form
|
||||
|
||||
def getFields(self, obj):
|
||||
'''getFields(obj) ... transfers values from UI to obj's proprties'''
|
||||
"""getFields(obj) ... transfers values from UI to obj's proprties"""
|
||||
self.updateToolController(obj, self.form.toolController)
|
||||
self.updateCoolant(obj, self.form.coolantController)
|
||||
|
||||
if obj.Side != str(self.form.cutSide.currentText()):
|
||||
obj.Side = str(self.form.cutSide.currentText())
|
||||
if obj.Direction != str(self.form.direction.currentText()):
|
||||
obj.Direction = str(self.form.direction.currentText())
|
||||
PathGui.updateInputField(obj, 'OffsetExtra', self.form.extraOffset)
|
||||
if obj.Side != str(self.form.cutSide.currentData()):
|
||||
obj.Side = str(self.form.cutSide.currentData())
|
||||
if obj.Direction != str(self.form.direction.currentData()):
|
||||
obj.Direction = str(self.form.direction.currentData())
|
||||
PathGui.updateInputField(obj, "OffsetExtra", self.form.extraOffset)
|
||||
|
||||
if obj.UseComp != self.form.useCompensation.isChecked():
|
||||
obj.UseComp = self.form.useCompensation.isChecked()
|
||||
@@ -91,13 +91,17 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
obj.processCircles = self.form.processCircles.isChecked()
|
||||
|
||||
def setFields(self, obj):
|
||||
'''setFields(obj) ... transfers obj's property values to UI'''
|
||||
"""setFields(obj) ... transfers obj's property values to UI"""
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
self.setupCoolant(obj, self.form.coolantController)
|
||||
|
||||
self.selectInComboBox(obj.Side, self.form.cutSide)
|
||||
self.selectInComboBox(obj.Direction, self.form.direction)
|
||||
self.form.extraOffset.setText(FreeCAD.Units.Quantity(obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString)
|
||||
self.form.extraOffset.setText(
|
||||
FreeCAD.Units.Quantity(
|
||||
obj.OffsetExtra.Value, FreeCAD.Units.Length
|
||||
).UserString
|
||||
)
|
||||
|
||||
self.form.useCompensation.setChecked(obj.UseComp)
|
||||
self.form.useStartPoint.setChecked(obj.UseStartPoint)
|
||||
@@ -108,7 +112,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
self.updateVisibility()
|
||||
|
||||
def getSignalsForUpdate(self, obj):
|
||||
'''getSignalsForUpdate(obj) ... return list of signals for updating obj'''
|
||||
"""getSignalsForUpdate(obj) ... return list of signals for updating obj"""
|
||||
signals = []
|
||||
signals.append(self.form.toolController.currentIndexChanged)
|
||||
signals.append(self.form.coolantController.currentIndexChanged)
|
||||
@@ -127,13 +131,13 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
hasFace = False
|
||||
objBase = list()
|
||||
|
||||
if hasattr(self.obj, 'Base'):
|
||||
if hasattr(self.obj, "Base"):
|
||||
objBase = self.obj.Base
|
||||
|
||||
if objBase.__len__() > 0:
|
||||
for (base, subsList) in objBase:
|
||||
for sub in subsList:
|
||||
if sub[:4] == 'Face':
|
||||
if sub[:4] == "Face":
|
||||
hasFace = True
|
||||
break
|
||||
|
||||
@@ -148,15 +152,21 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
|
||||
def registerSignalHandlers(self, obj):
|
||||
self.form.useCompensation.stateChanged.connect(self.updateVisibility)
|
||||
|
||||
|
||||
# Eclass
|
||||
|
||||
|
||||
Command = PathOpGui.SetupOperation('Profile',
|
||||
PathProfile.Create,
|
||||
TaskPanelOpPage,
|
||||
'Path_Contour',
|
||||
QtCore.QT_TRANSLATE_NOOP("Path_Profile", "Profile"),
|
||||
QtCore.QT_TRANSLATE_NOOP("Path_Profile", "Profile entire model, selected face(s) or selected edge(s)"),
|
||||
PathProfile.SetupProperties)
|
||||
Command = PathOpGui.SetupOperation(
|
||||
"Profile",
|
||||
PathProfile.Create,
|
||||
TaskPanelOpPage,
|
||||
"Path_Contour",
|
||||
QT_TRANSLATE_NOOP("Path", "Profile"),
|
||||
QT_TRANSLATE_NOOP(
|
||||
"Path", "Profile entire model, selected face(s) or selected edge(s)"
|
||||
),
|
||||
PathProfile.SetupProperties,
|
||||
)
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathProfileFacesGui... done\n")
|
||||
|
||||
Reference in New Issue
Block a user