Search code examples
pythontreeviewmaya

Item 'layer 7' already exists in the treeview : in Maya


I want to add two different items that have the same name to a TreeView but they have a different parent. But I get the error:

Item 'layer 7' already exists in the TreeView

What should I do to avoid this.

My code:

import maya.cmds as cmds
import os

window = cmds.window()
layout = cmds.formLayout()

control = cmds.treeView( parent = layout, numberOfButtons = 0, abr = False )

cmds.formLayout(layout,e=True, attachForm=(control,'top', 2))
cmds.formLayout(layout,e=True, attachForm=(control,'left', 2))
cmds.formLayout(layout,e=True, attachForm=(control,'bottom', 2))
cmds.formLayout(layout,e=True, attachForm=(control,'right', 2))

cmds.showWindow( window )
startpath="C:/MyFolder/"    

cmds.treeView( control, e=True, addItem = ("layer 1", ""))
cmds.treeView( control, e=True, addItem = ("layer 2", ""))
cmds.treeView( control, e=True, addItem = ("layer 3", ""))
cmds.treeView( control, e=True, addItem = ("layer 4", ""))
cmds.treeView( control, e=True, addItem = ("layer 5", ""))
cmds.treeView( control, e=True, addItem = ("layer 6", ""))
cmds.treeView( control, e=True, addItem = ("layer 7", "layer 2"))
cmds.treeView( control, e=True, addItem = ("layer 7", "layer 3"))
cmds.treeView( control, e=True, addItem = ("layer 9", "layer 2"))
cmds.treeView( control, e=True, addItem = ("layer 10", "layer 8"))
cmds.treeView( control, e=True, addItem = ("layer 11", "layer 2"))
cmds.treeView( control, e=True, addItem = ("layer 12", ""))
cmds.treeView( control, e=True, addItem = ("layer 13", "layer 10"))

N. B: I tried to find a solution here but in vain.


Solution

  • you are trying to put your "layer 7" into two different parents, that why

    cmds.treeView( control, e=True, addItem = ("layer 7", "layer 2"))
    cmds.treeView( control, e=True, addItem = ("layer 7", "layer 3"))
    

    === Edit ===

    I've miss-read your question. So it is a limitation on how maya.cmds wrap Qt QTreeView. If you want to have twice layer 7 in your graph, here is how I would do this in cmds :

    import maya.cmds as cmds
    from collections import defaultdict
    
    treepop = defaultdict(list)
    treepop[""]=['layer_1_0',
                 'layer_2_0',
                 'layer_3_0',
                 'layer_4_0',
                 'layer_5_0',
                 'layer_6_0',
                 'layer_12_0']
    treepop["layer_2_0"] = ['layer_7_1',
                            'layer_9_1',
                            'layer_11_1']
    treepop["layer_3_0"] = ['layer_7_2']
    treepop["layer_8_0"] = ['layer_10_1']
    treepop["layer_10_0"] = ['layer_13_1']
    
    
    window = cmds.window()
    layout = cmds.formLayout()
    
    control = cmds.treeView( parent = layout, numberOfButtons = 0, abr = False )
    
    cmds.formLayout(layout,e=True, attachForm=(control,'top', 2))
    cmds.formLayout(layout,e=True, attachForm=(control,'left', 2))
    cmds.formLayout(layout,e=True, attachForm=(control,'bottom', 2))
    cmds.formLayout(layout,e=True, attachForm=(control,'right', 2))
    
    cmds.showWindow( window )
    
    for k in treepop[""]:
        cmds.treeView( control, e=True, addItem=(k, ""))
    for k in treepop:
        if k == "":
            continue
        for v in treepop[k]:
            cmds.treeView( control, e=True, addItem=(v, k))
    

    so you can strip the last '_' to get the name of the layer.

    Otherwise, wrap yourself QtWidgets.QTreeView or QTreeWidget, it might be even easier

    === EDIT 2 ===

    I have an example on how you can extend maya.cmds with qtreewidget :

    from PySide2 import QtWidgets
    from maya import OpenMayaUI, cmds
    from collections import defaultdict
    import shiboken2
    
    treepop = defaultdict(list)
    treepop[""]=['layer_1',
                 'layer_2',
                 'layer_3',
                 'layer_4',
                 'layer_5',
                 'layer_6',
                 'layer_12']
    treepop["layer_2"] = ['layer_7',
                            'layer_9',
                            'layer_11']
    treepop["layer_3"] = ['layer_7']
    treepop["layer_8"] = ['layer_10']
    treepop["layer_10"] = ['layer_13']
    
    def mayaToQT(name):
        # Maya -> QWidget
        ptr = OpenMayaUI.MQtUtil.findControl(name)
        if ptr is None:         ptr = OpenMayaUI.MQtUtil.findLayout(name)
        if ptr is None:         ptr = OpenMayaUI.MQtUtil.findMenuItem(name)
        if ptr is not None:     return shiboken2.wrapInstance(long(ptr),
                                                              QtWidgets.QWidget)
    
    
    cmds.window()
    layout = cmds.columnLayout(rowSpacing=10, columnWidth=250)
    qwidget= mayaToQT(layout)
    qlayout = qwidget.children()[0]
    treeview = QtWidgets.QTreeWidget()
    treeview.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
    treeview.setColumnCount(1)
    treeview.setAlternatingRowColors(True)
    treeview.clear()
    qlayout.addWidget(treeview)
    
    items = []
    for k in treepop[""]:
        root_item = QtWidgets.QTreeWidgetItem()
        root_item.setText(0,k)
        print(k)
    
        if k in treepop:
            for v in treepop[k]:
                child_item = QtWidgets.QTreeWidgetItem()
                child_item.setText(0,v)
                root_item.addChild(child_item)
    
        items.append(root_item)
    treeview.addTopLevelItems(items)
    
    cmds.showWindow()
    
    def getSelected():
        items = treeview.selectedItems()
        for i in items:
            print(i.text(0))