purge archpanel support

This commit is contained in:
sliptonic
2021-08-12 10:45:13 -05:00
parent c03c771839
commit 13779a6db9
7 changed files with 1611 additions and 834 deletions

View File

@@ -20,6 +20,8 @@
# * *
# ***************************************************************************
from PathScripts.PathPostProcessor import PostProcessor
from PySide import QtCore
import FreeCAD
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferences as PathPreferences
@@ -29,13 +31,11 @@ import PathScripts.PathToolController as PathToolController
import PathScripts.PathUtil as PathUtil
import json
import time
from PathScripts.PathPostProcessor import PostProcessor
from PySide import QtCore
# lazily loaded modules
from lazy_loader.lazy_loader import LazyLoader
ArchPanel = LazyLoader('ArchPanel', globals(), 'ArchPanel')
Draft = LazyLoader('Draft', globals(), 'Draft')
Draft = LazyLoader("Draft", globals(), "Draft")
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
@@ -48,45 +48,41 @@ def translate(context, text, disambig=None):
class JobTemplate:
# pylint: disable=no-init
'''Attribute and sub element strings for template export/import.'''
Description = 'Desc'
GeometryTolerance = 'Tolerance'
Job = 'Job'
PostProcessor = 'Post'
PostProcessorArgs = 'PostArgs'
PostProcessorOutputFile = 'Output'
Fixtures = 'Fixtures'
OrderOutputBy = 'OrderOutputBy'
SplitOutput = 'SplitOutput'
SetupSheet = 'SetupSheet'
Stock = 'Stock'
"""Attribute and sub element strings for template export/import."""
Description = "Desc"
GeometryTolerance = "Tolerance"
Job = "Job"
PostProcessor = "Post"
PostProcessorArgs = "PostArgs"
PostProcessorOutputFile = "Output"
Fixtures = "Fixtures"
OrderOutputBy = "OrderOutputBy"
SplitOutput = "SplitOutput"
SetupSheet = "SetupSheet"
Stock = "Stock"
# TCs are grouped under Tools in a job, the template refers to them directly though
ToolController = 'ToolController'
Version = 'Version'
def isArchPanelSheet(obj):
return hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet)
ToolController = "ToolController"
Version = "Version"
def isResourceClone(obj, propLink, resourceName):
# pylint: disable=unused-argument
if hasattr(propLink, 'PathResource') and (resourceName is None or resourceName == propLink.PathResource):
if hasattr(propLink, "PathResource") and (
resourceName is None or resourceName == propLink.PathResource
):
return True
return False
def createResourceClone(obj, orig, name, icon):
if isArchPanelSheet(orig):
# can't clone panel sheets - they have to be panel sheets
return orig
clone = Draft.clone(orig)
clone.Label = "%s-%s" % (name, orig.Label)
clone.addProperty('App::PropertyString', 'PathResource')
clone.addProperty("App::PropertyString", "PathResource")
clone.PathResource = name
if clone.ViewObject:
import PathScripts.PathIconViewProvider
PathScripts.PathIconViewProvider.Attach(clone.ViewObject, icon)
clone.ViewObject.Visibility = False
clone.ViewObject.Transparency = 80
@@ -95,7 +91,7 @@ def createResourceClone(obj, orig, name, icon):
def createModelResourceClone(obj, orig):
return createResourceClone(obj, orig, 'Model', 'BaseGeometry')
return createResourceClone(obj, orig, "Model", "BaseGeometry")
class NotificationClass(QtCore.QObject):
@@ -106,30 +102,108 @@ Notification = NotificationClass()
class ObjectJob:
def __init__(self, obj, models, templateFile=None):
self.obj = obj
obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "The NC output file for this project"))
obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Select the Post Processor"))
obj.addProperty("App::PropertyString", "PostProcessorArgs", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Arguments for the Post Processor (specific to the script)"))
obj.addProperty("App::PropertyString", "LastPostProcessDate", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Last Time the Job was post-processed"))
obj.setEditorMode('LastPostProcessDate', 2) # Hide
obj.addProperty("App::PropertyString", "LastPostProcessOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Last Time the Job was post-processed"))
obj.setEditorMode('LastPostProcessOutput', 2) # Hide
obj.addProperty(
"App::PropertyFile",
"PostProcessorOutputFile",
"Output",
QtCore.QT_TRANSLATE_NOOP("PathJob", "The NC output file for this project"),
)
obj.addProperty(
"App::PropertyEnumeration",
"PostProcessor",
"Output",
QtCore.QT_TRANSLATE_NOOP("PathJob", "Select the Post Processor"),
)
obj.addProperty(
"App::PropertyString",
"PostProcessorArgs",
"Output",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "Arguments for the Post Processor (specific to the script)"
),
)
obj.addProperty(
"App::PropertyString",
"LastPostProcessDate",
"Output",
QtCore.QT_TRANSLATE_NOOP("PathJob", "Last Time the Job was post-processed"),
)
obj.setEditorMode("LastPostProcessDate", 2) # Hide
obj.addProperty(
"App::PropertyString",
"LastPostProcessOutput",
"Output",
QtCore.QT_TRANSLATE_NOOP("PathJob", "Last Time the Job was post-processed"),
)
obj.setEditorMode("LastPostProcessOutput", 2) # Hide
obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("PathJob", "An optional description for this job"))
obj.addProperty("App::PropertyString", "CycleTime", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "Job Cycle Time Estimation"))
obj.setEditorMode('CycleTime', 1) # read-only
obj.addProperty("App::PropertyDistance", "GeometryTolerance", "Geometry", QtCore.QT_TRANSLATE_NOOP("PathJob", "For computing Paths; smaller increases accuracy, but slows down computation"))
obj.addProperty(
"App::PropertyString",
"Description",
"Path",
QtCore.QT_TRANSLATE_NOOP("PathJob", "An optional description for this job"),
)
obj.addProperty(
"App::PropertyString",
"CycleTime",
"Path",
QtCore.QT_TRANSLATE_NOOP("PathOp", "Job Cycle Time Estimation"),
)
obj.setEditorMode("CycleTime", 1) # read-only
obj.addProperty(
"App::PropertyDistance",
"GeometryTolerance",
"Geometry",
QtCore.QT_TRANSLATE_NOOP(
"PathJob",
"For computing Paths; smaller increases accuracy, but slows down computation",
),
)
obj.addProperty("App::PropertyLink", "Stock", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock."))
obj.addProperty("App::PropertyLink", "Operations", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Compound path of all operations in the order they are processed."))
obj.addProperty(
"App::PropertyLink",
"Stock",
"Base",
QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock."),
)
obj.addProperty(
"App::PropertyLink",
"Operations",
"Base",
QtCore.QT_TRANSLATE_NOOP(
"PathJob",
"Compound path of all operations in the order they are processed.",
),
)
obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Split output into multiple gcode files"))
obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
obj.addProperty("App::PropertyStringList", "Fixtures", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "The Work Coordinate Systems for the Job"))
obj.OrderOutputBy = ['Fixture', 'Tool', 'Operation']
obj.Fixtures = ['G54']
obj.addProperty(
"App::PropertyBool",
"SplitOutput",
"Output",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "Split output into multiple gcode files"
),
)
obj.addProperty(
"App::PropertyEnumeration",
"OrderOutputBy",
"WCS",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "If multiple WCS, order the output this way"
),
)
obj.addProperty(
"App::PropertyStringList",
"Fixtures",
"WCS",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "The Work Coordinate Systems for the Job"
),
)
obj.OrderOutputBy = ["Fixture", "Tool", "Operation"]
obj.Fixtures = ["G54"]
obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors()
@@ -142,14 +216,16 @@ class ObjectJob:
obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()
ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
ops = FreeCAD.ActiveDocument.addObject(
"Path::FeatureCompoundPython", "Operations"
)
if ops.ViewObject:
ops.ViewObject.Proxy = 0
ops.ViewObject.Visibility = False
obj.Operations = ops
obj.setEditorMode('Operations', 2) # hide
obj.setEditorMode('Placement', 2)
obj.setEditorMode("Operations", 2) # hide
obj.setEditorMode("Placement", 2)
self.setupSetupSheet(obj)
self.setupBaseModel(obj, models)
@@ -171,41 +247,73 @@ class ObjectJob:
obj.Stock.ViewObject.Visibility = False
def setupSetupSheet(self, obj):
if not getattr(obj, 'SetupSheet', None):
obj.addProperty('App::PropertyLink', 'SetupSheet', 'Base', QtCore.QT_TRANSLATE_NOOP('PathJob', 'SetupSheet holding the settings for this job'))
if not getattr(obj, "SetupSheet", None):
obj.addProperty(
"App::PropertyLink",
"SetupSheet",
"Base",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "SetupSheet holding the settings for this job"
),
)
obj.SetupSheet = PathSetupSheet.Create()
if obj.SetupSheet.ViewObject:
import PathScripts.PathIconViewProvider
PathScripts.PathIconViewProvider.Attach(obj.SetupSheet.ViewObject, 'SetupSheet')
PathScripts.PathIconViewProvider.Attach(
obj.SetupSheet.ViewObject, "SetupSheet"
)
self.setupSheet = obj.SetupSheet.Proxy
def setupBaseModel(self, obj, models=None):
PathLog.track(obj.Label, models)
if not hasattr(obj, 'Model'):
obj.addProperty("App::PropertyLink", "Model", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "The base objects for all operations"))
model = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "Model")
if not hasattr(obj, "Model"):
obj.addProperty(
"App::PropertyLink",
"Model",
"Base",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "The base objects for all operations"
),
)
model = FreeCAD.ActiveDocument.addObject(
"App::DocumentObjectGroup", "Model"
)
if model.ViewObject:
model.ViewObject.Visibility = False
if models:
model.addObjects([createModelResourceClone(obj, base) for base in models])
model.addObjects(
[createModelResourceClone(obj, base) for base in models]
)
obj.Model = model
if hasattr(obj, 'Base'):
PathLog.info("Converting Job.Base to new Job.Model for {}".format(obj.Label))
if hasattr(obj, "Base"):
PathLog.info(
"Converting Job.Base to new Job.Model for {}".format(obj.Label)
)
obj.Model.addObject(obj.Base)
obj.Base = None
obj.removeProperty('Base')
obj.removeProperty("Base")
def setupToolTable(self, obj):
if not hasattr(obj, 'Tools'):
obj.addProperty("App::PropertyLink", "Tools", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of all tool controllers for the job"))
toolTable = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "Tools")
toolTable.Label = 'Tools'
if not hasattr(obj, "Tools"):
obj.addProperty(
"App::PropertyLink",
"Tools",
"Base",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "Collection of all tool controllers for the job"
),
)
toolTable = FreeCAD.ActiveDocument.addObject(
"App::DocumentObjectGroup", "Tools"
)
toolTable.Label = "Tools"
if toolTable.ViewObject:
toolTable.ViewObject.Visibility = False
if hasattr(obj, 'ToolController'):
if hasattr(obj, "ToolController"):
toolTable.addObjects(obj.ToolController)
obj.removeProperty('ToolController')
obj.removeProperty("ToolController")
obj.Tools = toolTable
def removeBase(self, obj, base, removeFromModel):
@@ -219,16 +327,22 @@ class ObjectJob:
return PathStock.shapeBoundBox(obj.Model.Group)
def onDelete(self, obj, arg2=None):
'''Called by the view provider, there doesn't seem to be a callback on the obj itself.'''
"""Called by the view provider, there doesn't seem to be a callback on the obj itself."""
PathLog.track(obj.Label, arg2)
doc = obj.Document
if getattr(obj, 'Operations', None):
if getattr(obj, "Operations", None):
# the first to tear down are the ops, they depend on other resources
PathLog.debug('taking down ops: %s' % [o.Name for o in self.allOperations()])
PathLog.debug(
"taking down ops: %s" % [o.Name for o in self.allOperations()]
)
while obj.Operations.Group:
op = obj.Operations.Group[0]
if not op.ViewObject or not hasattr(op.ViewObject.Proxy, 'onDelete') or op.ViewObject.Proxy.onDelete(op.ViewObject, ()):
if (
not op.ViewObject
or not hasattr(op.ViewObject.Proxy, "onDelete")
or op.ViewObject.Proxy.onDelete(op.ViewObject, ())
):
PathUtil.clearExpressionEngine(op)
doc.removeObject(op.Name)
obj.Operations.Group = []
@@ -236,14 +350,14 @@ class ObjectJob:
obj.Operations = None
# stock could depend on Model, so delete it first
if getattr(obj, 'Stock', None):
PathLog.debug('taking down stock')
if getattr(obj, "Stock", None):
PathLog.debug("taking down stock")
PathUtil.clearExpressionEngine(obj.Stock)
doc.removeObject(obj.Stock.Name)
obj.Stock = None
# base doesn't depend on anything inside job
if getattr(obj, 'Model', None):
if getattr(obj, "Model", None):
for base in obj.Model.Group:
PathLog.debug("taking down base %s" % base.Label)
self.removeBase(obj, base, False)
@@ -252,8 +366,8 @@ class ObjectJob:
obj.Model = None
# Tool controllers might refer to either legacy tool or toolbit
if getattr(obj, 'Tools', None):
PathLog.debug('taking down tool controller')
if getattr(obj, "Tools", None):
PathLog.debug("taking down tool controller")
for tc in obj.Tools.Group:
if hasattr(tc.Tool, "Proxy"):
PathUtil.clearExpressionEngine(tc.Tool)
@@ -266,7 +380,7 @@ class ObjectJob:
obj.Tools = None
# SetupSheet
if getattr(obj, 'SetupSheet', None):
if getattr(obj, "SetupSheet", None):
PathUtil.clearExpressionEngine(obj.SetupSheet)
doc.removeObject(obj.SetupSheet.Name)
obj.SetupSheet = None
@@ -274,13 +388,15 @@ class ObjectJob:
return True
def fixupOperations(self, obj):
if getattr(obj.Operations, 'ViewObject', None):
if getattr(obj.Operations, "ViewObject", None):
try:
obj.Operations.ViewObject.DisplayMode
except Exception: # pylint: disable=broad-except
name = obj.Operations.Name
label = obj.Operations.Label
ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
ops = FreeCAD.ActiveDocument.addObject(
"Path::FeatureCompoundPython", "Operations"
)
ops.ViewObject.Proxy = 0
ops.Group = obj.Operations.Group
obj.Operations.Group = []
@@ -294,23 +410,49 @@ class ObjectJob:
self.setupSetupSheet(obj)
self.setupToolTable(obj)
obj.setEditorMode('Operations', 2) # hide
obj.setEditorMode('Placement', 2)
obj.setEditorMode("Operations", 2) # hide
obj.setEditorMode("Placement", 2)
if not hasattr(obj, 'CycleTime'):
obj.addProperty("App::PropertyString", "CycleTime", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "Operations Cycle Time Estimation"))
obj.setEditorMode('CycleTime', 1) # read-only
if not hasattr(obj, "CycleTime"):
obj.addProperty(
"App::PropertyString",
"CycleTime",
"Path",
QtCore.QT_TRANSLATE_NOOP("PathOp", "Operations Cycle Time Estimation"),
)
obj.setEditorMode("CycleTime", 1) # read-only
if not hasattr(obj, "Fixtures"):
obj.addProperty("App::PropertyStringList", "Fixtures", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "The Work Coordinate Systems for the Job"))
obj.Fixtures = ['G54']
obj.addProperty(
"App::PropertyStringList",
"Fixtures",
"WCS",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "The Work Coordinate Systems for the Job"
),
)
obj.Fixtures = ["G54"]
if not hasattr(obj, "OrderOutputBy"):
obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
obj.OrderOutputBy = ['Fixture', 'Tool', 'Operation']
obj.addProperty(
"App::PropertyEnumeration",
"OrderOutputBy",
"WCS",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "If multiple WCS, order the output this way"
),
)
obj.OrderOutputBy = ["Fixture", "Tool", "Operation"]
if not hasattr(obj, "SplitOutput"):
obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Split output into multiple gcode files"))
obj.addProperty(
"App::PropertyBool",
"SplitOutput",
"Output",
QtCore.QT_TRANSLATE_NOOP(
"PathJob", "Split output into multiple gcode files"
),
)
obj.SplitOutput = False
def onChanged(self, obj, prop):
@@ -320,17 +462,17 @@ class ObjectJob:
self.tooltipArgs = processor.tooltipArgs
def baseObject(self, obj, base):
'''Return the base object, not its clone.'''
if isResourceClone(obj, base, 'Model') or isResourceClone(obj, base, 'Base'):
"""Return the base object, not its clone."""
if isResourceClone(obj, base, "Model") or isResourceClone(obj, base, "Base"):
return base.Objects[0]
return base
def baseObjects(self, obj):
'''Return the base objects, not their clones.'''
"""Return the base objects, not their clones."""
return [self.baseObject(obj, base) for base in obj.Model.Group]
def resourceClone(self, obj, base):
'''resourceClone(obj, base) ... Return the resource clone for base if it exists.'''
"""resourceClone(obj, base) ... Return the resource clone for base if it exists."""
if isResourceClone(obj, base, None):
return base
for b in obj.Model.Group:
@@ -339,11 +481,11 @@ class ObjectJob:
return None
def setFromTemplateFile(self, obj, template):
'''setFromTemplateFile(obj, template) ... extract the properties from the given template file and assign to receiver.
This will also create any TCs stored in the template.'''
"""setFromTemplateFile(obj, template) ... extract the properties from the given template file and assign to receiver.
This will also create any TCs stored in the template."""
tcs = []
if template:
with open(PathUtil.toUnicode(template), 'rb') as fp:
with open(PathUtil.toUnicode(template), "rb") as fp:
attrs = json.load(fp)
if attrs.get(JobTemplate.Version) and 1 == int(attrs[JobTemplate.Version]):
@@ -352,15 +494,19 @@ class ObjectJob:
self.setupSheet.setFromTemplate(attrs[JobTemplate.SetupSheet])
if attrs.get(JobTemplate.GeometryTolerance):
obj.GeometryTolerance = float(attrs.get(JobTemplate.GeometryTolerance))
obj.GeometryTolerance = float(
attrs.get(JobTemplate.GeometryTolerance)
)
if attrs.get(JobTemplate.PostProcessor):
obj.PostProcessor = attrs.get(JobTemplate.PostProcessor)
if attrs.get(JobTemplate.PostProcessorArgs):
obj.PostProcessorArgs = attrs.get(JobTemplate.PostProcessorArgs)
else:
obj.PostProcessorArgs = ''
obj.PostProcessorArgs = ""
if attrs.get(JobTemplate.PostProcessorOutputFile):
obj.PostProcessorOutputFile = attrs.get(JobTemplate.PostProcessorOutputFile)
obj.PostProcessorOutputFile = attrs.get(
JobTemplate.PostProcessorOutputFile
)
if attrs.get(JobTemplate.Description):
obj.Description = attrs.get(JobTemplate.Description)
@@ -368,10 +514,14 @@ class ObjectJob:
for tc in attrs.get(JobTemplate.ToolController):
tcs.append(PathToolController.FromTemplate(tc))
if attrs.get(JobTemplate.Stock):
obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock))
obj.Stock = PathStock.CreateFromTemplate(
obj, attrs.get(JobTemplate.Stock)
)
if attrs.get(JobTemplate.Fixtures):
obj.Fixtures = [x for y in attrs.get(JobTemplate.Fixtures) for x in y]
obj.Fixtures = [
x for y in attrs.get(JobTemplate.Fixtures) for x in y
]
if attrs.get(JobTemplate.OrderOutputBy):
obj.OrderOutputBy = attrs.get(JobTemplate.OrderOutputBy)
@@ -382,12 +532,15 @@ class ObjectJob:
PathLog.debug("setting tool controllers (%d)" % len(tcs))
obj.Tools.Group = tcs
else:
PathLog.error(translate('PathJob', "Unsupported PathJob template version %s") % attrs.get(JobTemplate.Version))
PathLog.error(
translate("PathJob", "Unsupported PathJob template version %s")
% attrs.get(JobTemplate.Version)
)
if not tcs:
self.addToolController(PathToolController.Create())
def templateAttrs(self, obj):
'''templateAttrs(obj) ... answer a dictionary with all properties of the receiver that should be stored in a template file.'''
"""templateAttrs(obj) ... answer a dictionary with all properties of the receiver that should be stored in a template file."""
attrs = {}
attrs[JobTemplate.Version] = 1
if obj.PostProcessor:
@@ -408,13 +561,13 @@ class ObjectJob:
def __setstate__(self, state):
for obj in FreeCAD.ActiveDocument.Objects:
if hasattr(obj, 'Proxy') and obj.Proxy == self:
if hasattr(obj, "Proxy") and obj.Proxy == self:
self.obj = obj
break
return None
def execute(self, obj):
if getattr(obj, 'Operations', None):
if getattr(obj, "Operations", None):
obj.Path = obj.Operations.Path
self.getCycleTime()
@@ -425,18 +578,23 @@ class ObjectJob:
for op in self.obj.Operations.Group:
# Skip inactive operations
if PathUtil.opProperty(op, 'Active') is False:
if PathUtil.opProperty(op, "Active") is False:
continue
# Skip operations that don't have a cycletime attribute
if PathUtil.opProperty(op, 'CycleTime') is None:
if PathUtil.opProperty(op, "CycleTime") is None:
continue
formattedCycleTime = PathUtil.opProperty(op, 'CycleTime')
formattedCycleTime = PathUtil.opProperty(op, "CycleTime")
opCycleTime = 0
try:
# Convert the formatted time from HH:MM:SS to just seconds
opCycleTime = sum(x * int(t) for x, t in zip([1, 60, 3600], reversed(formattedCycleTime.split(":"))))
opCycleTime = sum(
x * int(t)
for x, t in zip(
[1, 60, 3600], reversed(formattedCycleTime.split(":"))
)
)
except Exception:
continue
@@ -469,10 +627,26 @@ class ObjectJob:
def addToolController(self, tc):
group = self.obj.Tools.Group
PathLog.debug("addToolController(%s): %s" % (tc.Label, [t.Label for t in group]))
PathLog.debug(
"addToolController(%s): %s" % (tc.Label, [t.Label for t in group])
)
if tc.Name not in [str(t.Name) for t in group]:
tc.setExpression('VertRapid', "%s.%s" % (self.setupSheet.expressionReference(), PathSetupSheet.Template.VertRapid))
tc.setExpression('HorizRapid', "%s.%s" % (self.setupSheet.expressionReference(), PathSetupSheet.Template.HorizRapid))
tc.setExpression(
"VertRapid",
"%s.%s"
% (
self.setupSheet.expressionReference(),
PathSetupSheet.Template.VertRapid,
),
)
tc.setExpression(
"HorizRapid",
"%s.%s"
% (
self.setupSheet.expressionReference(),
PathSetupSheet.Template.HorizRapid,
),
)
self.obj.Tools.addObject(tc)
Notification.updateTC.emit(self.obj, tc)
@@ -480,17 +654,19 @@ class ObjectJob:
ops = []
def collectBaseOps(op):
if hasattr(op, 'TypeId'):
if op.TypeId == 'Path::FeaturePython':
if hasattr(op, "TypeId"):
if op.TypeId == "Path::FeaturePython":
ops.append(op)
if hasattr(op, 'Base'):
if hasattr(op, "Base"):
collectBaseOps(op.Base)
if op.TypeId == 'Path::FeatureCompoundPython':
if op.TypeId == "Path::FeatureCompoundPython":
ops.append(op)
for sub in op.Group:
collectBaseOps(sub)
if getattr(self.obj, 'Operations', None) and getattr(self.obj.Operations, 'Group', None):
if getattr(self.obj, "Operations", None) and getattr(
self.obj.Operations, "Group", None
):
for op in self.obj.Operations.Group:
collectBaseOps(op)
@@ -505,25 +681,32 @@ class ObjectJob:
@classmethod
def baseCandidates(cls):
'''Answer all objects in the current document which could serve as a Base for a job.'''
return sorted([obj for obj in FreeCAD.ActiveDocument.Objects if cls.isBaseCandidate(obj)], key=lambda o: o.Label)
"""Answer all objects in the current document which could serve as a Base for a job."""
return sorted(
[obj for obj in FreeCAD.ActiveDocument.Objects if cls.isBaseCandidate(obj)],
key=lambda o: o.Label,
)
@classmethod
def isBaseCandidate(cls, obj):
'''Answer true if the given object can be used as a Base for a job.'''
return PathUtil.isValidBaseObject(obj) or isArchPanelSheet(obj)
"""Answer true if the given object can be used as a Base for a job."""
return PathUtil.isValidBaseObject(obj)
def Instances():
'''Instances() ... Return all Jobs in the current active document.'''
"""Instances() ... Return all Jobs in the current active document."""
if FreeCAD.ActiveDocument:
return [job for job in FreeCAD.ActiveDocument.Objects if hasattr(job, 'Proxy') and isinstance(job.Proxy, ObjectJob)]
return [
job
for job in FreeCAD.ActiveDocument.Objects
if hasattr(job, "Proxy") and isinstance(job.Proxy, ObjectJob)
]
return []
def Create(name, base, templateFile=None):
'''Create(name, base, templateFile=None) ... creates a new job and all it's resources.
If a template file is specified the new job is initialized with the values from the template.'''
"""Create(name, base, templateFile=None) ... creates a new job and all it's resources.
If a template file is specified the new job is initialized with the values from the template."""
if isinstance(base[0], str):
models = []
for baseName in base: