Search code examples
pythonqtqtableviewqlistviewqabstractitemmodel

Set QTableView cell size when using fetch more?


I can set the size of my table rows using the following code:

    table = QTableView()
    table.setModel(CustomModel(dataFrame))
    table.resizeRowsToContents()

My CustomModel.data() function returns a size when role is Qt.SizeHintRole:

class CustomModel(QAbstractTableModel):

    [...]

    def data(self, index: QModelIndex, role=Qt.ItemDataRole):
        if not index.isValid():
            return None
        
        path = self._dataframe.iloc[index.row(), index.column()]
        pixmap = QPixmap(path)
        if role == Qt.SizeHintRole:
           return pixmap.size()

But when I modify my model so that it can fetch more items, as in the official example, the size is not taken into account anymore:

def setDataFrame(self, dataFrame: pd.DataFrame):
    self._dataframe = dataFrame
    self.beginResetModel()
    self._rowCount = 0
    self.endResetModel()
    return

def canFetchMore(self, parent=QModelIndex()) -> bool:
    return False if parent.isValid() else self._rowCount < len(self._dataframe)

def fetchMore(self, parent: QModelIndex | QPersistentModelIndex) -> None:
    if parent.isValid(): return

    remainder = len(self._dataframe) - self._rowCount
    itemsToFetch = min(100, remainder)

    if itemsToFetch <= 0: return

    self.beginInsertRows(QModelIndex(), self._rowCount, self._rowCount + itemsToFetch - 1)
    self._rowCount += itemsToFetch
    self.endInsertRows()

def rowCount(self, parent=QModelIndex()) -> int:
    return self._rowCount if parent == QModelIndex() else 0

When I change rowCount() so that it always returns len(self._dataframe), the size works again (but the "fetch more" feature breaks):

def rowCount(self, parent=QModelIndex()) -> int:
    return len(self._dataframe) if parent == QModelIndex() else 0

Any idea why this happens?


Solution

  • As @musicamante and @relent95 explained, resizeRowsToContents() does not resize rows in the future ; so I have to call it whenever a new row is instered.

    Adding table.model().rowsInserted.connect(lambda: self.content.resizeRowsToContents()) solved my problem.