0

I have a QHeaderView that does a few things when clicking either to the left or right of the center of a section header.

For this, I need to know the position of the click in relation to the (possibly scrolled) content of the QHeaderView's viewport. The actual click position, however, refers only to the QHeaderView (which is always fixed).

I tried variants of mapTo/From, but can't find the correct way to do it. Here's simplified code:

void MyTableHeader::headerSectionClicked(int section_index, int click_pos)
{
    int section_size = sectionSize(0); // All sections in a header are equally sized
    int section_center = (section_size * (section_index+ 1)) - (section_size / 2); // Center of the clicked section

    if (section_index>= 0)// if mouse is over an item
    {
        if (orientation() == Qt::Horizontal)
        {
            QPoint x_pos = QPoint(click_pos, 0);
            int mapped_offset = viewport()->mapFrom(this, x_pos).x();

            if (mapped_offset != -1)
            {
                // If the click was to the right of the center, iterate on the index
                if (mapped_offset >= section_center)
                {
                    section_index++;
                }
            }
        }
        else
        {
            // Same thing for the Y-dimension
        }
    }

    // Neat stuff after this
}

The part where the problem occurs, is where I want to find out on which side of the section the click happened.

// If the click was to the right of the center, iterate on the index
if (mapped_offset >= section_center)
{
    in_index++;
}

This mapped_offset does not properly refer to the same context as the section center.

i know nothing
  • 951
  • 1
  • 10
  • 27

1 Answers1

1

The following solution might give you an idea on what to do.

MyHeaderView.h

#pragma once

#include <QHeaderView>

class MyHeaderView : public QHeaderView
{
    Q_OBJECT
public:
    MyHeaderView(Qt::Orientation orientation, QWidget* parent = nullptr);
};

MyHeaderView.cpp

#include "MyHeaderView.h"
#include <QDebug>

MyHeaderView::MyHeaderView(Qt::Orientation orientation, QWidget* parent) : QHeaderView(orientation, parent)
{
    setSectionsClickable(true);
    connect(this, &MyHeaderView::sectionClicked, [this](int section)
        {
            QRect currentSectionRect;
            currentSectionRect.setRect(sectionViewportPosition(section), 0, sectionSize(section), viewport()->height());
            auto pos = QCursor::pos();
            auto localPos = mapFromGlobal(pos);

            qDebug() << currentSectionRect << localPos;
            qDebug() << currentSectionRect.contains(localPos); //"Always true!"
        });
}

main.cpp

#include "MyHeaderView.h"
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>

int main(int argc, char **args)
{
    QApplication app(argc, args);
    auto model = new QStandardItemModel;
    auto view = new QTableView;
    view->setModel(model);
    model->setRowCount(4);
    model->setColumnCount(4);
    view->setHorizontalHeader(new MyHeaderView(Qt::Horizontal));
    view->show();
    app.exec();
}
Aleph0
  • 5,816
  • 4
  • 29
  • 80
  • I think this might work, but not in my specific case. Because I can't use the "sectionClicked"-signal, and so the QCursor::pos() contains invalid values at the time a section click is registered in my case. Thanks nonetheless! – i know nothing Jun 25 '19 at 13:19