diff options
Diffstat (limited to 'src/gui/widgets/qscrollbar.cpp')
-rw-r--r-- | src/gui/widgets/qscrollbar.cpp | 764 |
1 files changed, 0 insertions, 764 deletions
diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp deleted file mode 100644 index 72f461fe63..0000000000 --- a/src/gui/widgets/qscrollbar.cpp +++ /dev/null @@ -1,764 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" -#include "qcursor.h" -#include "qevent.h" -#include "qpainter.h" -#include "qscrollbar.h" -#include "qstyle.h" -#include "qstyleoption.h" -#include "qmenu.h" -#include <QtCore/qelapsedtimer.h> - -#ifndef QT_NO_SCROLLBAR - -#ifndef QT_NO_ACCESSIBILITY -#include "qaccessible.h" -#endif -#include <limits.h> -#include "qabstractslider_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QScrollBar - \brief The QScrollBar widget provides a vertical or horizontal scroll bar. - - \ingroup basicwidgets - - A scroll bar is a control that enables the user to access parts of a - document that is larger than the widget used to display it. It provides - a visual indication of the user's current position within the document - and the amount of the document that is visible. Scroll bars are usually - equipped with other controls that enable more accurate navigation. - Qt displays scroll bars in a way that is appropriate for each platform. - - If you need to provide a scrolling view onto another widget, it may be - more convenient to use the QScrollArea class because this provides a - viewport widget and scroll bars. QScrollBar is useful if you need to - implement similar functionality for specialized widgets using QAbstractScrollArea; - for example, if you decide to subclass QAbstractItemView. - For most other situations where a slider control is used to obtain a value - within a given range, the QSlider class may be more appropriate for your - needs. - - \table - \row \o \image qscrollbar-picture.png - \o Scroll bars typically include four separate controls: a slider, - scroll arrows, and a page control. - - \list - \o a. The slider provides a way to quickly go to any part of the - document, but does not support accurate navigation within large - documents. - \o b. The scroll arrows are push buttons which can be used to accurately - navigate to a particular place in a document. For a vertical scroll bar - connected to a text editor, these typically move the current position one - "line" up or down, and adjust the position of the slider by a small - amount. In editors and list boxes a "line" might mean one line of text; - in an image viewer it might mean 20 pixels. - \o c. The page control is the area over which the slider is dragged (the - scroll bar's background). Clicking here moves the scroll bar towards - the click by one "page". This value is usually the same as the length of - the slider. - \endlist - \endtable - - Each scroll bar has a value that indicates how far the slider is from - the start of the scroll bar; this is obtained with value() and set - with setValue(). This value always lies within the range of values - defined for the scroll bar, from \l{QAbstractSlider::minimum()}{minimum()} - to \l{QAbstractSlider::minimum()}{maximum()} inclusive. The range of - acceptable values can be set with setMinimum() and setMaximum(). - At the minimum value, the top edge of the slider (for a vertical scroll - bar) or left edge (for a horizontal scroll bar) will be at the top (or - left) end of the scroll bar. At the maximum value, the bottom (or right) - edge of the slider will be at the bottom (or right) end of the scroll bar. - - The length of the slider is usually related to the value of the page step, - and typically represents the proportion of the document area shown in a - scrolling view. The page step is the amount that the value changes by - when the user presses the \key{Page Up} and \key{Page Down} keys, and is - set with setPageStep(). Smaller changes to the value defined by the - line step are made using the cursor keys, and this quantity is set with - \l{QAbstractSlider::}{setSingleStep()}. - - Note that the range of values used is independent of the actual size - of the scroll bar widget. You do not need to take this into account when - you choose values for the range and the page step. - - The range of values specified for the scroll bar are often determined - differently to those for a QSlider because the length of the slider - needs to be taken into account. If we have a document with 100 lines, - and we can only show 20 lines in a widget, we may wish to construct a - scroll bar with a page step of 20, a minimum value of 0, and a maximum - value of 80. This would give us a scroll bar with five "pages". - - \table - \row \o \inlineimage qscrollbar-values.png - \o The relationship between a document length, the range of values used - in a scroll bar, and the page step is simple in many common situations. - The scroll bar's range of values is determined by subtracting a - chosen page step from some value representing the length of the document. - In such cases, the following equation is useful: - \e{document length} = maximum() - minimum() + pageStep(). - \endtable - - QScrollBar only provides integer ranges. Note that although - QScrollBar handles very large numbers, scroll bars on current - screens cannot usefully represent ranges above about 100,000 pixels. - Beyond that, it becomes difficult for the user to control the - slider using either the keyboard or the mouse, and the scroll - arrows will have limited use. - - ScrollBar inherits a comprehensive set of signals from QAbstractSlider: - \list - \o \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the - scroll bar's value has changed. The tracking() determines whether this - signal is emitted during user interaction. - \o \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the - scroll bar's range of values has changed. - \o \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when - the user starts to drag the slider. - \o \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user - drags the slider. - \o \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when - the user releases the slider. - \o \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted - when the scroll bar is changed by user interaction or via the - \l{QAbstractSlider::triggerAction()}{triggerAction()} function. - \endlist - - A scroll bar can be controlled by the keyboard, but it has a - default focusPolicy() of Qt::NoFocus. Use setFocusPolicy() to - enable keyboard interaction with the scroll bar: - \list - \o Left/Right move a horizontal scroll bar by one single step. - \o Up/Down move a vertical scroll bar by one single step. - \o PageUp moves up one page. - \o PageDown moves down one page. - \o Home moves to the start (mininum). - \o End moves to the end (maximum). - \endlist - - The slider itself can be controlled by using the - \l{QAbstractSlider::triggerAction()}{triggerAction()} function to simulate - user interaction with the scroll bar controls. This is useful if you have - many different widgets that use a common range of values. - - Most GUI styles use the pageStep() value to calculate the size of the - slider. - - \table 100% - \row \o \inlineimage macintosh-horizontalscrollbar.png Screenshot of a Macintosh style scroll bar - \o A scroll bar shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage windowsxp-horizontalscrollbar.png Screenshot of a Windows XP style scroll bar - \o A scroll bar shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage plastique-horizontalscrollbar.png Screenshot of a Plastique style scroll bar - \o A scroll bar shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. - \endtable - - \sa QScrollArea, QSlider, QDial, QSpinBox, {fowler}{GUI Design Handbook: Scroll Bar}, {Sliders Example} -*/ - -class QScrollBarPrivate : public QAbstractSliderPrivate -{ - Q_DECLARE_PUBLIC(QScrollBar) -public: - QStyle::SubControl pressedControl; - bool pointerOutsidePressedControl; - - int clickOffset, snapBackPosition; - - void activateControl(uint control, int threshold = 500); - void stopRepeatAction(); - int pixelPosToRangeValue(int pos) const; - void init(); - bool updateHoverControl(const QPoint &pos); - QStyle::SubControl newHoverControl(const QPoint &pos); - - QStyle::SubControl hoverControl; - QRect hoverRect; -}; - -bool QScrollBarPrivate::updateHoverControl(const QPoint &pos) -{ - Q_Q(QScrollBar); - QRect lastHoverRect = hoverRect; - QStyle::SubControl lastHoverControl = hoverControl; - bool doesHover = q->testAttribute(Qt::WA_Hover); - if (lastHoverControl != newHoverControl(pos) && doesHover) { - q->update(lastHoverRect); - q->update(hoverRect); - return true; - } - return !doesHover; -} - -QStyle::SubControl QScrollBarPrivate::newHoverControl(const QPoint &pos) -{ - Q_Q(QScrollBar); - QStyleOptionSlider opt; - q->initStyleOption(&opt); - opt.subControls = QStyle::SC_All; - hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, pos, q); - if (hoverControl == QStyle::SC_None) - hoverRect = QRect(); - else - hoverRect = q->style()->subControlRect(QStyle::CC_ScrollBar, &opt, hoverControl, q); - return hoverControl; -} - -void QScrollBarPrivate::activateControl(uint control, int threshold) -{ - QAbstractSlider::SliderAction action = QAbstractSlider::SliderNoAction; - switch (control) { - case QStyle::SC_ScrollBarAddPage: - action = QAbstractSlider::SliderPageStepAdd; - break; - case QStyle::SC_ScrollBarSubPage: - action = QAbstractSlider::SliderPageStepSub; - break; - case QStyle::SC_ScrollBarAddLine: - action = QAbstractSlider::SliderSingleStepAdd; - break; - case QStyle::SC_ScrollBarSubLine: - action = QAbstractSlider::SliderSingleStepSub; - break; - case QStyle::SC_ScrollBarFirst: - action = QAbstractSlider::SliderToMinimum; - break; - case QStyle::SC_ScrollBarLast: - action = QAbstractSlider::SliderToMaximum; - break; - default: - break; - } - - if (action) { - q_func()->setRepeatAction(action, threshold); - q_func()->triggerAction(action); - } -} - -void QScrollBarPrivate::stopRepeatAction() -{ - Q_Q(QScrollBar); - QStyle::SubControl tmp = pressedControl; - q->setRepeatAction(QAbstractSlider::SliderNoAction); - pressedControl = QStyle::SC_None; - - if (tmp == QStyle::SC_ScrollBarSlider) - q->setSliderDown(false); - - QStyleOptionSlider opt; - q->initStyleOption(&opt); - q->repaint(q->style()->subControlRect(QStyle::CC_ScrollBar, &opt, tmp, q)); -} - -/*! - Initialize \a option with the values from this QScrollBar. This method - is useful for subclasses when they need a QStyleOptionSlider, but don't want - to fill in all the information themselves. - - \sa QStyleOption::initFrom() -*/ -void QScrollBar::initStyleOption(QStyleOptionSlider *option) const -{ - if (!option) - return; - - Q_D(const QScrollBar); - option->initFrom(this); - option->subControls = QStyle::SC_None; - option->activeSubControls = QStyle::SC_None; - option->orientation = d->orientation; - option->minimum = d->minimum; - option->maximum = d->maximum; - option->sliderPosition = d->position; - option->sliderValue = d->value; - option->singleStep = d->singleStep; - option->pageStep = d->pageStep; - option->upsideDown = d->invertedAppearance; - if (d->orientation == Qt::Horizontal) - option->state |= QStyle::State_Horizontal; -} - - -#define HORIZONTAL (d_func()->orientation == Qt::Horizontal) -#define VERTICAL !HORIZONTAL - -/*! - Constructs a vertical scroll bar. - - The \a parent argument is sent to the QWidget constructor. - - The \l {QAbstractSlider::minimum} {minimum} defaults to 0, the - \l {QAbstractSlider::maximum} {maximum} to 99, with a - \l {QAbstractSlider::singleStep} {singleStep} size of 1 and a - \l {QAbstractSlider::pageStep} {pageStep} size of 10, and an - initial \l {QAbstractSlider::value} {value} of 0. -*/ -QScrollBar::QScrollBar(QWidget *parent) - : QAbstractSlider(*new QScrollBarPrivate, parent) -{ - d_func()->orientation = Qt::Vertical; - d_func()->init(); -} - -/*! - Constructs a scroll bar with the given \a orientation. - - The \a parent argument is passed to the QWidget constructor. - - The \l {QAbstractSlider::minimum} {minimum} defaults to 0, the - \l {QAbstractSlider::maximum} {maximum} to 99, with a - \l {QAbstractSlider::singleStep} {singleStep} size of 1 and a - \l {QAbstractSlider::pageStep} {pageStep} size of 10, and an - initial \l {QAbstractSlider::value} {value} of 0. -*/ -QScrollBar::QScrollBar(Qt::Orientation orientation, QWidget *parent) - : QAbstractSlider(*new QScrollBarPrivate, parent) -{ - d_func()->orientation = orientation; - d_func()->init(); -} - - -#ifdef QT3_SUPPORT -/*! - Use one of the constructors that doesn't take the \a name - argument and then use setObjectName() instead. -*/ -QScrollBar::QScrollBar(QWidget *parent, const char *name) - : QAbstractSlider(*new QScrollBarPrivate, parent) -{ - setObjectName(QString::fromAscii(name)); - d_func()->orientation = Qt::Vertical; - d_func()->init(); -} - -/*! - Use one of the constructors that doesn't take the \a name - argument and then use setObjectName() instead. -*/ -QScrollBar::QScrollBar(Qt::Orientation orientation, QWidget *parent, const char *name) - : QAbstractSlider(*new QScrollBarPrivate, parent) -{ - setObjectName(QString::fromAscii(name)); - d_func()->orientation = orientation; - d_func()->init(); -} - -/*! - Use one of the constructors that doesn't take the \a name - argument and then use setObjectName() instead. -*/ -QScrollBar::QScrollBar(int minimum, int maximum, int lineStep, int pageStep, - int value, Qt::Orientation orientation, - QWidget *parent, const char *name) - : QAbstractSlider(*new QScrollBarPrivate, parent) -{ - Q_D(QScrollBar); - setObjectName(QString::fromAscii(name)); - d->minimum = minimum; - d->maximum = maximum; - d->singleStep = lineStep; - d->pageStep = pageStep; - d->value = value; - d->orientation = orientation; - d->init(); -} -#endif // QT3_SUPPORT - -/*! - Destroys the scroll bar. -*/ -QScrollBar::~QScrollBar() -{ -} - -void QScrollBarPrivate::init() -{ - Q_Q(QScrollBar); - invertedControls = true; - pressedControl = hoverControl = QStyle::SC_None; - pointerOutsidePressedControl = false; - q->setFocusPolicy(Qt::NoFocus); - QSizePolicy sp(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::Slider); - if (orientation == Qt::Vertical) - sp.transpose(); - q->setSizePolicy(sp); - q->setAttribute(Qt::WA_WState_OwnSizePolicy, false); - q->setAttribute(Qt::WA_OpaquePaintEvent); - -#if !defined(QT_NO_CONTEXTMENU) && defined(Q_WS_WINCE) - if (!q->style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, 0, q)) { - q->setContextMenuPolicy(Qt::PreventContextMenu); - } -#endif -} - -#ifndef QT_NO_CONTEXTMENU -/*! \reimp */ -void QScrollBar::contextMenuEvent(QContextMenuEvent *event) -{ - if (!style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, 0, this)) { - QAbstractSlider::contextMenuEvent(event); - return ; - } - -#ifndef QT_NO_MENU - bool horiz = HORIZONTAL; - QPointer<QMenu> menu = new QMenu(this); - QAction *actScrollHere = menu->addAction(tr("Scroll here")); - menu->addSeparator(); - QAction *actScrollTop = menu->addAction(horiz ? tr("Left edge") : tr("Top")); - QAction *actScrollBottom = menu->addAction(horiz ? tr("Right edge") : tr("Bottom")); - menu->addSeparator(); - QAction *actPageUp = menu->addAction(horiz ? tr("Page left") : tr("Page up")); - QAction *actPageDn = menu->addAction(horiz ? tr("Page right") : tr("Page down")); - menu->addSeparator(); - QAction *actScrollUp = menu->addAction(horiz ? tr("Scroll left") : tr("Scroll up")); - QAction *actScrollDn = menu->addAction(horiz ? tr("Scroll right") : tr("Scroll down")); - QAction *actionSelected = menu->exec(event->globalPos()); - delete menu; - if (actionSelected == 0) - /* do nothing */ ; - else if (actionSelected == actScrollHere) - setValue(d_func()->pixelPosToRangeValue(horiz ? event->pos().x() : event->pos().y())); - else if (actionSelected == actScrollTop) - triggerAction(QAbstractSlider::SliderToMinimum); - else if (actionSelected == actScrollBottom) - triggerAction(QAbstractSlider::SliderToMaximum); - else if (actionSelected == actPageUp) - triggerAction(QAbstractSlider::SliderPageStepSub); - else if (actionSelected == actPageDn) - triggerAction(QAbstractSlider::SliderPageStepAdd); - else if (actionSelected == actScrollUp) - triggerAction(QAbstractSlider::SliderSingleStepSub); - else if (actionSelected == actScrollDn) - triggerAction(QAbstractSlider::SliderSingleStepAdd); -#endif // QT_NO_MENU -} -#endif // QT_NO_CONTEXTMENU - - -/*! \reimp */ -QSize QScrollBar::sizeHint() const -{ - ensurePolished(); - QStyleOptionSlider opt; - initStyleOption(&opt); - - int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this); - int scrollBarSliderMin = style()->pixelMetric(QStyle::PM_ScrollBarSliderMin, &opt, this); - QSize size; - if (opt.orientation == Qt::Horizontal) - size = QSize(scrollBarExtent * 2 + scrollBarSliderMin, scrollBarExtent); - else - size = QSize(scrollBarExtent, scrollBarExtent * 2 + scrollBarSliderMin); - - return style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, size, this) - .expandedTo(QApplication::globalStrut()); - } - -/*!\reimp */ -void QScrollBar::sliderChange(SliderChange change) -{ - QAbstractSlider::sliderChange(change); -} - -/*! - \reimp -*/ -bool QScrollBar::event(QEvent *event) -{ - switch(event->type()) { - case QEvent::HoverEnter: - case QEvent::HoverLeave: - case QEvent::HoverMove: - if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event)) - d_func()->updateHoverControl(he->pos()); - break; -#ifndef QT_NO_WHEELEVENT - case QEvent::Wheel: { - event->ignore(); - // override wheel event without adding virtual function override - QWheelEvent *ev = static_cast<QWheelEvent *>(event); - int delta = ev->delta(); - // 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 - // horizontal orientation. - if (ev->orientation() == Qt::Horizontal) - delta = -delta; - Q_D(QScrollBar); - if (d->scrollByDelta(ev->orientation(), ev->modifiers(), delta)) - event->accept(); - return true; - } -#endif - default: - break; - } - return QAbstractSlider::event(event); -} - -/*! - \reimp -*/ -void QScrollBar::paintEvent(QPaintEvent *) -{ - Q_D(QScrollBar); - QPainter p(this); - QStyleOptionSlider opt; - initStyleOption(&opt); - opt.subControls = QStyle::SC_All; - if (d->pressedControl) { - opt.activeSubControls = (QStyle::SubControl)d->pressedControl; - if (!d->pointerOutsidePressedControl) - opt.state |= QStyle::State_Sunken; - } else { - opt.activeSubControls = (QStyle::SubControl)d->hoverControl; - } - style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this); -} - -/*! - \reimp -*/ -void QScrollBar::mousePressEvent(QMouseEvent *e) -{ - Q_D(QScrollBar); - - if (d->repeatActionTimer.isActive()) - d->stopRepeatAction(); - - bool midButtonAbsPos = style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition, - 0, this); - QStyleOptionSlider opt; - initStyleOption(&opt); - - 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))) - return; - - d->pressedControl = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this); - d->pointerOutsidePressedControl = false; - - QRect sr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, - QStyle::SC_ScrollBarSlider, this); - QPoint click = e->pos(); - QPoint pressValue = click - sr.center() + sr.topLeft(); - d->pressValue = d->orientation == Qt::Horizontal ? d->pixelPosToRangeValue(pressValue.x()) : - d->pixelPosToRangeValue(pressValue.y()); - if (d->pressedControl == QStyle::SC_ScrollBarSlider) { - d->clickOffset = HORIZONTAL ? (click.x()-sr.x()) : (click.y()-sr.y()); - d->snapBackPosition = d->position; - } - - if ((d->pressedControl == QStyle::SC_ScrollBarAddPage - || d->pressedControl == QStyle::SC_ScrollBarSubPage) - && ((midButtonAbsPos && e->button() == Qt::MidButton) - || (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)); - d->pressedControl = QStyle::SC_ScrollBarSlider; - d->clickOffset = sliderLength / 2; - } - const int initialDelay = 500; // default threshold - d->activateControl(d->pressedControl, initialDelay); - QElapsedTimer time; - time.start(); - repaint(style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this)); - if (time.elapsed() >= initialDelay && d->repeatActionTimer.isActive()) { - // It took more than 500ms (the initial timer delay) to process the repaint(), we - // therefore need to restart the timer in case we have a pending mouse release event; - // otherwise we'll get a timer event right before the release event, - // causing the repeat action to be invoked twice on a single mouse click. - // 50ms is the default repeat time (see activateControl/setRepeatAction). - d->repeatActionTimer.start(50, this); - } - if (d->pressedControl == QStyle::SC_ScrollBarSlider) - setSliderDown(true); -} - - -/*! - \reimp -*/ -void QScrollBar::mouseReleaseEvent(QMouseEvent *e) -{ - Q_D(QScrollBar); - if (!d->pressedControl) - return; - - if (e->buttons() & (~e->button())) // some other button is still pressed - return; - - d->stopRepeatAction(); -} - - -/*! - \reimp -*/ -void QScrollBar::mouseMoveEvent(QMouseEvent *e) -{ - Q_D(QScrollBar); - if (!d->pressedControl) - return; - - QStyleOptionSlider opt; - initStyleOption(&opt); - if (!(e->buttons() & Qt::LeftButton - || ((e->buttons() & Qt::MidButton) - && style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition, &opt, this)))) - return; - - if (d->pressedControl == QStyle::SC_ScrollBarSlider) { - QPoint click = e->pos(); - 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())) - newPosition = d->snapBackPosition; - } - setSliderPosition(newPosition); - } else if (!style()->styleHint(QStyle::SH_ScrollBar_ScrollWhenPointerLeavesControl, &opt, this)) { - - 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); - if (newSc == d->pressedControl && !d->pointerOutsidePressedControl) - return; // nothing to do - if (newSc & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) { - d->pointerOutsidePressedControl = false; - QRect scRect = style()->subControlRect(QStyle::CC_ScrollBar, &opt, newSc, this); - scRect |= style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this); - d->pressedControl = newSc; - d->activateControl(d->pressedControl, 0); - update(scRect); - return; - } - } - - // 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 ((d->pointerOutsidePressedControl = !d->pointerOutsidePressedControl)) { - d->pointerOutsidePressedControl = true; - setRepeatAction(SliderNoAction); - repaint(pr); - } else { - d->activateControl(d->pressedControl); - } - } - } -} - - -int QScrollBarPrivate::pixelPosToRangeValue(int pos) const -{ - Q_Q(const QScrollBar); - QStyleOptionSlider opt; - q->initStyleOption(&opt); - QRect gr = q->style()->subControlRect(QStyle::CC_ScrollBar, &opt, - QStyle::SC_ScrollBarGroove, q); - QRect sr = q->style()->subControlRect(QStyle::CC_ScrollBar, &opt, - QStyle::SC_ScrollBarSlider, q); - int sliderMin, sliderMax, sliderLength; - - if (orientation == Qt::Horizontal) { - sliderLength = sr.width(); - sliderMin = gr.x(); - sliderMax = gr.right() - sliderLength + 1; - if (q->layoutDirection() == Qt::RightToLeft) - opt.upsideDown = !opt.upsideDown; - } else { - sliderLength = sr.height(); - sliderMin = gr.y(); - sliderMax = gr.bottom() - sliderLength + 1; - } - - return QStyle::sliderValueFromPosition(minimum, maximum, pos - sliderMin, - sliderMax - sliderMin, opt.upsideDown); -} - -/*! \reimp -*/ -void QScrollBar::hideEvent(QHideEvent *) -{ - Q_D(QScrollBar); - if (d->pressedControl) { - d->pressedControl = QStyle::SC_None; - setRepeatAction(SliderNoAction); - } -} - -/*! - \fn bool QScrollBar::draggingSlider() - - Use isSliderDown() instead. -*/ - -/*! \internal - Returns the style option for scroll bar. -*/ -Q_GUI_EXPORT QStyleOptionSlider qt_qscrollbarStyleOption(QScrollBar *scrollbar) -{ - QStyleOptionSlider opt; - scrollbar->initStyleOption(&opt); - return opt; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCROLLBAR |