Search code examples
pythontreeviewmayadirectory-structureqtreewidget

PySide: TreeView widget for folders


I want to create a TreeView widget using PySide for Autodesk Maya that can display the content of a directory like the example below:

Treeview example

I did find an example using tkinter for a simple python script : Tkinter: Treeview widget. But I want to use Pyside so I can run it in Autodesk Maya

I did create a script that can display a simple TreeView widget:

this is my code:

try:
  from PySide2.QtCore import * 
  from PySide2.QtGui import * 
  from PySide2.QtWidgets import *
  from PySide2 import __version__
  from shiboken2 import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI
except ImportError:
  from PySide.QtCore import * 
  from PySide.QtGui import * 
  from PySide import __version__
  from shiboken import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI

treepop = collections.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 wrapInstance(long(ptr),
                                                          QWidget)


cmds.window()
layout = cmds.columnLayout(rowSpacing=10, columnWidth=250)
qwidget= mayaToQT(layout)
qlayout = qwidget.children()[0]
treeview = QTreeWidget()
treeview.setSelectionMode(QAbstractItemView.ExtendedSelection)
treeview.setColumnCount(1)
treeview.setAlternatingRowColors(True)
treeview.clear()
qlayout.addWidget(treeview)

items = []
for k in treepop[""]:
    root_item = QTreeWidgetItem()
    root_item.setText(0,k)
    print(k)

    if k in treepop:
        for v in treepop[k]:
            child_item = 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))

Can any one help me please!

Edit: I did fix the problem with your help, thank you all:

try:
  from PySide2.QtCore import * 
  from PySide2.QtGui import * 
  from PySide2.QtWidgets import *
  from PySide2 import __version__
  from shiboken2 import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI
  import os
except ImportError:
  from PySide.QtCore import * 
  from PySide.QtGui import * 
  from PySide import __version__
  from shiboken import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI
  import os
class MyTree(QTreeWidget):
    def __init__(self, parent=None):
        QTreeWidget.__init__(self, parent)        
        self.startDir = "C:/users/user/desktop/myFolder"
        self.setHeaderLabels([self.startDir])
        self.setColumnWidth(0,400)
        self.setContentsMargins(0, 0, 0, 0)
        self.header().setDefaultSectionSize(300)
        self.header().setStretchLastSection(False)
        self.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.header().setResizeMode(0, QHeaderView.Stretch)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setColumnCount(1)
        self.setAlternatingRowColors(True)
        self.fillTree()
        self.show()


    def fillTree(self):                
        def iterate(currentDir, currentItem):            
            for f in os.listdir(currentDir):

                path = os.path.join(currentDir, f)
                if os.path.isdir(path):

                    dirItem = QTreeWidgetItem(currentItem)
                    dirItem.setText(0, f)
                    iterate(path, dirItem)
        iterate(self.startDir, self)



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 wrapInstance(long(ptr),QWidget)


cmds.window(w=600, h=300)
layout = cmds.columnLayout(rowSpacing=60, columnWidth=400, w=600, h=600)
qwidget= mayaToQT(layout)
qlayout = qwidget.children()[0]
treeview = MyTree()

qlayout.addWidget(treeview)
cmds.showWindow()

But can any one help to set the height and width of QTreeView widget?


Solution

  • The QDirModel is great. Just in case you want another solution you can try this:

    class MyTree(QtWidgets.QTreeWidget):
        def __init__(self, parent=None):
            super(MyTree, self).__init__(parent=parent)
            self.startDir = "C:/daten/backup"
            self.fillTree()
            self.show()
    
        def fillTree(self):        
            def iterate(currentDir, currentItem):            
                for f in os.listdir(currentDir):
                    path = os.path.join(currentDir, f)
                    if os.path.isdir(path):
                        dirItem = QtWidgets.QTreeWidgetItem(currentItem)
                        dirItem.setText(0, f)
                        iterate(path, dirItem)
                    else:
                        fileItem = QtWidgets.QTreeWidgetItem(currentItem)
                        fileItem.setText(0, f)
            iterate(self.startDir, self)
    

    It simply iterates over a starting directory until it does not find any directories any more.