stuartP
stuartP

Reputation: 61

PyQT: adding to QAbstractItemModel using a button

I'm trying to implement a TreeView using QAbstractItemModel. I want to set up an empty model and then add an item to the model using a button.

This appears to be a lot more complex than I'd realised! I've modified a custom instance of the QAbstractItemModel example found in the Lib\site-packages\PyQt4\examples\itemviews\simpletreemodel\simpletreemodel.pyw.

Rather than setting up the model all at once, I want o build it incrementally.

When I click the button, I get the message showing that the process method is executing, but the model isn't updated.

Any pointers as to why it's not working would be greatly appreciated!

from PyQt4 import QtGui, QtCore
import sys

class myWindow(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.resize(500, 400)

        #Tree Widget
        self.treeView = QtGui.QTreeView(self)

        #Model
        self.model = TreeModel()                    
        self.treeView.setModel(self.model)

        # Button
        self.button = QtGui.QPushButton(self)
        self.button.setText('Add Item')    
        self.button.clicked.connect(self.process)

        # Add to Layout    
        self.gridLayout = QtGui.QGridLayout(self)
        self.gridLayout.addWidget(self.button,0,0)
        self.gridLayout.addWidget(self.treeView,1,0)

     def process(self):
        print "here"        
        newItem = TreeItem(["bob","bob","bob"],self.model.rootItem)       
        self.model.rootItem.appendChild(newItem) 

class TreeItem(object):
    def __init__(self, data, parent=None):
        self.parentItem = parent
        self.itemData = data
        self.childItems = []

    def appendChild(self, item):
        self.childItems.append(item)

    def child(self, row):
        return self.childItems[row]

    def childCount(self):
        return len(self.childItems)

    def columnCount(self):
        return len(self.itemData)

    def data(self, column):
        try:
            return self.itemData[column]
        except IndexError:
            return None

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)
        return 0

class TreeModel(QtCore.QAbstractItemModel):
    def __init__(self, parent=None):
        super(TreeModel, self).__init__(parent)
        self.rootItem = TreeItem(("Model", "Status","Location"))

    def columnCount(self, parent):
        if parent.isValid():
            return parent.internalPointer().columnCount()
        else:
            return self.rootItem.columnCount()

    def data(self, index, role):
        if not index.isValid():
            return None

        if role != QtCore.Qt.DisplayRole:
            return None

        item = index.internalPointer()

        return item.data(index.column())

    def flags(self, index):
        if not index.isValid():
            return QtCore.Qt.NoItemFlags

        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self.rootItem.data(section)

        return None

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        childItem = parentItem.child(row)
        if childItem:
            return self.createIndex(row, column, childItem)
        else:
            return QtCore.QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()

        childItem = index.internalPointer()
        parentItem = childItem.parent()

        if parentItem == self.rootItem:
            return QtCore.QModelIndex()

        return self.createIndex(parentItem.row(), 0, parentItem)

    def rowCount(self, parent):
        if parent.column() > 0:
            return 0

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        return parentItem.childCount()

if __name__ == "__main__":
    app = QtGui.QApplication.instance() # checks if QApplication already exists 
    if not app: # create QApplication if it doesnt exist 
        app = QtGui.QApplication(sys.argv)
    # Window
    window = myWindow()                    
    window.show()
    sys.exit(app.exec_())

Upvotes: 3

Views: 2165

Answers (1)

stuartP
stuartP

Reputation: 61

Using a QStandardItemModel has worked a treat!

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.resize(500, 400)

        #Tree Widget
        self.treeView = QTreeView()        

        #Model        
        self.model = QStandardItemModel()
        self.treeView.setModel(self.model)

        # Button
        self.button = QPushButton()
        self.button.setText('Add Item')    
        self.button.clicked.connect(self.addChildClick)

        # Add to Layout    
        self.gridLayout = QGridLayout(self)
        self.gridLayout.addWidget(self.button,0,0)
        self.gridLayout.addWidget(self.treeView,1,0)

    def addChildClick(self):        
        selection = self.treeView.selectedIndexes() 
        text = "bob"
        item = QStandardItem(text)

        # if nothing selected parent is model        
        if selection == []:        
            parent = self.model

        else: # Otherwise parent is what is selected
            s = selection[0] # Handling multiple selectons            
            parent = self.model.itemFromIndex(s)

        parent.appendRow(item)

        #cleanup        
        self.treeView.expandAll()
        self.treeView.clearSelection()

if __name__ == "__main__":
    app = QApplication.instance() # checks if QApplication already exists 
    if not app: # create QApplication if it doesnt exist 
        app = QApplication(sys.argv)

    # Window
    window = Window()                    
    window.show()
    app.exec_()

Upvotes: 3

Related Questions