diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-10-23 10:53:51 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-11-15 16:23:42 +0100 |
commit | 61aa482241a7e81116224b2a5ae642df49526982 (patch) | |
tree | 1c3743ae61c372e7be8951d8e1ca08e725a2539a /src/widgets | |
parent | ee4f69205a375f821c32b4d2dd77e8d603910820 (diff) |
QTabBar: Support scrolling with a kinetic wheel
QTabBar implements wheelEvent to move the current index up or down. This
is useful for clicky mouse wheels, but a bad user experience when using
a kinetic wheel or touch pad, as every pixel movement will change the
current index.
Instead, scroll the entire tab bar when the wheel event comes from a
device that supports scroll phases, without changing the current index.
As drive-by's, fix the test introduced in aa09bea00ca88c587cfb1f56 to
not leak memory or leave a test-specific style set on the QApplication
instance, which can break other tests.
Also, make relevant layout code in QTabBar respect the usesScrollButtons
property, const'ify local variables, and return an accepted QWheelEvent
if the event resulted in a change.
[ChangeLog][QtWidgets][QTabBar] Scrolling with a kinetic wheel or touch
pad scrolls the entire tab bar, without changing the current index.
Change-Id: I990e51466dd25c741877bbf0e197449f897a9efb
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/widgets/qtabbar.cpp | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 8d21e7d257..3fdd6fc314 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -2388,10 +2388,48 @@ void QTabBar::wheelEvent(QWheelEvent *event) { Q_D(QTabBar); if (style()->styleHint(QStyle::SH_TabBar_AllowWheelScrolling)) { - int delta = (qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()) ? - event->angleDelta().x() : event->angleDelta().y()); - int offset = delta > 0 ? -1 : 1; - d->setCurrentNextEnabledIndex(offset); + const bool wheelVertical = qAbs(event->angleDelta().y()) > qAbs(event->angleDelta().x()); + const bool tabsVertical = verticalTabs(d->shape); + if (event->device()->capabilities().testFlag(QInputDevice::Capability::PixelScroll)) { + // For wheels/touch pads with pixel precision, scroll the tab bar if + // it has the right orientation. + int delta = 0; + if (tabsVertical == wheelVertical) + delta = wheelVertical ? event->pixelDelta().y() : event->pixelDelta().x(); + if (layoutDirection() == Qt::RightToLeft) + delta = -delta; + if (delta && d->validIndex(d->lastVisible)) { + const int oldScrollOffset = d->scrollOffset; + const QRect lastTabRect = d->tabList.at(d->lastVisible)->rect; + const QRect scrollRect = d->normalizedScrollRect(d->lastVisible); + int scrollRectExtent = scrollRect.right(); + if (!d->leftB->isVisible()) + scrollRectExtent += tabsVertical ? d->leftB->height() : d->leftB->width(); + if (!d->rightB->isVisible()) + scrollRectExtent += tabsVertical ? d->rightB->height() : d->rightB->width(); + + const int maxScrollOffset = (tabsVertical ? lastTabRect.bottom() + : lastTabRect.right()) + - scrollRectExtent; + d->scrollOffset = qBound(0, d->scrollOffset - delta, maxScrollOffset); + d->leftB->setEnabled(d->scrollOffset > -scrollRect.left()); + d->rightB->setEnabled(maxScrollOffset > d->scrollOffset); + if (oldScrollOffset != d->scrollOffset) { + event->accept(); + update(); + return; + } + } + } else { + const int delta = wheelVertical ? event->angleDelta().y() : event->angleDelta().x(); + const int offset = delta > 0 ? -1 : 1; + const int oldCurrentIndex = d->currentIndex; + d->setCurrentNextEnabledIndex(offset); + if (oldCurrentIndex != d->currentIndex) { + event->accept(); + return; + } + } QWidget::wheelEvent(event); } } |