Search code examples
model-view-controllerpyqtqtableviewqabstracttablemodel

Understanding MVC in a QAbstractTableModel


I have some data which are represented by a class of my own ; to fix the ideas I give an example.

class MyOwnModel():
  def __init__(self, name="", number=0):
    self.name = name
    self.number = number

I then have a list of such instances, that I want to represent in a QTableView.

li = [MyOwnModel("a", 1), MyOwnModel("b", 2)]

Then I see two strategies to make a QTableView from that :

  1. change MyOwnModel so that it subclasses QAbstractTableModel
  2. build a new QAbstractTableModel which mimics MyOwnModel in a way that its attributes are for instance two QString and connect the dataChanged signal to a function which updates the instance of MyOwnModel

I am not completely satisfied with any of these, but I have no other idea for the moment.

Which one is the most suitable to my problem ? (I have a more complex class in practice but I would like to use the same framework)


Solution

  • As stated in the comment, your model is your list of object. You should subclass QAbstractTableModel to use this list.

    Here's my code snippet for this:

    import sys
    import signal
    import PyQt4.QtCore as PCore
    import PyQt4.QtGui as PGui
    
    class OneRow(PCore.QObject):
        def __init__(self):
            self.column0="text in column 0"
            self.column1="text in column 1"
    
    class TableModel(PCore.QAbstractTableModel):
        def __init__(self):
            super(TableModel,self).__init__()
            self.myList=[]
    
        def addRow(self,rowObject):
            row=len(self.myList)
            self.beginInsertRows(PCore.QModelIndex(),row,row)
            self.myList.append(rowObject)
            self.endInsertRows()
    
        #number of row
        def rowCount(self,QModelIndex):
            return len(self.myList)
    
        #number of columns
        def columnCount(self,QModelIndex):
            return 2
    
        #Define what do you print in the cells
        def data(self,index,role):
            row=index.row()
            col=index.column()
            if role==PCore.Qt.DisplayRole:
                if col==0:
                    return str( self.myList[row].column0)
                if col==1:
                    return str( self.myList[row].column1)
    
        #Rename the columns
        def headerData(self,section,orientation,role):
            if role==PCore.Qt.DisplayRole:
                if orientation==PCore.Qt.Horizontal:
                    if section==0:
                        return str("Column 1")
                    elif section==1:
                        return str("Column 2")
    
    if __name__=='__main__':
        PGui.QApplication.setStyle("plastique")
        app=PGui.QApplication(sys.argv)
    
        #Model
        model=TableModel()
        model.addRow(OneRow())
        model.addRow(OneRow())
    
        #View
        win=PGui.QTableView()
        win.setModel(model)
    
        #to be able to close wth ctrl+c
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        #to avoid warning when closing
        win.setAttribute(PCore.Qt.WA_DeleteOnClose)
    
        win.show()
        sys.exit(app.exec_())
    

    Each element of myList is a row in the table.