[Solved] Intercept manual resize of QHeaderView



  • I am fiddling around with the Qt undo framework, and I would like to be able to revert size changes of a QHeaderView - the ones initiated by the user via dragging the section delimiters.

    I already tried reimplementing "resizeSection":http://qt-project.org/doc/qt-5.1/qtwidgets/qheaderview.html#resizeSection and "event":http://qt-project.org/doc/qt-5.1/qtwidgets/qheaderview.html#event, both without being informed about the kind of change I wanted to intercept. Where else could I look? Would an event filter help and what kind of event would I need to filter?


  • Moderators

    subclassing resizeSection() method is wrong since it's not virtual. You should rather listen to the "sectionResized() signal":http://qt-project.org/doc/qt-5.1/qtwidgets/qheaderview.html#sectionResized.

    you can try the following:
    @
    void MyHeaderView::mousePressEvent(QMouseEvent* event)
    {
    m_PossibleSectionResize = true;
    QHeaderView::mousePressEvent(event);
    }

    void MyHeaderView::mouseReleaseEvent(QMouseEvent* event)
    {
    QHeaderView::mouseReleaseEvent(event);
    m_PossibleSectionResize = false;
    }

    //SLOT connected to QHeaderView::sectionResized(int,int,int) signal
    void MyHeaderView::onSectionResized(int logicalIndex, int oldSize, int newSize)
    {
    if( PossibleSectionResize )
    {
    //add your state to the QUndoRedoStack
    }
    }
    @



  • That is something I thought about. But since I would have to create a QUndoCommand, the section would be resized twice (the command is always invoked when pushed to the QUndoStack).


  • Moderators

    @
    void MyHeaderView::onSectionResized(int logicalIndex, int oldSize, int newSize)
    {
    if( PossibleSectionResize )
    {
    this->blockSignals(true);
    //add your state to the QUndoRedoStack
    this->blockSignals(false);
    }
    }
    @

    actually instead of saving the the sate on every time the signal is triggered you can alternatively set a bool member indicating that the section has resized. And then do the actual creation of the undoredo command on the release event. This also ensures that you don't create superfluous undo redo commands!

    @
    void MyHeaderView::mousePressEvent(QMouseEvent* event)
    {
    m_SectionsResized = false;
    QHeaderView::mousePressEvent(event);
    }

    void MyHeaderView::mouseReleaseEvent(QMouseEvent* event)
    {
        QHeaderView::mouseReleaseEvent(event);
        if( m_SectionsResized )
        {
             //create UndoRedoCommand
        }
    }
     
    //SLOT connected to QHeaderView::sectionResized(int,int,int) signal
    void MyHeaderView::onSectionResized(int logicalIndex, int oldSize, int newSize)
    {
        m_SectionsResized = true;   //you are free to optimize this part ;)
    }
    

    @



  • Thanks a lot, I did it like this now:
    @void HeaderView::mousePressEvent(QMouseEvent *e)
    {
    if(e->button() == Qt::LeftButton)
    {
    sizesBeforeResize.clear();//a QList<int> that stores the former sizes
    for(int i = 0 ; i < this->count() ; i ++)
    {
    sizesBeforeResize.append(this->sectionSize(i));
    }
    }
    QHeaderView::mousePressEvent(e);
    }

    void HeaderView::mouseReleaseEvent(QMouseEvent *e)
    {
    if(e->button() == Qt::LeftButton && !sizesBeforeResize.isEmpty())
    {
    QMap<int, int> oldSizes, newSizes;
    for(int i = 0 ; i < this->count() ; i ++)
    {
    if(this->sectionSize(i) != sizesBeforeResize.at(i))
    {
    oldSizes.insert(i, sizesBeforeResize.at(i));
    newSizes.insert(i, this->sectionSize(i));
    }
    }
    if(!newSizes.isEmpty())
    {
    QUndoCommand *u = new Undo_ResizeHeaderSection(oldSizes, newSizes, this);
    undo->push(u); //my QUndoStack
    oldSizes.clear();
    }
    }
    QHeaderView::mouseReleaseEvent(e);
    }@

    I still added an additional check, because I don't want to provoke flickering (or whatever bad might happen):
    @void Undo_ResizeHeaderSection::redo()
    {
    Q_FOREACH(int i, newSizes.keys())
    {
    if(header->sectionSize(i) != newSizes.value(i))//additional check
    {
    header->resizeSection(i, newSizes.value(i));
    }
    }
    }@
    Or could I just leave the check out?


Log in to reply
 

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