[Solved] How to reimplement private function of QHeaderView to intercept sort indicator changes
I am currently using a "QHeaderView":http://qt-project.org/doc/qt-5.1/qtwidgets/qheaderview.html subclass to implement a couple of features I need. One of these would be to intercept the result of a click on a headerview section. The click results in a change of the "sortIndicator":http://qt-project.org/doc/qt-5.1/qtwidgets/qheaderview.html#setSortIndicator. Looking at Qts source code, I can see that inside the mouseReleaseEvent a private function of QHeaderView is called ("flipSortIndicator").
That private function is where I would need to act, but I don't know how.
The only "solution" I would see, is to completely reimplement the mouseReleaseEvent, but there are a lot of private members used in there, so whatever I could come up with would be very different than the base class implementation.
Has anybody a solution that doesn't involve recompiling Qt? This tiny thing seems to be overly complicated!
Thanks in advance, and have a nice day. :)
EDIT: A small update:
I reimplement the setSortIndicator function in my headerview, but since the private function calls the base classes implementation of that function, my work is undermined. Might there be a simple solution for this?
What changes do you want to make ? Is it esthetically ? In which case, did you consider the use of style sheet ?
It is not esthetically. I want control over the setting of the sort indicator. But the base class is using it's own implementation of setSortIndicator and I can't get a foot in the door.
What do you want to control ?
As a side note, I just saw something, setSortIndicator is not virtual so you can't reimplement it
I know, but how to get around that?
Depending on what you want to do, would a slot connected to
@void sortIndicatorChanged ( int logicalIndex, Qt::SortOrder order )@
As a very simplified example: When the user clicks the header section, instead of the sort order simply changing, I want to open a message box requesting confirmation first. For that I would have to intercept Qt trying to just go ahead with the change.
If I recompiled Qt (something I don't want to do), would making setSortIndicator() virtual be sufficient?
I think I'd handle rendering the sort indicators and setting the sort order myself. You can do that by reimplementing paintEvent and handling the sectionClicked signal.
That would also mean completely deactivating the initial sort mechanism and reimplementing mouseReleaseEvent(), at the very least. Seems like a lot of work for a not too ambitious goal.
This is what I did now, I would like some input:
This does not have any effect on the ordering - non-intuitively in my opinion:
This is my mouseReleaseEvent, I would like some input on line 21 - the rest is just for reference (the forum should be a little wider!):
@//QPoint leftButtonPressedPosition is set on mousePress
//SetSortIndicator is the function where I change the sortorder myself
void HeaderView::mouseReleaseEvent(QMouseEvent *e)
if(e->button() == Qt::LeftButton &&
(e->pos() - leftButtonPressedPosition).manhattanLength() < qApp->startDragDistance() &&
this->logicalIndexAt(e->pos()) == this->logicalIndexAt(leftButtonPressedPosition)
Qt::SortOrder order = Qt::AscendingOrder;
const QVariant value = this->model()->headerData(this->logicalIndexAt(e->pos()), Qt::Horizontal, Qt::InitialSortOrderRole);
order = static_castQt::SortOrder(value.toInt());
if(this->sortIndicatorSection() == this->logicalIndexAt(e->pos())) this->SetSortIndicator(this->sortIndicatorSection(), (this->sortIndicatorOrder() == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder); else this->SetSortIndicator(this->logicalIndexAt(e->pos()), order); leftButtonPressedPosition = QPoint(-1, -1); e->accept(); return;//am I losing any other functionality by not calling the base class?
leftButtonPressedPosition = QPoint(-1, -1);
So far it seems that this works as intended. I did not have to reimplement paint() (and I don't think it would help in any way since showing that little arrow for the sortorder is a completely separate setting). Only a short piece in the mousePressEvent
@if(e->button() == Qt::LeftButton)
leftButtonPressedPosition = e->pos();@
and the posted mouseReleaseEvent.
Going on a tangent here, but: Why is it that setSortIndicator (or other functions of similar "status") is not virtual? Things would have been pretty easy to handle if it was, I think.