Merge pull request #2314 from mlampert/refactor/pylint-warning-cleanup

Path: Refactor/pylint warning cleanup
This commit is contained in:
sliptonic
2019-07-01 21:20:12 -05:00
committed by GitHub
56 changed files with 797 additions and 537 deletions

View File

@@ -95,9 +95,13 @@ class PathWorkbench (Workbench):
prepcmdlist.append("Path_Shape")
extracmdlist.extend(["Path_Area", "Path_Area_Workplane"])
threedopcmdlist.append("Path_Surface")
threedcmdgroup = ['Path_3dTools']
FreeCADGui.addCommand('Path_3dTools', PathCommandGroup(threedopcmdlist, QtCore.QT_TRANSLATE_NOOP("Path",'3D Operations')))
try:
import ocl # pylint: disable=unused-variable
threedopcmdlist.append("Path_Surface")
threedcmdgroup = ['Path_3dTools']
FreeCADGui.addCommand('Path_3dTools', PathCommandGroup(threedopcmdlist, QtCore.QT_TRANSLATE_NOOP("Path",'3D Operations')))
except ImportError:
FreeCAD.Console.PrintError("OpenCamLib is not working!\n")
else:
threedcmdgroup = threedopcmdlist

View File

@@ -54,8 +54,9 @@ if LOGLEVEL:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -85,6 +86,7 @@ class ObjectOp(PathOp.ObjectOp):
def areaOpFeatures(self, obj):
'''areaOpFeatures(obj) ... overwrite to add operation specific features.
Can safely be overwritten by subclasses.'''
# pylint: disable=unused-argument
return 0
def initOperation(self, obj):
@@ -112,7 +114,7 @@ class ObjectOp(PathOp.ObjectOp):
def initAreaOp(self, obj):
'''initAreaOp(obj) ... overwrite if the receiver class needs initialisation.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def areaOpShapeForDepths(self, obj, job):
'''areaOpShapeForDepths(obj) ... returns the shape used to make an initial calculation for the depths being used.
@@ -130,7 +132,7 @@ class ObjectOp(PathOp.ObjectOp):
def areaOpOnChanged(self, obj, prop):
'''areaOpOnChanged(obj, porp) ... overwrite to process operation specific changes to properties.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def opOnChanged(self, obj, prop):
'''opOnChanged(obj, prop) ... base implementation of the notification framework - do not overwrite.
@@ -169,7 +171,7 @@ class ObjectOp(PathOp.ObjectOp):
def areaOpOnDocumentRestored(self, obj):
'''areaOpOnDocumentRestored(obj) ... overwrite to fully restore receiver'''
pass
pass # pylint: disable=unnecessary-pass
def opSetDefaultValues(self, obj, job):
'''opSetDefaultValues(obj) ... base implementation, do not overwrite.
@@ -189,7 +191,7 @@ class ObjectOp(PathOp.ObjectOp):
if PathOp.FeatureDepths & self.opFeatures(obj):
try:
shape = self.areaOpShapeForDepths(obj, job)
except Exception as ee:
except Exception as ee: # pylint: disable=broad-except
PathLog.error(ee)
shape = None
@@ -206,11 +208,10 @@ class ObjectOp(PathOp.ObjectOp):
# Adjust start and final depths if rotation is enabled
if obj.EnableRotation != 'Off':
self.initWithRotation = True
self.stockBB = PathUtils.findParentJob(obj).Stock.Shape.BoundBox
self.stockBB = PathUtils.findParentJob(obj).Stock.Shape.BoundBox # pylint: disable=attribute-defined-outside-init
# Calculate rotational distances/radii
opHeights = self.opDetermineRotationRadii(obj) # return is list with tuples [(xRotRad, yRotRad, zRotRad), (clrOfst, safOfset)]
(xRotRad, yRotRad, zRotRad) = opHeights[0]
# (clrOfset, safOfst) = opHeights[1]
(xRotRad, yRotRad, zRotRad) = opHeights[0] # pylint: disable=unused-variable
PathLog.debug("opHeights[0]: " + str(opHeights[0]))
PathLog.debug("opHeights[1]: " + str(opHeights[1]))
@@ -250,16 +251,17 @@ class ObjectOp(PathOp.ObjectOp):
def areaOpSetDefaultValues(self, obj, job):
'''areaOpSetDefaultValues(obj, job) ... overwrite to set initial values of operation specific properties.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def _buildPathArea(self, obj, baseobject, isHole, start, getsim):
'''_buildPathArea(obj, baseobject, isHole, start, getsim) ... internal function.'''
# pylint: disable=unused-argument
PathLog.track()
area = Path.Area()
area.setPlane(PathUtils.makeWorkplane(baseobject))
area.add(baseobject)
areaParams = self.areaOpAreaParams(obj, isHole)
areaParams = self.areaOpAreaParams(obj, isHole) # pylint: disable=assignment-from-no-return
heights = [i for i in self.depthparams]
PathLog.debug('depths: {}'.format(heights))
@@ -273,7 +275,7 @@ class ObjectOp(PathOp.ObjectOp):
shapelist = [sec.getShape() for sec in sections]
PathLog.debug("shapelist = %s" % shapelist)
pathParams = self.areaOpPathParams(obj, isHole)
pathParams = self.areaOpPathParams(obj, isHole) # pylint: disable=assignment-from-no-return
pathParams['shapes'] = shapelist
pathParams['feedrate'] = self.horizFeed
pathParams['feedrate_v'] = self.vertFeed
@@ -297,7 +299,7 @@ class ObjectOp(PathOp.ObjectOp):
(pp, end_vector) = Path.fromShapes(**pathParams)
PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
self.endVector = end_vector
self.endVector = end_vector # pylint: disable=attribute-defined-outside-init
simobj = None
if getsim:
@@ -309,7 +311,7 @@ class ObjectOp(PathOp.ObjectOp):
return pp, simobj
def opExecute(self, obj, getsim=False):
def opExecute(self, obj, getsim=False): # pylint: disable=arguments-differ
'''opExecute(obj, getsim=False) ... implementation of Path.Area ops.
determines the parameters for _buildPathArea().
Do not overwrite, implement
@@ -321,12 +323,12 @@ class ObjectOp(PathOp.ObjectOp):
PathLog.track()
# Instantiate class variables for operation reference
self.endVector = None
self.rotateFlag = False
self.leadIn = 2.0 # self.safOfst / 2.0
self.cloneNames = []
self.guiMsgs = [] # list of message tuples (title, msg) to be displayed in GUI
self.stockBB = PathUtils.findParentJob(obj).Stock.Shape.BoundBox
self.endVector = None # pylint: disable=attribute-defined-outside-init
self.rotateFlag = False # pylint: disable=attribute-defined-outside-init
self.leadIn = 2.0 # pylint: disable=attribute-defined-outside-init
self.cloneNames = [] # pylint: disable=attribute-defined-outside-init
self.guiMsgs = [] # pylint: disable=attribute-defined-outside-init
self.stockBB = PathUtils.findParentJob(obj).Stock.Shape.BoundBox # pylint: disable=attribute-defined-outside-init
self.useTempJobClones('Delete') # Clear temporary group and recreate for temp job clones
# Import OpFinalDepth from pre-existing operation for recompute() scenarios
@@ -346,42 +348,42 @@ class ObjectOp(PathOp.ObjectOp):
if obj.EnableRotation != 'Off':
# Calculate operation heights based upon rotation radii
opHeights = self.opDetermineRotationRadii(obj)
(self.xRotRad, self.yRotRad, self.zRotRad) = opHeights[0]
(self.clrOfset, self.safOfst) = opHeights[1]
(self.xRotRad, self.yRotRad, self.zRotRad) = opHeights[0] # pylint: disable=attribute-defined-outside-init
(self.clrOfset, self.safOfst) = opHeights[1] # pylint: disable=attribute-defined-outside-init
# Set clearnance and safe heights based upon rotation radii
if obj.EnableRotation == 'A(x)':
self.strDep = self.xRotRad
strDep = self.xRotRad
elif obj.EnableRotation == 'B(y)':
self.strDep = self.yRotRad
strDep = self.yRotRad
else:
self.strDep = max(self.xRotRad, self.yRotRad)
self.finDep = -1 * self.strDep
strDep = max(self.xRotRad, self.yRotRad)
finDep = -1 * strDep
obj.ClearanceHeight.Value = self.strDep + self.clrOfset
obj.SafeHeight.Value = self.strDep + self.safOfst
obj.ClearanceHeight.Value = strDep + self.clrOfset
obj.SafeHeight.Value = strDep + self.safOfst
if self.initWithRotation is False:
if obj.FinalDepth.Value == obj.OpFinalDepth.Value:
obj.FinalDepth.Value = self.finDep
obj.FinalDepth.Value = finDep
if obj.StartDepth.Value == obj.OpStartDepth.Value:
obj.StartDepth.Value = self.strDep
obj.StartDepth.Value = strDep
# Create visual axes when debugging.
if PathLog.getLevel(PathLog.thisModule()) == 4:
self.visualAxis()
else:
self.strDep = obj.StartDepth.Value
self.finDep = obj.FinalDepth.Value
strDep = obj.StartDepth.Value
finDep = obj.FinalDepth.Value
# Set axial feed rates based upon horizontal feed rates
safeCircum = 2 * math.pi * obj.SafeHeight.Value
self.axialFeed = 360 / safeCircum * self.horizFeed
self.axialRapid = 360 / safeCircum * self.horizRapid
self.axialFeed = 360 / safeCircum * self.horizFeed # pylint: disable=attribute-defined-outside-init
self.axialRapid = 360 / safeCircum * self.horizRapid # pylint: disable=attribute-defined-outside-init
# Initiate depthparams and calculate operation heights for rotational operation
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
self.depthparams = PathUtils.depth_params(
self.depthparams = PathUtils.depth_params( # pylint: disable=attribute-defined-outside-init
clearance_height=obj.ClearanceHeight.Value,
safe_height=obj.SafeHeight.Value,
start_depth=obj.StartDepth.Value,
@@ -396,7 +398,7 @@ class ObjectOp(PathOp.ObjectOp):
else:
start = None
aOS = self.areaOpShapes(obj) # list of tuples (shape, isHole, sub, angle, axis)
aOS = self.areaOpShapes(obj) # pylint: disable=assignment-from-no-return
# Adjust tuples length received from other PathWB tools/operations beside PathPocketShape
shapes = []
@@ -432,14 +434,14 @@ class ObjectOp(PathOp.ObjectOp):
nextAxis = 'L'
for ns in range(0, numShapes):
(shape, isHole, sub, angle, axis, strDep, finDep) = shapes[ns]
(shape, isHole, sub, angle, axis, strDep, finDep) = shapes[ns] # pylint: disable=unused-variable
if ns < numShapes - 1:
nextAxis = shapes[ns + 1][4]
else:
nextAxis = 'L'
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
self.depthparams = PathUtils.depth_params(
self.depthparams = PathUtils.depth_params( # pylint: disable=attribute-defined-outside-init
clearance_height=obj.ClearanceHeight.Value,
safe_height=obj.SafeHeight.Value,
start_depth=strDep, # obj.StartDepth.Value,
@@ -450,7 +452,7 @@ class ObjectOp(PathOp.ObjectOp):
try:
(pp, sim) = self._buildPathArea(obj, shape, isHole, start, getsim)
except Exception as e:
except Exception as e: # pylint: disable=broad-except
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Check project and tool config.")
else:
@@ -485,7 +487,7 @@ class ObjectOp(PathOp.ObjectOp):
# Eif
if self.areaOpRetractTool(obj):
self.endVector = None
self.endVector = None # pylint: disable=attribute-defined-outside-init
# Raise cutter to safe height and rotate back to original orientation
if self.rotateFlag is True:
@@ -500,28 +502,33 @@ class ObjectOp(PathOp.ObjectOp):
def areaOpRetractTool(self, obj):
'''areaOpRetractTool(obj) ... return False to keep the tool at current level between shapes. Default is True.'''
# pylint: disable=unused-argument
return True
def areaOpAreaParams(self, obj, isHole):
'''areaOpAreaParams(obj, isHole) ... return operation specific area parameters in a dictionary.
Note that the resulting parameters are stored in the property AreaParams.
Must be overwritten by subclasses.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
def areaOpPathParams(self, obj, isHole):
'''areaOpPathParams(obj, isHole) ... return operation specific path parameters in a dictionary.
Note that the resulting parameters are stored in the property PathParams.
Must be overwritten by subclasses.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
def areaOpShapes(self, obj):
'''areaOpShapes(obj) ... return all shapes to be processed by Path.Area for this op.
Must be overwritten by subclasses.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
def areaOpUseProjection(self, obj):
'''areaOpUseProcjection(obj) ... return True if the operation can use procjection, defaults to False.
Can safely be overwritten by subclasses.'''
# pylint: disable=unused-argument
return False
# Rotation-related methods
@@ -680,7 +687,7 @@ class ObjectOp(PathOp.ObjectOp):
rtn = False
if angle == 500.0:
angle == 0.0
angle = 0.0
rtn = False
if rtn is False:
@@ -690,8 +697,7 @@ class ObjectOp(PathOp.ObjectOp):
rtn = True
if rtn is True:
self.rotateFlag = True
# rtn = True
self.rotateFlag = True # pylint: disable=attribute-defined-outside-init
if obj.ReverseDirection is True:
if angle < 180.0:
angle = angle + 180.0
@@ -721,13 +727,13 @@ class ObjectOp(PathOp.ObjectOp):
for entry in self.guiMsgs:
(title, msg) = entry
QMessageBox.warning(None, title, msg)
self.guiMsgs = [] # Reset messages
self.guiMsgs = [] # pylint: disable=attribute-defined-outside-init
return True
else:
for entry in self.guiMsgs:
(title, msg) = entry
PathLog.warning("{}:: {}".format(title, msg))
self.guiMsgs = [] # Reset messages
self.guiMsgs = [] # pylint: disable=attribute-defined-outside-init
return True
return False

View File

@@ -85,6 +85,7 @@ class ObjectOp(PathOp.ObjectOp):
def circularHoleFeatures(self, obj):
'''circularHoleFeatures(obj) ... overwrite to add operations specific features.
Can safely be overwritten by subclasses.'''
# pylint: disable=unused-argument
return 0
def initOperation(self, obj):
@@ -97,10 +98,11 @@ class ObjectOp(PathOp.ObjectOp):
def initCircularHoleOperation(self, obj):
'''initCircularHoleOperation(obj) ... overwrite if the subclass needs initialisation.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def baseIsArchPanel(self, obj, base):
'''baseIsArchPanel(obj, base) ... return true if op deals with an Arch.Panel.'''
# pylint: disable=unused-argument
return hasattr(base, "Proxy") and isinstance(base.Proxy, ArchPanel.PanelSheet)
def getArchPanelEdge(self, obj, base, sub):
@@ -112,6 +114,7 @@ class ObjectOp(PathOp.ObjectOp):
Obviously this is as fragile as can be, but currently the best we can do while the panel sheets
hide the actual features from Path and they can't be referenced directly.
'''
# pylint: disable=unused-argument
ids = sub.split(".")
holeId = int(ids[0])
wireId = int(ids[1])
@@ -184,15 +187,15 @@ class ObjectOp(PathOp.ObjectOp):
baseSubsTuples = []
subCount = 0
allTuples = []
self.cloneNames = []
self.guiMsgs = [] # list of message tuples (title, msg) to be displayed in GUI
self.rotateFlag = False
self.useTempJobClones('Delete') # Clear temporary group and recreate for temp job clones
self.stockBB = PathUtils.findParentJob(obj).Stock.Shape.BoundBox
self.clearHeight = obj.ClearanceHeight.Value
self.safeHeight = obj.SafeHeight.Value
self.axialFeed = 0.0
self.axialRapid = 0.0
self.cloneNames = [] # pylint: disable=attribute-defined-outside-init
self.guiMsgs = [] # pylint: disable=attribute-defined-outside-init
self.rotateFlag = False # pylint: disable=attribute-defined-outside-init
self.useTempJobClones('Delete') # pylint: disable=attribute-defined-outside-init
self.stockBB = PathUtils.findParentJob(obj).Stock.Shape.BoundBox # pylint: disable=attribute-defined-outside-init
self.clearHeight = obj.ClearanceHeight.Value # pylint: disable=attribute-defined-outside-init
self.safeHeight = obj.SafeHeight.Value # pylint: disable=attribute-defined-outside-init
self.axialFeed = 0.0 # pylint: disable=attribute-defined-outside-init
self.axialRapid = 0.0 # pylint: disable=attribute-defined-outside-init
trgtDep = None
def haveLocations(self, obj):
@@ -203,27 +206,27 @@ class ObjectOp(PathOp.ObjectOp):
if obj.EnableRotation == 'Off':
# maxDep = self.stockBB.ZMax
# minDep = self.stockBB.ZMin
self.strDep = obj.StartDepth.Value
self.finDep = obj.FinalDepth.Value
strDep = obj.StartDepth.Value
finDep = obj.FinalDepth.Value
else:
# Calculate operation heights based upon rotation radii
opHeights = self.opDetermineRotationRadii(obj)
(self.xRotRad, self.yRotRad, self.zRotRad) = opHeights[0]
(self.clrOfset, self.safOfst) = opHeights[1]
(self.xRotRad, self.yRotRad, self.zRotRad) = opHeights[0] # pylint: disable=attribute-defined-outside-init
(clrOfset, safOfst) = opHeights[1]
PathLog.debug("Exec. opHeights[0]: " + str(opHeights[0]))
PathLog.debug("Exec. opHeights[1]: " + str(opHeights[1]))
# Set clearnance and safe heights based upon rotation radii
if obj.EnableRotation == 'A(x)':
self.strDep = self.xRotRad
strDep = self.xRotRad
elif obj.EnableRotation == 'B(y)':
self.strDep = self.yRotRad
strDep = self.yRotRad
else:
self.strDep = max(self.xRotRad, self.yRotRad)
self.finDep = -1 * self.strDep
strDep = max(self.xRotRad, self.yRotRad)
finDep = -1 * strDep
obj.ClearanceHeight.Value = self.strDep + self.clrOfset
obj.SafeHeight.Value = self.strDep + self.safOfst
obj.ClearanceHeight.Value = strDep + clrOfset
obj.SafeHeight.Value = strDep + safOfst
# Create visual axises when debugging.
if PathLog.getLevel(PathLog.thisModule()) == 4:
@@ -231,8 +234,8 @@ class ObjectOp(PathOp.ObjectOp):
# Set axial feed rates based upon horizontal feed rates
safeCircum = 2 * math.pi * obj.SafeHeight.Value
self.axialFeed = 360 / safeCircum * self.horizFeed
self.axialRapid = 360 / safeCircum * self.horizRapid
self.axialFeed = 360 / safeCircum * self.horizFeed # pylint: disable=attribute-defined-outside-init
self.axialRapid = 360 / safeCircum * self.horizRapid # pylint: disable=attribute-defined-outside-init
# Complete rotational analysis and temp clone creation as needed
if obj.EnableRotation == 'Off':
@@ -248,14 +251,14 @@ class ObjectOp(PathOp.ObjectOp):
shape = getattr(base.Shape, sub)
rtn = False
(norm, surf) = self.getFaceNormAndSurf(shape)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
if rtn is True:
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, subCount)
# Verify faces are correctly oriented - InverseAngle might be necessary
PathLog.debug("Verifing {} orientation: running faceRotationAnalysis() again.".format(sub))
faceIA = getattr(clnBase.Shape, sub)
(norm, surf) = self.getFaceNormAndSurf(faceIA)
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
if rtn is True:
msg = obj.Name + ":: "
msg += translate("Path", "{} might be misaligned after initial rotation.".format(sub)) + " "
@@ -355,7 +358,7 @@ class ObjectOp(PathOp.ObjectOp):
holes is a list of dictionaries with 'x', 'y' and 'r' specified for each hole.
Note that for Vertexes, non-circular Edges and Locations r=0.
Must be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def findAllHoles(self, obj):
if not self.getJob(obj):
@@ -585,7 +588,7 @@ class ObjectOp(PathOp.ObjectOp):
rtn = False
if angle == 500.0:
angle == 0.0
angle = 0.0
rtn = False
if rtn is False:
@@ -595,7 +598,7 @@ class ObjectOp(PathOp.ObjectOp):
rtn = True
if rtn is True:
self.rotateFlag = True
self.rotateFlag = True # pylint: disable=attribute-defined-outside-init
# rtn = True
if obj.ReverseDirection is True:
if angle < 180.0:
@@ -626,13 +629,13 @@ class ObjectOp(PathOp.ObjectOp):
for entry in self.guiMsgs:
(title, msg) = entry
QMessageBox.warning(None, title, msg)
self.guiMsgs = [] # Reset messages
self.guiMsgs = [] # pylint: disable=attribute-defined-outside-init
return True
else:
for entry in self.guiMsgs:
(title, msg) = entry
PathLog.warning("{}:: {}".format(title, msg))
self.guiMsgs = [] # Reset messages
self.guiMsgs = [] # pylint: disable=attribute-defined-outside-init
return True
return False
@@ -818,7 +821,7 @@ class ObjectOp(PathOp.ObjectOp):
else:
strDep = min(obj.StartDepth.Value, stockTop)
if strDep <= finDep:
strDep = stockTop # self.strDep
strDep = stockTop
msg = translate('Path', "Start depth <= face depth.\nIncreased to stock top.")
PathLog.error(msg)
return (strDep, finDep)

