Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QAbstractItemModel: much time lost on nothing between beginResetModel() and endResetModel()



  • MyTableModel inherits from QAbstractItemModel.

    Occasionally, my data change deeply: new number of rows, and new contents in each single row. So I call from within MyTableModel:

    beginResetModel();
    endResetModel();
    

    This redraws the entire table, calling numerous times the function MyTableModel::data (which overrides QAbstractItemModel::data). Works perfectly, but too slowly. For a table with a few thousand entries, it takes several seconds from beginResetModel to endResetModel.

    Of course my first suspicion was that computations in my own data function take too long. So I replaced it by

    QVariant
    MyTableModel::data(const QModelIndex& index, int role) const override
    {
        return {};
    }
    

    Almost no effect. The seconds are really spent on some Qt internal overhead.

    Questions, obviously: What is Qt doing? How to make it faster?



  • @Joachim-W
    begin/endResetModel() tell any attached views that the model has changed, and they need to redraw. They are the callers of the data() method.

    You need to look at whatever views you have attached to the model are up to for the time taken. I don't know how long it takes your view(s) to redraw against "a table with a few thousand entries".



  • @JonB MyTableView inherits from QTreeView (and not from QTableView, which for forgotten reasons did not yield the right layout). Upon signal QAbstractItemModel::modelReset, it calls QTreeView::resizeColumnToContents for each column. This is probably a stupid thing to do as it calls MyTableModel::data for all columns and all rows. Yet I wonder: why does this overhead machinery by itself consume much more time than whatever computations within MyTableModel::data?



  • @Joachim-W said in QAbstractItemModel: much time lost on nothing between beginResetModel() and endResetModel():

    Yet I wonder: why does this overhead machinery by itself consume much more time than whatever computations within MyTableModel::data?

    ? Because there's a lot more work to for visual computation that there is for mere model access! For example, resizeColumnToContents() is going to have to measure the font width of every string shown to decide how wide it is in order to line up.... That's why it may not be a great idea to show "thousands" of rows (with multiple columns) in a view, but up to you.


  • Qt Champions 2019

    You should not use QHeaderView::ResizeToContents in your views when there is a large amount of data - because it needs, as @JonB already said, to calculate all cell widths.



  • @Christian-Ehrlicher , @Joachim-W
    As an observation.

    resizeColumnToContents() is slow with a large table model. IIRC, in Windows at least when you double-click on a column-width-drag-resizer-line to make it size to widest shown, I think it always calculates only from those rows/columns which are visible in the current pane. If you scroll down you can still meet wider items, and have to double-click again.

    OTOH, I think the Qt resizeColumnToContents() calculates on all rows/columns in the view, regardless of viewport visibility.

    There will be a big speed difference between these two behaviours on large data. Would be nice if the Qt one could do the visible, fast one, maybe you have to override resizeColumnToContents() with your own code to implement?


  • Qt Champions 2019

    @JonB said in QAbstractItemModel: much time lost on nothing between beginResetModel() and endResetModel():

    all rows/columns in the view, regardless of viewport visibility.

    No :)

    See https://doc.qt.io/qt-5/qheaderview.html#setResizeContentsPrecision
    And if this is not enough you can overwrite QTableView::sizeHintForColumn() iirc.



  • @Christian-Ehrlicher
    Wow! Yep, good for you & Qt

    The default value is 1000
    Special value 0 means that it will look at only the visible area.

    @Joachim-W
    Try changing that value from 1,000 to 0 and see how it affects your speed situation?



  • I removed the call to resizeColumnToContents() for good. Computation is now faster, and independent of table size.


  • Qt Champions 2019

    @Joachim-W Then please mark this topic as solved, thx.