Modified combobox selection

cleaned up translation method

Profile translation cleanup

Incorporating additional suggestions
This commit is contained in:
sliptonic
2021-12-15 09:12:44 -06:00
parent 1eccba10ca
commit 21765dec9c
3 changed files with 153 additions and 136 deletions

View File

@@ -35,6 +35,7 @@ import PathScripts.PathSetupSheet as PathSetupSheet
import PathScripts.PathUtil as PathUtil
import PathScripts.PathUtils as PathUtils
import importlib
from PySide.QtCore import QT_TRANSLATE_NOOP
from PySide import QtCore, QtGui
@@ -43,16 +44,18 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Base classes and framework for Path operation's UI"
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
translate = FreeCAD.Qt.translate
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
if False:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
class ViewProvider(object):
"""Generic view provider for path objects.
"""
Generic view provider for path objects.
Deducts the icon name from operation name, brings up the TaskPanel
with pages corresponding to the operation's opFeatures() and forwards
property change notifications to the page controllers.
@@ -79,10 +82,12 @@ class ViewProvider(object):
return
def deleteObjectsOnReject(self):
"""deleteObjectsOnReject() ... return true if all objects should
"""
deleteObjectsOnReject() ... return true if all objects should
be created if the user hits cancel. This is used during the initial
edit session, if the user does not press OK, it is assumed they've
changed their mind about creating the operation."""
changed their mind about creating the operation.
"""
PathLog.track()
return hasattr(self, "deleteOnReject") and self.deleteOnReject
@@ -186,7 +191,7 @@ class ViewProvider(object):
PathLog.track()
for action in menu.actions():
menu.removeAction(action)
action = QtGui.QAction(translate("Path", "Edit"), menu)
action = QtGui.QAction(translate("PathOp", "Edit"), menu)
action.triggered.connect(self.setEdit)
menu.addAction(action)
@@ -353,30 +358,27 @@ class TaskPanelPage(object):
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
# helpers
def selectInComboBox(self, name, combo):
"""selectInComboBox(name, combo) ...
helper function to select a specific value in a combo box."""
index = combo.findText(name, QtCore.Qt.MatchFixedString)
if index >= 0:
combo.blockSignals(True)
combo.setCurrentIndex(index)
combo.blockSignals(False)
def selectInComboBoxNew(self, name, combo):
'''selectInComboBox(name, combo) ...
helper function to select a specific value in a combo box.'''
combo.blockSignals(True)
cnt = combo.count()
blocker = QtCore.QSignalBlocker(combo)
index = combo.currentIndex() # Save initial index
while cnt > 0:
cnt -= 1
combo.setCurrentIndex(cnt)
if name == combo.currentData():
combo.blockSignals(False)
return
# Search using currentData and return if found
newindex = combo.findData(name)
if newindex >= 0:
combo.setCurrentIndex(newindex)
return
# if not found, search using current text
newindex = combo.findText(name, QtCore.Qt.MatchFixedString)
if newindex >= 0:
combo.setCurrentIndex(newindex)
return
# not found, return unchanged
combo.setCurrentIndex(index)
combo.blockSignals(False)
return
def populateCombobox(self, form, enumTups, comboBoxesPropertyMap):
"""fillComboboxes(form, comboBoxesPropertyMap) ... populate comboboxes with translated enumerations
@@ -558,7 +560,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
if len(selection) != 1:
if not ignoreErrors:
msg = translate(
"PathProject",
"PathOp",
"Please select %s from a single solid" % self.featureName(),
)
FreeCAD.Console.PrintError(msg + "\n")
@@ -571,30 +573,28 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
and selection[0].SubObjects[0].ShapeType == "Vertex"
):
if not ignoreErrors:
PathLog.error(
translate("PathProject", "Vertexes are not supported")
)
PathLog.error(translate("PathOp", "Vertexes are not supported"))
return False
if (
not self.supportsEdges()
and selection[0].SubObjects[0].ShapeType == "Edge"
):
if not ignoreErrors:
PathLog.error(translate("PathProject", "Edges are not supported"))
PathLog.error(translate("PathOp", "Edges are not supported"))
return False
if (
not self.supportsFaces()
and selection[0].SubObjects[0].ShapeType == "Face"
):
if not ignoreErrors:
PathLog.error(translate("PathProject", "Faces are not supported"))
PathLog.error(translate("PathOp", "Faces are not supported"))
return False
else:
if not self.supportsPanels() or "Panel" not in sel.Object.Name:
if not ignoreErrors:
PathLog.error(
translate(
"PathProject",
"PathOp",
"Please select %s of a solid" % self.featureName(),
)
)
@@ -653,7 +653,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
opLabel = str(self.form.geometryImportList.currentText())
ops = FreeCAD.ActiveDocument.getObjectsByLabel(opLabel)
if len(ops) > 1:
msg = translate("PathOpGui", "Mulitiple operations are labeled as")
msg = translate("PathOp", "Mulitiple operations are labeled as")
msg += " {}\n".format(opLabel)
FreeCAD.Console.PrintWarning(msg)
(base, subList) = ops[0].Base[0]
@@ -850,7 +850,7 @@ class TaskPanelHeightsPage(TaskPanelPage):
)
def getTitle(self, obj):
return translate("Path", "Heights")
return translate("PathOp", "Heights")
def getFields(self, obj):
self.safeHeight.updateProperty()
@@ -1056,7 +1056,7 @@ class TaskPanelDiametersPage(TaskPanelPage):
)
def getTitle(self, obj):
return translate("Path", "Diameters")
return translate("PathOp", "Diameters")
def getFields(self, obj):
self.minDiameter.updateProperty()
@@ -1090,7 +1090,7 @@ class TaskPanel(object):
def __init__(self, obj, deleteOnReject, opPage, selectionFactory):
PathLog.track(obj.Label, deleteOnReject, opPage, selectionFactory)
FreeCAD.ActiveDocument.openTransaction(translate("Path", "AreaOp Operation"))
FreeCAD.ActiveDocument.openTransaction(translate("PathOp", "AreaOp Operation"))
self.obj = obj
self.deleteOnReject = deleteOnReject
self.featurePages = []
@@ -1220,7 +1220,7 @@ class TaskPanel(object):
FreeCAD.ActiveDocument.abortTransaction()
if self.deleteOnReject:
FreeCAD.ActiveDocument.openTransaction(
translate("Path", "Uncreate AreaOp Operation")
translate("PathOp", "Uncreate AreaOp Operation")
)
try:
PathUtil.clearExpressionEngine(self.obj)
@@ -1367,8 +1367,8 @@ class CommandSetStartPoint:
def GetResources(self):
return {
"Pixmap": "Path_StartPoint",
"MenuText": QtCore.QT_TRANSLATE_NOOP("Path", "Pick Start Point"),
"ToolTip": QtCore.QT_TRANSLATE_NOOP("Path", "Pick Start Point"),
"MenuText": QT_TRANSLATE_NOOP("PathOp", "Pick Start Point"),
"ToolTip": QT_TRANSLATE_NOOP("PathOp", "Pick Start Point"),
}
def IsActive(self):

View File

@@ -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

View File

@@ -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")