Merge pull request #2314 from mlampert/refactor/pylint-warning-cleanup
Path: Refactor/pylint warning cleanup
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'''
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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()):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
# ***************************************************************************
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import PathScripts.PathMillFace as PathMillFace
|
||||
import PathScripts.PathOpGui as PathOpGui
|
||||
import PathScripts.PathPocketBaseGui as PathPocketBaseGui
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()'''
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user