Search code examples
qtmodelpyqtqabstractitemmodel

QAbstractItemModel for QTreeView: what an I doing wrong?


I want to create a subclass a QAbstractItemModel to use it in QTreeView. At first, I decided to make a minimalistic model without any hierarchy supported. It should give a 2-by-3 table with simple text data (read-only one).

Alas, It does not crash but does not show any data: only a few column headers (1, 2). Cannot someone tell me, what am I doing wrong?

import os, sys

from PyQt5 import QtWidgets, QtCore, QtGui, QtSvg

from PyQt5.QtCore import QPointF, QRectF
from PyQt5.QtWidgets import QGraphicsItem


from gui.graphic_items import *



class MegaModel(QtCore.QAbstractItemModel):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._root_item = 7.40
        pass

    def columnCount(self, parent_index):
        if parent_index.isValid():
            return 0
        else:
            return 2

    def rowCount(self, parent_index):
        if parent_index.isValid():
            return 0
        else:
            return 3

    def data(self, index, role):
        if index.isValid():
            return QtCore.QVariant("Oy vey!")
        else:
            return None

    def index(self, row, column, parent=QtCore.QModelIndex()):
        print("index", row, column, parent)

        if parent.isValid():
            print("valid")
            return parent.internalPointer()
        else:
            print("invalid")
            return self.createIndex(row, column, self._root_item)

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


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)


    mega_view = QtWidgets.QTreeView()

    mega_model = MegaModel()

    mega_view.setModel(mega_model)

    mega_view.show()

    sys.exit(app.exec_())

Solution

  • Two mistakes:

    1. You shouldn't return parent.internalPointer() from index method - this method does not return the model's stored values, it is meant to only return indexes to model items
    2. In data method you return QtCore.QVariant("Oy vey!") for all roles. You should really only return this for QtCore.Qt.DisplayRole, for other roles it is ok to return None:

      def data(self, index, role):
          if not index.isValid():
              return None
          if role == QtCore.Qt.DisplayRole:
              return index.internalPointer()
          else:
              return None