Important: Please read the Qt Code of Conduct -

[Solved] Sorting QML Tableview is slow

  • Hello folks,

    we have implemented a sortable table in QML. Sorting takes a long time, I haven't measured exactly, but it is approximately a minute for about 8000 rows. I've ran the test through a profiler and according to that, within the QSortFilterProxyModel::sort() function, most of the time (>99%) is spent in QAbstractItemModel::LayoutChanged() and subsequent calls. We emit the layoutChanged() only after sorting has completed. So this is puzzling me quite a bit. So my question is: Is this signal emitted internally during the sort function? If yes, are these sort times normal for a QML table?

    void MySortFilterProxyModel::setSortOrder(Qt::SortOrder order)
    	QAbstractItemModel* src = qobject_cast<QAbstractItemModel*>(source());
    	emit src->layoutAboutToBeChanged();
    	QSortFilterProxyModel::sort(0, order);
    	emit src->layoutChanged();

    I read various threads and questions on the topic, but none of them seems to match our setup with using a QML tableview and they usually somewhere emit the layoutChanged() which makes them slow.

    On demand I could post complete sources but I do not think they are at fault here.

  • Results of profiling after sort() to show that none of our custom functions is involved..I've inspected the all of the tree and there is no more of our code involved, only Qt internals.

    99,78 QSortFilterProxyModel::sort
    99,78 ----QSortFilterProxyModelPrivate::sort
    99,78 --------QAbstractItemModel::layoutChanged
    99,78 ------------QMetaObject::activate
    99,78 ----------------QMetaObject::activate
    99,78 --------------------QMetaObject::metacall
    99,78 ------------------------QQmlDelegateModel::qt_metacall
    99,78 -----------------------------QQmlDelegateModel::qt_static_metacall
    99,78 ---------------------------------QQmlDelegateModel::_q_layoutChanged
    99,7 ---------------------------------------QQmlDelegateModel::_q_itemsMoved
    0,01 ---------------------------------------QList<QQmlDelegateModelItem *>::at
    0,01 ---------------------------------------QQmlDelegateModelItem::modelIndex
    0,01 ---------------------------------------QQmlDelegateModelItem::setModelIndex
    0,00 ---------------------------------------QQmlDelegateModelPrivate::itemsMoved
    0,00 ---------------------------------------QPersistentModelIndex::row
    0,00 ---------------------------------------QVectorQQmlListCompositor::Insert::~QVectorQQmlListCompositor::Insert
    0,00 ---------------------------------------@ILT+10530(?setModelIndex@QQmlDelegateModelItem@@QAEXH@Z)
    0,00 ---------------------------------------QQmlListCompositor::listItemsMoved

  • I am pretty sure the QSortFilterProxy tries to move the items in the model so that they can be animated. I think you might be better off with just resetting the entire model if you have a lot of items. I will say that you would think it wouldn't need to move items outside of the view, but idk how qml implements a tableview. You would call QAbstractItemModel::modelReset(). I guess you could try to slap it into a C++ table view and see if the same behavior is observed.

  • Hi eagain!

    I think Buttink is right. I suggest to add a boolean property to your model in C++ that is true only during sorting. Then you could use this property to detach the model from the view during sorting in QML like this:

    MyTableView {
    model: myModel.isSorting ? null : myModel


  • Wow, nice! That did indeed help. Works like a charm now. Cleaned it up a little while I was editing, turns out you don't need to emit layoutChanged at all.

  • Moderators

    @eagain you can use the "Mark Solved" in "Topic Tools" box to mark topic as solved ;)

  • @p3c0 I tried, but apparently im too blind to find that button. The "Topic Tools" only contain the option to "Delete Topic"

  • Moderators

    @eagain said:

    @p3c0 I tried, but apparently im too blind to find that button. The "Topic Tools" only contain the option to "Delete Topic"

    At the moment, only moderators can mark topics as solved: Tero, our community manager, is looking to give every user that ability.

    In the meantime, I believe you can mark it by editing the original post and adding "[Solved]" to the start of the title.