FreeCAD_assembly3/gui.py
2019-01-12 21:16:49 +08:00

903 lines
27 KiB
Python

from collections import OrderedDict
import FreeCAD, FreeCADGui
from PySide import QtCore, QtGui
from .deps import with_metaclass
from .utils import getElementPos,objName,addIconToFCAD,guilogger as logger
from .proxy import ProxyType
from .FCADLogger import FCADLogger
class SelectionObserver:
def __init__(self):
self._attached = False
self.timer = QtCore.QTimer()
self.timer.setSingleShot(True)
self.timer.timeout.connect(self.onTimer)
self.cmds = []
self.elements = dict()
self.attach()
def setCommands(self,cmds):
self.cmds = cmds
def _setElementVisible(self,obj,subname,vis):
sobj = obj.getSubObject(subname,1)
from .assembly import isTypeOf,AsmConstraint,\
AsmElement,AsmElementLink
if isTypeOf(sobj,(AsmElement,AsmElementLink)):
res = sobj.Proxy.parent.Object.isElementVisible(sobj.Name)
if res and vis:
return False
sobj.Proxy.parent.Object.setElementVisible(sobj.Name,vis)
elif isTypeOf(sobj,AsmConstraint):
vis = [vis] * len(sobj.Group)
sobj.setPropertyStatus('VisibilityList','-Immutable')
sobj.VisibilityList = vis
sobj.setPropertyStatus('VisibilityList','Immutable')
else:
return
if vis:
FreeCADGui.Selection.updateSelection(vis,obj,subname)
def setElementVisible(self,docname,objname,subname,vis,presel=False):
if FreeCAD.isRestoring():
self.resetElementVisible()
return
if not AsmCmdManager.AutoElementVis:
self.elements.clear()
return
doc = FreeCAD.getDocument(docname)
if not doc:
return
obj = doc.getObject(objname)
if not obj:
return
key = (docname,objname,subname)
val = None
if not vis:
val = self.elements.get(key,None)
if val is None or (presel and val):
return
if logger.catchWarn('',self._setElementVisible,
obj,subname,vis) is False and presel:
return
if not vis:
self.elements.pop(key,None)
elif not presel:
self.elements[key] = True
else:
self.elements.setdefault(key,False)
def resetElementVisible(self):
elements = list(self.elements)
self.elements.clear()
for docname,objname,subname in elements:
doc = FreeCAD.getDocument(docname)
if not doc:
continue
obj = doc.getObject(objname)
if not obj:
continue
logger.catchWarn('',self._setElementVisible,obj,subname,False)
def onChange(self,hasSelection=True):
if not hasSelection:
self.timer.stop()
for cmd in self.cmds:
cmd.onSelectionChange(False)
return
self.timer.start(50)
def onTimer(self):
hasSelection = FreeCADGui.Selection.hasSelection()
for cmd in self.cmds:
cmd.onSelectionChange(hasSelection)
def addSelection(self,docname,objname,subname,_pos):
self.onChange()
self.setElementVisible(docname,objname,subname,True)
def removeSelection(self,docname,objname,subname):
self.onChange(FreeCADGui.Selection.hasSelection())
self.setElementVisible(docname,objname,subname,False)
def setPreselection(self,docname,objname,subname):
self.setElementVisible(docname,objname,subname,True,True)
def removePreselection(self,docname,objname,subname):
self.setElementVisible(docname,objname,subname,False,True)
def setSelection(self,*_args):
self.onChange()
if AsmCmdManager.AutoElementVis:
self.resetElementVisible()
for sel in FreeCADGui.Selection.getSelectionEx('*',False):
for sub in sel.SubElementNames:
self.setElementVisible(sel.Object.Document.Name,
sel.Object.Name,sub,True)
def clearSelection(self,*_args):
self.onChange(False)
self.resetElementVisible()
def attach(self):
logger.trace('attach selection aboserver {}',self._attached)
if not self._attached:
FreeCADGui.Selection.addObserver(self,False)
self._attached = True
def detach(self):
logger.trace('detach selection aboserver {}',self._attached)
if self._attached:
FreeCADGui.Selection.removeObserver(self)
self._attached = False
self.clearSelection('')
class AsmCmdManager(ProxyType):
_HiddenToolbars = set()
Toolbars = OrderedDict()
Menus = OrderedDict()
_defaultMenuGroupName = '&Assembly3'
WorkbenchActivated = False
@staticmethod
def getToolbarParams():
return FreeCAD.ParamGet('User parameter:BaseApp/MainWindow/Toolbars')
@classmethod
def init(mcs):
if not mcs.getParam('Bool','GuiInited',False):
hgrp = mcs.getToolbarParams()
for toolbar in mcs._HiddenToolbars:
hgrp.SetBool(toolbar,False)
mcs.setParam('Bool','GuiInited',True)
@classmethod
def toggleToolbars(mcs):
hgrp = mcs.getToolbarParams()
show = False
for toolbar in mcs._HiddenToolbars:
if not hgrp.GetBool(toolbar,True):
show = True
break
mw = FreeCADGui.getMainWindow()
for toolbar in mcs._HiddenToolbars:
if show != hgrp.GetBool(toolbar,True):
hgrp.SetBool(toolbar,show)
tb = mw.findChild(QtGui.QToolBar,toolbar)
if not tb:
logger.error('cannot find toolbar "{}"',toolbar)
tb.setVisible(show)
@classmethod
def register(mcs,cls):
if cls._id < 0:
return
super(AsmCmdManager,mcs).register(cls)
FreeCADGui.addCommand(cls.getName(),cls)
if cls._toolbarName:
tb = mcs.Toolbars.setdefault(cls._toolbarName,[])
if not tb and not getattr(cls,'_toolbarVisible',True):
mcs._HiddenToolbars.add(cls._toolbarName)
tb.append(cls)
if cls._menuGroupName is not None:
name = cls._menuGroupName
if not name:
name = mcs._defaultMenuGroupName
mcs.Menus.setdefault(name,[]).append(cls)
@classmethod
def getParamGroup(mcs):
return FreeCAD.ParamGet(
'User parameter:BaseApp/Preferences/Mod/Assembly3')
@classmethod
def getParam(mcs,tp,name,default=None):
return getattr(mcs.getParamGroup(),'Get'+tp)(name,default)
@classmethod
def setParam(mcs,tp,name,v):
getattr(mcs.getParamGroup(),'Set'+tp)(name,v)
def workbenchActivated(cls):
pass
def workbenchDeactivated(cls):
pass
def getContextMenuName(cls):
if cls.IsActive() and cls._contextMenuName:
return cls._contextMenuName
def getName(cls):
return 'asm3'+cls.__name__[3:]
def getMenuText(cls):
return cls._menuText
def getToolTip(cls):
return getattr(cls,'_tooltip',cls.getMenuText())
def IsActive(cls):
if cls._id<0 or not FreeCAD.ActiveDocument:
return False
if cls._active is None:
cls.checkActive()
return cls._active
def onSelectionChange(cls, hasSelection):
_ = hasSelection
class AsmCmdBase(with_metaclass(AsmCmdManager, object)):
_id = -1
_active = None
_toolbarName = 'Assembly3'
_menuGroupName = ''
_contextMenuName = 'Assembly'
_accel = None
@classmethod
def checkActive(cls):
cls._active = True
@classmethod
def getIconName(cls):
return addIconToFCAD(cls._iconName)
@classmethod
def GetResources(cls):
ret = {
'Pixmap':cls.getIconName(),
'MenuText':cls.getMenuText(),
'ToolTip':cls.getToolTip()
}
if cls._accel:
ret['Accel'] = cls._accel
return ret
class AsmCmdNew(AsmCmdBase):
_id = 0
_menuText = 'Create assembly'
_iconName = 'Assembly_New_Assembly.svg'
_accel = 'A, N'
@classmethod
def Activated(cls):
from . import assembly
assembly.Assembly.make()
class AsmCmdSolve(AsmCmdBase):
_id = 1
_menuText = 'Solve constraints'
_iconName = 'AssemblyWorkbench.svg'
_accel = 'A, S'
@classmethod
def Activated(cls):
from . import solver
FreeCAD.setActiveTransaction('Assembly solve')
logger.report('command "{}" exception'.format(cls.getName()),
solver.solve,reportFailed=True)
FreeCAD.closeActiveTransaction()
class AsmCmdQuickSolve(AsmCmdBase):
_id = 21
_menuText = 'Quick solve'
_iconName = 'Assembly_QuickSolve.svg'
_accel = 'A, F'
@classmethod
def Activated(cls):
from . import solver
FreeCAD.setActiveTransaction('Assembly quick solve')
logger.report('command "{}" exception'.format(cls.getName()),
solver.solve)
FreeCAD.closeActiveTransaction()
class AsmCmdNewElement(AsmCmdBase):
_id = 19
_menuText = 'Create element'
_iconName = 'Assembly_New_Element.svg'
_accel = 'A, E'
@classmethod
def Activated(cls):
from . import assembly
logger.report('Failed to add element',
assembly.AsmElement.make, undo=True, allowDuplicate=
QtGui.QApplication.keyboardModifiers()==QtCore.Qt.ControlModifier)
@classmethod
def checkActive(cls):
from . import assembly
cls._active = logger.catchTrace(
'',assembly.AsmElement.getSelections) is not None
@classmethod
def onSelectionChange(cls,hasSelection):
cls._active = None if hasSelection else False
class AsmCmdMove(AsmCmdBase):
_id = 2
_menuText = 'Move part'
_iconName = 'Assembly_Move.svg'
_accel = 'A, M'
_moveInfo = None
@classmethod
def Activated(cls):
from . import mover
mover.movePart(True,cls._moveInfo)
@classmethod
def canMove(cls):
from . import mover
cls._moveInfo = None
cls._moveInfo = mover.getMovingElementInfo()
mover.checkFixedPart(cls._moveInfo.ElementInfo)
return True
@classmethod
def checkActive(cls):
cls._active = True if logger.catchTrace('',cls.canMove) else False
@classmethod
def onSelectionChange(cls,hasSelection):
if not hasSelection:
cls._active = False
else:
cls._active = None
cls._moveInfo = None
class AsmCmdAxialMove(AsmCmdBase):
_id = 3
_menuText = 'Axial move part'
_iconName = 'Assembly_AxialMove.svg'
_useCenterballDragger = False
_accel = 'A, A'
@classmethod
def IsActive(cls):
return AsmCmdMove.IsActive()
@classmethod
def Activated(cls):
from . import mover
mover.movePart(False,AsmCmdMove._moveInfo)
class AsmCmdQuickMove(AsmCmdAxialMove):
_id = 13
_menuText = 'Quick move'
_tooltip = 'Bring an object contained in an assembly to where the mouse\n'\
'is located. This is designed to help bringing an object far\n'\
'away quickly into view.'
_iconName = 'Assembly_QuickMove.svg'
_accel = 'A, Q'
@classmethod
def Activated(cls):
from . import mover
mover.quickMove()
class AsmCmdCheckable(AsmCmdBase):
_id = -2
_saveParam = False
_defaultValue = False
@classmethod
def getAttributeName(cls):
return cls.__name__[6:]
@classmethod
def getChecked(cls):
return getattr(cls.__class__,cls.getAttributeName())
@classmethod
def setChecked(cls,v):
setattr(cls.__class__,cls.getAttributeName(),v)
if cls._saveParam:
cls.setParam('Bool',cls.getAttributeName(),v)
@classmethod
def onRegister(cls):
if cls._saveParam:
v = cls.getParam('Bool',cls.getAttributeName(),cls._defaultValue)
else:
v = False
cls.setChecked(v)
@classmethod
def GetResources(cls):
ret = super(AsmCmdCheckable,cls).GetResources()
ret['Checkable'] = cls.getChecked()
return ret
@classmethod
def Activated(cls,checked):
cls.setChecked(True if checked else False)
class AsmCmdLockMover(AsmCmdCheckable):
_id = 15
_menuText = 'Lock mover'
_tooltip = 'Lock mover for fixed part'
_iconName = 'Assembly_LockMover.svg'
_saveParam = True
@classmethod
def Activated(cls,checked):
super(AsmCmdLockMover,cls).Activated(checked)
AsmCmdMove._active = None
AsmCmdAxialMove._active = None
AsmCmdQuickMove._active = None
class AsmCmdToggleVisibility(AsmCmdBase):
_id = 17
_menuText = 'Toggle part visibility'
_tooltip = 'Toggle the visibility of the selected part'
_iconName = 'Assembly_TogglePartVisibility.svg'
_accel = 'A, Space'
@classmethod
def Activated(cls):
moveInfo = AsmCmdMove._moveInfo
if not moveInfo:
return
info = moveInfo.ElementInfo
if info.Subname:
subs = moveInfo.SelSubname[:-len(info.Subname)]
else:
subs = moveInfo.SelSubname
subs = subs.split('.')
if isinstance(info.Part,tuple):
part = info.Part[0]
vis = part.isElementVisible(str(info.Part[1]))
part.setElementVisible(str(info.Part[1]),not vis)
else:
from .assembly import resolveAssembly
partGroup = resolveAssembly(info.Parent).getPartGroup()
vis = partGroup.isElementVisible(info.Part.Name)
partGroup.setElementVisible(info.Part.Name,not vis)
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(moveInfo.SelObj,'.'.join(subs))
FreeCADGui.runCommand('Std_TreeSelection')
if vis:
FreeCADGui.runCommand('Std_TreeCollapse')
@classmethod
def IsActive(cls):
return AsmCmdMove._moveInfo is not None
class AsmCmdTrace(AsmCmdCheckable):
_id = 4
_menuText = 'Trace part move'
_iconName = 'Assembly_Trace.svg'
_object = None
_subname = None
@classmethod
def Activated(cls,checked):
super(AsmCmdTrace,cls).Activated(checked)
if not checked:
cls._object = None
return
sel = FreeCADGui.Selection.getSelectionEx('',False)
if len(sel)==1:
subs = sel[0].SubElementNames
if len(subs)==1:
cls._object = sel[0].Object
cls._subname = subs[0]
logger.info('trace {}.{}',cls._object.Name,cls._subname)
return
logger.info('trace moving element')
@classmethod
def getPosition(cls):
if not cls._object:
return
try:
if cls._object.Document != FreeCAD.ActiveDocument:
cls._object = None
return getElementPos((cls._object,cls._subname))
except Exception:
cls._object = None
class AsmCmdAutoRecompute(AsmCmdCheckable):
_id = 5
_menuText = 'Auto recompute'
_iconName = 'Assembly_AutoRecompute.svg'
_saveParam = True
@classmethod
def IsActive(cls):
return True
class AsmCmdSmartRecompute(AsmCmdCheckable):
_id = 22
_menuText = 'Smart recompute'
_tooltip = 'Toggle smart recompute to reduce recompution time'
_iconName = 'Assembly_SmartRecompute.svg'
_saveParam = True
@classmethod
def IsActive(cls):
return True
class AsmCmdAutoElementVis(AsmCmdCheckable):
_id = 9
_menuText = 'Auto element visibility'
_iconName = 'Assembly_AutoElementVis.svg'
_saveParam = True
_defaultValue = True
@classmethod
def IsActive(cls):
return True
@classmethod
def Activated(cls,checked):
super(AsmCmdAutoElementVis,cls).Activated(checked)
from .assembly import isTypeOf,AsmConstraint,\
AsmElement,AsmElementLink,AsmElementGroup
for doc in FreeCAD.listDocuments().values():
for obj in doc.Objects:
if isTypeOf(obj,(AsmConstraint,AsmElementGroup)):
obj.Visibility = False
if isTypeOf(obj,AsmConstraint):
obj.ViewObject.OnTopWhenSelected = 2
obj.setPropertyStatus('VisibilityList',
'NoModify' if checked else '-NoModify')
elif isTypeOf(obj,(AsmElementLink,AsmElement)):
if checked:
obj.Proxy.parent.Object.setElementVisible(
obj.Name,False)
obj.Visibility = False
obj.ViewObject.OnTopWhenSelected = 2
class AsmCmdAddWorkplane(AsmCmdBase):
_id = 8
_menuText = 'Add workplane'
_iconName = 'Assembly_Add_Workplane.svg'
_toolbarName = None
_menuGroupName = None
_accel = 'A, P'
_makeType = 0
@classmethod
def checkActive(cls):
from . import assembly
if logger.catchTrace('Add workplane selection',
assembly.AsmWorkPlane.getSelection):
cls._active = True
else:
cls._active = False
@classmethod
def onSelectionChange(cls,hasSelection):
cls._active = None if hasSelection else False
@classmethod
def Activated(cls,idx=0):
_ = idx
from . import assembly
assembly.AsmWorkPlane.make(tp=cls._makeType)
class AsmCmdAddWorkplaneXZ(AsmCmdAddWorkplane):
_id = 10
_menuText = 'Add XZ workplane'
_iconName = 'Assembly_Add_WorkplaneXZ.svg'
_makeType = 1
class AsmCmdAddWorkplaneZY(AsmCmdAddWorkplane):
_id = 11
_menuText = 'Add ZY workplane'
_iconName = 'Assembly_Add_WorkplaneZY.svg'
_makeType = 2
class AsmCmdAddOrigin(AsmCmdCheckable):
_id = 14
_menuText = 'Add Origin'
_iconName = 'Assembly_Add_Origin.svg'
_makeType = 3
_saveParam = False
_toolbarName = None
_menuGroupName = None
@classmethod
def IsActive(cls):
return True
@classmethod
def Activated(cls,checked):
logger.info('checked {}'.format(checked))
cls.setChecked(checked)
if checked:
from . import assembly
sels = logger.catchTrace('Add origin selection',
assembly.AsmWorkPlane.getSelection)
if sels:
assembly.AsmWorkPlane.make(sels,tp=cls._makeType)
class AsmCmdAddWorkplaneGroup(AsmCmdBase):
_id = 12
_iconName = AsmCmdAddWorkplane._iconName
_menuText = AsmCmdAddWorkplane._menuText
_menuGroupName = ''
_toolbarName = AsmCmdBase._toolbarName
_cmds = (AsmCmdAddWorkplane.getName(),
AsmCmdAddWorkplaneXZ.getName(),
AsmCmdAddWorkplaneZY.getName(),
AsmCmdAddOrigin.getName())
@classmethod
def IsActive(cls):
return True
@classmethod
def GetCommands(cls):
return cls._cmds
class AsmCmdGotoRelation(AsmCmdBase):
_id = 16
_menuText = 'Go to relation'
_tooltip = 'Select the corresponding part object in the relation group'
_iconName = 'Assembly_GotoRelation.svg'
_accel = 'A, R'
_toolbarName = ''
@classmethod
def Activated(cls):
from .assembly import AsmRelationGroup
if AsmCmdMove._moveInfo:
AsmRelationGroup.gotoRelation(AsmCmdMove._moveInfo)
return
sels = FreeCADGui.Selection.getSelectionEx('',0,True)
if sels and len(sels[0].SubElementNames)==1:
AsmRelationGroup.gotoRelationOfConstraint(
sels[0].Object,sels[0].SubElementNames[0])
@classmethod
def IsActive(cls):
if AsmCmdMove._moveInfo:
return True
if cls._active is None:
cls.checkActive()
return cls._active
@classmethod
def checkActive(cls):
from .assembly import isTypeOf, AsmConstraint, AsmElementLink
sels = FreeCADGui.Selection.getSelection('',1,True)
if sels and isTypeOf(sels[0],(AsmConstraint,AsmElementLink)):
cls._active = True
else:
cls._active = False
@classmethod
def onSelectionChange(cls,hasSelection):
cls._active = None if hasSelection else False
class AsmCmdGotoLinked(AsmCmdBase):
_id = 20
_menuText = 'Select linked object'
_tooltip = 'Select the linked object'
_accel = 'A, G'
_toolbarName = ''
@classmethod
def getIconName(cls):
return 'LinkSelect'
@classmethod
def Activated(cls):
from .assembly import isTypeOf, \
AsmElement, AsmElementLink, AsmElementGroup
sels = FreeCADGui.Selection.getSelectionEx('',0,True)
if not sels:
return
if not sels[0].SubElementNames:
FreeCADGui.runCommand('Std_LinkSelectLinked')
return
subname = sels[0].SubElementNames[0]
obj = sels[0].Object.getSubObject(subname,retType=1)
if not isTypeOf(obj,AsmElementLink) and not isTypeOf(obj,AsmElement):
FreeCADGui.runCommand('Std_LinkSelectLinked')
return
import Part
subname = Part.splitSubname(subname)[0].split('.')
link = obj.LinkedObject
if isinstance(link,tuple):
linkSub = link[1]
link = link[0]
else:
linkSub = link.Name + '.'
link = obj.Proxy.getAssembly().getElementGroup()
if isTypeOf(obj,AsmElementLink):
subname = subname[:-4]
if not isTypeOf(link,AsmElementGroup):
subname.append('3')
else:
subname = subname[:-2]
subname[-1] = '2'
subname.append(link.Name)
subname = '.'.join(subname+linkSub.split('.'))
sobj = sels[0].Object.getSubObject(subname,retType=1)
if not sobj:
logger.error('Cannot find sub object {}.{}',
objName(sels[0].Object),subname)
return
FreeCADGui.Selection.pushSelStack()
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(sels[0].Object,subname)
FreeCADGui.Selection.pushSelStack()
FreeCADGui.runCommand('Std_TreeSelection')
@classmethod
def IsActive(cls):
return FreeCADGui.isCommandActive('Std_LinkSelectLinked')
class AsmCmdGotoLinkedFinal(AsmCmdBase):
_id = 23
_menuText = 'Select linked final'
_tooltip = 'Select the deepest linked object'
_accel = 'A, F'
_toolbarName = ''
@classmethod
def getIconName(cls):
return 'LinkSelectFinal'
@classmethod
def Activated(cls):
from .assembly import isTypeOf, AsmElement, AsmElementLink
sels = FreeCADGui.Selection.getSelectionEx('',0,True)
if not sels:
return
if not sels[0].SubElementNames:
FreeCADGui.runCommand('Std_LinkSelectLinkedFinal')
return
subname = sels[0].SubElementNames[0]
obj = sels[0].Object.getSubObject(subname,retType=1)
if not isTypeOf(obj,(AsmElementLink,AsmElement)):
FreeCADGui.runCommand('Std_LinkSelectLinkedFinal')
return
while True:
linked = obj.LinkedObject
if isinstance(linked,tuple):
subname = linked[1]
linked = linked[0]
else:
subname = ''
obj = linked.getSubObject(subname,retType=1)
if not isTypeOf(obj,AsmElement):
break
obj = obj.getLinkedObject(True)
import Part
subname = Part.splitSubname(subname)[-1]
FreeCADGui.Selection.pushSelStack()
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(obj,subname)
FreeCADGui.Selection.pushSelStack()
FreeCADGui.runCommand('Std_TreeSelection')
@classmethod
def IsActive(cls):
from .assembly import isTypeOf, AsmElement, AsmElementLink
sels = FreeCADGui.Selection.getSelectionEx('',0,True)
if len(sels)==1 and sels[0].SubElementNames:
obj = sels[0].Object.getSubObject(sels[0].SubElementNames[0],1)
if isTypeOf(obj, (AsmElementLink,AsmElement)):
return True
return FreeCADGui.isCommandActive('Std_LinkSelectLinkedFinal')
class AsmCmdUp(AsmCmdBase):
_id = 6
_menuText = 'Move item up'
_iconName = 'Assembly_TreeItemUp.svg'
@classmethod
def getSelection(cls):
from .assembly import isTypeOf, Assembly, AsmGroup
sels = FreeCADGui.Selection.getSelectionEx('',False)
if len(sels)!=1 or len(sels[0].SubElementNames)!=1:
return
ret= sels[0].Object.resolve(sels[0].SubElementNames[0])
obj,parent = ret[0],ret[1]
if isTypeOf(parent,Assembly) or not isTypeOf(parent,AsmGroup) or \
len(parent.Group) <= 1:
return
return (obj,parent,sels[0].Object,sels[0].SubElementNames[0])
@classmethod
def checkActive(cls):
cls._active = True if cls.getSelection() else False
@classmethod
def move(cls,step):
ret = cls.getSelection()
if not ret:
return
obj,parent,topParent,subname = ret
children = parent.Group
i = children.index(obj)
j = i+step
if j<0:
j = len(children)-1
elif j>=len(children):
j = 0
logger.debug('move {}:{} -> {}:{}',
i,objName(obj),j,objName(children[j]))
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')
FreeCAD.closeActiveTransaction();
# The tree view may deselect the item because of claimChildren changes,
# so we restore the selection here
FreeCADGui.Selection.addSelection(topParent,subname)
@classmethod
def onSelectionChange(cls,hasSelection):
cls._active = None if hasSelection else False
@classmethod
def Activated(cls):
cls.move(-1)
class AsmCmdDown(AsmCmdUp):
_id = 7
_menuText = 'Move item down'
_iconName = 'Assembly_TreeItemDown.svg'
@classmethod
def Activated(cls):
cls.move(1)
class AsmCmdMultiply(AsmCmdBase):
_id = 18
_menuText = 'Multiply constraint'
_tooltip = 'Mutiply the part owner of the first element to constrain\n'\
'against the rest of the elements.\n\n'\
'To activate this function, the FIRST part must be of the\n'\
'FIRST element of a link array. In will optionally expand\n'\
'colplanar circular edges with the same radius in the second\n'\
'element on wards. To disable auto expansion, use NoExpand\n'\
'property in the element link.'
_iconName = 'Assembly_ConstraintMultiply.svg'
@classmethod
def checkActive(cls):
from .assembly import AsmConstraint
if logger.catchTrace('',AsmConstraint.makeMultiply,True):
cls._active = True
else:
cls._active = False
@classmethod
def Activated(cls):
from .assembly import AsmConstraint
logger.report('',AsmConstraint.makeMultiply)
@classmethod
def onSelectionChange(cls,hasSelection):
cls._active = None if hasSelection else False