Friday, January 27, 2012

Qt 4.8 Model/View Tutorial - Part 5

The following code is based on Qt 4.8 Model/View Tutorial - 2.5 The Minimal Editing Example.



#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''
    PyQt4 conversion of Qt Model-View Tutorial
    
    In this example, we are going to build an application that 
    automatically populates a window title with content by repeating 
    values entered into table cells. 
    
    Differences from previous examples:
        - uses QMainWindow to display the table
        - overrides QAbstractTableModel.flags() to allow edits
        - overrides QAbstractTableModel.setData()
        - includes a custom signal
     
    NOTES:
    =====
        Used a multidimensional list to hold the table data
           (see ref link for a FAQ entry on multidimensional lists)
           
        With the introduction of QMainWindow, a separate main()
        method is once again callable without producing QTimer
        errors on exit (see Part 1)
        
    
last modified: 2012-01-28 jg
ref:
    http://developer.qt.nokia.com/doc/qt-4.8/modelview.html#2-5-the-minimal-editing-example
    http://pyfaq.infogami.com/how-do-i-create-a-multidimensional-list
    
'''
from PyQt4.QtGui import (QApplication, QMainWindow, QTableView)
from PyQt4.QtCore import (Qt, QAbstractTableModel, QModelIndex,
                          pyqtSlot, pyqtSignal)

class MyModel(QAbstractTableModel):
    ROWS = 2
    COLS = 3

    def __init__(self, parent=None):    # initialise base class
        super(MyModel, self).__init__(parent)

        # create an empty, multidimensional list to hold the
        # table data 
        self._mGridData = [ [''] * MyModel.COLS
                           for i in range(MyModel.ROWS)]

    editCompleted = pyqtSignal(str, name="editCompleted")

    def rowCount(self, index=QModelIndex()):
        return MyModel.ROWS

    def columnCount(self, index=QModelIndex()):
        return MyModel.COLS

    def data(self, index, role):
        row = index.row()
        col = index.column()

        if role == Qt.DisplayRole:
            return self._mGridData[row][col]
        else:
            return None

    def setData(self, index, value, role):
        row = index.row()
        col = index.column()

        if role == Qt.EditRole:
            # save edit value
            self._mGridData[row][col] = str(value)

            # for presentation purposes, build and emit a joined string
            result = ''
            for row in self._mGridData:
                result += ', '.join(row)
            self.editCompleted.emit(result)
        return True

    def flags(self, index):
        return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled

class MainWindow(QMainWindow):
    def __init__(self, parent=None):    # initialise base class
        super(MainWindow, self).__init__(parent)

        tableView = QTableView(self)
        self.setCentralWidget(tableView)
        myModel = MyModel(self)
        tableView.setModel(myModel)

        myModel.editCompleted.connect(self.showWindowTitle)

    @pyqtSlot(str)
    def showWindowTitle(self, title):
        self.setWindowTitle(title)

# main ========================================================================
def main():
    import sys

    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()

    sys.exit(app.exec_())

if __name__ == '__main__':
    main()