def initUI(self): # clear the parent name (if any) self.parentDoc.clear() self.partLCSlist.clear() self.attLCSlist.clear() # the selected link's name self.linkName.setText( Asm4.labelName(self.selectedObj) ) # linked part & doc dText = '' if self.selectedObj.LinkedObject.Document != self.activeDoc : dText = self.selectedObj.LinkedObject.Document.Name +'#' # if the linked part has been renamed by the user, keep the label and add (.Name) pText = Asm4.labelName(self.selectedObj.LinkedObject) self.linkedDoc.setText( dText + pText ) # Initialize the assembly tree with the Parent Assembly as first element # clear the available parents combo box self.parentTable = [] self.parentList.clear() self.parentTable.append( [] ) self.parentList.addItem('Please select') self.parentTable.append( self.rootAssembly ) parentIcon = self.rootAssembly.ViewObject.Icon self.parentList.addItem( parentIcon, 'Parent Assembly', self.rootAssembly ) # set the old position values self.XtranslSpinBox.setValue(self.old_LinkPosition[0]) self.YtranslSpinBox.setValue(self.old_LinkPosition[1]) self.ZtranslSpinBox.setValue(self.old_LinkPosition[2])
def addSelection(self, doc, obj, sub, pnt): parentFound = False # selected object selObj = Gui.Selection.getSelection()[0] selPath = Asm4.getSelectionPath(doc, obj, sub) # check that a datum object is selected if selObj.TypeId in Asm4.datumTypes and len(selPath) > 2: selLink = self.activeDoc.getObject(selPath[2]) # if it's the selected link to be placed: if selLink == self.selectedObj: # try to find the selected LCS in the partLCS list found = self.partLCSlist.findItems(Asm4.labelName(selObj), QtCore.Qt.MatchExactly) if len(found) > 0: self.partLCSlist.clearSelection() self.partLCSlist.scrollToItem(found[0]) self.partLCSlist.setCurrentItem(found[0]) # show and highlight LCS selObj.Visibility=True # highlight the entire object if selected in the 3D window if pnt != (0,0,0): pass # preview the part's placement self.Apply() # if it's a child in the assembly: elif selLink in self.parentTable: # find the parent idx = self.parentList.findText(Asm4.labelName(selLink), QtCore.Qt.MatchExactly) if idx >= 0: self.parentList.setCurrentIndex(idx) # this has triggered to fill in the attachment LCS list parentFound = True # if it's the object itself, then it belongs to the root assembly elif selLink == selObj and obj == self.rootAssembly.Name: self.parentList.setCurrentIndex(1) # this has triggered to fill in the attachment LCS list parentFound = True # if a parent was found if parentFound: # now lets try to find the selected LCS in this list found = self.attLCSlist.findItems(Asm4.labelName(selObj), QtCore.Qt.MatchExactly) if len(found) > 0: self.attLCSlist.clearSelection() self.attLCSlist.scrollToItem(found[0]) self.attLCSlist.setCurrentItem(found[0]) # show and highlight LCS selObj.Visibility=True # highlight the entire object if selected in the 3D window if pnt != (0,0,0): pass # preview the part's placement self.Apply()
def onParentList(self): # clear the LCS list self.attLCSlist.clear() self.attLCStable = [] # clear the selection in the GUI window Gui.Selection.clearSelection() # keep the fastener selected Gui.Selection.addSelection(self.activeDoc.Name, self.rootAssembly.Name, self.selectedFastener.Name + '.') # the current text in the combo-box is the link's name... # ... or it's 'Parent Assembly' then the parent is the 'Model' root App::Part if self.parentList.currentText() == 'Parent Assembly': parentName = 'Parent Assembly' # parentPart = self.activeDoc.getObject( 'Model' ) parentPart = self.rootAssembly # we get the LCS directly in the root App::Part self.attLCStable = Asm4.getPartLCS(parentPart) self.parentDoc.setText(parentPart.Document.Name + '#' + Asm4.labelName(parentPart)) # if something is selected elif self.parentList.currentIndex() > 1: parentName = self.parentTable[self.parentList.currentIndex()].Name parentPart = self.activeDoc.getObject(parentName) if parentPart: # we get the LCS from the linked part self.attLCStable = Asm4.getPartLCS(parentPart.LinkedObject) # linked part & doc dText = parentPart.LinkedObject.Document.Name + '#' # if the linked part has been renamed by the user pText = Asm4.labelName(parentPart.LinkedObject) self.parentDoc.setText(dText + pText) # highlight the selected part: Gui.Selection.addSelection( \ parentPart.Document.Name, self.rootAssembly.Name, parentPart.Name+'.' ) QtCore.QTimer.singleShot(1500, lambda:Gui.Selection.removeSelection( \ parentPart.Document.Name, self.rootAssembly.Name, parentPart.Name+'.' ) ) # something wrong else: return # build the list self.attLCSlist.clear() for lcs in self.attLCStable: newItem = QtGui.QListWidgetItem() newItem.setText(Asm4.labelName(lcs)) newItem.setIcon(lcs.ViewObject.Icon) self.attLCSlist.addItem(newItem) #self.attLCStable.append(lcs) return
def lookForParts( self, doc=None ): self.allParts = [] self.partsDoc = [] self.partList.clear() if doc is None: docList = App.listDocuments().values() else: docList = [doc] for doc in docList: # don't consider temporary documents if not doc.Temporary: for obj in doc.findObjects("App::Part"): # we don't want to link to itself to the 'Model' object # other App::Part in the same document are OK # but only those at top level (not nested inside other containers) if obj != self.rootAssembly and obj.getParentGeoFeatureGroup() is None: self.allParts.append( obj ) self.partsDoc.append( doc ) for obj in doc.findObjects("PartDesign::Body"): # but only those at top level (not nested inside other containers) if obj.getParentGeoFeatureGroup() is None: self.allParts.append( obj ) self.partsDoc.append( doc ) # build the list for part in self.allParts: newItem = QtGui.QListWidgetItem() newItem.setText( part.Document.Name +"#"+ Asm4.labelName(part) ) newItem.setIcon(part.ViewObject.Icon) self.partList.addItem(newItem)
def addSelection(self, doc, obj, sub, pnt): selPath = Asm4.getSelectionPath(doc, obj, sub) selObj = Gui.Selection.getSelection()[0] if selObj and len(selPath) > 2: selLinkName = selPath[2] selLink = App.ActiveDocument.getObject(selLinkName) idx = self.parentList.findText(Asm4.labelName(selLink), QtCore.Qt.MatchExactly) # if selLink is in the child list if idx >= 0: self.parentList.setCurrentIndex(idx) # else it might be an LCS in the root assembly elif selLink.TypeId in Asm4.datumTypes: self.parentList.setCurrentIndex(1) # this has triggered to fill the LCS list found = self.attLCSlist.findItems(Asm4.labelName(selObj), QtCore.Qt.MatchExactly) if len(found) > 0: self.attLCSlist.clearSelection() found[0].setSelected(True) self.attLCSlist.scrollToItem(found[0]) self.attLCSlist.setCurrentRow(self.attLCSlist.row(found[0])) self.onApply()
def Activated(self): # check what we have selected selectedObj = self.checkSelection() if not selectedObj: return objName = selectedObj.Name objLabel = selectedObj.Label objType = selectedObj.TypeId # ask for confirmation before resetting everything confirmText = 'This command will release all attachments on '+Asm4.labelName(selectedObj) \ +' and set it to manual positioning in its current location.' if not Asm4.confirmBox(confirmText): # don't do anything return # the root Assembly4 Model # model = App.ActiveDocument.getObject('Model') model = Asm4.getAssembly() # handle object types differently # an App::Link if objType == 'App::Link': # unset the ExpressionEngine for the Placement selectedObj.setExpression('Placement', None) # reset Asm4 properties Asm4.makeAsmProperties(selectedObj, reset=True) # a datum object else: # reset Asm4 properties Asm4.makeAsmProperties(selectedObj, reset=True) # unset both Placements (who knows what confusion the user has done) selectedObj.setExpression('Placement', None) selectedObj.setExpression('AttachmentOffset', None) # if it's a datum object if objType == 'PartDesign::CoordinateSystem' or objType == 'PartDesign::Plane' or objType == 'PartDesign::Line' or objType == 'PartDesign::Point': # unset the MapMode; this actually keeps the MapMode parameters intact, # so it's easy for the user to re-enable it selectedObj.MapMode = 'Deactivated' # recompute the assembly model model.recompute(True)
def clicked(self, bt): if bt == QtGui.QDialogButtonBox.Ignore: # ask for confirmation before resetting everything msgName = Asm4.labelName(self.selectedFastener) # see whether the ExpressionEngine field is filled if self.old_EE: # if yes, then ask for confirmation confirmed = Asm4.confirmBox( 'This command will release all attachments on ' + msgName + ' and set it to manual positioning in its current location.' ) else: # if not, then it's useless to bother the user confirmed = True if confirmed: # unset the ExpressionEngine in the Placement self.selectedFastener.setExpression('Placement', None) # reset Asm4 properties Asm4.makeAsmProperties(self.selectedFastener, reset=True) self.finish()
def clicked(self, button): if button == QtGui.QDialogButtonBox.Apply: self.Apply() elif button == QtGui.QDialogButtonBox.Ignore: # ask for confirmation before resetting everything msgName = Asm4.labelName(self.selectedObj) # see whether the ExpressionEngine field is filled if self.selectedObj.ExpressionEngine : # if yes, then ask for confirmation confirmed = Asm4.confirmBox('This command will release all attachments on '+msgName+' and set it to manual positioning in its current location.') # if not, then it's useless to bother the user else: confirmed = True if confirmed: # unset the ExpressionEngine for the Placement self.selectedObj.setExpression('Placement', None) # reset the assembly properties Asm4.makeAsmProperties( self.selectedObj, reset=True ) # finish FCC.PrintMessage("Part is now manually placed\n") self.finish() else: FCC.PrintMessage("Part untouched\n") self.finish()
def __init__(self): # self.base = QtGui.QWidget() # self.form = self.base self.form = QtGui.QWidget() self.form.setWindowIcon(QtGui.QIcon(iconFile)) self.form.setWindowTitle('Attach a Fastener in the assembly') # get the current active document to avoid errors if user changes tab self.activeDoc = App.activeDocument() # the parent (top-level) assembly is the App::Part called Model (hard-coded) self.rootAssembly = Asm4.getAssembly() # has been checked before calling self.selectedFastener = getSelectionFS() # check where the fastener was attached to (self.old_Parent, separator, self.old_parentLCS) = self.selectedFastener.AttachedTo.partition('#') # get and store the Placement's current ExpressionEngine: self.old_EE = Asm4.placementEE(self.selectedFastener.ExpressionEngine) if hasattr(self.selectedFastener, 'AttachmentOffset'): self.old_AO = self.selectedFastener.AttachmentOffset else: self.old_AO = None # Now we can draw the UI self.drawUI() self.initUI() # now self.parentList and self.parentTable are available # find all the linked parts in the assembly for obj in self.activeDoc.findObjects("App::Link"): if self.rootAssembly.getObject(obj.Name) is not None and hasattr( obj.LinkedObject, 'isDerivedFrom'): linkedObj = obj.LinkedObject FCC.PrintMessage("found link to " + linkedObj.Name) if linkedObj.isDerivedFrom( 'App::Part') or linkedObj.isDerivedFrom( 'PartDesign::Body'): # add to the object table holding the objects ... self.parentTable.append(obj) # ... and add to the drop-down combo box with the assembly tree's parts objIcon = linkedObj.ViewObject.Icon objText = Asm4.labelName(obj) self.parentList.addItem(objIcon, objText, obj) # decode the old ExpressionEngine # if the decode is unsuccessful, old_Expression is set to False # and old_attPart and old_attLCS are set to 'None' old_Parent = '' old_parentPart = '' old_parentLCS = '' if self.old_EE and self.old_Parent: (old_Parent, old_parentPart, old_parentLCS) = self.splitExpressionFastener( self.old_EE, self.old_Parent) # find the oldPart in the part list... parent_index = 1 if old_Parent == 'Parent Assembly': parent_found = True else: parent_found = False for item in self.parentTable[1:]: if item.Name == old_Parent: parent_found = True break else: parent_index += 1 if not parent_found: parent_index = 0 self.parentList.setCurrentIndex(parent_index) # this should have triggered self.getPartLCS() to fill the LCS list # find the oldLCS in the list of LCS of the linked part... lcs_found = [] lcs_found = self.attLCSlist.findItems(old_parentLCS, QtCore.Qt.MatchExactly) # may-be it was renamed, see if we can find it as (name) if not lcs_found: lcs_found = self.attLCSlist.findItems('(' + old_parentLCS + ')', QtCore.Qt.MatchContains) if lcs_found: # ... and select it self.attLCSlist.setCurrentItem(lcs_found[0]) Gui.Selection.addObserver(self, 0)
def __init__(self): # remove selectionFilter self.selectionFilterStatus = selectionFilter.observerStatus() selectionFilter.observerDisable() # get the current active document to avoid errors if user changes tab self.activeDoc = App.ActiveDocument # we have checked before that all this is correct selection = Asm4.getSelectedLink() if selection is None: selection = Asm4.getSelectedVarLink() self.selectedObj = selection #self.rootAssembly = self.selectedObj.getParentGeoFeatureGroup() self.rootAssembly = Asm4.getAssembly() # has been checked before, this is for security only if Asm4.isAsm4EE(self.selectedObj): # get the old values self.old_AO = self.selectedObj.AttachmentOffset self.old_linkLCS = self.selectedObj.AttachedBy[1:] else: # this shouldn't happen FCC.PrintWarning("WARNING : unsupported Assembly/Solver/Part combination, you shouldn't be seeing this\n") Asm4.makeAsmProperties(self.selectedObj) self.old_AO = [] self.old_linkLCS = '' # define the GUI # draw the GUI, objects are defined later down # self.UI = QtGui.QWidget() # self.form = self.UI self.form = QtGui.QWidget() iconFile = os.path.join( Asm4.iconPath , 'Place_Link.svg') self.form.setWindowIcon(QtGui.QIcon( iconFile )) self.form.setWindowTitle('Place linked Part') self.drawUI(self.form) #save original AttachmentOffset of linked part self.old_LinkAttachmentOffset = self.selectedObj.AttachmentOffset self.old_LinkRotation = self.selectedObj.AttachmentOffset.Rotation self.old_LinkPosition = self.selectedObj.AttachmentOffset.Base # default values correspond to original AttachmentOffset of linked part self.Xtranslation = self.old_LinkPosition[0] self.Ytranslation = self.old_LinkPosition[1] self.Ztranslation = self.old_LinkPosition[2] self.XrotationAngle = self.old_LinkRotation.toEuler()[0] self.YrotationAngle = self.old_LinkRotation.toEuler()[1] self.ZrotationAngle = self.old_LinkRotation.toEuler()[2] # save previous view properties self.old_OverrideMaterial = self.selectedObj.ViewObject.OverrideMaterial self.old_DrawStyle = self.selectedObj.ViewObject.DrawStyle self.old_LineWidth = self.selectedObj.ViewObject.LineWidth self.old_DiffuseColor = self.selectedObj.ViewObject.ShapeMaterial.DiffuseColor self.old_Transparency = self.selectedObj.ViewObject.ShapeMaterial.Transparency # set new view properties self.selectedObj.ViewObject.OverrideMaterial = True self.selectedObj.ViewObject.DrawStyle = DrawStyle self.selectedObj.ViewObject.LineWidth = LineWidth self.selectedObj.ViewObject.ShapeMaterial.DiffuseColor = DiffuseColor self.selectedObj.ViewObject.ShapeMaterial.Transparency = Transparency # get the old values self.old_EE = '' old_Parent = '' old_ParentPart = '' old_attLCS = '' constrName = '' linkedDoc = '' old_linkLCS = '' # get and store the current expression engine: self.old_EE = Asm4.placementEE(self.selectedObj.ExpressionEngine) # decode the old ExpressionEngine # if the decode is unsuccessful, old_Expression is set to False and the other things are set to 'None' (self.old_Parent, separator, self.old_parentLCS) = self.selectedObj.AttachedTo.partition('#') ( old_Parent, old_attLCS, old_linkLCS ) = self.splitExpressionLink( self.old_EE, self.old_Parent ) # sometimes, the object is in << >> which is an error by FreeCAD, # because that's reserved for labels, but we still look for it if len(old_attLCS)>4 and old_attLCS[:2]=='<<' and old_attLCS[-2:]=='>>': old_attLCS = old_attLCS[2:-2] if len(old_linkLCS)>4 and old_linkLCS[:2]=='<<' and old_linkLCS[-2:]=='>>': old_linkLCS = old_linkLCS[2:-2] # initialize the UI with the current data self.attLCStable = [] self.initUI() # now self.parentList and self.parentTable are available # find all the linked parts in the assembly for obj in self.activeDoc.findObjects("App::Link"): if self.rootAssembly.getObject(obj.Name) is not None and hasattr(obj.LinkedObject,'isDerivedFrom'): linkedObj = obj.LinkedObject if linkedObj.isDerivedFrom('App::Part') or linkedObj.isDerivedFrom('PartDesign::Body'): # ... except if it's the selected link itself if obj != self.selectedObj: self.parentTable.append( obj ) # add to the drop-down combo box with the assembly tree's parts objIcon = linkedObj.ViewObject.Icon objText = Asm4.labelName(obj) self.parentList.addItem( objIcon, objText, obj) # find all the LCS in the selected link self.partLCStable = Asm4.getPartLCS( self.selectedObj.LinkedObject ) # build the list self.partLCSlist.clear() for lcs in self.partLCStable: newItem = QtGui.QListWidgetItem() newItem.setText(Asm4.labelName(lcs)) newItem.setIcon( lcs.ViewObject.Icon ) self.partLCSlist.addItem(newItem) # find the old LCS in the list of LCS of the linked part... # MatchExactly, MatchContains, MatchEndsWith ... # find with Name ... lcs_found = self.partLCSlist.findItems( old_linkLCS, QtCore.Qt.MatchExactly ) # ... or with (Name) if not lcs_found: lcs_found = self.partLCSlist.findItems( '('+old_linkLCS+')', QtCore.Qt.MatchEndsWith ) if lcs_found: # ... and select it self.partLCSlist.setCurrentItem( lcs_found[0] ) # find the oldPart in the part list... if old_Parent == 'Parent Assembly': parent_found = True parent_index = 1 else: parent_found = False parent_index = 1 for item in self.parentTable[1:]: if item.Name == old_Parent: parent_found = True break else: parent_index = parent_index +1 if not parent_found: parent_index = 0 self.parentList.setCurrentIndex( parent_index ) # this should have triggered self.getPartLCS() to fill the LCS list # find the old attachment Datum in the list of the Datums in the linked part... lcs_found = self.attLCSlist.findItems( old_attLCS, QtCore.Qt.MatchExactly ) if not lcs_found: lcs_found = self.attLCSlist.findItems( '('+old_attLCS+')', QtCore.Qt.MatchEndsWith ) if lcs_found: # ... and select it self.attLCSlist.setCurrentItem( lcs_found[0] ) # selection observer to detect selection of LCS in the 3D window and tree Gui.Selection.addObserver(self, 0)
def Activated(self): (selDatum, selTree) = Asm4.getSelectionTree() # the selected datum is not deep enough if not selTree or len(selTree) < 3: message = selDatum.Name + ' is already at the top-level and cannot be imported' Asm4.warningBox(message) return # the root parent container is the first in the selection tree rootContainer = App.ActiveDocument.getObject(selTree[0]) selection = self.getSelectedDatums() # special case where 2 objects are selected in order to update the placement of the second one if len(selection) == 2 and selection[1].getParentGeoFeatureGroup( ) == rootContainer: confirm = False targetDatum = selection[1] # target datum is free if targetDatum.MapMode == 'Deactivated': message = 'This will superimpose ' + Asm4.labelName( targetDatum) + ' in ' + Asm4.labelName( rootContainer) + ' on:\n\n' for objName in selTree[1:-1]: message += '> ' + objName + '\n' message += '> ' + Asm4.labelName(selDatum) Asm4.warningBox(message) confirm = True # target datum is attached else: message = Asm4.labelName(targetDatum) + ' in ' + Asm4.labelName( rootContainer) + ' is already attached to some geometry. ' message += 'This will superimpose its Placement on:\n\n' for objName in selTree[1:-1]: message += '> ' + objName + '\n' message += '> ' + Asm4.labelName(selDatum) confirm = Asm4.confirmBox(message) if confirm: self.setupTargetDatum(targetDatum, self.getDatumExpression(selTree)) # hide initial datum selDatum.Visibility = False # select the newly created datum Gui.Selection.clearSelection() Gui.Selection.addSelection(App.ActiveDocument.Name, rootContainer.Name, targetDatum.Name + '.') # recompute assembly rootContainer.recompute(True) # Done with the special case, no need to continue with the normal process return # Single or Multiple selection(s) for regular case # Notify user that default names will be used and import all the objects proposedName = selTree[-2] + '_' + selDatum.Label if len(selection) == 1: message = 'Create a new ' + selDatum.TypeId + ' in ' + Asm4.labelName( rootContainer) + ' \nsuperimposed on:\n\n' for objName in selTree[1:]: message += '> ' + objName + '\n' message += '\nEnter name for this datum :' + ' ' * 40 userSpecifiedName, confirm = QtGui.QInputDialog.getText( None, 'Import Datum', message, text=proposedName) else: message = str( len(selection) ) + " selected datum objects will be imported into the root assembly\n" message += "with their default names such as:\n" message += proposedName confirm = Asm4.confirmBox(message) if confirm: for index in range(len(selection)): (selDatum, selTree) = Asm4.getSelectionTree(index) # create a new datum object if len(selection) == 1: proposedName = userSpecifiedName else: proposedName = selTree[-2] + '_' + selDatum.Label targetDatum = rootContainer.newObject(selDatum.TypeId, proposedName) targetDatum.Label = proposedName # apply existing view properties if applicable if hasattr(selDatum, 'ResizeMode') and selDatum.ResizeMode == 'Manual': targetDatum.ResizeMode = 'Manual' if hasattr(selDatum, 'Length'): targetDatum.Length = selDatum.Length if hasattr(selDatum, 'Width'): targetDatum.Width = selDatum.Width targetDatum.ViewObject.ShapeColor = selDatum.ViewObject.ShapeColor targetDatum.ViewObject.Transparency = selDatum.ViewObject.Transparency self.setupTargetDatum(targetDatum, self.getDatumExpression(selTree)) # hide initial datum selDatum.Visibility = False # select the last created datum Gui.Selection.clearSelection() Gui.Selection.addSelection(App.ActiveDocument.Name, rootContainer.Name, targetDatum.Name + '.') # recompute assembly rootContainer.recompute(True)
def Activated(self): # This function is executed when the command is activated self.UI = QtGui.QDialog() self.drawUI() # initialise stuff self.activeDoc = App.ActiveDocument self.rootAssembly = None self.origLink = None self.brokenLink = False self.allParts = [] self.partsDoc = [] self.filterPartList.clear() self.partList.clear() self.linkNameInput.clear() # if an Asm4 Assembly is present, that's where we put the variant link if Asm4.getAssembly(): self.rootAssembly = Asm4.getAssembly() # an App::Part at the root of the document is selected, we insert the link there elif Asm4.getSelectedRootPart(): self.rootAssembly = Asm4.getSelectedRootPart() # if a variant link is selected, we see if we can duplicate it if Asm4.getSelectedVarLink(): selObj = Asm4.getSelectedVarLink() parent = selObj.getParentGeoFeatureGroup() # if the selected link is in a root App::Part if parent.TypeId == 'App::Part' and parent.getParentGeoFeatureGroup() is None: self.rootAssembly = parent self.origLink = selObj self.origPart = selObj.SourceObject ''' # if a broken link is selected elif len(Gui.Selection.getSelection())==1 : selObj = Gui.Selection.getSelection()[0] if selObj.isDerivedFrom('App::Link') and selObj.LinkedObject is None: parent = selObj.getParentGeoFeatureGroup() # if the selected (broken) link is in a root App::Part if parent.TypeId == 'App::Part' and parent.getParentGeoFeatureGroup() is None: self.brokenLink = True self.rootAssembly = parent self.origLink = selObj self.UI.setWindowTitle('Re-link broken link') self.insertButton.setText('Replace') self.linkNameInput.setText(Asm4.labelName(selObj)) self.linkNameInput.setEnabled(False) ''' if self.rootAssembly is None: Asm4.warningBox( 'Please create an Assembly' ) return # Search for all App::Parts having a "Variables" property container in all open documents # Also store the document of the part for doc in App.listDocuments().values(): # don't consider temporary documents if not doc.Temporary: for obj in doc.findObjects("App::Part"): # we don't want to link to itself to the 'Model' object # other App::Part in the same document are OK # but only those at top level (not nested inside other containers) if obj != self.rootAssembly and obj.getParentGeoFeatureGroup() is None: # and only those that have a Variables property container variables = obj.getObject('Variables') if hasattr(variables,'Type') and variables.Type=='App::PropertyContainer': self.allParts.append( obj ) self.partsDoc.append( doc ) # build the list for part in self.allParts: newItem = QtGui.QListWidgetItem() newItem.setText( part.Document.Name +"#"+ Asm4.labelName(part) ) newItem.setIcon(part.ViewObject.Icon) self.partList.addItem(newItem) # if an existing valid App::Link was selected if self.origLink and not self.brokenLink: origPart = self.origLink.SourceObject # try to find the original part of the selected link origPartText = origPart.Document.Name +"#"+ Asm4.labelName(origPart) # MatchExactly, MatchContains, MatchEndsWith, MatchStartsWith ... partFound = self.partList.findItems( origPartText, QtCore.Qt.MatchExactly ) if partFound: self.partList.setCurrentItem(partFound[0]) # self.onItemClicked(partFound[0]) # if the last character is a number, we increment this number origName = self.origLink.Label lastChar = origName[-1] if lastChar.isnumeric(): (rootName,sep,num) = origName.rpartition('_') proposedLinkName = Asm4.nextInstance(rootName,startAtOne=True) # else we take the next instance else: proposedLinkName = Asm4.nextInstance(origName) # set the proposed name in the entry field if not self.brokenLink: self.linkNameInput.setText( proposedLinkName ) # show the UI self.UI.show()