[Solved] How to reimplement private function of QHeaderView to intercept sort indicator changes
-
Hello.
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? -
Hi,
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 )@
help ? -
Sadly not.
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->setSectionsClickable(false);@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 myselfvoid 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);
if(value.canConvert(QVariant::Int))
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?
}
QHeaderView::mouseReleaseEvent(e);
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.