diff options
Diffstat (limited to 'src/widgets/widgets/qscrollbar.cpp')
-rw-r--r-- | src/widgets/widgets/qscrollbar.cpp | 129 |
1 files changed, 56 insertions, 73 deletions
diff --git a/src/widgets/widgets/qscrollbar.cpp b/src/widgets/widgets/qscrollbar.cpp index b4168268a0..789cffba99 100644 --- a/src/widgets/widgets/qscrollbar.cpp +++ b/src/widgets/widgets/qscrollbar.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qapplication.h" #include "qcursor.h" @@ -44,12 +8,16 @@ #include "qscrollbar.h" #include "qstyle.h" #include "qstyleoption.h" +#include "qstylepainter.h" #if QT_CONFIG(menu) #include "qmenu.h" #endif + #include <QtCore/qelapsedtimer.h> +#include <QtCore/qpointer.h> + -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) #include "qaccessible.h" #endif #include <limits.h> @@ -175,7 +143,7 @@ QT_BEGIN_NAMESPACE \li Up/Down move a vertical scroll bar by one single step. \li PageUp moves up one page. \li PageDown moves down one page. - \li Home moves to the start (mininum). + \li Home moves to the start (minimum). \li End moves to the end (maximum). \endlist @@ -187,7 +155,7 @@ QT_BEGIN_NAMESPACE Most GUI styles use the pageStep() value to calculate the size of the slider. - \sa QScrollArea, QSlider, QDial, QSpinBox, {fowler}{GUI Design Handbook: Scroll Bar}, {Sliders Example} + \sa QScrollArea, QSlider, QDial, QSpinBox, {Sliders Example} */ bool QScrollBarPrivate::updateHoverControl(const QPoint &pos) @@ -224,7 +192,9 @@ void QScrollBarPrivate::setTransient(bool value) if (transient != value) { transient = value; if (q->isVisible()) { - if (q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, q)) + QStyleOptionSlider opt; + q->initStyleOption(&opt); + if (q->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, q)) q->update(); } else if (!transient) { q->show(); @@ -235,7 +205,9 @@ void QScrollBarPrivate::setTransient(bool value) void QScrollBarPrivate::flash() { Q_Q(QScrollBar); - if (!flashed && q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, q)) { + QStyleOptionSlider opt; + q->initStyleOption(&opt); + if (!flashed && q->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, q)) { flashed = true; if (!q->isVisible()) q->show(); @@ -319,7 +291,7 @@ void QScrollBar::initStyleOption(QStyleOptionSlider *option) const option->upsideDown = d->invertedAppearance; if (d->orientation == Qt::Horizontal) option->state |= QStyle::State_Horizontal; - if ((d->flashed || !d->transient) && style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, this)) + if ((d->flashed || !d->transient) && style()->styleHint(QStyle::SH_ScrollBar_Transient, option, this)) option->state |= QStyle::State_On; } @@ -376,7 +348,9 @@ void QScrollBarPrivate::init() invertedControls = true; pressedControl = hoverControl = QStyle::SC_None; pointerOutsidePressedControl = false; - transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, q); + QStyleOption opt; + opt.initFrom(q); + transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, q); flashed = false; flashTimer = 0; q->setFocusPolicy(Qt::NoFocus); @@ -392,7 +366,7 @@ void QScrollBarPrivate::init() /*! \reimp */ void QScrollBar::contextMenuEvent(QContextMenuEvent *event) { - if (!style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, 0, this)) { + if (!style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, nullptr, this)) { QAbstractSlider::contextMenuEvent(event); return ; } @@ -412,7 +386,7 @@ void QScrollBar::contextMenuEvent(QContextMenuEvent *event) QAction *actScrollDn = menu->addAction(horiz ? tr("Scroll right") : tr("Scroll down")); QAction *actionSelected = menu->exec(event->globalPos()); delete menu; - if (actionSelected == 0) + if (actionSelected == nullptr) /* do nothing */ ; else if (actionSelected == actScrollHere) setValue(d_func()->pixelPosToRangeValue(horiz ? event->pos().x() : event->pos().y())); @@ -448,8 +422,7 @@ QSize QScrollBar::sizeHint() const else size = QSize(scrollBarExtent, scrollBarExtent * 2 + scrollBarSliderMin); - return style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, size, this) - .expandedTo(QApplication::globalStrut()); + return style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, size, this); } /*!\reimp */ @@ -469,14 +442,19 @@ bool QScrollBar::event(QEvent *event) case QEvent::HoverLeave: case QEvent::HoverMove: if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event)) - d_func()->updateHoverControl(he->pos()); + d_func()->updateHoverControl(he->position().toPoint()); break; - case QEvent::StyleChange: - d_func()->setTransient(style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, this)); + case QEvent::StyleChange: { + QStyleOptionSlider opt; + initStyleOption(&opt); + d_func()->setTransient(style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, this)); break; + } case QEvent::Timer: if (static_cast<QTimerEvent *>(event)->timerId() == d->flashTimer) { - if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, this)) { + QStyleOptionSlider opt; + initStyleOption(&opt); + if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, this)) { d->flashed = false; update(); } @@ -497,16 +475,20 @@ bool QScrollBar::event(QEvent *event) void QScrollBar::wheelEvent(QWheelEvent *event) { event->ignore(); - int delta = event->delta(); + bool horizontal = qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()); + // The vertical wheel can be used to scroll a horizontal scrollbar, but only if + // there is no simultaneous horizontal wheel movement. This is to avoid chaotic + // scrolling on touchpads. + if (!horizontal && event->angleDelta().x() != 0 && orientation() == Qt::Horizontal) + return; // scrollbar is a special case - in vertical mode it reaches minimum // value in the upper position, however QSlider's minimum value is on - // the bottom. So we need to invert a value, but since the scrollbar is - // inverted by default, we need to inverse the delta value for the + // the bottom. So we need to invert the value, but since the scrollbar is + // inverted by default, we need to invert the delta value only for the // horizontal orientation. - if (event->orientation() == Qt::Horizontal) - delta = -delta; + int delta = horizontal ? -event->angleDelta().x() : event->angleDelta().y(); Q_D(QScrollBar); - if (d->scrollByDelta(event->orientation(), event->modifiers(), delta)) + if (d->scrollByDelta(horizontal ? Qt::Horizontal : Qt::Vertical, event->modifiers(), delta)) event->accept(); if (event->phase() == Qt::ScrollBegin) @@ -522,7 +504,7 @@ void QScrollBar::wheelEvent(QWheelEvent *event) void QScrollBar::paintEvent(QPaintEvent *) { Q_D(QScrollBar); - QPainter p(this); + QStylePainter p(this); QStyleOptionSlider opt; initStyleOption(&opt); opt.subControls = QStyle::SC_All; @@ -533,7 +515,7 @@ void QScrollBar::paintEvent(QPaintEvent *) } else { opt.activeSubControls = (QStyle::SubControl)d->hoverControl; } - style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this); + p.drawComplexControl(QStyle::CC_ScrollBar, opt); } /*! @@ -547,21 +529,22 @@ void QScrollBar::mousePressEvent(QMouseEvent *e) d->stopRepeatAction(); bool midButtonAbsPos = style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition, - 0, this); + nullptr, this); QStyleOptionSlider opt; initStyleOption(&opt); + opt.keyboardModifiers = e->modifiers(); if (d->maximum == d->minimum // no range || (e->buttons() & (~e->button())) // another button was clicked before - || !(e->button() == Qt::LeftButton || (midButtonAbsPos && e->button() == Qt::MidButton))) + || !(e->button() == Qt::LeftButton || (midButtonAbsPos && e->button() == Qt::MiddleButton))) return; - d->pressedControl = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this); + d->pressedControl = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->position().toPoint(), this); d->pointerOutsidePressedControl = false; QRect sr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, this); - QPoint click = e->pos(); + QPoint click = e->position().toPoint(); QPoint pressValue = click - sr.center() + sr.topLeft(); d->pressValue = d->orientation == Qt::Horizontal ? d->pixelPosToRangeValue(pressValue.x()) : d->pixelPosToRangeValue(pressValue.y()); @@ -572,12 +555,12 @@ void QScrollBar::mousePressEvent(QMouseEvent *e) if ((d->pressedControl == QStyle::SC_ScrollBarAddPage || d->pressedControl == QStyle::SC_ScrollBarSubPage) - && ((midButtonAbsPos && e->button() == Qt::MidButton) + && ((midButtonAbsPos && e->button() == Qt::MiddleButton) || (style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition, &opt, this) && e->button() == Qt::LeftButton))) { int sliderLength = HORIZONTAL ? sr.width() : sr.height(); - setSliderPosition(d->pixelPosToRangeValue((HORIZONTAL ? e->pos().x() - : e->pos().y()) - sliderLength / 2)); + setSliderPosition(d->pixelPosToRangeValue((HORIZONTAL ? e->position().toPoint().x() + : e->position().toPoint().y()) - sliderLength / 2)); d->pressedControl = QStyle::SC_ScrollBarSlider; d->clickOffset = sliderLength / 2; } @@ -628,18 +611,18 @@ void QScrollBar::mouseMoveEvent(QMouseEvent *e) QStyleOptionSlider opt; initStyleOption(&opt); if (!(e->buttons() & Qt::LeftButton - || ((e->buttons() & Qt::MidButton) + || ((e->buttons() & Qt::MiddleButton) && style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition, &opt, this)))) return; if (d->pressedControl == QStyle::SC_ScrollBarSlider) { - QPoint click = e->pos(); + QPoint click = e->position().toPoint(); int newPosition = d->pixelPosToRangeValue((HORIZONTAL ? click.x() : click.y()) -d->clickOffset); int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this); if (m >= 0) { QRect r = rect(); r.adjust(-m, -m, m, m); - if (! r.contains(e->pos())) + if (! r.contains(e->position().toPoint())) newPosition = d->snapBackPosition; } setSliderPosition(newPosition); @@ -647,7 +630,7 @@ void QScrollBar::mouseMoveEvent(QMouseEvent *e) if (style()->styleHint(QStyle::SH_ScrollBar_RollBetweenButtons, &opt, this) && d->pressedControl & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) { - QStyle::SubControl newSc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this); + QStyle::SubControl newSc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->position().toPoint(), this); if (newSc == d->pressedControl && !d->pointerOutsidePressedControl) return; // nothing to do if (newSc & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) { @@ -664,7 +647,7 @@ void QScrollBar::mouseMoveEvent(QMouseEvent *e) // stop scrolling when the mouse pointer leaves a control // similar to push buttons QRect pr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this); - if (pr.contains(e->pos()) == d->pointerOutsidePressedControl) { + if (pr.contains(e->position().toPoint()) == d->pointerOutsidePressedControl) { if ((d->pointerOutsidePressedControl = !d->pointerOutsidePressedControl)) { d->pointerOutsidePressedControl = true; setRepeatAction(SliderNoAction); |