SimonD
SimonD

Reputation: 638

Updating sort-order indicator in QTableView/QHeaderView when model is sorted

I want to know how to ensure the sort indicator in the horizontal header of a QTableView is updated when a programmatic sort is performed on the model.

Here's the problem:

QStandardItemModel model(3,1);
QTableView view;
view.setModel( &model );

// Populate the model ensuring it is not in a sorted order
for( int row = 0; row < model.rowCount(); ++row )
{
    model.setItem( row , 0 ,
                   new QStandardItem(QString::number((row+1)%model.rowCount())));
}

view.setSortingEnabled( true );
// At this point everything is consistent since enabling the sorting
// triggers a sort that matches the indicator in the horizontalHeader (see A)

model.sort( 0 , Qt::AscendingOrder );
// However at this point the sort order has been reversed but the
// header's sort indicator remains unchanged (see B)

A: A: immediately after setSortingEnabled(true) B:Immediately after model.sort(0,Qt::AscendingOrder)

As you can see the sort indicator remains the same and therefore is inconsistent with the actual sort order.

In my application I have two views that interact with the same model and sorting can be triggered from either of them. I don't see anything in QAbstractItemModel that signals when a sort has been performed. It seems like QHeaderView/TableView assume that they are the only thing that can trigger a sort.

Does Qt provide facilities for coping with this that I'm missing? If not, what's the best way of keeping the sort indicator up-to-date without breaking the encapsulation of the multiple views on the model too much?

Upvotes: 1

Views: 5299

Answers (2)

SimonD
SimonD

Reputation: 638

One of the ItemDataRole enumerators available since Qt 4.8 is InitialSortOrderRole.

http://qt-project.org/doc/qt-4.8/qt.html#ItemDataRole-enum

It should therefore be possible to transmit sort order information through the QAbstractItemModel::headerData method.

I've tried this however and found that QTableView and QHeaderView do not seem to update in response to changes in this headerData role. A customised header view would appear to be necessary...

It might be worth it because passing this information via the model allows any number of views to synchronise without any external agent having to track all the views in existence so that it can distribute notifications. It would also work seamlessly through model proxy stacks such as those built with QSortFilterModelProxy.

Upvotes: 3

SimonD
SimonD

Reputation: 638

The solution I've come up with to avoid breaking encapsulation too much is

  • to have a signal on each view (on QTableView the sortIndicatorChanged signal suffices and on my custom view I have added a similar signal).
  • the manager of views connects to these signals
  • when any view emits such a signal the manager of views calls a slot on all the other views so that they can synchronise their sort indicators

I still feel like I might be missing something - surely this is a common problem? It seems to me that QAbstractItemModel should have a way of transmitting sort-order information to views...

Upvotes: 0

Related Questions