View File

@@ -57,7 +57,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
return FreeCADGui.PySideUic.loadUi(":/panels/PageBaseHoleGeometryEdit.ui")
def initPage(self, obj):
self.updating = False
self.updating = False # pylint: disable=attribute-defined-outside-init
def setFields(self, obj):
'''setFields(obj) ... fill form with values from obj'''
@@ -65,7 +65,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
self.form.baseList.blockSignals(True)
self.form.baseList.clearContents()
self.form.baseList.setRowCount(0)
for i, (base, subs) in enumerate(obj.Base):
for (base, subs) in obj.Base:
for sub in subs:
self.form.baseList.insertRow(self.form.baseList.rowCount())
@@ -126,7 +126,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
self.form.baseList.blockSignals(False)
#self.obj.Proxy.execute(self.obj)
FreeCAD.ActiveDocument.recompute()
self.setFields(self.obj);
self.setFields(self.obj)
def updateBase(self):
'''updateBase() ... helper function to transfer current table to obj'''
@@ -140,9 +140,9 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
PathLog.debug("keeping (%s.%s)" % (obj.Label, sub))
newlist.append(base)
PathLog.debug("obj.Base=%s newlist=%s" % (self.obj.Base, newlist))
self.updating = True
self.updating = True # pylint: disable=attribute-defined-outside-init
self.obj.Base = newlist
self.updating = False
self.updating = False # pylint: disable=attribute-defined-outside-init
def checkedChanged(self):
'''checkeChanged() ... callback when checked status of a base feature changed'''

View File

@@ -83,8 +83,8 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
(depth, offset) = toolDepthAndOffset(obj.Width.Value, obj.ExtraDepth.Value, self.tool)
PathLog.track(obj.Label, depth, offset)
self.basewires = []
self.adjusted_basewires = []
self.basewires = [] # pylint: disable=attribute-defined-outside-init
self.adjusted_basewires = [] # pylint: disable=attribute-defined-outside-init
wires = []
for base, subs in obj.Base:
edges = []
@@ -97,7 +97,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
basewires.extend(sub.Wires)
else:
basewires.append(Part.Wire(sub.Edges))
self.edges = edges
self.edges = edges # pylint: disable=attribute-defined-outside-init
for edgelist in Part.sortEdges(edges):
basewires.append(Part.Wire(edgelist))
@@ -118,7 +118,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
zValues.append(depth)
PathLog.track(obj.Label, depth, zValues)
self.wires = wires
self.wires = wires # pylint: disable=attribute-defined-outside-init
self.buildpathocc(obj, wires, zValues, True)
# the last command is a move to clearance, which is automatically added by PathOp

View File

@@ -55,8 +55,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
return FreeCADGui.PySideUic.loadUi(":/panels/PageOpDeburrEdit.ui")
def initPage(self, obj):
self.opImagePath = "{}Mod/Path/Images/Ops/{}".format(FreeCAD.getHomePath(), 'chamfer.svg')
self.opImage = QtGui.QPixmap(self.opImagePath)
self.opImagePath = "{}Mod/Path/Images/Ops/{}".format(FreeCAD.getHomePath(), 'chamfer.svg') # pylint: disable=attribute-defined-outside-init
self.opImage = QtGui.QPixmap(self.opImagePath) # pylint: disable=attribute-defined-outside-init
self.form.opImage.setPixmap(self.opImage)
iconMiter = QtGui.QIcon(':/icons/edge-join-miter-not.svg')
iconMiter.addFile(':/icons/edge-join-miter.svg', state=QtGui.QIcon.On)

View File

@@ -32,7 +32,7 @@ from PySide import QtCore
if FreeCAD.GuiUp:
import FreeCADGui
"""Axis remapping Dressup object and FreeCAD command. This dressup remaps one axis of motion to another.
__doc__ = """Axis remapping Dressup object and FreeCAD command. This dressup remaps one axis of motion to another.
For example, you can re-map the Y axis to A to control a 4th axis rotary."""
# Qt translation handling
@@ -141,7 +141,7 @@ class ObjectDressup:
class ViewProviderDressup:
def __init__(self, vobj):
vobj.Proxy = self
self.obj = vobj.Object
def attach(self, vobj):
self.obj = vobj.Object
@@ -167,6 +167,7 @@ class ViewProviderDressup:
def onDelete(self, arg1=None, arg2=None):
'''this makes sure that the base operation is added back to the project and visible'''
# pylint: disable=unused-argument
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(arg1.Object)
job.Proxy.addOperation(arg1.Object.Base, arg1.Object)
@@ -174,6 +175,7 @@ class ViewProviderDressup:
return True
class CommandPathDressup:
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
@@ -185,7 +187,7 @@ class CommandPathDressup:
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return True
return False
def Activated(self):
@@ -213,7 +215,7 @@ class CommandPathDressup:
FreeCADGui.doCommand('obj.Base = base')
FreeCADGui.doCommand('obj.Radius = 45')
FreeCADGui.doCommand('job.Proxy.addOperation(obj, base)')
FreeCADGui.doCommand('PathScripts.PathDressupAxisMap.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = PathScripts.PathDressupAxisMap.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('Gui.ActiveDocument.getObject(base.Name).Visibility = False')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -35,8 +35,6 @@ import PathScripts.PathUtils as PathUtils
from PySide import QtCore
"""Dogbone Dressup object and FreeCAD command"""
LOG_MODULE = PathLog.thisModule()
LOGLEVEL = False
@@ -146,6 +144,8 @@ def edgesForCommands(cmds, startPt):
class Style:
# pylint: disable=no-init
Dogbone = 'Dogbone'
Tbone_H = 'T-bone horizontal'
Tbone_V = 'T-bone vertical'
@@ -155,6 +155,8 @@ class Style:
class Side:
# pylint: disable=no-init
Left = 'Left'
Right = 'Right'
All = [Left, Right]
@@ -169,6 +171,8 @@ class Side:
class Incision:
# pylint: disable=no-init
Fixed = 'fixed'
Adaptive = 'adaptive'
Custom = 'custom'
@@ -176,6 +180,8 @@ class Incision:
class Smooth:
# pylint: disable=no-init
Neither = 0
In = 1
Out = 2
@@ -192,6 +198,7 @@ class Smooth:
# Instances of Chord are generally considered immutable and all movement member
# functions return new instances.
class Chord (object):
def __init__(self, start=None, end=None):
if not start:
start = FreeCAD.Vector()
@@ -294,9 +301,9 @@ class Chord (object):
return not PathGeom.isRoughly(self.End.z, self.Start.z)
def foldsBackOrTurns(self, chord, side):
dir = chord.getDirectionOf(self)
PathLog.info(" - direction = %s/%s" % (dir, side))
return dir == 'Back' or dir == side
direction = chord.getDirectionOf(self)
PathLog.info(" - direction = %s/%s" % (direction, side))
return direction == 'Back' or direction == side
def connectsTo(self, chord):
return PathGeom.pointsCoincide(self.End, chord.Start)
@@ -313,25 +320,31 @@ class Bone:
self.smooth = Smooth.Neither
self.F = F
# initialized later
self.cDist = None
self.cAngle = None
self.tAngle = None
self.cPt = None
def angle(self):
if not hasattr(self, 'cAngle'):
if self.cAngle is None:
baseAngle = self.inChord.getAngleXY()
turnAngle = self.outChord.getAngle(self.inChord)
angle = addAngle(baseAngle, (turnAngle - math.pi)/2)
theta = addAngle(baseAngle, (turnAngle - math.pi)/2)
if self.obj.Side == Side.Left:
angle = addAngle(angle, math.pi)
theta = addAngle(theta, math.pi)
self.tAngle = turnAngle
self.cAngle = angle
self.cAngle = theta
return self.cAngle
def distance(self, toolRadius):
if not hasattr(self, 'cDist'):
if self.cDist is None:
self.angle() # make sure the angles are initialized
self.cDist = toolRadius / math.cos(self.tAngle/2)
return self.cDist
def corner(self, toolRadius):
if not hasattr(self, 'cPt'):
if self.cPt is None:
self.cPt = self.inChord.move(self.distance(toolRadius), self.angle()).End
return self.cPt
@@ -339,38 +352,42 @@ class Bone:
return (self.inChord.End.x, self.inChord.End.y)
def adaptiveLength(self, boneAngle, toolRadius):
angle = self.angle()
theta = self.angle()
distance = self.distance(toolRadius)
# there is something weird happening if the boneAngle came from a horizontal/vertical t-bone
# for some reason pi/2 is not equal to pi/2
if math.fabs(angle - boneAngle) < 0.00001:
if math.fabs(theta - boneAngle) < 0.00001:
# moving directly towards the corner
PathLog.debug("adaptive - on target: %.2f - %.2f" % (distance, toolRadius))
return distance - toolRadius
PathLog.debug("adaptive - angles: corner=%.2f bone=%.2f diff=%.12f" % (angle/math.pi, boneAngle/math.pi, angle - boneAngle))
PathLog.debug("adaptive - angles: corner=%.2f bone=%.2f diff=%.12f" % (theta/math.pi, boneAngle/math.pi, theta - boneAngle))
# The bones root and end point form a triangle with the intersection of the tool path
# with the toolRadius circle around the bone end point.
# In case the math looks questionable, look for "triangle ssa"
# c = distance
# b = self.toolRadius
# beta = fabs(boneAngle - angle)
beta = math.fabs(addAngle(boneAngle, -angle))
# beta = fabs(boneAngle - theta)
beta = math.fabs(addAngle(boneAngle, -theta)) # pylint: disable=invalid-unary-operand-type
D = (distance / toolRadius) * math.sin(beta)
if D > 1: # no intersection
PathLog.debug("adaptive - no intersection - no bone")
return 0
gamma = math.asin(D)
alpha = math.pi - beta - gamma
length = toolRadius * math.sin(alpha) / math.sin(beta)
if D < 1 and toolRadius < distance: # there exists a second solution
beta2 = beta
gamma2 = math.pi - gamma
alpha2 = math.pi - beta2 - gamma2
length2 = toolRadius * math.sin(alpha2) / math.sin(beta2)
length = min(length, length2)
if PathGeom.isRoughly(0.0, math.sin(beta)):
# it is not a good idea to divide by 0
length = 0.0
else:
length = toolRadius * math.sin(alpha) / math.sin(beta)
if D < 1 and toolRadius < distance: # there exists a second solution
beta2 = beta
gamma2 = math.pi - gamma
alpha2 = math.pi - beta2 - gamma2
length2 = toolRadius * math.sin(alpha2) / math.sin(beta2)
length = min(length, length2)
PathLog.debug("adaptive corner=%.2f * %.2f˚ -> bone=%.2f * %.2f˚" % (distance, angle, length, boneAngle))
PathLog.debug("adaptive corner=%.2f * %.2f˚ -> bone=%.2f * %.2f˚" % (distance, theta, length, boneAngle))
return length
@@ -396,6 +413,15 @@ class ObjectDressup:
obj.Proxy = self
obj.Base = base
# initialized later
self.boneShapes = None
self.toolRadius = 0
self.dbg = None
self.locationBlacklist = None
self.shapes = None
self.boneId = None
self.bones = None
def onDocumentRestored(self, obj):
obj.setEditorMode('BoneBlacklist', 2) # hide this one
@@ -418,6 +444,7 @@ class ObjectDressup:
return outChord.foldsBackOrTurns(inChord, self.theOtherSideOf(obj.Side))
def findPivotIntersection(self, pivot, pivotEdge, edge, refPt, d, color):
# pylint: disable=unused-argument
PathLog.track("(%.2f, %.2f)^%.2f - [(%.2f, %.2f), (%.2f, %.2f)]" % (pivotEdge.Curve.Center.x, pivotEdge.Curve.Center.y, pivotEdge.Curve.Radius, edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y))
ppt = None
pptDistance = 0
@@ -579,8 +606,8 @@ class ObjectDressup:
def tboneHorizontal(self, bone):
angle = bone.angle()
boneAngle = 0
if PathGeom.isRoughly(angle, math.pi) or math.fabs(angle) > math.pi/2:
boneAngle = -math.pi
if math.fabs(angle) > math.pi/2:
boneAngle = math.pi
return self.inOutBoneCommands(bone, boneAngle, self.toolRadius)
def tboneVertical(self, bone):
@@ -846,12 +873,12 @@ class ObjectDressup:
# If the receiver was loaded from file, then it never generated the bone list.
if not hasattr(self, 'bones'):
self.execute(obj)
for (id, loc, enabled, inaccessible) in self.bones:
for (nr, loc, enabled, inaccessible) in self.bones:
item = state.get(loc)
if item:
item[2].append(id)
item[2].append(nr)
else:
state[loc] = (enabled, inaccessible, [id])
state[loc] = (enabled, inaccessible, [nr])
return state
@@ -862,6 +889,7 @@ class TaskPanel:
def __init__(self, obj):
self.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(":/panels/DogboneEdit.ui")
self.s = None
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupDogbone", "Edit Dogbone Dress-up"))
def reject(self):
@@ -979,6 +1007,7 @@ class SelObserver:
PST.clear()
def addSelection(self, doc, obj, sub, pnt):
# pylint: disable=unused-argument
FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
FreeCADGui.updateGui()
@@ -986,7 +1015,8 @@ class SelObserver:
class ViewProviderDressup:
def __init__(self, vobj):
vobj.Proxy = self
self.vobj = vobj
self.obj = None
def attach(self, vobj):
self.obj = vobj.Object
@@ -1005,6 +1035,7 @@ class ViewProviderDressup:
return [self.obj.Base]
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
FreeCADGui.Control.closeDialog()
panel = TaskPanel(vobj.Object)
FreeCADGui.Control.showDialog(panel)
@@ -1019,6 +1050,7 @@ class ViewProviderDressup:
def onDelete(self, arg1=None, arg2=None):
'''this makes sure that the base operation is added back to the project and visible'''
# pylint: disable=unused-argument
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(arg1.Object)
job.Proxy.addOperation(arg1.Object.Base, arg1.Object)
@@ -1030,13 +1062,13 @@ def Create(base, name='DogboneDressup'):
'''
Create(obj, name='DogboneDressup') ... dresses the given PathProfile/PathContour object with dogbones.
'''
obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', 'DogboneDressup')
obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', name)
dbo = ObjectDressup(obj, base)
job = PathUtils.findParentJob(base)
job.Proxy.addOperation(obj, base)
if FreeCAD.GuiUp:
ViewProviderDressup(obj.ViewObject)
obj.ViewObject.Proxy = ViewProviderDressup(obj.ViewObject)
obj.Base.ViewObject.Visibility = False
dbo.setup(obj, True)
@@ -1044,6 +1076,7 @@ def Create(base, name='DogboneDressup'):
class CommandDressupDogbone:
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
@@ -1054,7 +1087,7 @@ class CommandDressupDogbone:
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return True
return False
def Activated(self):

View File

@@ -30,7 +30,7 @@ import math
import DraftVecUtils as D
import PathScripts.PathUtils as PathUtils
"""Dragknife Dressup object and FreeCAD command"""
__doc__ = """Dragknife Dressup object and FreeCAD command"""
if FreeCAD.GuiUp:
import FreeCADGui
@@ -66,8 +66,6 @@ class ObjectDressup:
'''Determines whether its shorter to twist CW or CCW to align with the next move'''
# get the vector of the last move
global arccommands
if queue[1].Name in arccommands:
arcLoc = FreeCAD.Vector(queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation['Z'])
radvector = arcLoc.sub(queue[1].Placement.Base) # .sub(arcLoc) # vector of chord from center to point
@@ -94,7 +92,6 @@ class ObjectDressup:
requires the previous command in order to calculate arcs correctly
if endpos = True, return the angle at the end of the segment.'''
global arccommands
if currCommand.Name in arccommands:
arcLoc = FreeCAD.Vector((prevCommand.x + currCommand.I), (prevCommand.y + currCommand.J), currentZ)
if endpos is True:
@@ -127,7 +124,7 @@ class ObjectDressup:
def arcExtension(self, obj, queue):
'''returns gcode for arc extension'''
global currLocation
global currLocation # pylint: disable=global-statement
results = []
offset = obj.offset
@@ -166,7 +163,7 @@ class ObjectDressup:
'''returns gcode to do an arc move toward an arc to perform
a corner action twist. Includes lifting and plungeing the knife'''
global currLocation
global currLocation # pylint: disable=global-statement
pivotheight = obj.pivotheight
offset = obj.offset
results = []
@@ -233,7 +230,7 @@ class ObjectDressup:
def lineExtension(self, obj, queue):
'''returns gcode for line extension'''
global currLocation
global currLocation # pylint: disable=global-statement
offset = float(obj.offset)
results = []
@@ -259,7 +256,7 @@ class ObjectDressup:
def lineTwist(self, obj, queue, lastXY, twistCW=False):
'''returns gcode to do an arc move toward a line to perform
a corner action twist. Includes lifting and plungeing the knife'''
global currLocation
global currLocation # pylint: disable=global-statement
pivotheight = obj.pivotheight
offset = obj.offset
@@ -310,7 +307,7 @@ class ObjectDressup:
def execute(self, obj):
newpath = []
global currLocation
global currLocation # pylint: disable=global-statement
if not obj.Base:
return
@@ -433,7 +430,7 @@ class ObjectDressup:
class ViewProviderDressup:
def __init__(self, vobj):
vobj.Proxy = self
self.Object = vobj.Object
def attach(self, vobj):
self.Object = vobj.Object
@@ -449,9 +446,11 @@ class ViewProviderDressup:
# FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
def unsetEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
return False
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
return True
def claimChildren(self):
@@ -461,9 +460,11 @@ class ViewProviderDressup:
return None
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
def onDelete(self, arg1=None, arg2=None):
# pylint: disable=unused-argument
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(arg1.Object.Base)
job.Proxy.addOperation(arg1.Object.Base, arg1.Object)
@@ -472,6 +473,7 @@ class ViewProviderDressup:
class CommandDressupDragknife:
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
@@ -482,7 +484,7 @@ class CommandDressupDragknife:
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return True
return False
def Activated(self):
@@ -512,7 +514,7 @@ class CommandDressupDragknife:
FreeCADGui.doCommand('job = PathScripts.PathUtils.findParentJob(base)')
FreeCADGui.doCommand('obj.Base = base')
FreeCADGui.doCommand('job.Proxy.addOperation(obj, base)')
FreeCADGui.doCommand('PathScripts.PathDressupDragknife.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = PathScripts.PathDressupDragknife.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('Gui.ActiveDocument.getObject(base.Name).Visibility = False')
FreeCADGui.doCommand('obj.filterangle = 20')
FreeCADGui.doCommand('obj.offset = 2')

View File

@@ -36,8 +36,6 @@ from PathScripts.PathDressupTagPreferences import HoldingTagPreferences
from PathScripts.PathUtils import waiting_effects
from PySide import QtCore
"""Holding Tags Dressup object and FreeCAD command"""
LOGLEVEL = False
if LOGLEVEL:
@@ -100,9 +98,9 @@ def debugCone(vector, r1, r2, height, label, color=None):
class Tag:
def __init__(self, id, x, y, width, height, angle, radius, enabled=True):
def __init__(self, nr, x, y, width, height, angle, radius, enabled=True):
PathLog.track("%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d" % (x, y, width, height, angle, radius, enabled))
self.id = id
self.nr = nr
self.x = x
self.y = y
self.width = math.fabs(width)
@@ -113,6 +111,14 @@ class Tag:
self.enabled = enabled
self.isSquare = False
# initialized later
self.toolRadius = None
self.realRadius = None
self.r1 = None
self.r2 = None
self.solid = None
self.z = None
def fullWidth(self):
return 2 * self.toolRadius + self.width
@@ -177,13 +183,13 @@ class Tag:
def filterIntersections(self, pts, face):
if type(face.Surface) == Part.Cone or type(face.Surface) == Part.Cylinder or type(face.Surface) == Part.Toroid:
PathLog.track("it's a cone/cylinder, checking z")
return list(filter(lambda pt: pt.z >= self.bottom() and pt.z <= self.top(), pts))
return list([pt for pt in pts if pt.z >= self.bottom() and pt.z <= self.top()])
if type(face.Surface) == Part.Plane:
PathLog.track("it's a plane, checking R")
c = face.Edges[0].Curve
if (type(c) == Part.Circle):
return list(filter(lambda pt: (pt - c.Center).Length <= c.Radius or PathGeom.isRoughly((pt - c.Center).Length, c.Radius), pts))
print("==== we got a %s" % face.Surface)
return list([pt for pt in pts if (pt - c.Center).Length <= c.Radius or PathGeom.isRoughly((pt - c.Center).Length, c.Radius)])
PathLog.error("==== we got a %s" % face.Surface)
def isPointOnEdge(self, pt, edge):
param = edge.Curve.parameter(pt)
@@ -268,6 +274,18 @@ class MapWireToTag:
self.complete = False
self.haveProblem = False
# initialized later
self.edgePoints = None
self.edgesCleanup = None
self.edgesOrder = None
self.entryEdges = None
self.exit = None
self.exitEdges = None
self.finalEdge = None
self.offendingEdge = None
self.realEntry = None
self.realExit = None
def addEdge(self, edge):
debugEdge(edge, '..........')
self.edges.append(edge)
@@ -324,16 +342,16 @@ class MapWireToTag:
# if there are no edges connected to entry/exit, it means the plunge in/out is vertical
# we need to add in the missing segment and collect the new entry/exit edges.
if not self.entryEdges:
print("fill entryEdges ...")
PathLog.debug("fill entryEdges ...")
self.realEntry = sorted(self.edgePoints, key=lambda p: (p - self.entry).Length)[0]
self.entryEdges = list(filter(lambda e: PathGeom.edgeConnectsTo(e, self.realEntry), edges))
self.entryEdges = list([e for e in edges if PathGeom.edgeConnectsTo(e, self.realEntry)])
edges.append(Part.Edge(Part.LineSegment(self.entry, self.realEntry)))
else:
self.realEntry = None
if not self.exitEdges:
print("fill exitEdges ...")
PathLog.debug("fill exitEdges ...")
self.realExit = sorted(self.edgePoints, key=lambda p: (p - self.exit).Length)[0]
self.exitEdges = list(filter(lambda e: PathGeom.edgeConnectsTo(e, self.realExit), edges))
self.exitEdges = list([e for e in edges if PathGeom.edgeConnectsTo(e, self.realExit)])
edges.append(Part.Edge(Part.LineSegment(self.realExit, self.exit)))
else:
self.realExit = None
@@ -407,13 +425,13 @@ class MapWireToTag:
if lastP == p0:
self.edgesOrder.append(outputEdges)
self.edgesOrder.append(edges)
print('input edges:')
PathLog.debug('input edges:')
for e in inputEdges:
debugEdge(e, ' ', False)
print('ordered edges:')
PathLog.debug('ordered edges:')
for e, flip in outputEdges:
debugEdge(e, ' %c ' % ('<' if flip else '>'), False)
print('remaining edges:')
PathLog.debug('remaining edges:')
for e in edges:
debugEdge(e, ' ', False)
raise ValueError("No connection to %s" % (p0))
@@ -449,13 +467,13 @@ class MapWireToTag:
wire.add(edge)
shell = wire.extrude(FreeCAD.Vector(0, 0, self.tag.height + 1))
nullFaces = list(filter(lambda f: PathGeom.isRoughly(f.Area, 0), shell.Faces))
nullFaces = list([f for f in shell.Faces if PathGeom.isRoughly(f.Area, 0)])
if nullFaces:
return shell.removeShape(nullFaces)
return shell
def commandsForEdges(self):
global failures
global failures # pylint: disable=global-statement
if self.edges:
try:
shape = self.shell().common(self.tag.solid)
@@ -476,7 +494,7 @@ class MapWireToTag:
commands.append(Path.Command('G0', {'X': rapid.x, 'Y': rapid.y, 'Z': rapid.z}))
rapid = None
return commands
except Exception as e:
except Exception as e: # pylint: disable=broad-except
PathLog.error("Exception during processing tag @(%.2f, %.2f) (%s) - disabling the tag" % (self.tag.x, self.tag.y, e.args[0]))
#if sys.version_info.major < 3:
# traceback.print_exc(e)
@@ -501,7 +519,7 @@ class MapWireToTag:
self.offendingEdge = edge
debugEdge(edge, 'offending Edge:', False)
o = self.tag.originAt(self.tag.z)
print('originAt: (%.2f, %.2f, %.2f)' % (o.x, o.y, o.z))
PathLog.debug('originAt: (%.2f, %.2f, %.2f)' % (o.x, o.y, o.z))
i = edge.valueAt(edge.FirstParameter)
if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)):
self.tail = edge
@@ -552,7 +570,7 @@ class PathData:
wire = Part.Wire(bottom)
if wire.isClosed():
return wire
except Exception:
except Exception: # pylint: disable=broad-except
#if sys.version_info.major < 3:
# traceback.print_exc(e)
#else:
@@ -581,6 +599,7 @@ class PathData:
return (edges[0], edges[-1])
def generateTags(self, obj, count, width=None, height=None, angle=None, radius=None, spacing=None):
# pylint: disable=unused-argument
PathLog.track(count, width, height, angle, spacing)
# for e in self.baseWire.Edges:
# debugMarker(e.Vertexes[0].Point, 'base', (0.0, 1.0, 1.0), 0.2)
@@ -683,7 +702,7 @@ class PathData:
ordered = []
for edge in self.bottomEdges:
ts = [t for t in tags if PathGeom.isRoughly(0, Part.Vertex(t.originAt(self.minZ)).distToShape(edge)[0], 0.1)]
for t in sorted(ts, key=lambda t: (t.originAt(self.minZ) - edge.valueAt(edge.FirstParameter)).Length):
for t in sorted(ts, key=lambda t, edge=edge: (t.originAt(self.minZ) - edge.valueAt(edge.FirstParameter)).Length):
tags.remove(t)
ordered.append(t)
# disable all tags that are not on the base wire.
@@ -725,6 +744,10 @@ class ObjectTagDressup:
self.obj = obj
self.solids = []
self.tags = []
self.pathData = None
self.toolRadius = None
self.mappers = []
def __getstate__(self):
return None
@@ -733,13 +756,13 @@ class ObjectTagDressup:
return None
def supportsTagGeneration(self, obj):
if not hasattr(self, 'pathData'):
if not self.pathData:
self.setup(obj)
return self.pathData.supportsTagGeneration()
def generateTags(self, obj, count):
if self.supportsTagGeneration(obj):
if hasattr(self, "pathData"):
if self.pathData:
self.tags = self.pathData.generateTags(obj, count, obj.Width.Value, obj.Height.Value, obj.Angle, obj.Radius.Value, None)
obj.Positions = [tag.originAt(self.pathData.minZ) for tag in self.tags]
obj.Disabled = []
@@ -836,7 +859,7 @@ class ObjectTagDressup:
return Path.Path(commands)
def problems(self):
return list(filter(lambda m: m.haveProblem, self.mappers))
return list([m for m in self.mappers if m.haveProblem])
def createTagsPositionDisabled(self, obj, positionsIn, disabledIn):
rawTags = []
@@ -869,7 +892,7 @@ class ObjectTagDressup:
PathLog.debug("previousTag = %d [%s]" % (i, prev))
else:
disabled.append(i)
tag.id = i # assigne final id
tag.nr = i # assigne final nr
tags.append(tag)
positions.append(tag.originAt(self.pathData.minZ))
return (tags, positions, disabled)
@@ -894,7 +917,7 @@ class ObjectTagDressup:
pathData = self.setup(obj)
if not pathData:
print("execute - no pathData")
PathLog.debug("execute - no pathData")
return
self.tags = []
@@ -906,13 +929,13 @@ class ObjectTagDressup:
obj.Disabled = disabled
if not self.tags:
print("execute - no tags")
PathLog.debug("execute - no tags")
obj.Path = obj.Base.Path
return
try:
self.processTags(obj)
except Exception as e:
except Exception as e: # pylint: disable=broad-except
PathLog.error("processing tags failed clearing all tags ... '%s'" % (e.args[0]))
#if sys.version_info.major < 3:
# traceback.print_exc(e)
@@ -925,15 +948,15 @@ class ObjectTagDressup:
solids = []
for tag in self.tags:
solids.append(tag.solid)
if not tag.enabled and tag.id not in disabled:
disabled.append(tag.id)
if not tag.enabled and tag.nr not in disabled:
disabled.append(tag.nr)
self.solids = solids
if obj.Disabled != disabled:
obj.Disabled = disabled
@waiting_effects
def processTags(self, obj):
global failures
global failures # pylint: disable=global-statement
failures = []
tagID = 0
if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
@@ -975,7 +998,7 @@ class ObjectTagDressup:
def setXyEnabled(self, triples):
PathLog.track()
if not hasattr(self, 'pathData'):
if not self.pathData:
self.setup(self.obj)
positions = []
disabled = []
@@ -988,12 +1011,12 @@ class ObjectTagDressup:
self.processTags(self.obj)
def pointIsOnPath(self, obj, point):
if not hasattr(self, 'pathData'):
if not self.pathData:
self.setup(obj)
return self.pathData.pointIsOnPath(point)
def pointAtBottom(self, obj, point):
if not hasattr(self, 'pathData'):
if not self.pathData:
self.setup(obj)
return self.pathData.pointAtBottom(point)
@@ -1010,7 +1033,7 @@ def Create(baseObject, name='DressupTag'):
PathLog.error(translate('Path_DressupTag', 'Please select a Profile object'))
return None
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
dbo = ObjectTagDressup(obj, baseObject)
job = PathUtils.findParentJob(baseObject)
job.Proxy.addOperation(obj, baseObject)

View File

@@ -34,7 +34,7 @@ import math
from PySide import QtCore
"""LeadInOut Dressup MASHIN-CRC USE ROLL-ON ROLL-OFF to profile"""
__doc__ = """LeadInOut Dressup MASHIN-CRC USE ROLL-ON ROLL-OFF to profile"""
if FreeCAD.GuiUp:
import FreeCADGui
@@ -48,7 +48,6 @@ PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03']
rapidcommands = ['G0', 'G00']
arccommands = ['G2', 'G3', 'G02', 'G03']
global currLocation
currLocation = {}
@@ -70,10 +69,14 @@ class ObjectDressup:
obj.RadiusCenter = ["Radius", "Center"]
obj.Proxy = self
self.wire = None
self.rapids = None
def __getstate__(self):
return None
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
def setup(self, obj):
@@ -122,7 +125,6 @@ class ObjectDressup:
def getLeadStart(self, obj, queue, action):
'''returns Lead In G-code.'''
global currLocation
results = []
# zdepth = currLocation["Z"]
op = PathDressup.baseOp(obj.Base)
@@ -171,10 +173,10 @@ class ObjectDressup:
extendcommand = Path.Command('G1', {"X": leadstart.x, "Y": leadstart.y, "Z": p1.z, "F": vertFeed})
results.append(extendcommand)
if obj.UseMachineCRC:
if self.getDirectionOfPath(obj) == 'right':
results.append(Path.Command('G42', {'D': toolnummer}))
else:
results.append(Path.Command('G41', {'D': toolnummer}))
if self.getDirectionOfPath(obj) == 'right':
results.append(Path.Command('G42', {'D': toolnummer}))
else:
results.append(Path.Command('G41', {'D': toolnummer}))
if obj.StyleOn == 'Arc':
arcmove = Path.Command(arcdir, {"X": p0.x, "Y": p0.y, "I": offsetvector.x, "J": offsetvector.y, "F": horizFeed}) # add G2/G3 move
results.append(arcmove)
@@ -187,7 +189,7 @@ class ObjectDressup:
def getLeadEnd(self, obj, queue, action):
'''returns the Gcode of LeadOut.'''
global currLocation
# pylint: disable=unused-argument
results = []
horizFeed = PathDressup.toolController(obj.Base).HorizFeed.Value
R = obj.Length.Value # Radius of roll or length
@@ -228,7 +230,7 @@ class ObjectDressup:
return results
def generateLeadInOutCurve(self, obj):
global currLocation
global currLocation # pylint: disable=global-statement
firstmove = Path.Command("G0", {"X": 0, "Y": 0, "Z": 0})
currLocation.update(firstmove.Parameters)
newpath = []
@@ -298,7 +300,7 @@ class ObjectDressup:
class ViewProviderDressup:
def __init__(self, vobj):
vobj.Proxy = self
self.obj = vobj.Object
def attach(self, vobj):
self.obj = vobj.Object
@@ -317,8 +319,9 @@ class ViewProviderDressup:
return [self.obj.Base]
def onDelete(self, arg1=None, arg2=None):
PathLog.debug("Deleting Dressup")
'''this makes sure that the base operation is added back to the project and visible'''
# pylint: disable=unused-argument
PathLog.debug("Deleting Dressup")
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(self.obj)
job.Proxy.addOperation(arg1.Object.Base, arg1.Object)
@@ -329,10 +332,12 @@ class ViewProviderDressup:
return None
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
class CommandPathDressupLeadInOut:
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
@@ -370,7 +375,7 @@ class CommandPathDressupLeadInOut:
FreeCADGui.doCommand('job = PathScripts.PathUtils.findParentJob(base)')
FreeCADGui.doCommand('obj.Base = base')
FreeCADGui.doCommand('job.Proxy.addOperation(obj, base)')
FreeCADGui.doCommand('PathScripts.PathDressupLeadInOut.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = PathScripts.PathDressupLeadInOut.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('Gui.ActiveDocument.getObject(base.Name).Visibility = False')
FreeCADGui.doCommand('dbo.setup(obj)')
FreeCAD.ActiveDocument.commitTransaction()

View File

@@ -60,6 +60,15 @@ class ObjectDressup:
obj.Proxy = self
self.setEditorProperties(obj)
# initialized later
self.wire = None
self.angle = None
self.rapids = None
self.method = None
self.outedges = None
self.ignoreAboveEnabled = None
self.ignoreAbove = None
def __getstate__(self):
return None
@@ -366,6 +375,7 @@ class ObjectDressup:
curPoint = p0 # start from the upper point of plunge
done = False
goingForward = True
i = 0
while not done:
for i, redge in enumerate(rampedges):
if redge.Length >= rampremaining:
@@ -432,6 +442,7 @@ class ObjectDressup:
curPoint = p0 # start from the upper point of plunge
done = False
i = 0
while not done:
for i, redge in enumerate(rampedges):
if redge.Length >= rampremaining:
@@ -621,7 +632,7 @@ class ObjectDressup:
class ViewProviderDressup:
def __init__(self, vobj):
vobj.Proxy = self
self.obj = vobj.Object
def attach(self, vobj):
self.obj = vobj.Object
@@ -640,8 +651,9 @@ class ViewProviderDressup:
return [self.obj.Base]
def onDelete(self, arg1=None, arg2=None):
PathLog.debug("Deleting Dressup")
'''this makes sure that the base operation is added back to the project and visible'''
# pylint: disable=unused-argument
PathLog.debug("Deleting Dressup")
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(self.obj)
job.Proxy.addOperation(arg1.Object.Base, arg1.Object)
@@ -656,6 +668,7 @@ class ViewProviderDressup:
class CommandPathDressupRampEntry:
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
@@ -693,7 +706,7 @@ class CommandPathDressupRampEntry:
FreeCADGui.doCommand('job = PathScripts.PathUtils.findParentJob(base)')
FreeCADGui.doCommand('obj.Base = base')
FreeCADGui.doCommand('job.Proxy.addOperation(obj, base)')
FreeCADGui.doCommand('PathScripts.PathDressupRampEntry.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = PathScripts.PathDressupRampEntry.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('Gui.ActiveDocument.getObject(base.Name).Visibility = False')
FreeCADGui.doCommand('dbo.setup(obj)')
FreeCAD.ActiveDocument.commitTransaction()

View File

@@ -29,7 +29,6 @@ import PathScripts.PathGeom as PathGeom
import PathScripts.PathLog as PathLog
import PathScripts.PathUtils as PathUtils
import math
import sys
from PathScripts.PathDressupTagPreferences import HoldingTagPreferences
from PySide import QtCore
@@ -42,6 +41,7 @@ PathLog.trackModule()
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
MaxInt = 99999999999999
class TagSolid:
def __init__(self, proxy, z, R):
@@ -127,6 +127,14 @@ class ObjectDressup:
self.obj = obj
self.solids = []
# initialized later
self.edges = None
self.masterSolid = None
self.ptMax = None
self.ptMin = None
self.tagSolid = None
self.wire = None
def __getstate__(self):
return None
@@ -156,11 +164,11 @@ class ObjectDressup:
self.obj = obj
minZ = +sys.maxint
minZ = +MaxInt
minX = minZ
minY = minZ
maxZ = -sys.maxint
maxZ = -MaxInt
maxX = maxZ
maxY = maxZ
@@ -187,7 +195,7 @@ class ObjectDressup:
self.solids = [self.masterSolid.cloneAt(pos) for pos in self.obj.Positions]
self.tagSolid = Part.Compound(self.solids)
self.wire, rapid = PathGeom.wireForPath(obj.Base.Path)
self.wire, rapid = PathGeom.wireForPath(obj.Base.Path) # pylint: disable=unused-variable
self.edges = self.wire.Edges
maxTagZ = minZ + obj.Height.Value
@@ -220,9 +228,11 @@ class ObjectDressup:
obj.Shape = solid
def supportsTagGeneration(self, obj):
# pylint: disable=unused-argument
return False
def pointIsOnPath(self, obj, p):
# pylint: disable=unused-argument
for e in self.edges:
if DraftGeomUtils.isPtOnEdge(p, e):
return True
@@ -241,7 +251,7 @@ def Create(baseObject, name='DressupTag'):
PathLog.error(translate('Path_DressupTag', 'Please select a Profile object'))
return None
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
dbo = ObjectDressup(obj, baseObject)
job = PathUtils.findParentJob(baseObject)
job.adddOperation(obj)

View File

@@ -69,6 +69,11 @@ class PathDressupTagTaskPanel:
self.pt = FreeCAD.Vector(0, 0, 0)
self.isDirty = True
self.buttonBox = None
self.tags = None
self.Positions = None
self.Disabled = None
self.editItem = None
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel)
@@ -322,12 +327,17 @@ class PathDressupTagViewProvider:
def __init__(self, vobj):
PathLog.track()
vobj.Proxy = self
self.vobj = vobj
self.panel = None
self.debugDisplay()
# initialized later
self.obj = None
self.tags = None
self.switch = None
self.colors = None
def debugDisplay(self):
# if False and addDebugDisplay():
# if not hasattr(self.vobj, 'Debug'):
@@ -385,8 +395,9 @@ class PathDressupTagViewProvider:
return [self.obj.Base]
def onDelete(self, arg1=None, arg2=None):
PathLog.track()
'''this makes sure that the base operation is added back to the job and visible'''
# pylint: disable=unused-argument
PathLog.track()
if self.obj.Base.ViewObject:
self.obj.Base.ViewObject.Visibility = True
job = PathUtils.findParentJob(self.obj)
@@ -428,11 +439,13 @@ class PathDressupTagViewProvider:
# tag.purgeTouched()
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
panel = PathDressupTagTaskPanel(vobj.Object, self)
self.setupTaskPanel(panel)
return True
def unsetEdit(self, vobj, mode):
# pylint: disable=unused-argument
if hasattr(self, 'panel') and self.panel:
self.panel.abort()
@@ -470,11 +483,13 @@ class PathDressupTagViewProvider:
return -1
def allow(self, doc, obj, sub):
# pylint: disable=unused-argument
if obj == self.obj:
return True
return False
def addSelection(self, doc, obj, sub, point):
# pylint: disable=unused-argument
PathLog.track(doc, obj, sub, point)
if self.panel:
i = self.tagAtPoint(point, sub is None)
@@ -489,13 +504,14 @@ def Create(baseObject, name='DressupTag'):
'''
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupTag", "Create a Tag dressup"))
obj = PathDressupTag.Create(baseObject, name)
vp = PathDressupTagViewProvider(obj.ViewObject)
obj.ViewObject.Proxy = PathDressupTagViewProvider(obj.ViewObject)
FreeCAD.ActiveDocument.commitTransaction()
obj.ViewObject.Document.setEdit(obj.ViewObject, 0)
return obj
class CommandPathDressupTag:
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
@@ -506,7 +522,7 @@ class CommandPathDressupTag:
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == 'Job':
return True
return True
return False
def Activated(self):

View File

@@ -52,6 +52,10 @@ def translate(context, text, disambig=None):
class ObjectEngrave(PathEngraveBase.ObjectOp):
'''Proxy class for Engrave operation.'''
def __init__(self, obj, name):
super(ObjectEngrave, self).__init__(obj, name)
self.wires = []
def opFeatures(self, obj):
'''opFeatures(obj) ... return all standard features and edges based geomtries'''
return PathOp.FeatureTool | PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureStepDown | PathOp.FeatureBaseEdges
@@ -130,7 +134,7 @@ class ObjectEngrave(PathEngraveBase.ObjectOp):
if self.commandlist:
self.commandlist.pop()
def opUpdateDepths(self, obj, ignoreErrors=False):
def opUpdateDepths(self, obj):
'''updateDepths(obj) ... engraving is always done at the top most z-value'''
job = PathUtils.findParentJob(obj)
self.opSetDefaultValues(obj, job)

View File

@@ -57,7 +57,6 @@ class ObjectOp(PathOp.ObjectOp):
zValues.append(z)
z -= obj.StepDown.Value
zValues.append(obj.FinalDepth.Value)
self.zValues = zValues
return zValues
def buildpathocc(self, obj, wires, zValues, rel=False):

View File

@@ -59,7 +59,7 @@ class Side:
@classmethod
def toString(cls, side):
"""(side)
"""toString(side)
Returns a string representation of the enum value."""
if side == cls.Left:
return 'Left'
@@ -69,7 +69,7 @@ class Side:
@classmethod
def of(cls, ptRef, pt):
"""(ptRef, pt)
"""of(ptRef, pt)
Determine the side of pt in relation to ptRef.
If both Points are viewed as vectors with their origin in (0,0,0)
then the two vectors either form a straight line (On) or pt
@@ -89,29 +89,29 @@ CmdMoveArc = CmdMoveCW + CmdMoveCCW
CmdMove = CmdMoveStraight + CmdMoveArc
def isRoughly(float1, float2, error=Tolerance):
"""(float1, float2, [error=%s])
Returns true if the two values are the same within a given error.""" % Tolerance
"""isRoughly(float1, float2, [error=Tolerance])
Returns true if the two values are the same within a given error."""
return math.fabs(float1 - float2) <= error
def pointsCoincide(p1, p2, error=Tolerance):
"""(p1, p2, [error=%s])
Return True if two points are roughly identical (see also isRoughly).""" % Tolerance
"""pointsCoincide(p1, p2, [error=Tolerance])
Return True if two points are roughly identical (see also isRoughly)."""
return isRoughly(p1.x, p2.x, error) and isRoughly(p1.y, p2.y, error) and isRoughly(p1.z, p2.z, error)
def edgesMatch(e0, e1, error=Tolerance):
"""(e0, e1, [error=%s]
Return true if the edges start and end at the same point and have the same type of curve.""" % Tolerance
"""edgesMatch(e0, e1, [error=Tolerance]
Return true if the edges start and end at the same point and have the same type of curve."""
if type(e0.Curve) != type(e1.Curve) or len(e0.Vertexes) != len(e1.Vertexes):
return False
return all(pointsCoincide(e0.Vertexes[i].Point, e1.Vertexes[i].Point) for i in range(len(e0.Vertexes)))
return all(pointsCoincide(e0.Vertexes[i].Point, e1.Vertexes[i].Point, error) for i in range(len(e0.Vertexes)))
def edgeConnectsTo(edge, vector, error=Tolerance):
"""(edge, vector, error=%f)
Returns True if edge connects to given vector.""" % Tolerance
return pointsCoincide(edge.valueAt(edge.FirstParameter), vector) or pointsCoincide(edge.valueAt(edge.LastParameter), vector)
"""edgeConnectsTop(edge, vector, error=Tolerance)
Returns True if edge connects to given vector."""
return pointsCoincide(edge.valueAt(edge.FirstParameter), vector, error) or pointsCoincide(edge.valueAt(edge.LastParameter), vector, error)
def getAngle(vector):
"""(vector)
"""getAngle(vector)
Returns the angle [-pi,pi] of a vector using the X-axis as the reference.
Positive angles for vertexes in the upper hemisphere (positive y values)
and negative angles for the lower hemisphere."""
@@ -121,7 +121,7 @@ def getAngle(vector):
return a
def diffAngle(a1, a2, direction = 'CW'):
"""(a1, a2, [direction='CW'])
"""diffAngle(a1, a2, [direction='CW'])
Returns the difference between two angles (a1 -> a2) into a given direction."""
if direction == 'CW':
while a1 < a2:
@@ -198,7 +198,7 @@ def isHorizontal(obj):
def commandEndPoint(cmd, defaultPoint = Vector(), X='X', Y='Y', Z='Z'):
"""(cmd, [defaultPoint=Vector()], [X='X'], [Y='Y'], [Z='Z'])
"""commandEndPoint(cmd, [defaultPoint=Vector()], [X='X'], [Y='Y'], [Z='Z'])
Extracts the end point from a Path Command."""
x = cmd.Parameters.get(X, defaultPoint.x)
y = cmd.Parameters.get(Y, defaultPoint.y)
@@ -206,7 +206,7 @@ def commandEndPoint(cmd, defaultPoint = Vector(), X='X', Y='Y', Z='Z'):
return Vector(x, y, z)
def xy(point):
"""(point)
"""xy(point)
Convenience function to return the projection of the Vector in the XY-plane."""
return Vector(point.x, point.y, 0)
@@ -234,7 +234,7 @@ def speedBetweenPoints(p0, p1, hSpeed, vSpeed):
return speed
def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50, hSpeed = 0, vSpeed = 0):
"""(edge, flip=False, useHelixForBSpline=True, segm=50) -> List(Path.Command)
"""cmdsForEdge(edge, flip=False, useHelixForBSpline=True, segm=50) -> List(Path.Command)
Returns a list of Path.Command representing the given edge.
If flip is True the edge is considered to be backwards.
If useHelixForBSpline is True an Edge based on a BSplineCurve is considered
@@ -314,7 +314,7 @@ def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50, hSpeed
return commands
def edgeForCmd(cmd, startPoint):
"""(cmd, startPoint).
"""edgeForCmd(cmd, startPoint).
Returns an Edge representing the given command, assuming a given startPoint."""
endPoint = commandEndPoint(cmd, startPoint)
@@ -369,7 +369,7 @@ def edgeForCmd(cmd, startPoint):
return None
def wireForPath(path, startPoint = Vector(0, 0, 0)):
"""(path, [startPoint=Vector(0,0,0)])
"""wireForPath(path, [startPoint=Vector(0,0,0)])
Returns a wire representing all move commands found in the given path."""
edges = []
rapid = []
@@ -384,7 +384,7 @@ def wireForPath(path, startPoint = Vector(0, 0, 0)):
return (Part.Wire(edges), rapid)
def wiresForPath(path, startPoint = Vector(0, 0, 0)):
"""(path, [startPoint=Vector(0,0,0)])
"""wiresForPath(path, [startPoint=Vector(0,0,0)])
Returns a collection of wires, each representing a continuous cutting Path in path."""
wires = []
if hasattr(path, "Commands"):
@@ -402,7 +402,7 @@ def wiresForPath(path, startPoint = Vector(0, 0, 0)):
return wires
def arcToHelix(edge, z0, z1):
"""(edge, z0, z1)
"""arcToHelix(edge, z0, z1)
Assuming edge is an arc it'll return a helix matching the arc starting at z0 and rising/falling to z1."""
@@ -421,7 +421,7 @@ def arcToHelix(edge, z0, z1):
def helixToArc(edge, z = 0):
"""(edge, z=0)
"""helixToArc(edge, z=0)
Returns the projection of the helix onto the XY-plane with a given offset."""
p1 = edge.valueAt(edge.FirstParameter)
p2 = edge.valueAt((edge.FirstParameter + edge.LastParameter)/2)
@@ -432,7 +432,7 @@ def helixToArc(edge, z = 0):
return Part.Edge(Part.Arc(p01, p02, p03))
def splitArcAt(edge, pt):
"""(edge, pt)
"""splitArcAt(edge, pt)
Returns a list of 2 edges which together form the original arc split at the given point.
The Vector pt has to represent a point on the given arc."""
p1 = edge.valueAt(edge.FirstParameter)
@@ -453,7 +453,7 @@ def splitArcAt(edge, pt):
return edges
def splitEdgeAt(edge, pt):
"""(edge, pt)
"""splitEdgeAt(edge, pt)
Returns a list of 2 edges, forming the original edge split at the given point.
The results are undefined if the Vector representing the point is not part of the edge."""
# I could not get the OCC parameterAt and split to work ...
@@ -545,7 +545,7 @@ def flipEdge(edge):
return Part.Edge(flipped)
global OddsAndEnds
global OddsAndEnds # pylint: disable=global-statement
OddsAndEnds.append(edge)
PathLog.warning(translate('PathGeom', "%s not support for flipping") % type(edge.Curve))

View File

@@ -59,6 +59,14 @@ class TaskPanel:
self.onPath = onPath
self.obj = None
self.pt = None
self.point = None
self.pointCbClick = None
self.pointCbMove = None
self.pointWhenDone = None
self.escape = None
self.view = None
def setupUi(self):
'''setupUi() ... internal function - do not call.'''
self.formPoint.buttonBox.accepted.connect(self.pointAccept)
@@ -148,6 +156,7 @@ class TaskPanel:
self.pointAcceptAndContinue()
def cancel():
# pylint: disable=unused-variable
self.pointReject()
self.pointWhenDone = whenDone

View File

@@ -47,6 +47,7 @@ else:
def _getProperty(obj, prop):
o = obj
attr = obj
name = None
for name in prop.split('.'):
o = attr
if not hasattr(o, name):
@@ -62,12 +63,12 @@ def _getProperty(obj, prop):
def getProperty(obj, prop):
'''getProperty(obj, prop) ... answer obj's property defined by its canonical name.'''
o, attr, name = _getProperty(obj, prop)
o, attr, name = _getProperty(obj, prop) # pylint: disable=unused-variable
return attr
def setProperty(obj, prop, value):
'''setProperty(obj, prop, value) ... set the property value of obj's property defined by its canonical name.'''
o, attr, name = _getProperty(obj, prop)
o, attr, name = _getProperty(obj, prop) # pylint: disable=unused-variable
if o and name:
setattr(o, name, value)

View File

@@ -21,8 +21,8 @@
# * USA *
# * *
# ***************************************************************************
# pylint: disable=unused-import
import PathScripts
import PathScripts.PathLog as PathLog
LOGLEVEL = False
@@ -36,7 +36,7 @@ else:
Processed = False
def Startup():
global Processed
global Processed # pylint: disable=global-statement
if not Processed:
PathLog.debug('Initializing PathGui')
from PathScripts import PathAdaptiveGui
@@ -74,7 +74,6 @@ def Startup():
except ImportError:
import FreeCAD
FreeCAD.Console.PrintError("OpenCamLib is not working!\n")
pass
from PathScripts import PathToolController
from PathScripts import PathToolControllerGui
from PathScripts import PathToolLibraryManager

View File

@@ -45,6 +45,10 @@ class ViewProvider(object):
def __init__(self, vobj, icon):
self.icon = icon
self.attach(vobj)
self.editModule = None
self.editCallback = None
vobj.Proxy = self
def attach(self, vobj):
@@ -78,14 +82,17 @@ class ViewProvider(object):
callback(self.obj, self.vobj, edit)
def setEdit(self, vobj=None, mode=0):
# pylint: disable=unused-argument
if 0 == mode:
self._onEditCallback(True)
return True
def unsetEdit(self, arg1, arg2):
# pylint: disable=unused-argument
self._onEditCallback(False)
def setupContextMenu(self, vobj, menu):
# pylint: disable=unused-argument
PathLog.track()
from PySide import QtCore, QtGui
edit = QtCore.QCoreApplication.translate('Path', 'Edit', None)
@@ -100,7 +107,7 @@ def Attach(vobj, name):
If no view provider was registered for the given name a default IconViewProvider is created.'''
PathLog.track(vobj.Object.Label, name)
global _factory
global _factory # pylint: disable=global-statement
for key,value in PathUtil.keyValueIter(_factory):
if key == name:
return value(vobj, name)
@@ -112,6 +119,6 @@ def RegisterViewProvider(name, provider):
an instance of provider is used instead.'''
PathLog.track(name)
global _factory
global _factory # pylint: disable=global-statement
_factory[name] = provider

View File

@@ -45,13 +45,13 @@ if LOGLEVEL:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
"""Path Job object and FreeCAD command"""
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class JobTemplate:
# pylint: disable=no-init
'''Attribute and sub element strings for template export/import.'''
Description = 'Desc'
GeometryTolerance = 'Tolerance'
@@ -68,6 +68,7 @@ def isArchPanelSheet(obj):
return hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet)
def isResourceClone(obj, propLink, resourceName):
# pylint: disable=unused-argument
if hasattr(propLink, 'PathResource') and (resourceName is None or resourceName == propLink.PathResource):
return True
return False
@@ -135,6 +136,9 @@ class ObjectJob:
self.setupSetupSheet(obj)
self.setupBaseModel(obj, models)
self.tooltip = None
self.tooltipArgs = None
obj.Proxy = self
self.setFromTemplateFile(obj, templateFile)
@@ -229,7 +233,7 @@ class ObjectJob:
if obj.Operations.ViewObject:
try:
obj.Operations.ViewObject.DisplayMode
except Exception:
except Exception: # pylint: disable=broad-except
name = obj.Operations.Name
label = obj.Operations.Label
ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
@@ -345,7 +349,7 @@ class ObjectJob:
if before:
try:
group.insert(group.index(before), op)
except Exception as e:
except Exception as e: # pylint: disable=broad-except
PathLog.error(e)
group.append(op)
else:
@@ -388,7 +392,7 @@ class ObjectJob:
@classmethod
def baseCandidates(cls):
'''Answer all objects in the current document which could serve as a Base for a job.'''
return sorted(filter(lambda obj: cls.isBaseCandidate(obj) , FreeCAD.ActiveDocument.Objects), key=lambda o: o.Label)
return sorted([obj for obj in FreeCAD.ActiveDocuemnt.Objects if cls.isBaseCandidate(obj)], key=lambda o: o.Label)
@classmethod
def isBaseCandidate(cls, obj):

View File

@@ -53,6 +53,9 @@ class CommandJobCreate:
and a template to be used for the initial creation.
'''
def __init__(self):
pass
def GetResources(self):
return {'Pixmap': 'Path-Job',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Job"),
@@ -90,6 +93,10 @@ class CommandJobTemplateExport:
on Job creation and be available for selection.
'''
def __init__(self):
pass
def GetResources(self):
return {'Pixmap': 'Path-ExportTemplate',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Export Template"),

View File

@@ -53,6 +53,7 @@ class _ItemDelegate(QtGui.QStyledItemDelegate):
QtGui.QStyledItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
# pylint: disable=unused-argument
editor = QtGui.QSpinBox(parent)
self.controller.setupColumnEditor(index, editor)
return editor
@@ -61,12 +62,18 @@ class JobCreate:
DataObject = QtCore.Qt.ItemDataRole.UserRole
def __init__(self, parent=None, sel=None):
# pylint: disable=unused-argument
self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobCreate.ui")
self.itemsSolid = QtGui.QStandardItem(translate('PathJob', 'Solids'))
self.items2D = QtGui.QStandardItem(translate('PathJob', '2D'))
self.itemsJob = QtGui.QStandardItem(translate('PathJob', 'Jobs'))
self.dialog.templateGroup.hide()
self.dialog.modelGroup.hide()
# debugging support
self.candidates = None
self.delegate = None
self.index = None
self.model = None
def setupTitle(self, title):
self.dialog.setWindowTitle(title)
@@ -90,7 +97,7 @@ class JobCreate:
expand2Ds = False
expandJobs = False
for i, base in enumerate(self.candidates):
for base in self.candidates:
if not base in jobResources and not PathJob.isResourceClone(job, base, None) and not hasattr(base, 'StockType'):
item0 = QtGui.QStandardItem()
item1 = QtGui.QStandardItem()
@@ -244,7 +251,7 @@ class JobCreate:
models = []
for i in range(self.itemsSolid.rowCount()):
for j in range(self.itemsSolid.child(i, 1).data(QtCore.Qt.EditRole)):
for j in range(self.itemsSolid.child(i, 1).data(QtCore.Qt.EditRole)): # pylint: disable=unused-variable
models.append(self.itemsSolid.child(i).data(self.DataObject))
for i in range(self.items2D.rowCount()):

View File

@@ -62,6 +62,7 @@ else:
def _OpenCloseResourceEditor(obj, vobj, edit):
# pylint: disable=unused-argument
job = PathUtils.findParentJob(obj)
if job and job.ViewObject and job.ViewObject.Proxy:
if edit:
@@ -103,6 +104,20 @@ class ViewProvider:
vobj.setEditorMode('Transparency', mode)
self.deleteOnReject = True
# initialized later
self.axs = None
self.mat = None
self.obj = None
self.sca = None
self.scs = None
self.sep = None
self.sph = None
self.switch = None
self.taskPanel = None
self.vobj = None
self.baseVisibility = None
self.stockVisibility = None
def attach(self, vobj):
self.vobj = vobj
self.obj = vobj.Object
@@ -146,6 +161,7 @@ class ViewProvider:
return hasattr(self, 'deleteOnReject') and self.deleteOnReject
def setEdit(self, vobj=None, mode=0):
# pylint: disable=unused-argument
PathLog.track(mode)
if 0 == mode:
self.openTaskPanel()
@@ -164,6 +180,7 @@ class ViewProvider:
self.taskPanel = None
def unsetEdit(self, arg1, arg2):
# pylint: disable=unused-argument
if self.taskPanel:
self.taskPanel.reject(False)
@@ -177,6 +194,7 @@ class ViewProvider:
return self.openTaskPanel()
def uneditObject(self, obj=None):
# pylint: disable=unused-argument
self.unsetEdit(None, None)
def getIcon(self):
@@ -220,6 +238,7 @@ class ViewProvider:
base.ViewObject.Visibility = True
def forgetBaseVisibility(self, obj, base):
# pylint: disable=unused-argument
if self.baseVisibility.get(base.Name):
visibility = self.baseVisibility[base.Name]
visibility[0].ViewObject.Visibility = visibility[1]
@@ -243,6 +262,7 @@ class ViewProvider:
obj.Stock.ViewObject.Visibility = self.stockVisibility
def setupContextMenu(self, vobj, menu):
# pylint: disable=unused-argument
PathLog.track()
for action in menu.actions():
menu.removeAction(action)
@@ -276,7 +296,7 @@ class StockEdit(object):
widget.hide()
if select:
self.form.stock.setCurrentIndex(self.Index)
editor = self.editorFrame()
editor = self.editorFrame() # pylint: disable=assignment-from-none
showHide(self.form.stockFromExisting, editor)
showHide(self.form.stockFromBase, editor)
showHide(self.form.stockCreateBox, editor)
@@ -311,11 +331,20 @@ class StockFromBaseBoundBoxEdit(StockEdit):
Index = 2
StockType = PathStock.StockType.FromBase
def __init__(self, obj, form, force):
super(StockFromBaseBoundBoxEdit, self).__init__(obj, form, force)
self.trackXpos = None
self.trackYpos = None
self.trackZpos = None
def editorFrame(self):
PathLog.track()
return self.form.stockFromBase
def getFieldsStock(self, stock, fields=['xneg', 'xpos', 'yneg', 'ypos', 'zneg', 'zpos']):
def getFieldsStock(self, stock, fields=None):
if fields is None:
fields = ['xneg', 'xpos', 'yneg', 'ypos', 'zneg', 'zpos']
try:
if 'xneg' in fields:
stock.ExtXneg = FreeCAD.Units.Quantity(self.form.stockExtXneg.text())
@@ -329,10 +358,12 @@ class StockFromBaseBoundBoxEdit(StockEdit):
stock.ExtZneg = FreeCAD.Units.Quantity(self.form.stockExtZneg.text())
if 'zpos' in fields:
stock.ExtZpos = FreeCAD.Units.Quantity(self.form.stockExtZpos.text())
except Exception:
except Exception: # pylint: disable=broad-except
pass
def getFields(self, obj, fields=['xneg', 'xpos', 'yneg', 'ypos', 'zneg', 'zpos']):
def getFields(self, obj, fields=None):
if fields is None:
fields = ['xneg', 'xpos', 'yneg', 'ypos', 'zneg', 'zpos']
PathLog.track(obj.Label, fields)
if self.IsStock(obj):
self.getFieldsStock(obj.Stock, fields)
@@ -409,7 +440,9 @@ class StockCreateBoxEdit(StockEdit):
def editorFrame(self):
return self.form.stockCreateBox
def getFields(self, obj, fields=['length', 'widht', 'height']):
def getFields(self, obj, fields=None):
if fields is None:
fields = ['length', 'widht', 'height']
try:
if self.IsStock(obj):
if 'length' in fields:
@@ -420,7 +453,7 @@ class StockCreateBoxEdit(StockEdit):
obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockBoxHeight.text())
else:
PathLog.error(translate('PathJob', 'Stock not a box!'))
except Exception:
except Exception: # pylint: disable=broad-except
pass
def setFields(self, obj):
@@ -445,7 +478,9 @@ class StockCreateCylinderEdit(StockEdit):
def editorFrame(self):
return self.form.stockCreateCylinder
def getFields(self, obj, fields=['radius', 'height']):
def getFields(self, obj, fields=None):
if fields is None:
fields = ['radius', 'height']
try:
if self.IsStock(obj):
if 'radius' in fields:
@@ -454,7 +489,7 @@ class StockCreateCylinderEdit(StockEdit):
obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockCylinderHeight.text())
else:
PathLog.error(translate('PathJob', 'Stock not a cylinder!'))
except Exception:
except Exception: # pylint: disable=broad-except
pass
def setFields(self, obj):
@@ -624,7 +659,7 @@ class TaskPanel:
if self.form.wcslist.item(i).checkState() == QtCore.Qt.CheckState.Checked:
flist.append(self.form.wcslist.item(i).text())
self.obj.Fixtures = flist
except Exception:
except Exception: # pylint: disable=broad-except
FreeCAD.Console.PrintWarning("The Job was created without fixture support. Please delete and recreate the job\r\n")
self.updateTooltips()
@@ -830,7 +865,7 @@ class TaskPanel:
elif 'Number' == prop:
try:
tc.ToolNumber = int(item.text())
except Exception:
except Exception: # pylint: disable=broad-except
pass
item.setText("%d" % tc.ToolNumber)
elif 'Spindle' == prop:
@@ -842,7 +877,7 @@ class TaskPanel:
speed = -speed
tc.SpindleDir = rot
tc.SpindleSpeed = speed
except Exception:
except Exception: # pylint: disable=broad-except
pass
item.setText("%s%g" % ('+' if tc.SpindleDir == 'Forward' else '-', tc.SpindleSpeed))
elif 'HorizFeed' == prop or 'VertFeed' == prop:
@@ -854,14 +889,14 @@ class TaskPanel:
elif FreeCAD.Units.Unit() == val.Unit:
val = FreeCAD.Units.Quantity(item.text() + vUnit)
setattr(tc, prop, val)
except Exception:
except Exception: # pylint: disable=broad-except
pass
item.setText("%g" % getattr(tc, prop).getValueAs(vUnit))
else:
try:
val = FreeCAD.Units.Quantity(item.text())
setattr(tc, prop, val)
except Exception:
except Exception: # pylint: disable=broad-except
pass
item.setText("%g" % getattr(tc, prop).Value)
@@ -1126,7 +1161,7 @@ class TaskPanel:
# first remove all obsolete base models
for model, count in PathUtil.keyValueIter(obsolete):
for i in range(count):
for i in range(count): # pylint: disable=unused-variable
# it seems natural to remove the last of all the base objects for a given model
base = [b for b in obj.Model.Group if proxy.baseObject(obj, b) == model][-1]
self.vproxy.forgetBaseVisibility(obj, base)
@@ -1248,15 +1283,19 @@ class TaskPanel:
# SelectionObserver interface
def addSelection(self, doc, obj, sub, pnt):
# pylint: disable=unused-argument
self.updateSelection()
def removeSelection(self, doc, obj, sub):
# pylint: disable=unused-argument
self.updateSelection()
def setSelection(self, doc):
# pylint: disable=unused-argument
self.updateSelection()
def clearSelection(self, doc):
# pylint: disable=unused-argument
self.updateSelection()
@@ -1272,7 +1311,7 @@ def Create(base, template=None):
obj.Document.recompute()
obj.ViewObject.Proxy.editObject(obj.Stock)
return obj
except Exception as exc:
except Exception as exc: # pylint: disable=broad-except
PathLog.error(exc)
traceback.print_exc(exc)
FreeCAD.ActiveDocument.abortTransaction()

View File

@@ -28,6 +28,7 @@ import traceback
class Level:
"""Enumeration of log levels, used for setLevel and getLevel."""
# pylint: disable=no-init
RESET = -1
ERROR = 0
WARNING = 1
@@ -49,15 +50,15 @@ _trackAll = False
def logToConsole(yes):
"""(boolean) - if set to True (default behaviour) log messages are printed to the console. Otherwise they are printed to stdout."""
global _useConsole
global _useConsole # pylint: disable=global-statement
_useConsole = yes
def setLevel(level, module = None):
"""(level, module = None)
if no module is specified the default log level is set.
Otherwise the module specific log level is changed (use RESET to clear)."""
global _defaultLogLevel
global _moduleLogLevel
global _defaultLogLevel # pylint: disable=global-statement
global _moduleLogLevel # pylint: disable=global-statement
if module:
if level == Level.RESET:
if _moduleLogLevel.get(module, -1) != -1:
@@ -83,12 +84,12 @@ def thisModule():
def _caller():
"""internal function to determine the calling module."""
file, line, func, text = traceback.extract_stack(limit=3)[0]
return os.path.splitext(os.path.basename(file))[0], line, func
filename, line, func, text = traceback.extract_stack(limit=3)[0] # pylint: disable=unused-variable
return os.path.splitext(os.path.basename(filename))[0], line, func
def _log(level, module_line_func, msg):
"""internal function to do the logging"""
module, line, func = module_line_func
module, line, func = module_line_func # pylint: disable=unused-variable
if getLevel(module) >= level:
message = "%s.%s: %s" % (module, Level.toString(level), msg)
if _useConsole:
@@ -124,32 +125,32 @@ def error(msg):
def trackAllModules(boolean):
"""(boolean) - if True all modules will be tracked, otherwise tracking is up to the module setting."""
global _trackAll
global _trackAll # pylint: disable=global-statement
_trackAll = boolean
def untrackAllModules():
"""In addition to stop tracking all modules it also clears the tracking flag for all individual modules."""
global _trackAll
global _trackModule
global _trackAll # pylint: disable=global-statement
global _trackModule # pylint: disable=global-statement
_trackAll = False
_trackModule = { }
def trackModule(module = None):
"""(module = None) - start tracking given module, current module if not set."""
global _trackModule
global _trackModule # pylint: disable=global-statement
if module:
_trackModule[module] = True
else:
mod, line, func = _caller()
mod, line, func = _caller() # pylint: disable=unused-variable
_trackModule[mod] = True
def untrackModule(module = None):
"""(module = None) - stop tracking given module, current module if not set."""
global _trackModule
global _trackModule # pylint: disable=global-statement
if module and _trackModule.get(module, None):
del _trackModule[module]
elif not module:
mod, line, func = _caller()
mod, line, func = _caller() # pylint: disable=unused-variable
if _trackModule.get(mod, None):
del _trackModule[mod]

View File

@@ -23,7 +23,6 @@
# ***************************************************************************
import FreeCAD
import FreeCADGui
import PathScripts.PathMillFace as PathMillFace
import PathScripts.PathOpGui as PathOpGui
import PathScripts.PathPocketBaseGui as PathPocketBaseGui

View File

@@ -161,6 +161,18 @@ class ObjectOp(object):
obj.addProperty("App::PropertyVectorDistance", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("PathOp", "The start point of this path"))
obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("PathOp", "Make True, if specifying a Start Point"))
# members being set later
self.commandlist = None
self.horizFeed = None
self.horizRapid = None
self.job = None
self.model = None
self.radius = None
self.stock = None
self.tool = None
self.vertFeed = None
self.vertRapid = None
self.initOperation(obj)
if not hasattr(obj, 'DoNotSetDefaultValues') or not obj.DoNotSetDefaultValues:
@@ -220,17 +232,18 @@ class ObjectOp(object):
'''opFeatures(obj) ... returns the OR'ed list of features used and supported by the operation.
The default implementation returns "FeatureTool | FeatureDeptsh | FeatureHeights | FeatureStartPoint"
Should be overwritten by subclasses.'''
# pylint: disable=unused-argument
return FeatureTool | FeatureDepths | FeatureHeights | FeatureStartPoint | FeatureBaseGeometry | FeatureFinishDepth
def initOperation(self, obj):
'''initOperation(obj) ... implement to create additional properties.
Should be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def opOnDocumentRestored(self, obj):
'''opOnDocumentRestored(obj) ... implement if an op needs special handling like migrating the data model.
Should be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def opOnChanged(self, obj, prop):
'''opOnChanged(obj, prop) ... overwrite to process property changes.
@@ -239,28 +252,29 @@ class ObjectOp(object):
distinguish between assigning a different value and assigning the same
value again.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def opSetDefaultValues(self, obj, job):
'''opSetDefaultValues(obj, job) ... overwrite to set initial default values.
Called after the receiver has been fully created with all properties.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def opUpdateDepths(self, obj):
'''opUpdateDepths(obj) ... overwrite to implement special depths calculation.
Can safely be overwritten by subclass.'''
pass
pass # pylint: disable=unnecessary-pass
def opExecute(self, obj):
'''opExecute(obj) ... called whenever the receiver needs to be recalculated.
See documentation of execute() for a list of base functionality provided.
Should be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def opRejectAddBase(self, obj, base, sub):
'''opRejectAddBase(base, sub) ... if op returns True the addition of the feature is prevented.
Should be overwritten by subclasses.'''
# pylint: disable=unused-argument
return False
def onChanged(self, obj, prop):
@@ -477,7 +491,7 @@ class ObjectOp(object):
if obj.Comment:
self.commandlist.append(Path.Command("(%s)" % obj.Comment))
result = self.opExecute(obj)
result = self.opExecute(obj) # pylint: disable=assignment-from-no-return
if FeatureHeights & self.opFeatures(obj):
# Let's finish by rapid to clearance...just for safety

View File

@@ -65,13 +65,17 @@ class ViewProvider(object):
def __init__(self, vobj, resources):
PathLog.track()
vobj.Proxy = self
self.deleteOnReject = True
self.OpIcon = ":/icons/%s.svg" % resources.pixmap
self.OpName = resources.name
self.OpPageModule = resources.opPageClass.__module__
self.OpPageClass = resources.opPageClass.__name__
# initialized later
self.vobj = vobj
self.Object = None
self.panel = None
def attach(self, vobj):
PathLog.track()
self.vobj = vobj
@@ -123,6 +127,7 @@ class ViewProvider(object):
job.ViewObject.Proxy.resetEditVisibility(job)
def unsetEdit(self, arg1, arg2):
# pylint: disable=unused-argument
if self.panel:
self.panel.reject(False)
@@ -172,10 +177,12 @@ class ViewProvider(object):
self.panel.updateData(obj, prop)
def onDelete(self, vobj, arg2=None):
# pylint: disable=unused-argument
PathUtil.clearExpressionEngine(vobj.Object)
return True
def setupContextMenu(self, vobj, menu):
# pylint: disable=unused-argument
PathLog.track()
for action in menu.actions():
menu.removeAction(action)
@@ -191,12 +198,13 @@ class TaskPanelPage(object):
'''__init__(obj, features) ... framework initialisation.
Do not overwrite, implement initPage(obj) instead.'''
self.obj = obj
self.form = self.getForm()
self.form = self.getForm() # pylint: disable=assignment-from-no-return
self.signalDirtyChanged = None
self.setClean()
self.setTitle('-')
self.setIcon(None)
self.features = features
self.isdirty = False
def onDirtyChanged(self, callback):
'''onDirtyChanged(callback) ... set callback when dirty state changes.'''
@@ -251,15 +259,17 @@ class TaskPanelPage(object):
'''getTitle(obj) ... return title to be used for the receiver page.
The default implementation returns what was previously set with setTitle(title).
Can safely be overwritten by subclasses.'''
# pylint: disable=unused-argument
return self.title
def setIcon(self, icon):
'''setIcon(icon) ... sets the icon for the page.'''
self.icon = icon
def getIcon(self, icon):
'''getIcon(icon) ... return icon for page or None.
def getIcon(self, obj):
'''getIcon(obj) ... return icon for page or None.
Can safely be overwritten by subclasses.'''
# pylint: disable=unused-argument
return self.icon
# subclass interface
@@ -267,37 +277,39 @@ class TaskPanelPage(object):
'''initPage(obj) ... overwrite to customize UI for specific model.
Note that this function is invoked after all page controllers have been created.
Should be overwritten by subclasses.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
def cleanupPage(self, obj):
'''cleanupPage(obj) ... overwrite to perform any cleanup tasks before page is destroyed.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def modifyStandardButtons(self, buttonBox):
'''modifyStandardButtons(buttonBox) ... overwrite if the task panel standard buttons need to be modified.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def getForm(self):
'''getForm() ... return UI form for this page.
Must be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def getFields(self, obj):
'''getFields(obj) ... overwrite to transfer values from UI to obj's properties.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def setFields(self, obj):
'''setFields(obj) ... overwrite to transfer obj's property values to UI.
Can safely be overwritten by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def getSignalsForUpdate(self, obj):
'''getSignalsForUpdate(obj) ... return signals which, when triggered, cause the receiver to update the model.
See also registerSignalHandlers(obj)
Can safely be overwritten by subclasses.'''
# pylint: disable=unused-argument
return []
def registerSignalHandlers(self, obj):
@@ -306,7 +318,8 @@ class TaskPanelPage(object):
(see getSignalsForUpdate(obj)) this function can be used to register signal handlers
manually.
Can safely be overwritten by subclasses.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
def updateData(self, obj, prop):
'''updateData(obj, prop) ... overwrite if the receiver needs to react to property changes that might not have been caused by the receiver itself.
@@ -318,12 +331,14 @@ class TaskPanelPage(object):
This can happen if a subclass unconditionally transfers all values in getFields(obj) to the model and just calls setFields(obj) in this callback.
In such a scenario the first property assignment will cause all changes in the UI of the other fields to be overwritten by setFields(obj).
You have been warned.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
def updateSelection(self, obj, sel):
'''updateSelection(obj, sel) ... overwrite to customize UI depending on current selection.
Can safely be overwritten by subclasses.'''
pass
# pylint: disable=unused-argument
pass # pylint: disable=unnecessary-pass
# helpers
def selectInComboBox(self, name, combo):
@@ -503,6 +518,12 @@ class TaskPanelBaseLocationPage(TaskPanelPage):
DataLocation = QtCore.Qt.ItemDataRole.UserRole
def __init__(self, obj, features):
super(TaskPanelBaseLocationPage, self).__init__(obj, features)
# members initialized later
self.editRow = None
def getForm(self):
self.formLoc = FreeCADGui.PySideUic.loadUi(":/panels/PageBaseLocationEdit.ui")
if QtCore.qVersion()[0] == '4':
@@ -564,6 +585,7 @@ class TaskPanelBaseLocationPage(TaskPanelPage):
self.getPoint.getPoint(self.addLocationAt)
def addLocationAt(self, point, obj):
# pylint: disable=unused-argument
if point:
locations = self.obj.Locations
locations.append(point)
@@ -581,6 +603,7 @@ class TaskPanelBaseLocationPage(TaskPanelPage):
self.getPoint.getPoint(self.editLocationAt, start)
def editLocationAt(self, point, obj):
# pylint: disable=unused-argument
if point:
self.formLoc.baseList.item(self.editRow, 0).setData(self.DataLocation, point.x)
self.formLoc.baseList.item(self.editRow, 1).setData(self.DataLocation, point.y)
@@ -608,6 +631,14 @@ class TaskPanelBaseLocationPage(TaskPanelPage):
class TaskPanelHeightsPage(TaskPanelPage):
'''Page controller for heights.'''
def __init__(self, obj, features):
super(TaskPanelHeightsPage, self).__init__(obj, features)
# members initialized later
self.clearanceHeight = None
self.safeHeight = None
def getForm(self):
return FreeCADGui.PySideUic.loadUi(":/panels/PageHeightsEdit.ui")
@@ -639,6 +670,16 @@ class TaskPanelHeightsPage(TaskPanelPage):
class TaskPanelDepthsPage(TaskPanelPage):
'''Page controller for depths.'''
def __init__(self, obj, features):
super(TaskPanelDepthsPage, self).__init__(obj, features)
# members initialized later
self.startDepth = None
self.finalDepth = None
self.finishDepth = None
self.stepDown = None
def getForm(self):
return FreeCADGui.PySideUic.loadUi(":/panels/PageDepthsEdit.ui")
@@ -779,6 +820,15 @@ class TaskPanel(object):
self.deleteOnReject = deleteOnReject
self.featurePages = []
# members initialized later
self.clearanceHeight = None
self.safeHeight = None
self.startDepth = None
self.finishDepth = None
self.finalDepth = None
self.stepDown = None
self.buttonBox = None
features = obj.Proxy.opFeatures(obj)
opPage.features = features
@@ -897,6 +947,7 @@ class TaskPanel(object):
def pageDirtyChanged(self, page):
'''pageDirtyChanged(page) ... internal callback'''
# pylint: disable=unused-argument
self.buttonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(self.isDirty())
def clicked(self, button):
@@ -971,20 +1022,26 @@ class TaskPanel(object):
# SelectionObserver interface
def addSelection(self, doc, obj, sub, pnt):
# pylint: disable=unused-argument
self.updateSelection()
def removeSelection(self, doc, obj, sub):
# pylint: disable=unused-argument
self.updateSelection()
def setSelection(self, doc):
# pylint: disable=unused-argument
self.updateSelection()
def clearSelection(self, doc):
# pylint: disable=unused-argument
self.updateSelection()
class CommandSetStartPoint:
'''Command to set the start point for an operation.'''
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-StartPoint',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path", "Pick Start Point"),
@@ -1000,6 +1057,7 @@ class CommandSetStartPoint:
return obj and hasattr(obj, 'StartPoint')
def setpoint(self, point, o):
# pylint: disable=unused-argument
obj = FreeCADGui.Selection.getSelection()[0]
obj.StartPoint.x = point.x
obj.StartPoint.y = point.y
@@ -1017,7 +1075,7 @@ def Create(res):
FreeCAD.ActiveDocument.openTransaction("Create %s" % res.name)
obj = res.objFactory(res.name)
if obj.Proxy:
vobj = ViewProvider(obj.ViewObject, res)
obj.ViewObject.Proxy = ViewProvider(obj.ViewObject, res)
FreeCAD.ActiveDocument.commitTransaction()
obj.ViewObject.Document.setEdit(obj.ViewObject, 0)
@@ -1039,14 +1097,14 @@ class CommandPathOp:
'MenuText': self.res.menuText,
'ToolTip': self.res.toolTip}
if self.res.accelKey:
ress['Accel'] = self.res.accelKey
ress['Accel'] = self.res.accelKey
return ress
def IsActive(self):
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return True
return False
def Activated(self):

View File

@@ -192,7 +192,7 @@ def offsetWire(wire, base, offset, forward):
return Part.Wire([edge])
# if we get to this point the assumption is that makeOffset2D can deal with the edge
pass
pass # pylint: disable=unnecessary-pass
owire = orientWire(wire.makeOffset2D(offset), True)
debugWire('makeOffset2D_%d' % len(wire.Edges), owire)
@@ -204,7 +204,7 @@ def offsetWire(wire, base, offset, forward):
PathLog.track('closed - inside')
try:
owire = wire.makeOffset2D(-offset)
except Exception:
except Exception: # pylint: disable=broad-except
# most likely offsetting didn't work because the wire is a hole
# and the offset is too big - making the hole vanish
return None

View File

@@ -54,7 +54,6 @@ if LOGLEVEL:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -71,7 +70,6 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
if not hasattr(obj, 'HandleMultipleFeatures'):
obj.addProperty('App::PropertyEnumeration', 'HandleMultipleFeatures', 'Pocket', QtCore.QT_TRANSLATE_NOOP('PathPocket', 'Choose how to process multiple Base Geometry features.'))
obj.HandleMultipleFeatures = ['Collectively', 'Individually']
pass
def opOnDocumentRestored(self, obj):
'''opOnDocumentRestored(obj) ... adds the properties if they doesn't exist.'''
@@ -83,7 +81,6 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
def areaOpShapes(self, obj):
'''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
PathLog.track()
PathLog.info("----- areaOpShapes() in PathPocket.py")
removalshapes = []
if obj.Base:

View File

@@ -53,12 +53,13 @@ class ObjectPocket(PathAreaOp.ObjectOp):
return PathOp.FeatureBaseFaces | PathOp.FeatureFinishDepth | self.pocketOpFeatures(obj)
def pocketOpFeatures(self, obj):
# pylint: disable=unused-argument
return 0
def initPocketOp(self, obj):
'''initPocketOp(obj) ... overwrite to initialize subclass.
Can safely be overwritten by subclass.'''
pass
pass # pylint: disable=unnecessary-pass
def pocketInvertExtraOffset(self):
'''pocketInvertExtraOffset() ... return True if ExtraOffset's direction is inward.

View File

@@ -54,7 +54,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
FeatureFacing ... used for face milling operation
FeatureOutline ... used for pocket-shape operation
Must be overwritten by subclasses'''
pass
pass # pylint: disable=unnecessary-pass
def getForm(self):
'''getForm() ... returns UI, adapted to the results from pocketFeatures()'''

View File

@@ -21,6 +21,15 @@
# * USA *
# * *
# ***************************************************************************
# * *
# * Additional modifications and contributions beginning 2019 *
# * Focus: 4th-axis integration *
# * by Russell Johnson <russ4262@gmail.com> *
# * *
# ***************************************************************************
# SCRIPT NOTES:
# - Need test models for testing vertical faces scenarios.
import FreeCAD
import Part
@@ -51,7 +60,6 @@ if LOGLEVEL:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -88,7 +96,7 @@ def selectOffsetWire(feature, wires):
closest = None
for w in wires:
dist = feature.distToShape(w)[0]
if closest is None or dist > closest[0]:
if closest is None or dist > closest[0]: # pylint: disable=unsubscriptable-object
closest = (dist, w)
if closest is not None:
return closest[1]
@@ -128,6 +136,8 @@ class Extension(object):
self.length = length
self.direction = direction
self.wire = None
def getSubLink(self):
return "%s:%s" % (self.feature, self.sub)
@@ -220,7 +230,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
'''Proxy object for Pocket operation.'''
def areaOpFeatures(self, obj):
return super(self.__class__, self).areaOpFeatures(obj) | PathOp.FeatureLocations
return super(ObjectPocket, self).areaOpFeatures(obj) | PathOp.FeatureLocations
def initPocketOp(self, obj):
'''initPocketOp(obj) ... setup receiver'''
@@ -362,7 +372,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
if obj.Base:
PathLog.debug('Processing... obj.Base')
self.removalshapes = []
self.removalshapes = [] # pylint: disable=attribute-defined-outside-init
# ----------------------------------------------------------------------
if obj.EnableRotation == 'Off':
stock = PathUtils.findParentJob(obj).Stock
for (base, subList) in obj.Base:
@@ -379,14 +390,14 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
PathLog.info("Common Surface.Axis or normalAt() value found for loop faces.")
rtn = False
subCount += 1
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
PathLog.info("angle: {}; axis: {}".format(angle, axis))
if rtn is True:
faceNums = ""
for f in subsList:
faceNums += '_' + f.replace('Face', '')
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, faceNums)
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, faceNums) # pylint: disable=unused-variable
# Verify faces are correctly oriented - InverseAngle might be necessary
PathLog.debug("Checking if faces are oriented correctly after rotation...")
@@ -420,7 +431,6 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
for sub in subsList:
subCount += 1
if 'Face' in sub:
PathLog.debug(translate('Path', "Base Geometry sub: {}".format(sub)))
rtn = False
face = base.Shape.getElement(sub)
if type(face.Surface) == Part.SurfaceOfExtrusion:
@@ -437,7 +447,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
PathLog.error(translate("Path", "Failed to create a planar face from edges in {}.".format(sub)))
(norm, surf) = self.getFaceNormAndSurf(face)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
if rtn is True:
faceNum = sub.replace('Face', '')
@@ -445,7 +455,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
# Verify faces are correctly oriented - InverseAngle might be necessary
faceIA = clnBase.Shape.getElement(sub)
(norm, surf) = self.getFaceNormAndSurf(faceIA)
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
if rtn is True:
PathLog.debug("Face not aligned after initial rotation.")
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
@@ -471,8 +481,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
PathLog.error(translate('Path', "Selected feature is not a Face. Ignoring: {}".format(ignoreSub)))
for o in baseSubsTuples:
self.horiz = []
self.vert = []
self.horiz = [] # pylint: disable=attribute-defined-outside-init
self.vert = [] # pylint: disable=attribute-defined-outside-init
subBase = o[0]
subsList = o[1]
angle = o[2]
@@ -494,8 +504,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
if vFace.BoundBox.ZMin > vFinDep:
vFinDep = vFace.BoundBox.ZMin
# Determine if vertical faces for a loop: Extract planar loop wire as new horizontal face.
self.vertical = PathGeom.combineConnectedShapes(self.vert)
self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical]
self.vertical = PathGeom.combineConnectedShapes(self.vert) # pylint: disable=attribute-defined-outside-init
self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical] # pylint: disable=attribute-defined-outside-init
for wire in self.vWires:
w = PathGeom.removeDuplicateEdges(wire)
face = Part.Face(w)
@@ -514,7 +524,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
self.guiMessage(title, msg, False)
# add faces for extensions
self.exts = []
self.exts = [] # pylint: disable=attribute-defined-outside-init
for ext in self.getExtensions(obj):
wire = ext.getWire()
if wire:
@@ -528,7 +538,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
f.translate(FreeCAD.Vector(0, 0, finDep - f.BoundBox.ZMin))
# check all faces and see if they are touching/overlapping and combine those into a compound
self.horizontal = []
self.horizontal = [] # pylint: disable=attribute-defined-outside-init
for shape in PathGeom.combineConnectedShapes(self.horiz):
shape.sewShape()
# shape.tessellate(0.1)
@@ -558,18 +568,18 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
PathLog.debug(translate("Path", 'Processing model as a whole ...'))
finDep = obj.FinalDepth.Value
strDep = obj.StartDepth.Value
self.outlines = [Part.Face(TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1))) for base in self.model]
self.outlines = [Part.Face(TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1))) for base in self.model] # pylint: disable=attribute-defined-outside-init
stockBB = self.stock.Shape.BoundBox
self.removalshapes = []
self.bodies = []
self.removalshapes = [] # pylint: disable=attribute-defined-outside-init
self.bodies = [] # pylint: disable=attribute-defined-outside-init
for outline in self.outlines:
outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
body = outline.extrude(FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
self.bodies.append(body)
self.removalshapes.append((self.stock.Shape.cut(body), False, 'pathPocketShape', 0.0, 'X', strDep, finDep))
for (shape, hole, sub, angle, axis, strDep, finDep) in self.removalshapes:
for (shape, hole, sub, angle, axis, strDep, finDep) in self.removalshapes: # pylint: disable=unused-variable
shape.tessellate(0.05) # originally 0.1
if self.removalshapes:
@@ -682,7 +692,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
if PathGeom.isRoughly(0, saSum.y):
if PathGeom.isRoughly(0, saSum.z):
PathLog.debug("Combined subs suggest loop of faces. Checking ...")
go is True
go = True
if go is True:
lastExtrusion = None
@@ -717,7 +727,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
rnded = FreeCAD.Vector(roundValue(precision, raw.x), roundValue(precision, raw.y), roundValue(precision, raw.z))
if rnded.x == 0.0 or rnded.y == 0.0 or rnded.z == 0.0:
for fc2 in tmpExt.Shape.Faces:
(norm2, raw2) = self.getFaceNormAndSurf(fc2)
(norm2, raw2) = self.getFaceNormAndSurf(fc2) # pylint: disable=unused-variable
rnded2 = FreeCAD.Vector(roundValue(precision, raw2.x), roundValue(precision, raw2.y), roundValue(precision, raw2.z))
if rnded == rnded2:
matchList.append(fc2)
@@ -778,7 +788,7 @@ def SetupProperties():
return setup
def Create(name, obj = None):
def Create(name, obj=None):
'''Create(name) ... Creates and returns a Pocket operation.'''
if obj is None:
obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', name)

View File

@@ -139,8 +139,6 @@ class _Extension(object):
def deselect(self):
self.material.transparency = self.TransparencyDeselected
Page = None
class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
DataObject = QtCore.Qt.ItemDataRole.UserRole
DataSwitch = QtCore.Qt.ItemDataRole.UserRole + 2
@@ -153,18 +151,18 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
def initPage(self, obj):
self.setTitle("Extensions")
self.extensions = obj.Proxy.getExtensions(obj)
self.extensions = obj.Proxy.getExtensions(obj) # pylint: disable=attribute-defined-outside-init
self.defaultLength = PathGui.QuantitySpinBox(self.form.defaultLength, obj, 'ExtensionLengthDefault')
self.defaultLength = PathGui.QuantitySpinBox(self.form.defaultLength, obj, 'ExtensionLengthDefault') # pylint: disable=attribute-defined-outside-init
self.form.extensionTree.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.form.extensionTree.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.switch = coin.SoSwitch()
self.switch = coin.SoSwitch() # pylint: disable=attribute-defined-outside-init
self.obj.ViewObject.RootNode.addChild(self.switch)
self.switch.whichChild = coin.SO_SWITCH_ALL
self.model = QtGui.QStandardItemModel(self.form.extensionTree)
self.model = QtGui.QStandardItemModel(self.form.extensionTree) # pylint: disable=attribute-defined-outside-init
self.model.setHorizontalHeaderLabels(['Base', 'Extension'])
if 0 < len(obj.ExtensionFeature):
@@ -172,10 +170,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
else:
self.form.showExtensions.setCheckState(QtCore.Qt.Unchecked)
self.blockUpdateData = False
global Page
Page = self
self.blockUpdateData = False # pylint: disable=attribute-defined-outside-init
def cleanupPage(self, obj):
# If the object was already destroyed we can't access obj.Name.
@@ -196,7 +191,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
for modelRow in range(self.model.rowCount()):
model = self.model.item(modelRow, 0)
for featureRow in range(model.rowCount()):
feature = model.child(featureRow, 0);
feature = model.child(featureRow, 0)
for edgeRow in range(feature.rowCount()):
item = feature.child(edgeRow, 0)
ext = item.data(self.DataObject)
@@ -212,19 +207,19 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
return extensions
def updateProxyExtensions(self, obj):
self.extensions = self.currentExtensions()
self.extensions = self.currentExtensions() # pylint: disable=attribute-defined-outside-init
obj.Proxy.setExtensions(obj, self.extensions)
def getFields(self, obj):
PathLog.track(obj.Label, self.model.rowCount(), self.model.columnCount())
self.blockUpdateData = True
self.blockUpdateData = True # pylint: disable=attribute-defined-outside-init
if obj.ExtensionCorners != self.form.extendCorners.isChecked():
obj.ExtensionCorners = self.form.extendCorners.isChecked()
self.defaultLength.updateProperty()
self.updateProxyExtensions(obj)
self.blockUpdateData = False
self.blockUpdateData = False # pylint: disable=attribute-defined-outside-init
def setFields(self, obj):
PathLog.track(obj.Label)
@@ -232,7 +227,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
if obj.ExtensionCorners != self.form.extendCorners.isChecked():
self.form.extendCorners.toggle()
self.defaultLength.updateSpinBox()
self.extensions = obj.Proxy.getExtensions(obj)
self.extensions = obj.Proxy.getExtensions(obj) # pylint: disable=attribute-defined-outside-init
self.setExtensions(self.extensions)
def createItemForBaseModel(self, base, sub, edges, extensions):
@@ -273,13 +268,13 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
def edgesMatchShape(e0, e1):
return PathGeom.edgesMatch(e0, e1) or PathGeom.edgesMatch(e0, PathGeom.flipEdge(e1))
self.extensionEdges = extensionEdges
self.extensionEdges = extensionEdges # pylint: disable=attribute-defined-outside-init
for edgeList in Part.sortEdges(list(extensionEdges.keys())):
self.edgeList = edgeList
self.edgeList = edgeList # pylint: disable=attribute-defined-outside-init
if len(edgeList) == 1:
label = "Edge%s" % [extensionEdges[keyEdge] for keyEdge in extensionEdges.keys() if edgesMatchShape(keyEdge, edgeList[0])][0]
else:
label = "Wire(%s)" % ','.join(sorted([extensionEdges[keyEdge] for e in edgeList for keyEdge in extensionEdges.keys() if edgesMatchShape(e, keyEdge)], key=lambda s: int(s)))
label = "Wire(%s)" % ','.join(sorted([extensionEdges[keyEdge] for e in edgeList for keyEdge in extensionEdges.keys() if edgesMatchShape(e, keyEdge)], key=lambda s: int(s))) # pylint: disable=unnecessary-lambda
ext0 = _Extension(self.obj, base, sub, label)
createSubItem(label, ext0)
@@ -302,12 +297,13 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
if not self.form.extensionTree.isExpanded(model.index()):
collapsedModels.append(modelName)
for featureRow in range(model.rowCount()):
feature = model.child(featureRow, 0);
feature = model.child(featureRow, 0)
if not self.form.extensionTree.isExpanded(feature.index()):
collapsedFeatures.append("%s.%s" % (modelName, feature.data(QtCore.Qt.EditRole)))
# remove current extensions and all their visuals
def removeItemSwitch(item, ext):
# pylint: disable=unused-argument
ext.hide()
self.switch.removeChild(ext.root)
self.forAllItemsCall(removeItemSwitch)
@@ -334,7 +330,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
if modelName in collapsedModels:
self.form.extensionTree.setExpanded(model.index(), False)
for featureRow in range(model.rowCount()):
feature = model.child(featureRow, 0);
feature = model.child(featureRow, 0)
featureName = "%s.%s" % (modelName, feature.data(QtCore.Qt.EditRole))
if featureName in collapsedFeatures:
self.form.extensionTree.setExpanded(feature.index(), False)
@@ -369,6 +365,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
FreeCADGui.Selection.clearSelection()
def selectItem(item, ext):
# pylint: disable=unused-argument
for sel in selection:
if ext.base == sel.obj and ext.edge == sel.sub:
return True
@@ -431,6 +428,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
def showHideExtension(self):
if self.form.showExtensions.isChecked():
def enableExtensionEdit(item, ext):
# pylint: disable=unused-argument
ext.show()
self.forAllItemsCall(enableExtensionEdit)
else:
@@ -461,7 +459,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
self.model.itemChanged.connect(self.updateItemEnabled)
self.selectionModel = self.form.extensionTree.selectionModel()
self.selectionModel = self.form.extensionTree.selectionModel() # pylint: disable=attribute-defined-outside-init
self.selectionModel.selectionChanged.connect(self.selectionChanged)
self.selectionChanged()
@@ -474,7 +472,7 @@ class TaskPanelOpPage(PathPocketBaseGui.TaskPanelOpPage):
def taskPanelBaseLocationPage(self, obj, features):
if not hasattr(self, 'extensionsPanel'):
self.extensionsPanel = TaskPanelExtensionPage(obj, features)
self.extensionsPanel = TaskPanelExtensionPage(obj, features) # pylint: disable=attribute-defined-outside-init
return self.extensionsPanel
def pageRegisterSignalHandlers(self):

View File

@@ -50,15 +50,17 @@ def translate(context, text, disambig=None):
class _TempObject:
Path = None
Name = "Fixture"
InList = []
Label = "Fixture"
# pylint: disable=no-init
Path = None
Name = "Fixture"
InList = []
Label = "Fixture"
class DlgSelectPostProcessor:
def __init__(self, parent=None):
# pylint: disable=unused-argument
self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgSelectPostProcessor.ui")
firstItem = None
for post in PathPreferences.allEnabledPostProcessors():
@@ -93,6 +95,7 @@ class DlgSelectPostProcessor:
class CommandPathPost:
# pylint: disable=no-init
subpart = 1
def resolveFileName(self, job):
@@ -188,7 +191,7 @@ class CommandPathPost:
return False
def exportObjectsWith(self, objs, job, needFilename=True, filepart=None):
def exportObjectsWith(self, objs, job, needFilename=True):
PathLog.track()
# check if the user has a project and has set the default post and
# output filename
@@ -234,7 +237,7 @@ class CommandPathPost:
elif hasattr(sel, "Path"):
try:
job = PathUtils.findParentJob(sel)
except Exception:
except Exception: # pylint: disable=broad-except
job = None
else:
job = None
@@ -378,7 +381,7 @@ class CommandPathPost:
postlist.append(sublist)
fail = True
rc = ''
rc = '' # pylint: disable=unused-variable
if split:
for slist in postlist:
(fail, rc) = self.exportObjectsWith(slist, job)

View File

@@ -22,7 +22,6 @@
# * *
# ***************************************************************************
import FreeCAD
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferences as PathPreferences
import sys
@@ -47,7 +46,7 @@ class PostProcessor:
namespace = {}
#can't modify function local scope with exec in python3
exec("import %s as current_post" % postname, namespace)
exec("import %s as current_post" % postname, namespace) # pylint: disable=exec-used
current_post = namespace['current_post']
# make sure the script is reloaded if it was previously loaded
@@ -56,40 +55,34 @@ class PostProcessor:
# resulting in 2 load messages if the script outputs one of those.
try:
# Python 2.7
exec("reload(%s)" % 'current_post')
exec("reload(%s)" % 'current_post') # pylint: disable=exec-used
except NameError:
# Python 3.4+
from importlib import reload
exec("reload(%s)" % 'current_post')
from importlib import reload # pylint: disable=redefined-builtin,unused-import
exec("reload(%s)" % 'current_post') # pylint: disable=exec-used
sys.path = syspath
instance = PostProcessor(current_post)
instance.units = None
if hasattr(current_post, "UNITS"):
if current_post.UNITS == "G21":
instance.units = "Metric"
else:
instance.units = "Inch"
instance.machineName = None
if hasattr(current_post, "MACHINE_NAME"):
instance.machineName = current_post.MACHINE_NAME
instance.cornerMax = None
if hasattr(current_post, "CORNER_MAX"):
instance.cornerMax = {'x': current_post.CORNER_MAX['x'],
'y': current_post.CORNER_MAX['y'],
'z': current_post.CORNER_MAX['z']}
instance.cornerMin = None
if hasattr(current_post, "CORNER_MIN"):
instance.cornerMin = {'x': current_post.CORNER_MIN['x'],
'y': current_post.CORNER_MIN['y'],
'z': current_post.CORNER_MIN['z']}
instance.tooltip = None
instance.tooltipArgs = None
if hasattr(current_post, "TOOLTIP"):
instance.tooltip = current_post.TOOLTIP
if hasattr(current_post, "TOOLTIP_ARGS"):
@@ -98,6 +91,12 @@ class PostProcessor:
def __init__(self, script):
self.script = script
self.tooltip = None
self.tooltipArgs = None
self.cornerMax = None
self.cornerMin = None
self.units = None
self.machineName = None
def export(self, obj, filename, args):
return self.script.export(obj, filename, args)

View File

@@ -118,10 +118,10 @@ def defaultJobTemplate():
return template
return ''
def setJobDefaults(filePath, jobTemplate, geometryTolerance, curveAccuracy):
PathLog.track("(%s='%s', %s, %s, %s)" % (DefaultFilePath, filePath, jobTemplate, geometryTolerance, curveAccuracy))
def setJobDefaults(fileName, jobTemplate, geometryTolerance, curveAccuracy):
PathLog.track("(%s='%s', %s, %s, %s)" % (DefaultFilePath, fileName, jobTemplate, geometryTolerance, curveAccuracy))
pref = preferences()
pref.SetString(DefaultFilePath, filePath)
pref.SetString(DefaultFilePath, fileName)
pref.SetString(DefaultJobTemplate, jobTemplate)
pref.SetFloat(GeometryTolerance, geometryTolerance)
pref.SetFloat(LibAreaCurveAccuracy, curveAccuracy)
@@ -131,7 +131,7 @@ def postProcessorBlacklist():
blacklist = pref.GetString(PostProcessorBlacklist, "")
if not blacklist:
return []
return eval(blacklist)
return eval(blacklist) # pylint: disable=eval-used
def setPostProcessorDefaults(processor, args, blacklist):
pref = preferences()
@@ -140,9 +140,9 @@ def setPostProcessorDefaults(processor, args, blacklist):
pref.SetString(PostProcessorBlacklist, "%s" % (blacklist))
def setOutputFileDefaults(file, policy):
def setOutputFileDefaults(fileName, policy):
pref = preferences()
pref.SetString(PostProcessorOutputFile, file)
pref.SetString(PostProcessorOutputFile, fileName)
pref.SetString(PostProcessorOutputPolicy, policy)
def defaultOutputFile():
@@ -164,9 +164,4 @@ def setDefaultTaskPanelLayout(style):
preferences().SetInt(DefaultTaskPanelLayout, style)
def experimentalFeaturesEnabled():
try:
import ocl
return preferences().GetBool(EnableExperimentalFeatures, False)
except ImportError:
FreeCAD.Console.PrintError("OpenCamLib is not working!\n")
return False
return preferences().GetBool(EnableExperimentalFeatures, False)

View File

@@ -22,9 +22,6 @@
# * *
# ***************************************************************************
import FreeCAD
import PathScripts.PathPreferences as PathPreferences
from PySide import QtCore, QtGui
# Qt translation handling
@@ -38,6 +35,7 @@ def RegisterDressup(dressup):
class DressupPreferencesPage:
def __init__(self, parent=None):
# pylint: disable=unused-argument
self.form = QtGui.QToolBox()
self.form.setWindowTitle(translate("Path_PreferencesPathDressup", 'Dressups'))
pages = []

View File

@@ -39,6 +39,7 @@ PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
class JobPreferencesPage:
def __init__(self, parent=None):
# pylint: disable=unused-argument
import FreeCADGui
self.form = FreeCADGui.PySideUic.loadUi(":preferences/PathJob.ui")
self.form.toolBox.setCurrentIndex(0) # Take that qt designer!

View File

@@ -33,8 +33,6 @@ import PathScripts.PathUtils as PathUtils
from DraftGeomUtils import findWires
from PySide import QtCore
"""Path Profile from Edges Object and Command"""
LOGLEVEL = False
if LOGLEVEL:
@@ -79,11 +77,14 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
if obj.Base:
basewires = []
zMin = None
for b in obj.Base:
edgelist = []
for sub in b[1]:
edgelist.append(getattr(b[0].Shape, sub))
basewires.append((b[0], findWires(edgelist)))
if zMin is None or b[0].Shape.BoundBox.ZMin < zMin:
zMin = b[0].Shape.BoundBox.ZMin
for base,wires in basewires:
for wire in wires:
@@ -91,7 +92,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
# shift the compound to the bottom of the base object for
# proper sectioning
zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin
zShift = zMin - f.BoundBox.ZMin
newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation)
f.Placement = newPlace
env = PathUtils.getEnvelope(base.Shape, subshape=f, depthparams=self.depthparams)

View File

@@ -100,15 +100,9 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
self.baseObject().initAreaOp(obj)
def opOnDocumentRestored(self, obj):
'''opOnDocumentRestored(obj) ... adds the properties if they doesn't exist.'''
# self.initAreaOp(obj)
pass
def areaOpShapes(self, obj):
'''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
PathLog.track()
PathLog.info("----- areaOpShapes() in PathProfileFaces.py")
if obj.UseComp:
self.commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
@@ -116,9 +110,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
self.commandlist.append(Path.Command("(Uncompensated Tool Path)"))
shapes = []
self.profileshape = []
startDepths = []
faceDepths = []
self.profileshape = [] # pylint: disable=attribute-defined-outside-init
baseSubsTuples = []
subCount = 0
@@ -134,13 +126,13 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
if isinstance(shape, Part.Face):
rtn = False
(norm, surf) = self.getFaceNormAndSurf(shape)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
if rtn is True:
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, subCount)
# Verify faces are correctly oriented - InverseAngle might be necessary
faceIA = getattr(clnBase.Shape, sub)
(norm, surf) = self.getFaceNormAndSurf(faceIA)
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
if rtn is True:
PathLog.error(translate("Path", "Face appears misaligned after initial rotation."))
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
@@ -212,7 +204,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
startDepths.append(strDep)
# Recalculate depthparams
self.depthparams = PathUtils.depth_params(
self.depthparams = PathUtils.depth_params( # pylint: disable=attribute-defined-outside-init
clearance_height=obj.ClearanceHeight.Value,
safe_height=obj.SafeHeight.Value,
start_depth=strDep, # obj.StartDepth.Value,
@@ -240,7 +232,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
PathLog.track()
try:
env = PathUtils.getEnvelope(base.Shape, subshape=profileshape, depthparams=self.depthparams)
except Exception:
except Exception: # pylint: disable=broad-except
# PathUtils.getEnvelope() failed to return an object.
PathLog.error(translate('Path', 'Unable to create path for face(s).'))
else:
@@ -296,7 +288,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
tup = env, False, 'pathProfileFaces', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value
shapes.append(tup)
self.removalshapes = shapes
self.removalshapes = shapes # pylint: disable=attribute-defined-outside-init
PathLog.debug("%d shapes" % len(shapes))
return shapes

View File

@@ -35,22 +35,25 @@ if LOGLEVEL:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
class PathBaseGate(object):
# pylint: disable=no-init
pass
class EGate:
def allow(self, doc, obj, sub):
class EGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
return sub and sub[0:4] == 'Edge'
class MESHGate:
def allow(self, doc, obj, sub):
class MESHGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
return obj.TypeId[0:4] == 'Mesh'
class ENGRAVEGate:
def allow(self, doc, obj, sub):
class ENGRAVEGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
try:
shape = obj.Shape
except Exception:
except Exception: # pylint: disable=broad-except
return False
if math.fabs(shape.Volume) < 1e-9 and len(shape.Wires) > 0:
@@ -66,11 +69,11 @@ class ENGRAVEGate:
return False
class CHAMFERGate:
def allow(self, doc, obj, sub):
class CHAMFERGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
try:
shape = obj.Shape
except Exception:
except Exception: # pylint: disable=broad-except
return False
if math.fabs(shape.Volume) < 1e-9 and len(shape.Wires) > 0:
@@ -88,8 +91,8 @@ class CHAMFERGate:
return False
class DRILLGate:
def allow(self, doc, obj, sub):
class DRILLGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
PathLog.debug('obj: {} sub: {}'.format(obj, sub))
if hasattr(obj, "Shape") and sub:
shape = obj.Shape
@@ -99,13 +102,13 @@ class DRILLGate:
return False
class PROFILEGate:
def allow(self, doc, obj, sub):
class PROFILEGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
profileable = False
try:
obj = obj.Shape
except Exception:
except Exception: # pylint: disable=broad-except
return False
if obj.ShapeType == 'Edge':
@@ -134,13 +137,13 @@ class PROFILEGate:
return profileable
class POCKETGate:
def allow(self, doc, obj, sub):
class POCKETGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
pocketable = False
try:
obj = obj.Shape
except Exception:
except Exception: # pylint: disable=broad-except
return False
if obj.ShapeType == 'Edge':
@@ -159,19 +162,19 @@ class POCKETGate:
return pocketable
class ADAPTIVEGate:
def allow(self, doc, obj, sub):
class ADAPTIVEGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
adaptive = True
try:
obj = obj.Shape
except Exception:
except Exception: # pylint: disable=broad-except
return False
return adaptive
class CONTOURGate:
def allow(self, doc, obj, sub):
class CONTOURGate(PathBaseGate):
def allow(self, doc, obj, sub): # pylint: disable=unused-argument
pass
def contourselect():

View File

@@ -48,6 +48,8 @@ def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
class Template:
# pylint: disable=no-init
HorizRapid = 'HorizRapid'
VertRapid = 'VertRapid'
SafeHeightOffset = 'SafeHeightOffset'
@@ -259,9 +261,9 @@ class SetupSheet:
propName = OpPropertyName(opName, prop)
if hasattr(self.obj, propName):
setattr(obj, prop, getattr(self.obj, propName))
except Exception:
except Exception: # pylint: disable=broad-except
PathLog.info("SetupSheet has no support for {}".format(opName))
#traceback.print_exc(exc)
#traceback.print_exc()
def Create(name = 'SetupSheet'):
obj = FreeCAD.ActiveDocument.addObject('App::FeaturePython', name)
@@ -283,7 +285,7 @@ class _RegisteredOp(object):
return ptt
def RegisterOperation(name, objFactory, setupProperties):
global _RegisteredOps
global _RegisteredOps # pylint: disable=global-statement
_RegisteredOps[name] = _RegisteredOp(objFactory, setupProperties)
def OpNamePrefix(name):

View File

@@ -60,6 +60,8 @@ class ViewProvider:
vobj.Proxy = self
self.icon = name
# mode = 2
self.obj = None
self.vobj = None
def attach(self, vobj):
PathLog.track()
@@ -73,12 +75,15 @@ class ViewProvider:
return None
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
def getDisplayMode(self, mode):
# pylint: disable=unused-argument
return 'Default'
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
PathLog.track()
taskPanel = TaskPanel(vobj)
FreeCADGui.Control.closeDialog()
@@ -87,6 +92,7 @@ class ViewProvider:
return True
def unsetEdit(self, vobj, mode):
# pylint: disable=unused-argument
FreeCADGui.Control.closeDialog()
return
@@ -105,6 +111,7 @@ class Delegate(QtGui.QStyledItemDelegate):
# #PathLog.track(index.column(), type(option))
def createEditor(self, parent, option, index):
# pylint: disable=unused-argument
if index.data(self.EditorRole) is None:
editor = PathSetupSheetOpPrototypeGui.Editor(index.data(self.PropertyRole))
index.model().setData(index, editor, self.EditorRole)
@@ -115,12 +122,14 @@ class Delegate(QtGui.QStyledItemDelegate):
index.data(self.EditorRole).setEditorData(widget)
def setModelData(self, widget, model, index):
# pylint: disable=unused-argument
PathLog.track(index.row(), index.column())
editor = index.data(self.EditorRole)
editor.setModelData(widget)
index.model().setData(index, editor.prop.displayString(), QtCore.Qt.DisplayRole)
def updateEditorGeometry(self, widget, option, index):
# pylint: disable=unused-argument
widget.setGeometry(option.rect)
class OpTaskPanel:
@@ -143,7 +152,12 @@ class OpTaskPanel:
self.props = sorted(op.properties())
self.prototype = op.prototype(name)
# initialized later
self.delegate = None
self.model = None
def updateData(self, topLeft, bottomRight):
# pylint: disable=unused-argument
if 0 == topLeft.column():
isset = self.model.item(topLeft.row(), 0).checkState() == QtCore.Qt.Checked
self.model.item(topLeft.row(), 1).setEnabled(isset)
@@ -217,7 +231,7 @@ class OpsDefaultEditor:
def __init__(self, obj, form):
self.form = form
self.obj = obj
self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key = lambda op: op.name)
self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key = lambda op: op.name) # pylint: disable=protected-access
if form:
parent = form.tabOpDefaults
for op in self.ops:
@@ -276,6 +290,12 @@ class GlobalEditor(object):
self.form = form
self.obj = obj
# initialized later
self.clearanceHeightOffs = None
self.safeHeightOffs = None
self.rapidHorizontal = None
self.rapidVertical = None
def reject(self):
pass

View File

@@ -90,9 +90,9 @@ class PropertyEnumeration(Property):
def setValue(self, value):
if list == type(value):
self.enums = value
self.enums = value # pylint: disable=attribute-defined-outside-init
else:
super(self.__class__, self).setValue(value)
super(PropertyEnumeration, self).setValue(value)
def getEnumValues(self):
return self.enums
@@ -167,7 +167,7 @@ class OpPrototype(object):
if name in ['Label', 'DoNotSetDefaultValues', 'properties', 'Proxy']:
if name == 'Proxy':
val = None # make sure the proxy is never set
return super(self.__class__, self).__setattr__(name, val)
return super(OpPrototype, self).__setattr__(name, val)
self.properties[name].setValue(val)
def addProperty(self, typeString, name, category, info = None):

View File

@@ -53,23 +53,23 @@ class _PropertyEditor(object):
def widget(self, parent):
'''widget(parent) ... called by the delegate to get a new editor widget.
Must be implemented by subclasses and return the widget.'''
pass
pass # pylint: disable=unnecessary-pass
def setEditorData(self, widget):
'''setEditorData(widget) ... called by the delegate to initialize the editor.
The widget is the object returned by widget().
Must be implemented by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
def setModelData(self, widget):
'''setModelData(widget) ... called by the delegate to store new values.
Must be implemented by subclasses.'''
pass
pass # pylint: disable=unnecessary-pass
class _PropertyEnumEditor(_PropertyEditor):
'''Editor for enumeration values - uses a combo box.'''
def widget(self, parent):
PathLog.track(self.prop.name, self.prop.getEnumValues())
return QtGui.QComboBox(parent);
return QtGui.QComboBox(parent)
def setEditorData(self, widget):
widget.clear()

View File

@@ -44,6 +44,8 @@ def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class StockType:
# pylint: disable=no-init
NoStock = 'None'
FromBase = 'FromBase'
CreateBox = 'CreateBox'
@@ -121,6 +123,12 @@ class StockFromBase(Stock):
PathLog.track(obj.Label, base.Label)
obj.Proxy = self
# debugging aids
self.origin = None
self.length = None
self.width = None
self.height = None
def __getstate__(self):
return None
def __setstate__(self, state):

View File

@@ -43,6 +43,8 @@ def translate(context, text, disambig=None):
class ToolControllerTemplate:
'''Attribute and sub element strings for template export/import.'''
# pylint: disable=no-init
Expressions = 'xengine'
ExprExpr = 'expr'
ExprProp = 'prop'

View File

@@ -41,6 +41,7 @@ class ViewProvider:
def __init__(self, vobj):
vobj.Proxy = self
self.vobj = vobj
def attach(self, vobj):
mode = 2
@@ -65,6 +66,7 @@ class ViewProvider:
return ":/icons/Path-ToolController.svg"
def onChanged(self, vobj, prop):
# pylint: disable=unused-argument
mode = 2
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
@@ -74,11 +76,13 @@ class ViewProvider:
vobj.setEditorMode('Selectable', mode)
def onDelete(self, vobj, args=None):
# pylint: disable=unused-argument
PathUtil.clearExpressionEngine(vobj.Object)
return True
def updateData(self, vobj, prop):
# this is executed when a property of the APP OBJECT changes
# pylint: disable=unused-argument
pass
def setEdit(self, vobj=None, mode=0):
@@ -97,9 +101,11 @@ class ViewProvider:
def unsetEdit(self, vobj, mode):
# this is executed when the user cancels or terminates edit mode
# pylint: disable=unused-argument
return False
def setupContextMenu(self, vobj, menu):
# pylint: disable=unused-argument
PathLog.track()
for action in menu.actions():
menu.removeAction(action)
@@ -115,7 +121,9 @@ def Create(name = 'Default Tool', tool=None, toolNumber=1):
return obj
class CommandPathToolController:
class CommandPathToolController(object):
# pylint: disable=no-init
def GetResources(self):
return {'Pixmap': 'Path-LengthOffset',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolController", "Add Tool Controller to the Job"),
@@ -125,14 +133,14 @@ class CommandPathToolController:
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return True
return False
def Activated(self):
PathLog.track()
Create()
class ToolControllerEditor:
class ToolControllerEditor(object):
def __init__(self, obj, asDialog):
self.form = FreeCADGui.PySideUic.loadUi(":/panels/DlgToolControllerEdit.ui")
@@ -177,7 +185,7 @@ class ToolControllerEditor:
self.editor.updateTool()
tc.Tool = self.editor.tool
except Exception as e:
except Exception as e: # pylint: disable=broad-except
PathLog.error(translate("PathToolController", "Error updating TC: %s") % e)
@@ -235,10 +243,12 @@ class TaskPanel:
self.toolrep.Shape = t
def edit(self, item, column):
# pylint: disable=unused-argument
if not self.updating:
self.resetObject()
def resetObject(self, remove=None):
# pylint: disable=unused-argument
"transfers the values from the widget to the object"
FreeCAD.ActiveDocument.recompute()

View File

@@ -149,12 +149,12 @@ class ToolEditorImage(object):
class ToolEditorEndmill(ToolEditorImage):
'''Tool parameter editor for endmills.'''
def __init__(self, editor):
super(self.__class__, self).__init__(editor, 'endmill.svg', 'da', 'S')
super(ToolEditorEndmill, self).__init__(editor, 'endmill.svg', 'da', 'S')
class ToolEditorDrill(ToolEditorImage):
'''Tool parameter editor for drills.'''
def __init__(self, editor):
super(self.__class__, self).__init__(editor, 'drill.svg', 'dS', '')
super(ToolEditorDrill, self).__init__(editor, 'drill.svg', 'dS', '')
def quantityCuttingEdgeAngle(self, propertyToDisplay):
if propertyToDisplay:
@@ -164,7 +164,7 @@ class ToolEditorDrill(ToolEditorImage):
class ToolEditorEngrave(ToolEditorImage):
'''Tool parameter editor for v-bits.'''
def __init__(self, editor):
super(self.__class__, self).__init__(editor, 'v-bit.svg', '', 'HS')
super(ToolEditorEngrave, self).__init__(editor, 'v-bit.svg', '', 'HS')
def quantityCuttingEdgeHeight(self, propertyToDisplay):
PathLog.track()

View File

@@ -49,33 +49,34 @@ class FreeCADTooltableHandler(xml.sax.ContentHandler):
# http://www.tutorialspoint.com/python/python_xml_processing.htm
def __init__(self):
xml.sax.ContentHandler.__init__(self)
self.tooltable = None
self.tool = None
self.number = None
# Call when an element is found
def startElement(self, tag, attributes):
if tag == "Tooltable":
def startElement(self, name, attrs):
if name == "Tooltable":
self.tooltable = Path.Tooltable()
elif tag == "Toolslot":
self.number = int(attributes["number"])
elif tag == "Tool":
elif name == "Toolslot":
self.number = int(attrs["number"])
elif name == "Tool":
self.tool = Path.Tool()
self.tool.Name = str(attributes["name"])
self.tool.ToolType = str(attributes["type"])
self.tool.Material = str(attributes["mat"])
self.tool.Name = str(attrs["name"])
self.tool.ToolType = str(attrs["type"])
self.tool.Material = str(attrs["mat"])
# for some reason without the following line I get an error
#print attributes["diameter"]
self.tool.Diameter = float(attributes["diameter"])
self.tool.LengthOffset = float(attributes["length"])
self.tool.FlatRadius = float(attributes["flat"])
self.tool.CornerRadius = float(attributes["corner"])
self.tool.CuttingEdgeAngle = float(attributes["angle"])
self.tool.CuttingEdgeHeight = float(attributes["height"])
#print attrs["diameter"]
self.tool.Diameter = float(attrs["diameter"])
self.tool.LengthOffset = float(attrs["length"])
self.tool.FlatRadius = float(attrs["flat"])
self.tool.CornerRadius = float(attrs["corner"])
self.tool.CuttingEdgeAngle = float(attrs["angle"])
self.tool.CuttingEdgeHeight = float(attrs["height"])
# Call when an elements ends
def endElement(self, tag):
if tag == "Toolslot":
def endElement(self, name):
if name == "Toolslot":
if self.tooltable and self.tool and self.number:
self.tooltable.setTool(self.number, self.tool)
self.number = None
@@ -85,18 +86,19 @@ class FreeCADTooltableHandler(xml.sax.ContentHandler):
class HeeksTooltableHandler(xml.sax.ContentHandler):
def __init__(self):
xml.sax.ContentHandler.__init__(self)
self.tooltable = Path.Tooltable()
self.tool = None
self.number = None
# Call when an element is found
def startElement(self, tag, attributes):
if tag == "Tool":
def startElement(self, name, attrs):
if name == "Tool":
self.tool = Path.Tool()
self.number = int(attributes["tool_number"])
self.tool.Name = str(attributes["title"])
elif tag == "params":
t = str(attributes["type"])
self.number = int(attrs["tool_number"])
self.tool.Name = str(attrs["title"])
elif name == "params":
t = str(attrs["type"])
if t == "drill":
self.tool.ToolType = "Drill"
elif t == "center_drill_bit":
@@ -111,25 +113,25 @@ class HeeksTooltableHandler(xml.sax.ContentHandler):
self.tool.ToolType = "Chamfer"
elif t == "engraving_bit":
self.tool.ToolType = "Engraver"
m = str(attributes["material"])
m = str(attrs["material"])
if m == "0":
self.tool.Material = "HighSpeedSteel"
elif m == "1":
self.tool.Material = "Carbide"
# for some reason without the following line I get an error
#print attributes["diameter"]
self.tool.Diameter = float(attributes["diameter"])
self.tool.LengthOffset = float(attributes["tool_length_offset"])
self.tool.FlatRadius = float(attributes["flat_radius"])
self.tool.CornerRadius = float(attributes["corner_radius"])
#print attrs["diameter"]
self.tool.Diameter = float(attrs["diameter"])
self.tool.LengthOffset = float(attrs["tool_length_offset"])
self.tool.FlatRadius = float(attrs["flat_radius"])
self.tool.CornerRadius = float(attrs["corner_radius"])
self.tool.CuttingEdgeAngle = float(
attributes["cutting_edge_angle"])
attrs["cutting_edge_angle"])
self.tool.CuttingEdgeHeight = float(
attributes["cutting_edge_height"])
attrs["cutting_edge_height"])
# Call when an elements ends
def endElement(self, tag):
if tag == "Tool":
def endElement(self, name):
if name == "Tool":
if self.tooltable and self.tool and self.number:
self.tooltable.setTool(self.number, self.tool)
self.number = None
@@ -286,7 +288,7 @@ class ToolLibraryManager():
if listname == "<Main>":
self.saveMainLibrary(tt)
return True
except Exception as e:
except Exception as e: # pylint: disable=broad-except
print("could not parse file", e)
@@ -309,7 +311,7 @@ class ToolLibraryManager():
fp,fname = openFileWithExtension(filename[0], '.tbl')
for key in tt.Tools:
t = tt.Tools[key]
fp.write("T{} P{} Y{} Z{} A{} B{} C{} U{} V{} W{} D{} I{} J{} Q{} ;{}\n".format(key,key,0,t.LengthOffset,0,0,0,0,0,0,t.Diameter,0,0,0,t.Name))
fp.write("T{0} P{0} Y{1} Z{2} A{3} B{4} C{5} U{6} V{7} W{8} D{9} I{10} J{11} Q{12} ;{13}\n".format(key,0,t.LengthOffset,0,0,0,0,0,0,t.Diameter,0,0,0,t.Name))
else:
fp,fname = openFileWithExtension(filename[0], '.json')
json.dump(self.templateAttrs(tt), fp, sort_keys=True, indent=2)
@@ -317,7 +319,7 @@ class ToolLibraryManager():
fp.close()
print("Written ", PathUtil.toUnicode(fname))
except Exception as e:
except Exception as e: # pylint: disable=broad-except
print("Could not write file:", e)
def addnew(self, listname, tool, position = None):
@@ -605,6 +607,9 @@ class EditorPanel():
self.setFields()
class CommandToolLibraryEdit():
def __init__(self):
pass
def edit(self, job=None, cb=None):
editor = EditorPanel(job, cb)
editor.setupUi()

View File

@@ -104,7 +104,7 @@ There is currently a bug that invalidates the DAG if an object
is deleted that still has one or more expressions attached to it.
Use this function to remove all expressions before deletion.'''
if hasattr(obj, 'ExpressionEngine'):
for attr,expr in obj.ExpressionEngine:
for attr, expr in obj.ExpressionEngine: # pylint: disable=unused-variable
obj.setExpression(attr, None)
def toUnicode(string):

View File

@@ -72,57 +72,6 @@ def waiting_effects(function):
return new_function
def cleanedges(splines, precision):
'''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths.
Returns Lines as is. Filters Circle and Arcs for over 180 degrees. Discretizes Ellipses. Ignores other geometry. '''
PathLog.track()
edges = []
for spline in splines:
if geomType(spline) == "BSplineCurve":
arcs = spline.Curve.toBiArcs(precision)
for i in arcs:
edges.append(Part.Edge(i))
elif geomType(spline) == "BezierCurve":
newspline = spline.Curve.toBSpline()
arcs = newspline.toBiArcs(precision)
for i in arcs:
edges.append(Part.Edge(i))
elif geomType(spline) == "Ellipse":
edges = curvetowire(spline, 1.0) # fixme hardcoded value
elif geomType(spline) == "Circle":
arcs = filterArcs(spline)
for i in arcs:
edges.append(Part.Edge(i))
elif geomType(spline) == "Line":
edges.append(spline)
elif geomType(spline) == "LineSegment":
edges.append(spline)
else:
pass
return edges
def curvetowire(obj, steps):
'''adapted from DraftGeomUtils, because the discretize function changed a bit '''
PathLog.track()
points = obj.copy().discretize(Distance=eval('steps'))
p0 = points[0]
edgelist = []
for p in points[1:]:
edge = Part.makeLine((p0.x, p0.y, p0.z), (p.x, p.y, p.z))
edgelist.append(edge)
p0 = p
return edgelist
def isDrillable(obj, candidate, tooldiameter=None, includePartials=False):
"""
Checks candidates to see if they can be drilled.
@@ -201,12 +150,12 @@ def isDrillable(obj, candidate, tooldiameter=None, includePartials=False):
else:
drillable = True
PathLog.debug("candidate is drillable: {}".format(drillable))
except Exception as ex:
except Exception as ex: # pylint: disable=broad-except
PathLog.warning(translate("PathUtils", "Issue determine drillability: {}").format(ex))
return drillable
# fixme set at 4 decimal places for testing
# set at 4 decimal places for testing
def fmt(val):
return format(val, '.4f')
@@ -408,7 +357,7 @@ def getToolControllers(obj):
'''returns all the tool controllers'''
try:
job = findParentJob(obj)
except Exception:
except Exception: # pylint: disable=broad-except
job = None
if job:
@@ -509,7 +458,6 @@ def rapid(x=None, y=None, z=None):
def feed(x=None, y=None, z=None, horizFeed=0, vertFeed=0):
""" Return gcode string to perform a linear feed."""
global feedxy
retstr = "G01 F"
if(x is None) and (y is None):
retstr += str("%.4f" % horizFeed)
@@ -579,9 +527,8 @@ def helicalPlunge(plungePos, rampangle, destZ, startZ, toold, plungeR, horizFeed
# toold = self.radius * 2
helixCmds = "(START HELICAL PLUNGE)\n"
if(plungePos is None):
if plungePos is None:
raise Exception("Helical plunging requires a position!")
return None
helixX = plungePos.x + toold / 2 * plungeR
helixY = plungePos.y
@@ -630,12 +577,10 @@ def rampPlunge(edge, rampangle, destZ, startZ):
rampCmds = "(START RAMP PLUNGE)\n"
if(edge is None):
raise Exception("Ramp plunging requires an edge!")
return None
sPoint = edge.Vertexes[0].Point
ePoint = edge.Vertexes[1].Point
# Evidently edges can get flipped- pick the right one in this case
# FIXME: This is iffy code, based on what already existed in the "for vpos ..." loop below
if ePoint == sPoint:
# print "FLIP"
ePoint = edge.Vertexes[-1].Point
@@ -647,7 +592,6 @@ def rampPlunge(edge, rampangle, destZ, startZ):
rampCmds += rapid(z=startZ)
# Ramp down to the requested depth
# FIXME: This might be an arc, so handle that as well
curZ = max(startZ - rampDZ, destZ)
done = False
@@ -667,11 +611,13 @@ def rampPlunge(edge, rampangle, destZ, startZ):
return rampCmds
def sort_jobs(locations, keys, attractors=[]):
def sort_jobs(locations, keys, attractors=None):
""" sort holes by the nearest neighbor method
keys: two-element list of keys for X and Y coordinates. for example ['x','y']
originally written by m0n5t3r for PathHelix
"""
if attractors is None:
attractors = []
try:
from queue import PriorityQueue
except ImportError:
@@ -703,7 +649,7 @@ def sort_jobs(locations, keys, attractors=[]):
# prevent dictionary comparison by inserting the index
q.put((dist(j, location) + weight(j), i, j))
prio, i, result = q.get()
prio, i, result = q.get() # pylint: disable=unused-variable
return result

View File

@@ -52,12 +52,12 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter):
self.highlightingRules.append((QtCore.QRegExp("\\bF[0-9\\.]+\\b"),speedFormat))
def highlightBlock(self, text):
for pattern, format in self.highlightingRules:
for pattern, hlFormat in self.highlightingRules:
expression = QtCore.QRegExp(pattern)
index = expression.indexIn(text)
while index >= 0:
length = expression.matchedLength()
self.setFormat(index, length, format)
self.setFormat(index, length, hlFormat)
index = expression.indexIn(text, index + length)

View File

@@ -59,16 +59,20 @@ EXTERNAL_MODULES+=' PySide.QtGui'
EXTERNAL_MODULES+=' TechDraw'
EXTERNAL_MODULES+=' area'
EXTERNAL_MODULES+=' importlib'
EXTERNAL_MODULES+=' ocl'
EXTERNAL_MODULES+=' pivy'
ARGS+=" --errors-only"
#ARGS+=" --errors-only"
ARGS+=" --disable=C,R"
ARGS+=" --ignored-modules=$(echo ${EXTERNAL_MODULES} | tr ' ' ',')"
ARGS+=" --ignore=post"
ARGS+=" --jobs=4"
if [ -z "$(which pylint)" ]; then
if [ -z "$(which pylint3)" ]; then
echo "Cannot find pylint, please install and try again!"
exit 1
fi
#pylint ${ARGS} PathScripts/ PathTests/
pylint ${ARGS} PathScripts/
#pylint3 ${ARGS} PathScripts/ PathTests/
pylint3 ${ARGS} PathScripts/