diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-11-25 22:03:38 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2020-12-01 18:43:35 +0000 |
commit | 8b7d6a14fcae3bcd201df6ddb8eb6f17258cb03b (patch) | |
tree | 6f2d3cc584e61485eff1a89a4a48923096fe30b1 /src/widgets/itemviews | |
parent | b5ecdce605685996a5e280edd164f8853f8326df (diff) |
QHeaderView: fix spurious sorting
QHeaderView sorting may be triggered when the user performs
some mouse interactions that should really not result in sorting.
Generally speaking, this happens when the user:
* presses on a non-movable section (A)
* moves on another section (B)
* releases on that section
resulting in B becoming sorted / flipping sorting.
(Non-movable is required, otherwise dragging would cause section moving,
not sorting.)
To make the matter worse, QHeaderView doesn't check that the release
happens within its geometry. This makes sense when moving sections: one
is able to drag a section horizontally/vertically even if the mouse
leaves the QHeaderView.
But when not moving sections, this means that one can
* press on section (A),
* move the mouse anywhere vertically (for a horizontal bar, mut.mut
for a vertical) above or below another section (B), that is,
outside QHeaderView's geometry
* release the mouse
and cause B to be sorted.
Fix it by
1) remembering which one was the section that the user originally
clicked on; that's the only one that can possibly become sorted
(if we're not moving and other conditions hold). No other variable
seemed to remember this.
2) on release, check that it happens within that section's geometry.
If so, sort.
Change-Id: Icfb67662221efbde019711f933781ee1e7d9ac43
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit b5b2640a65de20d05890fa9e6462bb7b88f83964)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/widgets/itemviews')
-rw-r--r-- | src/widgets/itemviews/qheaderview.cpp | 30 | ||||
-rw-r--r-- | src/widgets/itemviews/qheaderview_p.h | 2 |
2 files changed, 26 insertions, 6 deletions
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 8daa2bab9a..daaad42346 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -2528,7 +2528,7 @@ void QHeaderView::mousePressEvent(QMouseEvent *e) int handle = d->sectionHandleAt(pos); d->originalSize = -1; // clear the stored original size if (handle == -1) { - d->pressed = logicalIndexAt(pos); + d->firstPressed = d->pressed = logicalIndexAt(pos); if (d->clickableSections) emit sectionPressed(d->pressed); @@ -2576,7 +2576,7 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e) // just before the mouseReleaseEvent and resets the state. This prevents // column dragging from working. So this code is disabled under Cocoa. d->state = QHeaderViewPrivate::NoState; - d->pressed = -1; + d->firstPressed = d->pressed = -1; } switch (d->state) { case QHeaderViewPrivate::ResizeSection: { @@ -2705,9 +2705,27 @@ void QHeaderView::mouseReleaseEvent(QMouseEvent *e) case QHeaderViewPrivate::NoState: if (d->clickableSections) { int section = logicalIndexAt(pos); - if (section != -1 && section == d->pressed) { - d->flipSortIndicator(section); - emit sectionClicked(section); + if (section != -1 && section == d->firstPressed) { + QRect firstPressedSectionRect; + switch (d->orientation) { + case Qt::Horizontal: + firstPressedSectionRect.setRect(sectionViewportPosition(d->firstPressed), + 0, + sectionSize(d->firstPressed), + d->viewport->height()); + break; + case Qt::Vertical: + firstPressedSectionRect.setRect(0, + sectionViewportPosition(d->firstPressed), + d->viewport->width(), + sectionSize(d->firstPressed)); + break; + }; + + if (firstPressedSectionRect.contains(e->position().toPoint())) { + d->flipSortIndicator(section); + emit sectionClicked(section); + } } if (d->pressed != -1) updateSection(d->pressed); @@ -2721,7 +2739,7 @@ void QHeaderView::mouseReleaseEvent(QMouseEvent *e) break; } d->state = QHeaderViewPrivate::NoState; - d->pressed = -1; + d->firstPressed = d->pressed = -1; } /*! diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h index 59879e0838..148e723be4 100644 --- a/src/widgets/itemviews/qheaderview_p.h +++ b/src/widgets/itemviews/qheaderview_p.h @@ -82,6 +82,7 @@ public: originalSize(-1), section(-1), target(-1), + firstPressed(-1), pressed(-1), hover(-1), length(0), @@ -274,6 +275,7 @@ public: int originalSize; int section; // used for resizing and moving sections int target; + int firstPressed; int pressed; int hover; |