How to make QTreeWidget dragging semi-transparent and keep itemWidgets
Question: i have a treeWidget with itemWidget set on columns, but after dragging the
widgets are gone, and the dropping indicator is opaque

  1. How can i make the widget persist after dropping
  2. How to make dropping indicator transparent ? ( i'm on centos 6.5, the compositing manager is not running)

![dropping indicator not transparent](http://i.stack.imgur.com/d4sFP.png)

![item widgets gone after dropping](http://i.stack.imgur.com/2Oa9A.png)

executable example

    
    
    #!/usr/bin/env python2
    import os
    import sys
    import re
    
    from PyQt4 import QtGui, QtCore
    from PyQt4.QtCore import Qt, QString
    
    
    class MyTreeWidget(QtGui.QTreeWidget):
        def __init__(self, parent=None):
            super(MyTreeWidget, self).__init__(parent)
    
    class CommandWidget(QtGui.QDialog):
    
        def __init__(self, parent=None, level=0,script='echo /path/to/script'):
            super(CommandWidget, self).__init__()
            self.layout = QtGui.QHBoxLayout(self)
    
            browseBtn = QtGui.QPushButton(parent)
    
            browseBtn.setMinimumSize(QtCore.QSize(0, 25))
            # level, path = val
    
            # levelNum = re.search('(?<=level).+', level).group()
            browseBtn.setText('%s : %s' % (level, script))
            self._level = int(level)
            self._script = script
            browseBtn.setStyleSheet("text-align: left")
    
            self.layout.addWidget(browseBtn)
    
            # self.updateGeometry()
            self.browseBtn = browseBtn
            # self.layout.addWidget(browseBtn)
            self.browseBtn.clicked.connect(self.browseCommandScript)
            self.browseBtn.setIconSize(QtCore.QSize(64, 64))
    
        def browseCommandScript(self):
            script = QtGui.QFileDialog.getOpenFileName(
                self, 'Select Script file', '/home/xxx/python', ".py Files (*.py);;Executable Files (*)")
            if script:
                self._script = script
                button_label = re.search('[^\\/]*$',script).group()
                self.browseBtn.setText(('%s : %s' % (self._level, button_label)))
    
        @property
        def level(self):
            return self._level
    
        @level.setter
        def level(self, value):
            self._level = value
    
        @property
        def script(self):
            return self._script
    
        @script.setter
        def script(self, value):
            self._script = value
    
    
    class MyLineEdit(QtGui.QWidget):
        def __init__(self,value=None,parent=None):
            super(MyLineEdit,self).__init__(parent)
            self.layout = QtGui.QHBoxLayout(self)
            self.layout.setSpacing(0)
            self.layout.setMargin(3)
    
            self.lineEdit = QtGui.QLineEdit(value)
            spacer1 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
            spacer2 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
    
            self.lineEdit.setContentsMargins(2,2,2,2)
            self.lineEdit.setAlignment(Qt.AlignHCenter)
    
            self.layout.addItem(spacer1)
            self.layout.addWidget(self.lineEdit)
            self.layout.addItem(spacer2)
    
            self.lineEdit.setMaximumSize(QtCore.QSize(70, 25))
            self.lineEdit.textEdited.connect(self._update_item_widget_data)
    
        def text(self):
            return self.lineEdit.text()
    
        def setText(self,text):
            return self.lineEdit.setText(text)   
    
    
        def _update_item_widget_data(self,text):
            # print 'update',text
            self.treeWidgetItem.setData(1,Qt.UserRole,text)
    
    class TheUI(QtGui.QDialog):
    
        def __init__(self, args=None, parent=None):
            super(TheUI, self).__init__(parent)
            self.layout = QtGui.QVBoxLayout(self)
            treeWidget = MyTreeWidget()
    
            button = QtGui.QPushButton('Add')
            self.layout.addWidget(treeWidget)
            self.cssEditTE = QtGui.QPlainTextEdit()
    
            self.layout.addWidget(button)
            self.layout.addWidget(self.cssEditTE)
    
            self.cssEditTE.textChanged.connect(self._update_css)
    
            treeWidget.setHeaderHidden(True)
            treeWidget.setRootIsDecorated(False)
    
            layout = QtGui.QHBoxLayout(self)
            rootDecorationCB = QtGui.QCheckBox('RootIsDecorated')
            layout.addWidget(rootDecorationCB)
            self.layout.addLayout(layout)
            rootDecorationCB.stateChanged.connect(self._update_root_decorated)
    
            indentationSlider = QtGui.QSlider()
            indentationSlider.setOrientation(Qt.Horizontal)
            indentationSlider.setRange(0,100)
            indentationSlider.setValue(20)
            indentationSlider.valueChanged.connect(self._alter_indentation)
            layout.addWidget(indentationSlider)
    
    
            self.layout.setStretchFactor(treeWidget,1)
    
            self.treeWidget = treeWidget
            self.button = button
            self.button.clicked.connect(lambda *x: self.addCmd())
    
            HEADERS = ( "script", "chunksize", "mem" )
            self.treeWidget.setHeaderLabels(HEADERS)
            self.treeWidget.setColumnCount( len(HEADERS) )
    
            self.treeWidget.setColumnWidth(0,200)
            self.treeWidget.header().show()
    
            for i in range(len(HEADERS)):
                self.treeWidget.headerItem().setTextAlignment(i,Qt.AlignHCenter)
    
    
            self.treeWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
    
            self.treeWidget.setIndentation(60)
    
            self.resize(500,700)
    
            for i in xrange(2):
                self.addCmd()
    
            item = self.addCmd()
            self.addCmd(parent = item)
            self.addCmd(parent = item)
            item = self.addCmd()
    
            item=self.addCmd(parent = item)
            self.addCmd(parent = item)
            self.addCmd()
    
            self.treeWidget.setColumnWidth(0,200)
    
        def addCmd(self, level=0, script='echo /path/to/script',parent=None):
            'add a level to tree widget'
    
            root = self.treeWidget.invisibleRootItem()
    
            if parent is None:
                parent = root
            item = QtGui.QTreeWidgetItem(parent)
            # item = QtGui.QTreeWidgetItem(self.treeWidget.invisibleRootItem())
            item.setFlags(item.flags() | QtCore.Qt.ItemIsDropEnabled)
    
            existingLevels = self.treeWidget.topLevelItemCount()
            # level, path = val
            # level = level % existingLevels
    
            cmdWidget = CommandWidget(self.treeWidget, existingLevels, script)
            self.treeWidget.setItemWidget(item, 0, cmdWidget)
    
            line_edit_1 = MyLineEdit('1')
            line_edit_2 = MyLineEdit('200')
    
            self.treeWidget.setItemWidget(item, 1, line_edit_1)
            self.treeWidget.setItemWidget(item, 2, line_edit_2)
    
            item.setExpanded(True)
            return item
    
        def _update_css(self):
            self.treeWidget.setStyleSheet(self.cssEditTE.toPlainText())
    
        def _update_root_decorated(self,state):
            if state == Qt.Checked:
                self.treeWidget.setRootIsDecorated(True)
            else:
                self.treeWidget.setRootIsDecorated(False)
            self.treeWidget.updateGeometries()
    
        def _alter_indentation(self,value):
            print value
            self.treeWidget.setIndentation(value)
            self.treeWidget.updateGeometries()
    
    
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        gui = TheUI()
        gui.show()
        app.exec_()
    


Answer: > 1) How can i make the widget persist after dropping ?

Please use this to understand how to use `QItemDelegate` (running in Windows
7, Python 2.7, pyqt4):

    
    
    import sys
    import os
    from PyQt4 import QtCore, QtGui
    from functools import partial
    
    class QCustomDelegate (QtGui.QItemDelegate):
        def createEditor (self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 0:
                editorQWidget = QtGui.QPushButton(parentQWidget)
                self.connect(editorQWidget, QtCore.SIGNAL('released()'), partial(self.requestNewPath, indexQModelIndex))
                return editorQWidget            
            elif column in [1, 2]:
                editorQWidget = QtGui.QSpinBox(parentQWidget)
                editorQWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
                editorQWidget.setMinimum(0)
                editorQWidget.setMaximum(2 ** 16)
                return editorQWidget
            else:
                return QtGui.QItemDelegate.createEditor(self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex)
    
        def setEditorData (self, editorQWidget, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 0:
                textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
                editorQWidget.setText(textQString)
            elif column in [1, 2]:
                value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
                editorQWidget.setValue(value)
            else:
                QtGui.QItemDelegate.setEditorData(self, editorQWidget, indexQModelIndex)
    
        def setModelData (self, editorQWidget, modelQAbstractItemModel, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 0:
                textQString = editorQWidget.text()
                modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
            elif column in [1, 2]:
                value = editorQWidget.value()
                modelQAbstractItemModel.setData(indexQModelIndex, value, QtCore.Qt.EditRole)
            else:
                QtGui.QItemDelegate.setModelData(self, editorQWidget, modelQAbstractItemModel, indexQModelIndex)
    
        def updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex):
            column = indexQModelIndex.column()
            if column in [0, 1, 2]:
                editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
            else:
                QtGui.QItemDelegate.updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex)
    
        def requestNewPath (self, indexQModelIndex):
            self.emit(QtCore.SIGNAL('requestNewPath'), indexQModelIndex)
    
        def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 0:
                textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
                foundIndexQModelIndex = indexQModelIndex
                while foundIndexQModelIndex.parent() != QtCore.QModelIndex():
                    foundIndexQModelIndex = foundIndexQModelIndex.parent()
                buttonQStyleOptionButton = QtGui.QStyleOptionButton()
                buttonQStyleOptionButton.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
                buttonQStyleOptionButton.text = str(foundIndexQModelIndex.row() + 1) + ' : ' + os.path.basename(str(textQString))
                buttonQStyleOptionButton.state = QtGui.QStyle.State_Active
                QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, buttonQStyleOptionButton, painterQPainter)
            elif column in [1, 2]:
                value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
                textQStyleOptionViewItem = optionQStyleOptionViewItem
                textQStyleOptionViewItem.displayAlignment = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
                currentQRect = QtCore.QRect(optionQStyleOptionViewItem.rect)
                currentQRect.setWidth(currentQRect.width() - 22)
                self.drawDisplay(painterQPainter, textQStyleOptionViewItem, currentQRect, QtCore.QString(str(value)));
                spinBoxQStyleOptionSpinBox = QtGui.QStyleOptionSpinBox()
                spinBoxQStyleOptionSpinBox.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
                QtGui.QApplication.style().drawComplexControl(QtGui.QStyle.CC_SpinBox, spinBoxQStyleOptionSpinBox, painterQPainter)
            else:
                QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)
    
    class QCustomTreeWidget (QtGui.QTreeWidget):
        def __init__(self, parent = None):
            super(QCustomTreeWidget, self).__init__(parent)
            self.setDragEnabled(True)
            self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
            self.setColumnCount(3)
            self.setHeaderLabels(('script', 'chunksize', 'mem'))
            for i in range(self.columnCount()):
                self.headerItem().setTextAlignment(i, QtCore.Qt.AlignHCenter)
            self.header().setStretchLastSection(False)
            self.header().setResizeMode(0, QtGui.QHeaderView.Stretch)
            self.setIndentation(60)
            self.setColumnWidth(0, 200)
            myQCustomDelegate = QCustomDelegate()
            self.setItemDelegate(myQCustomDelegate)
            self.connect(myQCustomDelegate, QtCore.SIGNAL('requestNewPath'), self.getNewPath)
    
        def addMenu (self, script = 'echo path_to_script', chunksize = 1, mem = 200, parentQTreeWidgetItem = None):
            if parentQTreeWidgetItem == None:
                parentQTreeWidgetItem = self.invisibleRootItem()
            currentQTreeWidgetItem = QtGui.QTreeWidgetItem(parentQTreeWidgetItem)
            currentQTreeWidgetItem.setData(0, QtCore.Qt.EditRole, script)
            currentQTreeWidgetItem.setData(1, QtCore.Qt.EditRole, chunksize)
            currentQTreeWidgetItem.setData(2, QtCore.Qt.EditRole, mem)
            currentQTreeWidgetItem.setFlags(currentQTreeWidgetItem.flags() | QtCore.Qt.ItemIsEditable)
            for i in range(self.columnCount()):
                currentQSize = currentQTreeWidgetItem.sizeHint(i)
                currentQTreeWidgetItem.setSizeHint(i, QtCore.QSize(currentQSize.width(), currentQSize.height() + 30))
            currentQTreeWidgetItem.setExpanded(True)
            return currentQTreeWidgetItem
    
        def getNewPath (self, indexQModelIndex):
            currentQTreeWidgetItem = self.itemFromIndex(indexQModelIndex)
            pathQString = QtGui.QFileDialog.getOpenFileName (
                self, 'Select Script file', '', '.py Files (*.py);;Executable Files (*)')
            if not pathQString.isEmpty():
                currentQTreeWidgetItem.setData(indexQModelIndex.column(), QtCore.Qt.EditRole, pathQString)
    
    class QCustomQDialog (QtGui.QDialog):
        def __init__ (self, parent = None):
            super(QCustomQDialog, self).__init__(parent)
            self.myQCustomTreeWidget = QCustomTreeWidget(self)
            self.addQPushButton = QtGui.QPushButton('Add', self)
            self.connect(self.addQPushButton, QtCore.SIGNAL('released()'), self.myQCustomTreeWidget.addMenu)
            self.cssQPlainTextEdit = QtGui.QPlainTextEdit(self)
            self.connect(self.cssQPlainTextEdit, QtCore.SIGNAL('textChanged()'), self.updateCss)
            self.rootDecorationCBQCheckBox = QtGui.QCheckBox('Root is decorated')
            self.connect(self.rootDecorationCBQCheckBox, QtCore.SIGNAL('stateChanged(int)'), self.updateRootDecorated)
            self.updateRootDecorated(self.rootDecorationCBQCheckBox.checkState())
            self.indentationQSlider = QtGui.QSlider(self)
            self.indentationQSlider.setOrientation(QtCore.Qt.Horizontal)
            self.indentationQSlider.setRange(0, 100)
            self.indentationQSlider.setValue(20)
            self.connect(self.indentationQSlider, QtCore.SIGNAL('valueChanged(int)'), self.alterIndentation)
            self.alterIndentation(self.indentationQSlider.value())
            self.layoutQVBoxLayout = QtGui.QVBoxLayout()
            self.layoutQVBoxLayout.addWidget(self.myQCustomTreeWidget)
            self.layoutQVBoxLayout.addWidget(self.addQPushButton)
            self.layoutQVBoxLayout.addWidget(self.cssQPlainTextEdit)
            self.downMenuQHBoxLayout = QtGui.QHBoxLayout()
            self.downMenuQHBoxLayout.addWidget(self.rootDecorationCBQCheckBox)
            self.downMenuQHBoxLayout.addWidget(self.indentationQSlider)
            self.layoutQVBoxLayout.addLayout(self.downMenuQHBoxLayout)
            self.layoutQVBoxLayout.setStretchFactor(self.myQCustomTreeWidget, 1)
            self.setLayout(self.layoutQVBoxLayout)
            self.resize(480, 640)
            _ = self.myQCustomTreeWidget.addMenu()
            _ = self.myQCustomTreeWidget.addMenu()
            currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu()
            self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
            self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
            currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu()
            currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
            currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
            _ = self.myQCustomTreeWidget.addMenu()
    
        def updateCss (self):
            self.myQCustomTreeWidget.setStyleSheet(self.cssQPlainTextEdit.toPlainText())
    
        def alterIndentation (self, value):
            self.myQCustomTreeWidget.setIndentation(value)
            self.myQCustomTreeWidget.updateGeometries()
    
        def updateRootDecorated (self, state):
            if state == QtCore.Qt.Checked:
                self.myQCustomTreeWidget.setRootIsDecorated(True)
            else:
                self.myQCustomTreeWidget.setRootIsDecorated(False)
            self.myQCustomTreeWidget.updateGeometries()
    
    app = QtGui.QApplication([])
    myQCustomQDialog = QCustomQDialog()
    myQCustomQDialog.show()
    sys.exit(app.exec_())
    

You are not the only one who has experienced this problem. I strongly
recommend using `QItemDelegate`.

The document says:

> If you want to display custom dynamic content or implement a custom editor
> widget, use QTreeView and subclass `QItemDelegate` instead.

And (user ? or) you want 'editors' always visible. It can do it in
`QItemDelegate`. But in class `QItemDelegate`, implements `QItemDelegate.paint
(self, QPainter painter, QStyleOptionViewItem option, QModelIndex index)`
(reference in later). And other property 'createEditor', 'setEditorData', etc.

Example for implementing this class:

    
    
    import sys
    from PyQt4 import QtCore, QtGui
    from functools import partial
    
    class QCustomDelegate (QtGui.QItemDelegate):
        def createEditor (self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 1:
                editorQWidget = QtGui.QSpinBox(parentQWidget)
                editorQWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
                editorQWidget.setMinimum(0)
                editorQWidget.setMaximum(100)
                return editorQWidget
            elif column == 2:
                editorQWidget = QtGui.QLineEdit(parentQWidget)
                editorQWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
                return editorQWidget
            elif column == 3:
                editorQWidget = QtGui.QPushButton(parentQWidget)
                return editorQWidget            
            else:
                return QtGui.QItemDelegate.createEditor(self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex)
    
        def setEditorData (self, editorQWidget, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 1:
                value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
                editorQWidget.setValue(value)
            elif column == 2:
                textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
                editorQWidget.setText(textQString)
            elif column == 3:
                textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
                self.connect(editorQWidget, QtCore.SIGNAL('released()'), partial(self.requestNewPath, indexQModelIndex))
                editorQWidget.setText(textQString)
            else:
                QtGui.QItemDelegate.setEditorData(self, editorQWidget, indexQModelIndex)
    
        def setModelData (self, editorQWidget, modelQAbstractItemModel, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 1:
                value = editorQWidget.value()
                modelQAbstractItemModel.setData(indexQModelIndex, value, QtCore.Qt.EditRole)
            elif column == 2:
                textQString = editorQWidget.text()
                modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
            elif column == 3:
                textQString = editorQWidget.text()
                modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
            else:
                QtGui.QItemDelegate.setModelData(self, editorQWidget, modelQAbstractItemModel, indexQModelIndex)
    
        def updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 1:
                editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
            elif column == 2:
                editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
            elif column == 3:
                editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
            else:
                QtGui.QItemDelegate.updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex)
    
        def requestNewPath (self, indexQModelIndex):
            self.emit(QtCore.SIGNAL('requestNewPath'), indexQModelIndex)
    
        def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
            column = indexQModelIndex.column()
            if column == 1:
                value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
                textQStyleOptionViewItem = optionQStyleOptionViewItem
                textQStyleOptionViewItem.displayAlignment = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
                currentQRect = QtCore.QRect(optionQStyleOptionViewItem.rect)
                currentQRect.setWidth(currentQRect.width() - 22)
                self.drawDisplay(painterQPainter, textQStyleOptionViewItem, currentQRect, QtCore.QString(str(value)));
                spinBoxQStyleOptionSpinBox = QtGui.QStyleOptionSpinBox()
                spinBoxQStyleOptionSpinBox.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
                QtGui.QApplication.style().drawComplexControl(QtGui.QStyle.CC_SpinBox, spinBoxQStyleOptionSpinBox, painterQPainter)
            elif column == 2:
                textQStyleOptionViewItem = optionQStyleOptionViewItem
                textQStyleOptionViewItem.displayAlignment = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
                QtGui.QItemDelegate.paint(self, painterQPainter, textQStyleOptionViewItem, indexQModelIndex)
            elif column == 3:
                textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
                buttonQStyleOptionButton = QtGui.QStyleOptionButton()
                buttonQStyleOptionButton.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
                buttonQStyleOptionButton.text = textQString
                buttonQStyleOptionButton.state = QtGui.QStyle.State_Active
                QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, buttonQStyleOptionButton, painterQPainter)
            else:
                QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)
    
    class QCustomTreeWidget (QtGui.QTreeWidget):
        def __init__(self, parent = None):
            super(QCustomTreeWidget, self).__init__(parent)
            self.setDragEnabled(True)
            self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
            self.setColumnCount(4)
            myQCustomDelegate = QCustomDelegate()
            self.setItemDelegate(myQCustomDelegate)
            self.connect(myQCustomDelegate, QtCore.SIGNAL('requestNewPath'), self.getNewPath)
    
        def addMenu (self, title, value, text, path, parentQTreeWidgetItem = None):
            if parentQTreeWidgetItem == None:
                parentQTreeWidgetItem = self.invisibleRootItem()
            currentQTreeWidgetItem = QtGui.QTreeWidgetItem(parentQTreeWidgetItem)
            currentQTreeWidgetItem.setData(0, QtCore.Qt.EditRole, title)
            currentQTreeWidgetItem.setData(1, QtCore.Qt.EditRole, value)
            currentQTreeWidgetItem.setData(2, QtCore.Qt.EditRole, text)
            currentQTreeWidgetItem.setData(3, QtCore.Qt.EditRole, path)
            currentQTreeWidgetItem.setFlags(currentQTreeWidgetItem.flags() | QtCore.Qt.ItemIsEditable)
            for i in range(self.columnCount()):
                currentQSize = currentQTreeWidgetItem.sizeHint(i)
                currentQTreeWidgetItem.setSizeHint(i, QtCore.QSize(currentQSize.width(), currentQSize.height() + 40))
    
        def getNewPath (self, indexQModelIndex):
            currentQTreeWidgetItem = self.itemFromIndex(indexQModelIndex)
            pathQStringList = QtGui.QFileDialog.getOpenFileNames()
            if pathQStringList.count() > 0:
                textQString = pathQStringList.first()
                currentQTreeWidgetItem.setData(indexQModelIndex.column(), QtCore.Qt.EditRole, textQString)
    
    class QCustomQWidget (QtGui.QWidget):
        def __init__ (self, parent = None):
            super(QCustomQWidget, self).__init__(parent)
            self.myQCustomTreeWidget = QCustomTreeWidget(self)
            self.allQHBoxLayout = QtGui.QHBoxLayout()
            self.allQHBoxLayout.addWidget(self.myQCustomTreeWidget)
            self.setLayout(self.allQHBoxLayout)
            self.myQCustomTreeWidget.addMenu('1', 10, 'A', 'home/Meyoko/Desktop')
            self.myQCustomTreeWidget.addMenu('4', 14, 'B', 'home/Kitsune/Desktop')
            self.myQCustomTreeWidget.addMenu('7', 17, 'C', 'home/Elbert/Desktop')
    
    app = QtGui.QApplication([])
    myQCustomQWidget = QCustomQWidget()
    myQCustomQWidget.show()
    sys.exit(app.exec_())
    

[Spin Box Delegate Example (C++)](http://doc.qt.digia.com/4.6/itemviews-
spinboxdelegate.html)

[`QItemDelegate`](http://pyqt.sourceforge.net/Docs/PyQt4/qitemdelegate.html)

