diff --git a/assembly.py b/assembly.py index 933713c..56e8887 100644 --- a/assembly.py +++ b/assembly.py @@ -7,16 +7,6 @@ from .utils import logger, objName from .constraint import Constraint, cstrName from .system import System -def setupUndo(doc,undoDocs,name): - if undoDocs is None: - return - if doc.HasPendingTransaction or doc in undoDocs: - return - if not name: - name = 'Assembly solve' - doc.openTransaction(name) - undoDocs.add(doc) - def isTypeOf(obj,tp,resolve=False): if not obj: return False @@ -367,7 +357,7 @@ class AsmElement(AsmBase): Subname=link.Subname+subElement) @staticmethod - def make(selection=None,name='Element'): + def make(selection=None,name='Element',undo=False): '''Add/get/modify an element with the given selected object''' if not selection: selection = AsmElement.getSelection() @@ -443,22 +433,32 @@ class AsmElement(AsmBase): group.Name,subname)) element = selection.Element - if not element: - elements = group.Proxy.getAssembly().getElementGroup() - # try to search the element group for an existing element - for e in elements.Group: - sub = logger.catch('',e.Proxy.getSubName) - if sub == subname: - return e - element = elements.Document.addObject("App::FeaturePython", - name,AsmElement(elements),None,True) - ViewProviderAsmElement(element.ViewObject) - elements.setLink({-1:element}) - elements.setElementVisible(element.Name,False) - element.Proxy._initializing = False - elements.cacheChildLabel() - element.setLink(group,subname) + try: + if undo: + FreeCAD.setActiveTransaction('Assembly change element' \ + if element else 'Assembly create element') + if not element: + elements = group.Proxy.getAssembly().getElementGroup() + # try to search the element group for an existing element + for e in elements.Group: + sub = logger.catch('',e.Proxy.getSubName) + if sub == subname: + return e + element = elements.Document.addObject("App::FeaturePython", + name,AsmElement(elements),None,True) + ViewProviderAsmElement(element.ViewObject) + elements.setLink({-1:element}) + elements.setElementVisible(element.Name,False) + element.Proxy._initializing = False + elements.cacheChildLabel() + element.setLink(group,subname) + if undo: + FreeCAD.closeActiveTransaction() + except Exception: + if undo: + FreeCAD.closeActiveTransaction(True) + raise return element @@ -483,7 +483,7 @@ class ViewProviderAsmElement(ViewProviderAsmOnTop): def dropObjectEx(self,vobj,_obj,owner,subname): AsmElement.make(AsmElement.Selection(Element=vobj.Object, - Group=owner, Subname=subname)) + Group=owner, Subname=subname),undo=True) PartInfo = namedtuple('AsmPartInfo', ('Parent','SubnameRef','Part', @@ -747,7 +747,7 @@ class AsmElementLink(AsmBase): return self.info @staticmethod - def setPlacement(part,pla,undoDocs,undoName): + def setPlacement(part,pla): ''' called by solver after solving to adjust the placement. @@ -756,13 +756,10 @@ class AsmElementLink(AsmBase): ''' if isinstance(part,tuple): if isinstance(part[1],int): - setupUndo(part[0].Document,undoDocs,undoName) part[0].PlacementList = {part[1]:pla} else: - setupUndo(part[1].Document,undoDocs,undoName) part[1].Placement = pla else: - setupUndo(part.Document,undoDocs,undoName) part.Placement = pla MakeInfo = namedtuple('AsmElementLinkMakeInfo', @@ -777,8 +774,8 @@ class AsmElementLink(AsmBase): link.Proxy.setLink(info.Owner,info.Subname) return link -def setPlacement(part,pla,undoDocs,undoName=None): - AsmElementLink.setPlacement(part,pla,undoDocs,undoName) +def setPlacement(part,pla): + AsmElementLink.setPlacement(part,pla) class ViewProviderAsmElementLink(ViewProviderAsmOnTop): @@ -989,15 +986,13 @@ class AsmConstraint(AsmGroup): if not sel: sel = AsmConstraint.getSelection(typeid) if sel.Constraint: + if undo: + FreeCAD.setActiveTransaction('Assembly change constraint') cstr = sel.Constraint - if undo: - doc = cstr.Document - doc.openTransaction('Assembly change constraint') else: - constraints = sel.Assembly.Proxy.getConstraintGroup() if undo: - doc = constraints.Document - doc.openTransaction('Assembly make constraint') + FreeCAD.setActiveTransaction('Assembly create constraint') + constraints = sel.Assembly.Proxy.getConstraintGroup() cstr = constraints.Document.addObject("App::FeaturePython", name,AsmConstraint(constraints),None,True) proxy = ViewProviderAsmConstraint(cstr.ViewObject) @@ -1016,7 +1011,7 @@ class AsmConstraint(AsmGroup): logger.catch('solver exception when auto recompute', solver.solve, sel.Assembly, undo=undo) if undo: - doc.commitTransaction() + FreeCAD.closeActiveTransaction() if sel.SelObject: FreeCADGui.Selection.clearSelection() @@ -1031,7 +1026,7 @@ class AsmConstraint(AsmGroup): except Exception: if undo: - doc.abortTransaction() + FreeCAD.closeActiveTransaction(True) raise @@ -1202,7 +1197,8 @@ class Assembly(AsmGroup): def buildShape(self): obj = self.Object if obj.BuildShape == BuildShapeNone: - obj.Shape = Part.Shape() + if not obj.Shape.isNull(): + obj.Shape = Part.Shape() return shape = [] @@ -1358,7 +1354,7 @@ class Assembly(AsmGroup): if not doc: raise RuntimeError('No active document') if undo: - doc.openTransaction('Create assembly') + FreeCAD.setActiveTransaction('Create assembly') try: obj = doc.addObject( "Part::FeaturePython",name,Assembly(),None,True) @@ -1366,10 +1362,10 @@ class Assembly(AsmGroup): obj.Visibility = True obj.purgeTouched() if undo: - doc.commitTransaction() + FreeCAD.closeActiveTransaction() except Exception: if undo: - doc.abortTransaction() + FreeCAD.closeActiveTransaction(True) raise return obj @@ -1541,8 +1537,6 @@ class AsmMovingPart(object): self.trace.recompute() return pla - _undoName = 'Assembly move' - def move(self): obj = self.assembly.Object pla = obj.ViewObject.DraggingPlacement @@ -1557,7 +1551,7 @@ class AsmMovingPart(object): # parent assembly instead rollback.append((obj.Name,obj,obj.Placement.copy())) pla = obj.Placement.multiply(movement) - setPlacement(obj,pla,self.undos,self._undoName) + setPlacement(obj,pla) update = False else: # fixed position, so reset translation @@ -1573,7 +1567,7 @@ class AsmMovingPart(object): if update: # obtain and update the part placement pla = pla.multiply(self.offsetInv) - setPlacement(self.part,pla,self.undos,self._undoName) + setPlacement(self.part,pla) rollback.append((self.partName,self.part,self.oldPlacement.copy())) if not gui.AsmCmdManager.AutoRecompute or \ @@ -1746,14 +1740,13 @@ class ViewProviderAssembly(ViewProviderAsmGroup): self._movingPart.bbox) def onDragStart(self): - self._movingPart.undos = set() + FreeCAD.setActiveTransaction('Assembly move') def onDragMotion(self): return self._movingPart.move() def onDragEnd(self): - for doc in self._movingPart.undos: - doc.commitTransaction() + FreeCAD.closeActiveTransaction() def unsetEdit(self,_vobj,_mode): self._movingPart = None @@ -1808,7 +1801,7 @@ class AsmWorkPlane(object): info = AsmWorkPlane.getSelection(sels) doc = info.PartGroup.Document if undo: - doc.openTransaction('Assembly make workplane') + FreeCAD.setActiveTransaction('Assembly create workplane') try: obj = doc.addObject('Part::FeaturePython',name) AsmWorkPlane(obj) @@ -1819,7 +1812,8 @@ class AsmWorkPlane(object): obj.Width = obj.Length obj.recompute(True) info.PartGroup.setLink({-1:obj}) - doc.commitTransaction() + if undo: + FreeCAD.closeActiveTransaction() FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(info.SelObj, @@ -1828,7 +1822,7 @@ class AsmWorkPlane(object): return obj except Exception: if undo: - doc.abortTransaction() + FreeCAD.closeActiveTransaction(True) raise diff --git a/gui.py b/gui.py index a058f6a..4cf6a92 100644 --- a/gui.py +++ b/gui.py @@ -276,14 +276,14 @@ class AsmCmdUp(AsmCmdBase): j = 0 logger.debug('move {}:{} -> {}:{}'.format( i,objName(obj),j,objName(children[j]))) - parent.Document.openTransaction(cls._menuText) + FreeCAD.setActiveTransaction(cls._menuText) readonly = 'Immutable' in parent.getPropertyStatus('Group') if readonly: parent.setPropertyStatus('Group','-Immutable') parent.Group = {i:children[j],j:obj} if readonly: parent.setPropertyStatus('Group','Immutable') - parent.Document.commitTransaction() + FreeCAD.closeActiveTransaction(); # The tree view may deselect the item because of claimChildren changes, # so we restore the selection here FreeCADGui.Selection.addSelection(topParent,subname) diff --git a/solver.py b/solver.py index edb6d22..5c4d602 100644 --- a/solver.py +++ b/solver.py @@ -56,14 +56,13 @@ class Solver(object): if dragPart in self._fixedParts: raise RuntimeError('cannot drag fixed part') info = self._partMap.get(dragPart,None) - if not info: - raise RuntimeError('invalid dragging part') - - # add dragging point - self.system.log('add drag point {}'.format(info.Workplane[1])) - # TODO: slvs addWhereDragged doesn't work as expected, need to - # investigate more - # addDragPoint(info.Workplane[1],group=self.group) + if info: + # add dragging point + self.system.log('add drag point ' + '{}'.format(info.Workplane[1])) + # TODO: slvs addWhereDragged doesn't work as expected, need + # to investigate more + # addDragPoint(info.Workplane[1],group=self.group) self.system.log('solving {}'.format(objName(assembly))) try: @@ -107,7 +106,7 @@ class Solver(object): touched = True self.system.log('moving {} {} {} {}'.format( partInfo.PartName,partInfo.Params,params,pla)) - setPlacement(part,pla,undoDocs) + setPlacement(part,pla) if rollback is not None: rollback.append((partInfo.PartName, part, @@ -216,7 +215,7 @@ def solve(objs=None,recursive=None,reportFailed=True, if rollback is not None: for name,part,pla in reversed(rollback): logger.debug('roll back {} to {}'.format(name,pla)) - setPlacement(part,pla,None) + setPlacement(part,pla) raise return True