diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index 456365768e..4bc342dc01 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -151,6 +151,7 @@ class ObjectJob: 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, ()): + PathUtil.clearExpressionEngine(op) doc.removeObject(op.Name) obj.Operations.Group = [] doc.removeObject(obj.Operations.Name) @@ -158,22 +159,27 @@ class ObjectJob: # stock could depend on Base if obj.Stock: 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 obj.Base: PathLog.debug('taking down base') if isResourceClone(obj, 'Base'): + PathUtil.clearExpressionEngine(obj.Base) doc.removeObject(obj.Base.Name) obj.Base = None # Tool controllers don't depend on anything PathLog.debug('taking down tool controller') for tc in obj.ToolController: + PathUtil.clearExpressionEngine(tc) doc.removeObject(tc.Name) obj.ToolController = [] # SetupSheet + PathUtil.clearExpressionEngine(obj.SetupSheet) doc.removeObject(obj.SetupSheet.Name) obj.SetupSheet = None + return True def fixupResourceClone(self, obj, name, icon): if not isResourceClone(obj, name, name) and not isArchPanelSheet(obj): diff --git a/src/Mod/Path/PathScripts/PathOpGui.py b/src/Mod/Path/PathScripts/PathOpGui.py index 2205e9c133..4da4017ec0 100644 --- a/src/Mod/Path/PathScripts/PathOpGui.py +++ b/src/Mod/Path/PathScripts/PathOpGui.py @@ -30,6 +30,7 @@ import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog import PathScripts.PathSelection as PathSelection import PathScripts.PathOp as PathOp +import PathScripts.PathUtil as PathUtil import PathScripts.PathUtils as PathUtils import importlib @@ -161,6 +162,10 @@ class ViewProvider(object): if self.panel: self.panel.updateData(obj, prop) + def onDelete(self, vobj, arg2=None): + PathUtil.clearExpressionEngine(vobj.Object) + return True + class TaskPanelPage(object): '''Base class for all task panel pages.''' @@ -767,6 +772,7 @@ class TaskPanel(object): FreeCAD.ActiveDocument.abortTransaction() if self.deleteOnReject: FreeCAD.ActiveDocument.openTransaction(translate("Path", "Uncreate AreaOp Operation")) + PathUtil.clearExpressionEngine(self.obj) FreeCAD.ActiveDocument.removeObject(self.obj.Name) FreeCAD.ActiveDocument.commitTransaction() self.cleanup(resetEdit) diff --git a/src/Mod/Path/PathScripts/PathToolController.py b/src/Mod/Path/PathScripts/PathToolController.py index fa59f41ad0..b132827496 100644 --- a/src/Mod/Path/PathScripts/PathToolController.py +++ b/src/Mod/Path/PathScripts/PathToolController.py @@ -28,6 +28,7 @@ import Part import Path import PathScripts import PathScripts.PathLog as PathLog +import PathScripts.PathUtil as PathUtil from FreeCAD import Units from PySide import QtCore @@ -191,6 +192,10 @@ class ViewProvider: vobj.setEditorMode('BoundingBox', mode) vobj.setEditorMode('Selectable', mode) + def onDelete(self, vobj, args=None): + PathUtil.clearExpressionEngine(vobj.Object) + return True + def updateData(self, vobj, prop): # this is executed when a property of the APP OBJECT changes pass diff --git a/src/Mod/Path/PathScripts/PathUtil.py b/src/Mod/Path/PathScripts/PathUtil.py index bda4577edd..b340c156ff 100644 --- a/src/Mod/Path/PathScripts/PathUtil.py +++ b/src/Mod/Path/PathScripts/PathUtil.py @@ -87,3 +87,12 @@ def getPublicObject(obj): return getPublicObject(body) return obj +def clearExpressionEngine(obj): + '''clearExpressionEngine(obj) ... removes all expressions from obj. + +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: + obj.setExpression(attr, None)