summaryrefslogtreecommitdiffstats
path: root/src/widgets/qscrollbar.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2011-07-10 15:24:15 -0500
committerTimothy Pearson <[email protected]>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /src/widgets/qscrollbar.cpp
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'src/widgets/qscrollbar.cpp')
-rw-r--r--src/widgets/qscrollbar.cpp1072
1 files changed, 1072 insertions, 0 deletions
diff --git a/src/widgets/qscrollbar.cpp b/src/widgets/qscrollbar.cpp
new file mode 100644
index 0000000..9a5e8f4
--- /dev/null
+++ b/src/widgets/qscrollbar.cpp
@@ -0,0 +1,1072 @@
+/****************************************************************************
+**
+** Implementation of QScrollBar class
+**
+** Created : 940427
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the widgets module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at [email protected].
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qscrollbar.h"
+#ifndef QT_NO_SCROLLBAR
+#include "qpainter.h"
+#include "qbitmap.h"
+#include "qapplication.h"
+#include "qtimer.h"
+#include "qstyle.h"
+#ifndef QT_NO_CURSOR
+#include <qcursor.h>
+#endif
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+#include "qaccessible.h"
+#endif
+#include <limits.h>
+
+/*!
+ \class QScrollBar
+ \brief The QScrollBar widget provides a vertical or horizontal scroll bar.
+
+ \ingroup basic
+
+ A scroll bar allows the user to control a value within a
+ program-definable range and gives users a visible indication of
+ the current value of a \link QRangeControl range control \endlink.
+
+ Scroll bars include four separate controls:
+
+ \list
+
+ \i The \e line-up and \e line-down controls are little buttons
+ which the user can use to move one "line" up or down. The meaning
+ of line is configurable. In editors and list boxes it means one
+ line of text; in an image viewer it might mean 20 pixels.
+
+ \i The \e slider is the handle that indicates the current value of
+ the scroll bar, which the user can drag to change the value. This
+ part of the scroll bar is sometimes called the "thumb".
+
+ \i The \e page-up/page-down control is the area on which the
+ slider slides (the scroll bar's background). Clicking here moves
+ the scroll bar towards the click. The meaning of "page" is also
+ configurable: in editors and list boxes it means as many lines as
+ there is space for in the widget.
+
+ \endlist
+
+ QScrollBar has very few of its own functions; it mostly relies on
+ QRangeControl. The most useful functions are setValue() to set the
+ scroll bar directly to some value; addPage(), addLine(),
+ subtractPage(), and subtractLine() to simulate the effects of
+ clicking (useful for accelerator keys); setSteps() to define the
+ values of pageStep() and lineStep(); and setRange() to set the
+ minValue() and maxValue() of the scroll bar. QScrollBar has a
+ convenience constructor with which you can set most of these
+ properties.
+
+ Some GUI styles (for example, the Windows and Motif styles
+ provided with Qt), also use the pageStep() value to calculate the
+ size of the slider.
+
+ In addition to the access functions from QRangeControl, QScrollBar
+ provides a comprehensive set of signals:
+ \table
+ \header \i Signal \i Emitted when
+ \row \i \l valueChanged()
+ \i the scroll bar's value has changed. The tracking()
+ determines whether this signal is emitted during user
+ interaction.
+ \row \i \l sliderPressed()
+ \i the user starts to drag the slider.
+ \row \i \l sliderMoved()
+ \i the user drags the slider.
+ \row \i \l sliderReleased()
+ \i the user releases the slider.
+ \row \i \l nextLine()
+ \i the scroll bar has moved one line down or right. Line is
+ defined in QRangeControl.
+ \row \i \l prevLine()
+ \i the scroll bar has moved one line up or left.
+ \row \i \l nextPage()
+ \i the scroll bar has moved one page down or right.
+ \row \i \l prevPage()
+ \i the scroll bar has moved one page up or left.
+ \endtable
+
+ QScrollBar only provides integer ranges. Note that although
+ QScrollBar handles very large numbers, scroll bars on current
+ screens cannot usefully control ranges above about 100,000 pixels.
+ Beyond that, it becomes difficult for the user to control the
+ scroll bar using either the keyboard or the mouse.
+
+ A scroll bar can be controlled by the keyboard, but it has a
+ default focusPolicy() of \c NoFocus. Use setFocusPolicy() to
+ enable keyboard focus. See keyPressEvent() for a list of key
+ bindings.
+
+ If you need to add scroll bars to an interface, consider using the
+ QScrollView class, which encapsulates the common uses for scroll
+ bars.
+
+ <img src=qscrbar-m.png> <img src=qscrbar-w.png>
+
+ \sa QSlider QSpinBox QScrollView
+ \link guibooks.html#fowler GUI Design Handbook: Scroll Bar\endlink
+*/
+
+
+/*!
+ \fn void QScrollBar::valueChanged( int value )
+
+ This signal is emitted when the scroll bar value has changed, with
+ the new scroll bar \a value as an argument.
+*/
+
+/*!
+ \fn void QScrollBar::sliderPressed()
+
+ This signal is emitted when the user presses the slider with the
+ mouse.
+*/
+
+/*!
+ \fn void QScrollBar::sliderMoved( int value )
+
+ This signal is emitted when the slider is dragged by the user, with
+ the new scroll bar \a value as an argument.
+
+ This signal is emitted even when tracking is turned off.
+
+ \sa tracking() valueChanged() nextLine() prevLine() nextPage()
+ prevPage()
+*/
+
+/*!
+ \fn void QScrollBar::sliderReleased()
+
+ This signal is emitted when the user releases the slider with the
+ mouse.
+*/
+
+/*!
+ \fn void QScrollBar::nextLine()
+
+ This signal is emitted when the scroll bar scrolls one line down
+ or right.
+*/
+
+/*!
+ \fn void QScrollBar::prevLine()
+
+ This signal is emitted when the scroll bar scrolls one line up or
+ left.
+*/
+
+/*!
+ \fn void QScrollBar::nextPage()
+
+ This signal is emitted when the scroll bar scrolls one page down
+ or right.
+*/
+
+/*!
+ \fn void QScrollBar::prevPage()
+
+ This signal is emitted when the scroll bar scrolls one page up or
+ left.
+*/
+
+
+
+static const int thresholdTime = 500;
+static const int repeatTime = 50;
+
+#define HORIZONTAL (orientation() == Horizontal)
+#define VERTICAL !HORIZONTAL
+#define MOTIF_BORDER 2
+#define SLIDER_MIN 9
+
+
+/*!
+ Constructs a vertical scroll bar.
+
+ The \a parent and \a name arguments are sent on to the QWidget
+ constructor.
+
+ The \c minValue defaults to 0, the \c maxValue to 99, with a \c
+ lineStep size of 1 and a \c pageStep size of 10, and an initial
+ \c value of 0.
+*/
+
+QScrollBar::QScrollBar( QWidget *parent, const char *name )
+ : QWidget( parent, name ), orient( Vertical )
+{
+ init();
+}
+
+/*!
+ Constructs a scroll bar.
+
+ The \a orientation must be \c Qt::Vertical or \c Qt::Horizontal.
+
+ The \a parent and \a name arguments are sent on to the QWidget
+ constructor.
+
+ The \c minValue defaults to 0, the \c maxValue to 99, with a \c
+ lineStep size of 1 and a \c pageStep size of 10, and an initial
+ \c value of 0.
+*/
+
+QScrollBar::QScrollBar( Orientation orientation, QWidget *parent,
+ const char *name )
+ : QWidget( parent, name ), orient( orientation )
+{
+ init();
+}
+
+/*!
+ Constructs a scroll bar whose value can never be smaller than \a
+ minValue or greater than \a maxValue, whose line step size is \a
+ lineStep and page step size is \a pageStep and whose value is
+ initially \a value (which is guaranteed to be in range using
+ bound()).
+
+ If \a orientation is \c Vertical the scroll bar is vertical and if
+ it is \c Horizontal the scroll bar is horizontal.
+
+ The \a parent and \a name arguments are sent on to the QWidget
+ constructor.
+*/
+
+QScrollBar::QScrollBar( int minValue, int maxValue, int lineStep, int pageStep,
+ int value, Orientation orientation,
+ QWidget *parent, const char *name )
+ : QWidget( parent, name ),
+ QRangeControl( minValue, maxValue, lineStep, pageStep, value ),
+ orient( orientation )
+{
+ init();
+}
+
+/*!
+ Destructor.
+*/
+QScrollBar::~QScrollBar()
+{
+}
+
+void QScrollBar::init()
+{
+ track = TRUE;
+ sliderPos = 0;
+ pressedControl = QStyle::SC_None;
+ clickedAt = FALSE;
+ setFocusPolicy( NoFocus );
+
+ repeater = 0;
+
+ setBackgroundMode((Qt::BackgroundMode)
+ style().styleHint(QStyle::SH_ScrollBar_BackgroundMode));
+
+ QSizePolicy sp( QSizePolicy::Minimum, QSizePolicy::Fixed );
+ if ( orient == Vertical )
+ sp.transpose();
+ setSizePolicy( sp );
+ clearWState( WState_OwnSizePolicy );
+}
+
+
+/*!
+ \property QScrollBar::orientation
+ \brief the orientation of the scroll bar
+
+ The orientation must be \l Qt::Vertical (the default) or \l
+ Qt::Horizontal.
+*/
+
+void QScrollBar::setOrientation( Orientation orientation )
+{
+ if ( orientation == orient )
+ return;
+ if ( !testWState( WState_OwnSizePolicy ) ) {
+ QSizePolicy sp = sizePolicy();
+ sp.transpose();
+ setSizePolicy( sp );
+ clearWState( WState_OwnSizePolicy );
+ }
+
+ orient = orientation;
+
+ positionSliderFromValue();
+ update();
+ updateGeometry();
+}
+
+/*!
+ \property QScrollBar::tracking
+ \brief whether scroll bar tracking is enabled
+
+ If tracking is enabled (the default), the scroll bar emits the
+ valueChanged() signal while the slider is being dragged. If
+ tracking is disabled, the scroll bar emits the valueChanged()
+ signal only when the user releases the mouse button after moving
+ the slider.
+*/
+
+
+/*!
+ \property QScrollBar::draggingSlider
+ \brief whether the user has clicked the mouse on the slider and is currently dragging it
+*/
+
+bool QScrollBar::draggingSlider() const
+{
+ return pressedControl == QStyle::SC_ScrollBarSlider;
+}
+
+
+/*!
+ Reimplements the virtual function QWidget::setPalette().
+
+ Sets the background color to the mid color for Motif style scroll
+ bars using palette \a p.
+*/
+
+void QScrollBar::setPalette( const QPalette &p )
+{
+ QWidget::setPalette( p );
+ setBackgroundMode((Qt::BackgroundMode)
+ style().styleHint(QStyle::SH_ScrollBar_BackgroundMode));
+}
+
+
+/*! \reimp */
+QSize QScrollBar::sizeHint() const
+{
+ constPolish();
+ int sbextent = style().pixelMetric(QStyle::PM_ScrollBarExtent, this);
+
+ if ( orient == Horizontal ) {
+ return QSize( 30, sbextent );
+ } else {
+ return QSize( sbextent, 30 );
+ }
+}
+
+/*! \fn void QScrollBar::setSizePolicy( QSizePolicy::SizeType, QSizePolicy::SizeType, bool )
+ \reimp
+*/
+
+/*! \reimp */
+void QScrollBar::setSizePolicy( QSizePolicy sp )
+{
+ //## remove 4.0
+ QWidget::setSizePolicy( sp );
+}
+
+/*!
+ \internal
+ Implements the virtual QRangeControl function.
+*/
+
+void QScrollBar::valueChange()
+{
+ int tmp = sliderPos;
+ positionSliderFromValue();
+ if ( tmp != sliderPos && isVisible() )
+ drawControls(QStyle::SC_ScrollBarAddPage |
+ QStyle::SC_ScrollBarSubPage |
+ QStyle::SC_ScrollBarSlider,
+ pressedControl );
+ emit valueChanged(value());
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
+#endif
+}
+
+/*!
+ \internal
+ Implements the virtual QRangeControl function.
+*/
+
+void QScrollBar::stepChange()
+{
+ rangeChange();
+}
+
+/*!
+ \internal
+ Implements the virtual QRangeControl function.
+*/
+
+void QScrollBar::rangeChange()
+{
+ positionSliderFromValue();
+
+ if ( isVisible() )
+ drawControls(QStyle::SC_ScrollBarAddLine |
+ QStyle::SC_ScrollBarSubLine |
+ QStyle::SC_ScrollBarAddPage |
+ QStyle::SC_ScrollBarSubPage |
+ QStyle::SC_ScrollBarFirst |
+ QStyle::SC_ScrollBarLast |
+ QStyle::SC_ScrollBarSlider,
+ pressedControl );
+}
+
+
+/*!
+ Handles timer events for the scroll bar.
+*/
+
+void QScrollBar::doAutoRepeat()
+{
+ bool sendRepeat = clickedAt;
+#if !defined( QT_NO_CURSOR ) && !defined( QT_NO_STYLE )
+ if(sendRepeat && (pressedControl == QStyle::SC_ScrollBarAddPage ||
+ pressedControl == QStyle::SC_ScrollBarSubPage) &&
+ style().styleHint(QStyle::SH_ScrollBar_StopMouseOverSlider, this) &&
+ style().querySubControl(QStyle::CC_ScrollBar, this,
+ mapFromGlobal(QCursor::pos()) ) == QStyle::SC_ScrollBarSlider)
+ sendRepeat = FALSE;
+#endif
+ if ( sendRepeat ){
+ if ( repeater )
+ repeater->changeInterval( repeatTime );
+ action( (QStyle::SubControl) pressedControl );
+ QApplication::syncX();
+ } else {
+ stopAutoRepeat();
+ }
+}
+
+
+/*!
+ Starts the auto-repeat logic. Some time after this function is
+ called, the auto-repeat starts taking effect and from then on
+ repeats until stopAutoRepeat() is called.
+*/
+
+void QScrollBar::startAutoRepeat()
+{
+ if ( !repeater ) {
+ repeater = new QTimer( this, "auto-repeat timer" );
+ connect( repeater, SIGNAL(timeout()),
+ this, SLOT(doAutoRepeat()) );
+ }
+ repeater->start( thresholdTime, FALSE );
+}
+
+
+/*!
+ Stops the auto-repeat logic.
+*/
+
+void QScrollBar::stopAutoRepeat()
+{
+ delete repeater;
+ repeater = 0;
+}
+
+
+/*!
+ \reimp
+*/
+#ifndef QT_NO_WHEELEVENT
+void QScrollBar::wheelEvent( QWheelEvent *e )
+{
+ static float offset = 0;
+ static QScrollBar* offset_owner = 0;
+ if (offset_owner != this){
+ offset_owner = this;
+ offset = 0;
+ }
+ if ( e->orientation() != orient && !rect().contains(e->pos()) )
+ return;
+ e->accept();
+ int step = QMIN( QApplication::wheelScrollLines()*lineStep(),
+ pageStep() );
+ if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) )
+ step = pageStep();
+ offset += -e->delta()*step/120;
+ if (QABS(offset)<1)
+ return;
+ setValue( value() + int(offset) );
+ offset -= int(offset);
+}
+#endif
+
+/*!
+ \reimp
+*/
+void QScrollBar::keyPressEvent( QKeyEvent *e )
+{
+ // \list
+ // \i Left/Right move a horizontal scrollbar by one line.
+ // \i Up/Down move a vertical scrollbar by one line.
+ // \i PageUp moves up one page.
+ // \i PageDown moves down one page.
+ // \i Home moves to the start (minValue()).
+ // \i End moves to the end (maxValue()).
+ // \endlist
+
+ // Note that unless you call setFocusPolicy(), the default NoFocus
+ // will apply and the user will not be able to use the keyboard to
+ // interact with the scrollbar.
+ switch ( e->key() ) {
+ case Key_Left:
+ if ( orient == Horizontal )
+ subtractLine();
+ break;
+ case Key_Right:
+ if ( orient == Horizontal )
+ addLine();
+ break;
+ case Key_Up:
+ if ( orient == Vertical )
+ subtractLine();
+ break;
+ case Key_Down:
+ if ( orient == Vertical )
+ addLine();
+ break;
+ case Key_PageUp:
+ subtractPage();
+ break;
+ case Key_PageDown:
+ addPage();
+ break;
+ case Key_Home:
+ setValue( minValue() );
+ break;
+ case Key_End:
+ setValue( maxValue() );
+ break;
+ default:
+ e->ignore();
+ break;
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void QScrollBar::resizeEvent( QResizeEvent * )
+{
+ positionSliderFromValue();
+}
+
+
+/*!
+ \reimp
+*/
+void QScrollBar::paintEvent( QPaintEvent * )
+{
+ QPainter p( this );
+ drawControls(QStyle::SC_ScrollBarAddLine |
+ QStyle::SC_ScrollBarSubLine |
+ QStyle::SC_ScrollBarAddPage |
+ QStyle::SC_ScrollBarSubPage |
+ QStyle::SC_ScrollBarFirst |
+ QStyle::SC_ScrollBarLast |
+ QStyle::SC_ScrollBarSlider,
+ pressedControl, &p );
+}
+
+static QCOORD sliderStartPos = 0;
+
+/*!
+ \reimp
+ */
+void QScrollBar::contextMenuEvent( QContextMenuEvent *e )
+{
+ if(clickedAt)
+ e->consume();
+ else
+ e->ignore();
+}
+
+/*!
+ \reimp
+*/
+void QScrollBar::mousePressEvent( QMouseEvent *e )
+{
+ bool midButtonAbsPos =
+ style().styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition,
+ this);
+
+ if ( !(e->button() == LeftButton ||
+ (midButtonAbsPos && e->button() == MidButton) ) )
+ return;
+
+ if ( maxValue() == minValue() ) // nothing to be done
+ return;
+
+ if ( e->state() & MouseButtonMask ) // another button was already pressed
+ return;
+
+ clickedAt = TRUE;
+ pressedControl = style().querySubControl(QStyle::CC_ScrollBar, this, e->pos() );
+
+ if ( (pressedControl == QStyle::SC_ScrollBarAddPage ||
+ pressedControl == QStyle::SC_ScrollBarSubPage ||
+ pressedControl == QStyle::SC_ScrollBarSlider ) &&
+ ((midButtonAbsPos && e->button() == MidButton) ||
+ style().styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition) && e->button() == LeftButton)) {
+
+ QRect sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarSlider ),
+ gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarGroove );
+ int sliderMin, sliderMax, sliderLength;
+ sliderMin = sliderMax = sliderLength = 0;
+ if (HORIZONTAL) {
+ sliderMin = gr.x();
+ sliderMax = sliderMin + gr.width();
+ sliderLength = sr.width();
+ } else {
+ sliderMin = gr.y();
+ sliderMax = sliderMin + gr.height();
+ sliderLength = sr.height();
+ }
+
+ int newSliderPos = (HORIZONTAL ? e->pos().x() : e->pos().y())
+ - sliderLength/2;
+ newSliderPos = QMIN( newSliderPos, sliderMax - sliderLength );
+ newSliderPos = QMAX( newSliderPos, sliderMin );
+ setValue( sliderPosToRangeValue(newSliderPos) );
+ sliderPos = newSliderPos;
+ pressedControl = QStyle::SC_ScrollBarSlider;
+ }
+
+ if ( pressedControl == QStyle::SC_ScrollBarSlider ) {
+ clickOffset = (QCOORD)( (HORIZONTAL ? e->pos().x() : e->pos().y())
+ - sliderPos );
+ slidePrevVal = value();
+ sliderStartPos = sliderPos;
+ drawControls( pressedControl, pressedControl );
+ emit sliderPressed();
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ScrollingStart );
+#endif
+ } else if ( pressedControl != QStyle::SC_None ) {
+ drawControls( pressedControl, pressedControl );
+ action( (QStyle::SubControl) pressedControl );
+ startAutoRepeat();
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void QScrollBar::mouseReleaseEvent( QMouseEvent *e )
+{
+ if ( !clickedAt )
+ return;
+
+ if ( e->stateAfter() & MouseButtonMask ) // some other button is still pressed
+ return;
+
+ QStyle::SubControl tmp = (QStyle::SubControl) pressedControl;
+ clickedAt = FALSE;
+ stopAutoRepeat();
+ mouseMoveEvent( e ); // Might have moved since last mouse move event.
+ pressedControl = QStyle::SC_None;
+
+ if (tmp == QStyle::SC_ScrollBarSlider) {
+ directSetValue( calculateValueFromSlider() );
+ emit sliderReleased();
+ if ( value() != prevValue() ) {
+ emit valueChanged( value() );
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
+#endif
+ }
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ScrollingEnd );
+#endif
+ }
+ drawControls( tmp, pressedControl );
+ if ( e->button() == MidButton )
+ repaint( FALSE );
+}
+
+
+/*!
+ \reimp
+*/
+void QScrollBar::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( !isVisible() ) {
+ clickedAt = FALSE;
+ return;
+ }
+
+ bool mcab = style().styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition,
+ this);
+ if ( ! clickedAt || ! (e->state() & LeftButton ||
+ ((e->state() & MidButton) && mcab)))
+ return;
+
+ int newSliderPos;
+ if ( pressedControl == QStyle::SC_ScrollBarSlider ) {
+ QRect gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarGroove ),
+ sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarSlider );
+ int sliderMin, sliderMax, sliderLength;
+
+ if (HORIZONTAL) {
+ sliderLength = sr.width();
+ sliderMin = gr.x();
+ sliderMax = gr.right() - sliderLength + 1;
+ } else {
+ sliderLength = sr.height();
+ sliderMin = gr.y();
+ sliderMax = gr.bottom() - sliderLength + 1;
+ }
+
+ QRect r = rect();
+ int m = style().pixelMetric(QStyle::PM_MaximumDragDistance, this);
+ if ( m >= 0 ) {
+ if ( orientation() == Horizontal )
+ r.setRect( r.x() - m, r.y() - 2*m, r.width() + 2*m, r.height() + 4*m );
+ else
+ r.setRect( r.x() - 2*m, r.y() - m, r.width() + 4*m, r.height() + 2*m );
+ if (! r.contains( e->pos()))
+ newSliderPos = sliderStartPos;
+ else
+ newSliderPos = (HORIZONTAL ? e->pos().x() :
+ e->pos().y()) -clickOffset;
+ } else
+ newSliderPos = (HORIZONTAL ? e->pos().x() :
+ e->pos().y()) -clickOffset;
+
+ if ( newSliderPos < sliderMin )
+ newSliderPos = sliderMin;
+ else if ( newSliderPos > sliderMax )
+ newSliderPos = sliderMax;
+ int newVal = sliderPosToRangeValue(newSliderPos);
+ if ( newVal != slidePrevVal )
+ emit sliderMoved( newVal );
+ if ( track && newVal != value() ) {
+ directSetValue( newVal ); // Set directly, painting done below
+ emit valueChanged( value() );
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
+#endif
+ }
+ slidePrevVal = newVal;
+ sliderPos = (QCOORD)newSliderPos;
+ drawControls( QStyle::SC_ScrollBarAddPage |
+ QStyle::SC_ScrollBarSlider |
+ QStyle::SC_ScrollBarSubPage,
+ pressedControl );
+ } else if (! style().styleHint(QStyle::SH_ScrollBar_ScrollWhenPointerLeavesControl)) {
+ // stop scrolling when the mouse pointer leaves a control
+ // similar to push buttons
+ if ( pressedControl != (uint)style().querySubControl(QStyle::CC_ScrollBar, this, e->pos() ) ) {
+ drawControls( pressedControl, QStyle::SC_None );
+ stopAutoRepeat();
+ } else if ( !repeater ) {
+ drawControls( pressedControl, pressedControl );
+ action( (QStyle::SubControl) pressedControl );
+ startAutoRepeat();
+ }
+ }
+}
+
+
+/*!
+ \fn int QScrollBar::sliderStart() const
+
+ Returns the pixel position where the scroll bar slider starts.
+
+ This is equivalent to sliderRect().y() for vertical scroll bars or
+ sliderRect().x() for horizontal scroll bars.
+*/
+
+/*!
+ Returns the scroll bar slider rectangle.
+
+ \sa sliderStart()
+*/
+
+QRect QScrollBar::sliderRect() const
+{
+ return style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarSlider );
+}
+
+void QScrollBar::positionSliderFromValue()
+{
+ sliderPos = (QCOORD)rangeValueToSliderPos( value() );
+}
+
+int QScrollBar::calculateValueFromSlider() const
+{
+ return sliderPosToRangeValue( sliderPos );
+}
+
+int QScrollBar::rangeValueToSliderPos( int v ) const
+{
+ QRect gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarGroove );
+ QRect sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarSlider );
+ int sliderMin, sliderMax, sliderLength;
+
+ if (HORIZONTAL) {
+ sliderLength = sr.width();
+ sliderMin = gr.x();
+ sliderMax = gr.right() - sliderLength + 1;
+ } else {
+ sliderLength = sr.height();
+ sliderMin = gr.y();
+ sliderMax = gr.bottom() - sliderLength + 1;
+ }
+
+ return positionFromValue( v, sliderMax-sliderMin ) + sliderMin;
+}
+
+int QScrollBar::sliderPosToRangeValue( int pos ) const
+{
+ QRect gr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarGroove );
+ QRect sr = style().querySubControlMetrics(QStyle::CC_ScrollBar, this,
+ QStyle::SC_ScrollBarSlider );
+ int sliderMin, sliderMax, sliderLength;
+
+ if (HORIZONTAL) {
+ sliderLength = sr.width();
+ sliderMin = gr.x();
+ sliderMax = gr.right() - sliderLength + 1;
+ } else {
+ sliderLength = sr.height();
+ sliderMin = gr.y();
+ sliderMax = gr.bottom() - sliderLength + 1;
+ }
+
+ return valueFromPosition( pos - sliderMin, sliderMax - sliderMin );
+}
+
+
+void QScrollBar::action( int control )
+{
+ switch( control ) {
+ case QStyle::SC_ScrollBarAddLine:
+ addLine();
+ emit nextLine();
+ break;
+ case QStyle::SC_ScrollBarSubLine:
+ subtractLine();
+ emit prevLine();
+ break;
+ case QStyle::SC_ScrollBarAddPage:
+ addPage();
+ emit nextPage();
+ break;
+ case QStyle::SC_ScrollBarSubPage:
+ subtractPage();
+ emit prevPage();
+ break;
+ case QStyle::SC_ScrollBarFirst:
+ setValue( minValue() );
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
+#endif
+ emit valueChanged( minValue() );
+ break;
+ case QStyle::SC_ScrollBarLast:
+ setValue( maxValue() );
+#if defined(QT_ACCESSIBILITY_SUPPORT)
+ QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged );
+#endif
+ emit valueChanged( maxValue() );
+ break;
+ default:
+ break;
+ }
+}
+
+
+void QScrollBar::drawControls( uint controls, uint activeControl ) const
+{
+ QPainter p ( this );
+ drawControls( controls, activeControl, &p );
+}
+
+
+void QScrollBar::drawControls( uint controls, uint activeControl,
+ QPainter *p ) const
+{
+ if ( !isUpdatesEnabled() )
+ return;
+
+ QStyle::SFlags flags = QStyle::Style_Default;
+ if (isEnabled())
+ flags |= QStyle::Style_Enabled;
+ if (hasFocus())
+ flags |= QStyle::Style_HasFocus;
+ if ( orientation() == Horizontal )
+ flags |= QStyle::Style_Horizontal;
+
+ style().drawComplexControl(QStyle::CC_ScrollBar, p, this, rect(), colorGroup(),
+ flags, (QStyle::SubControl) controls,
+ (QStyle::SubControl) activeControl );
+}
+
+/*!
+ \reimp
+*/
+void QScrollBar::styleChange( QStyle& old )
+{
+ positionSliderFromValue();
+ setBackgroundMode((Qt::BackgroundMode)
+ style().styleHint(QStyle::SH_ScrollBar_BackgroundMode));
+ QWidget::styleChange( old );
+}
+
+/*!
+ \property QScrollBar::minValue
+ \brief the scroll bar's minimum value
+
+ When setting this property, the \l QScrollBar::maxValue is
+ adjusted if necessary to ensure that the range remains valid.
+
+ \sa setRange()
+*/
+int QScrollBar::minValue() const
+{
+ return QRangeControl::minValue();
+}
+
+void QScrollBar::setMinValue( int minVal )
+{
+ QRangeControl::setMinValue( minVal );
+}
+
+/*!
+ \property QScrollBar::maxValue
+ \brief the scroll bar's maximum value
+
+ When setting this property, the \l QScrollBar::minValue is
+ adjusted if necessary to ensure that the range remains valid.
+
+ \sa setRange()
+*/
+int QScrollBar::maxValue() const
+{
+ return QRangeControl::maxValue();
+}
+
+void QScrollBar::setMaxValue( int maxVal )
+{
+ QRangeControl::setMaxValue( maxVal );
+}
+
+/*!
+ \property QScrollBar::lineStep
+ \brief the line step
+
+ When setting lineStep, the virtual stepChange() function will be
+ called if the new line step is different from the previous
+ setting.
+
+ \sa setSteps() QRangeControl::pageStep() setRange()
+*/
+
+int QScrollBar::lineStep() const
+{
+ return QRangeControl::lineStep();
+}
+
+/*!
+ \property QScrollBar::pageStep
+ \brief the page step
+
+ When setting pageStep, the virtual stepChange() function will be
+ called if the new page step is different from the previous
+ setting.
+
+ \sa QRangeControl::setSteps() setLineStep() setRange()
+*/
+
+int QScrollBar::pageStep() const
+{
+ return QRangeControl::pageStep();
+}
+
+void QScrollBar::setLineStep( int i )
+{
+ setSteps( i, pageStep() );
+}
+
+void QScrollBar::setPageStep( int i )
+{
+ setSteps( lineStep(), i );
+}
+
+/*!
+ \property QScrollBar::value
+ \brief the scroll bar's value
+
+ \sa QRangeControl::value() prevValue()
+*/
+
+int QScrollBar::value() const
+{
+ return QRangeControl::value();
+}
+
+void QScrollBar::setValue( int i )
+{
+ QRangeControl::setValue( i );
+}
+
+
+/*!
+ This function is called when the scrollbar is hidden.
+*/
+void QScrollBar::hideEvent( QHideEvent* )
+{
+ pressedControl = QStyle::SC_None;
+ clickedAt = FALSE;
+}
+
+
+#undef ADD_LINE_ACTIVE
+#undef SUB_LINE_ACTIVE
+#endif