PDA

View Full Version : Sorting QTableView



Jimmy2775
8th February 2006, 19:50
I am trying to extend the QTableView class to create a table that sorts by column when the column header is clicked. So far the only way I can see to do this is by connecting the QTableView's horizontalHeader's sectionClicked() signal to the QTableView's sortByColumn() slot, but nothing seems to happen when I click the column header other than the sortIndicator changing. How can I get the column to sort, how can I specify how the column should be sorted (ascending vs. descending)?

Here is the constructor for my implementation of QTableView. This is where I am connecting the signal to the slot. I am new to QT so it is quite possible I am doing this completely wrong. Any advice is appreciated.



MyTableView::MyTableView(QWidget *parent) : QTableView(parent)
{
this->setDragEnabled(false);
this->setAlternatingRowColors(true);
this->setAcceptDrops(false);

QHeaderView* rowHeader = this->verticalHeader();
rowHeader->hide();

QHeaderView* columnHeader = this->horizontalHeader();
columnHeader->setClickable(true);
columnHeader->setSortIndicatorShown(true);
columnHeader->setSortIndicator(0, Qt::AscendingOrder);

QObject::connect(columnHeader, SIGNAL(sectionClicked(int)), this, SLOT(sortByColumn(int)));
}


Thanks.

jacek
8th February 2006, 20:05
The problem might be in model:

void QAbstractItemModel::sort ( int column, Qt::SortOrder order = Qt::AscendingOrder ) [virtual]
Sorts the model by column in the given order.
The base class implementation does nothing.
Also read this. (http://www.qtcentre.org/forum/showthread.php?t=467)

wysota
8th February 2006, 20:15
You should use a proxy model, like so:


QAbstractItemModel *model = new QStandardItemModel(...);
QTableView *view = new QTableView(...);
QSortFilterProxyModel *md = new QSortFilterProxyModel(this);
md->setSourceModel(model);
view->setModel(md);
md->sort(0);
view->header()->setSortIndicator(0, Qt::AscendingOrder);
view->header()->setSortIndicatorShown(true);
view->header()->setClickable(true);

Jimmy2775
8th February 2006, 20:16
Yes - I suppose it would help a great deal if I actually implemented the sorting function. :o

Thanks.

GreyGeek
8th February 2006, 21:51
You should use a proxy model, like so:


QAbstractItemModel *model = new QStandardItemModel(...);
QTableView *view = new QTableView(...);
QSortFilterProxyModel *md = new QSortFilterProxyModel(this);
md->setSourceModel(model);
view->setModel(md);
md->sort(0);
view->header()->setSortIndicator(0, Qt::AscendingOrder);
view->header()->setSortIndicatorShown(true);
view->header()->setClickable(true);
Is your example complete or have you left out important details?:


from the Assistant:
When subclassing QAbstractItemModel, at the very least you must implement index(), parent(), rowCount(), columnCount(), and data().
:confused:

wysota
8th February 2006, 22:20
It's complete (not counting the dots as constructor parameters). Take a closer look at the code -- I create a QStandardItemModel object and not a QAbstractItemModel one.

GreyGeek
9th February 2006, 17:39
It's complete (not counting the dots as constructor parameters). Take a closer look at the code -- I create a QStandardItemModel object and not a QAbstractItemModel one.
I thought I did:


QAbstractItemModel *model = new QStandardItemModel(...);

Isn't QStandardItemModel a subclass of QAbstractItemModel?

And, what is *model a subclass of?
QAbstractItemModel *model
or
*model = new QStandardItemModel?
:confused:
When you mix classes like that which one is the "winner"?
Does it matter as long as the one on the right is a subclass of the one on the left?

wysota
9th February 2006, 17:47
class A{};
class B : public class A{};
classA * obj = new classB();
// is equal to:
class B *tmp = new classB();
classA *obj = (obj*)tmp;

As long as class B inherits class A, you make make such a cast right? And all virtual functions from "obj" will be taken from classB, while all non virtual ones that were defined in classA will be taken from classA.

Because I don't need any features of standard item model while using the proxy, I can cast the pointer to its base class which is needed by the proxy. This was my way of showing that it works with any item model inherited from QAbstractItemModel (I couldn't instantiate a QAbstractItemModel object, as it is pure abstract, like you noted).