Qt World Summit: Submit your Presentation

Default sort indicator order in QHeaderView

  • Hi all,

    I noticed that when you set a QSortFilterProxyModel on a QTableView with sorting enabled, it gets sorted in descending order by default. I found this a little strange. In my opinion it is far more natural for data to be ordered in ascending order.

    By the way, the reason for this is the initialization of QHeaderViewPrivate::sortIndicatorOrder. The value is correctly used in QTableView::setSortingEnabled.

    The documentation for QHeaderView::sortIndicatorOrder however states: "If no section has a sort indicator the return value of this function is undefined." I find this somehow confusing. It should at least say that the default sort order is Qt::DescendingOrder so that applications can react to this properly.

    What do you guys think about this? Should the default value be changed to Qt::AscendingOrder? Or is it just a case of poor wording in the documentation?


  • Lifetime Qt Champion


    AFAIK, models are by default considered unordered. Hence there's no guarantee that its content is shown in any specific order nor that it is sortable.

  • Of course you are right. A model itself is not sorted in any way.

    But please see the following example: https://pastebin.com/CRS0NSji

    In the call to QHeaderView::setSortingEnabled, the current sort indicator order of QHeaderView is applied to the model. And if it's a QSortFilterProxyModel it gets sorted. Since the sort indicator order gets initialized with Qt::DescendingOrder, the model is now shown in descending order.

  • @MrBolton
    I'm confused but interested by all of this.

    Would you care to read through one of the first topics I ever created in this forum, https://forum.qt.io/topic/83294/how-to-prevent-qtableview-qtreeview-doing-query-sorting-multiple-times, I think especially my final post there? I never did get what I regraded as a "satisfactory" behaviour out of it (hence I did not mark it as solved!). It's a bit different, doubtless, to your point, but all related. I believe my findings were that initially I get a database query but with no ORDER BY at all (I know your example does not use a database, but I;m just saying), whereas you talk about descending, but it was also potentially an older Qt.

    Is it related/interesting to your situation?

  • @JonB
    Your problem and mine are somehow connected. What happens in your code is that the call to QTableView::setSortingEnabled results in a call to QAbstractItemModel::sort with the current sort indicator order of the QHeaderView.
    QSqlTableModel reimplements QAbstractItemModel::sort and applies the sorting to the query in the form of ORDER BY. After that another query to the database is executed.
    The solution to your problem would be to create an instance of QSortFilterProxyModel that has your QSqlTableModel as its source model. Then set the QSortFilterProxyModel instance on the QTableView.
    This way QSortFilterProxyModel::sort will get called and sorting happens on your machine (i.e. in memory).

    However without setting the sort order explicitly, the data will be sorted in descending order. And this kind of bugs me. I just wanted to get into discussion with others about whether the default should be changed to Qt::AscendingOrder. :)

  • @MrBolton
    Thanks for replying.

    Your solution is not what I am looking for, unfortunately. I do not even have a QSortFilterProxyModel. Specifically, I do not want sorting to happen at the client. I wish it to happen at the server with a ORDER BY. My problem, IIRC, is that

    QTableView::sortByColumn(col, Qt.DescendingOrder);

    causes two SQL queries to be sent to the database, one for each line. Reversing the order of the two lines does not help. According to me, it is therefore not possible to enable sorting and pick which column to sort by without executing two queries in a row, which is ridiculously wasteful since we only care about the result of the second query. Users may not even be aware that this is what is happening behind the scenes. There should surely be some way of enabling sorting and specifying the column+direction without issuing two separate queries to the database. Nobody else but me seems to think this is an issue/bad/wrong!

    I realise this question is now OT. If you would care to share your help on this matter please be kind enough to post in my original thread, https://forum.qt.io/topic/83294/how-to-prevent-qtableview-qtreeview-doing-query-sorting-multiple-times. Thank you.

  • I know the topic is quite old, but I experienced the exact same issue and this thread was popping up in my search. So, adding a QSortFilterProxyModel and enabling sorting with setSortingEnabled(true) sorts the table in descending order.

    I got the correct order when I explicitly specifying the order via indicator right before enabling the sort:

    table->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder);