[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?


  • Lifetime Qt Champion

    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.


  • Lifetime Qt Champion

    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?


  • Lifetime Qt Champion

    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 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);
    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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.