1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qapplication.h"
46 #include "qscrollbar.h"
48 #include "qstyleoption.h"
50 #include <QtCore/qelapsedtimer.h>
52 #ifndef QT_NO_SCROLLBAR
54 #ifndef QT_NO_ACCESSIBILITY
55 #include "qaccessible.h"
58 #include "qscrollbar_p.h"
64 \brief The QScrollBar widget provides a vertical or horizontal scroll bar.
69 A scroll bar is a control that enables the user to access parts of a
70 document that is larger than the widget used to display it. It provides
71 a visual indication of the user's current position within the document
72 and the amount of the document that is visible. Scroll bars are usually
73 equipped with other controls that enable more accurate navigation.
74 Qt displays scroll bars in a way that is appropriate for each platform.
76 If you need to provide a scrolling view onto another widget, it may be
77 more convenient to use the QScrollArea class because this provides a
78 viewport widget and scroll bars. QScrollBar is useful if you need to
79 implement similar functionality for specialized widgets using QAbstractScrollArea;
80 for example, if you decide to subclass QAbstractItemView.
81 For most other situations where a slider control is used to obtain a value
82 within a given range, the QSlider class may be more appropriate for your
86 \row \li \image qscrollbar-picture.png
87 \li Scroll bars typically include four separate controls: a slider,
88 scroll arrows, and a page control.
91 \li a. The slider provides a way to quickly go to any part of the
92 document, but does not support accurate navigation within large
94 \li b. The scroll arrows are push buttons which can be used to accurately
95 navigate to a particular place in a document. For a vertical scroll bar
96 connected to a text editor, these typically move the current position one
97 "line" up or down, and adjust the position of the slider by a small
98 amount. In editors and list boxes a "line" might mean one line of text;
99 in an image viewer it might mean 20 pixels.
100 \li c. The page control is the area over which the slider is dragged (the
101 scroll bar's background). Clicking here moves the scroll bar towards
102 the click by one "page". This value is usually the same as the length of
107 Each scroll bar has a value that indicates how far the slider is from
108 the start of the scroll bar; this is obtained with value() and set
109 with setValue(). This value always lies within the range of values
110 defined for the scroll bar, from \l{QAbstractSlider::minimum()}{minimum()}
111 to \l{QAbstractSlider::minimum()}{maximum()} inclusive. The range of
112 acceptable values can be set with setMinimum() and setMaximum().
113 At the minimum value, the top edge of the slider (for a vertical scroll
114 bar) or left edge (for a horizontal scroll bar) will be at the top (or
115 left) end of the scroll bar. At the maximum value, the bottom (or right)
116 edge of the slider will be at the bottom (or right) end of the scroll bar.
118 The length of the slider is usually related to the value of the page step,
119 and typically represents the proportion of the document area shown in a
120 scrolling view. The page step is the amount that the value changes by
121 when the user presses the \uicontrol{Page Up} and \uicontrol{Page Down} keys, and is
122 set with setPageStep(). Smaller changes to the value defined by the
123 line step are made using the cursor keys, and this quantity is set with
124 \l{QAbstractSlider::}{setSingleStep()}.
126 Note that the range of values used is independent of the actual size
127 of the scroll bar widget. You do not need to take this into account when
128 you choose values for the range and the page step.
130 The range of values specified for the scroll bar are often determined
131 differently to those for a QSlider because the length of the slider
132 needs to be taken into account. If we have a document with 100 lines,
133 and we can only show 20 lines in a widget, we may wish to construct a
134 scroll bar with a page step of 20, a minimum value of 0, and a maximum
135 value of 80. This would give us a scroll bar with five "pages".
138 \row \li \inlineimage qscrollbar-values.png
139 \li The relationship between a document length, the range of values used
140 in a scroll bar, and the page step is simple in many common situations.
141 The scroll bar's range of values is determined by subtracting a
142 chosen page step from some value representing the length of the document.
143 In such cases, the following equation is useful:
144 \e{document length} = maximum() - minimum() + pageStep().
147 QScrollBar only provides integer ranges. Note that although
148 QScrollBar handles very large numbers, scroll bars on current
149 screens cannot usefully represent ranges above about 100,000 pixels.
150 Beyond that, it becomes difficult for the user to control the
151 slider using either the keyboard or the mouse, and the scroll
152 arrows will have limited use.
154 ScrollBar inherits a comprehensive set of signals from QAbstractSlider:
156 \li \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the
157 scroll bar's value has changed. The tracking() determines whether this
158 signal is emitted during user interaction.
159 \li \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the
160 scroll bar's range of values has changed.
161 \li \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when
162 the user starts to drag the slider.
163 \li \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user
165 \li \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when
166 the user releases the slider.
167 \li \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted
168 when the scroll bar is changed by user interaction or via the
169 \l{QAbstractSlider::triggerAction()}{triggerAction()} function.
172 A scroll bar can be controlled by the keyboard, but it has a
173 default focusPolicy() of Qt::NoFocus. Use setFocusPolicy() to
174 enable keyboard interaction with the scroll bar:
176 \li Left/Right move a horizontal scroll bar by one single step.
177 \li Up/Down move a vertical scroll bar by one single step.
178 \li PageUp moves up one page.
179 \li PageDown moves down one page.
180 \li Home moves to the start (mininum).
181 \li End moves to the end (maximum).
184 The slider itself can be controlled by using the
185 \l{QAbstractSlider::triggerAction()}{triggerAction()} function to simulate
186 user interaction with the scroll bar controls. This is useful if you have
187 many different widgets that use a common range of values.
189 Most GUI styles use the pageStep() value to calculate the size of the
193 \row \li \inlineimage macintosh-horizontalscrollbar.png Screenshot of a Macintosh style scroll bar
194 \li A scroll bar shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
195 \row \li \inlineimage windowsvista-horizontalscrollbar.png Screenshot of a Windows Vista style scroll bar
196 \li A scroll bar shown in the \l{Windows Vista Style Widget Gallery}{Windows Vista widget style}.
197 \row \li \inlineimage fusion-horizontalscrollbar.png Screenshot of a Fusion style scroll bar
198 \li A scroll bar shown in the \l{Fusion Style Widget Gallery}{Fusion widget style}.
201 \sa QScrollArea, QSlider, QDial, QSpinBox, {fowler}{GUI Design Handbook: Scroll Bar}, {Sliders Example}
204 bool QScrollBarPrivate::updateHoverControl(const QPoint &pos)
207 QRect lastHoverRect = hoverRect;
208 QStyle::SubControl lastHoverControl = hoverControl;
209 bool doesHover = q->testAttribute(Qt::WA_Hover);
210 if (lastHoverControl != newHoverControl(pos) && doesHover) {
211 q->update(lastHoverRect);
212 q->update(hoverRect);
218 QStyle::SubControl QScrollBarPrivate::newHoverControl(const QPoint &pos)
221 QStyleOptionSlider opt;
222 q->initStyleOption(&opt);
223 opt.subControls = QStyle::SC_All;
224 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, pos, q);
225 if (hoverControl == QStyle::SC_None)
228 hoverRect = q->style()->subControlRect(QStyle::CC_ScrollBar, &opt, hoverControl, q);
232 void QScrollBarPrivate::setTransient(bool value)
235 if (transient != value) {
237 if (q->isVisible()) {
238 if (q->style()->styleHint(QStyle::SH_ScrollBar_Transient))
240 } else if (!transient) {
246 void QScrollBarPrivate::flash()
249 if (!flashed && q->style()->styleHint(QStyle::SH_ScrollBar_Transient)) {
255 void QScrollBarPrivate::activateControl(uint control, int threshold)
257 QAbstractSlider::SliderAction action = QAbstractSlider::SliderNoAction;
259 case QStyle::SC_ScrollBarAddPage:
260 action = QAbstractSlider::SliderPageStepAdd;
262 case QStyle::SC_ScrollBarSubPage:
263 action = QAbstractSlider::SliderPageStepSub;
265 case QStyle::SC_ScrollBarAddLine:
266 action = QAbstractSlider::SliderSingleStepAdd;
268 case QStyle::SC_ScrollBarSubLine:
269 action = QAbstractSlider::SliderSingleStepSub;
271 case QStyle::SC_ScrollBarFirst:
272 action = QAbstractSlider::SliderToMinimum;
274 case QStyle::SC_ScrollBarLast:
275 action = QAbstractSlider::SliderToMaximum;
282 q_func()->setRepeatAction(action, threshold);
283 q_func()->triggerAction(action);
287 void QScrollBarPrivate::stopRepeatAction()
290 QStyle::SubControl tmp = pressedControl;
291 q->setRepeatAction(QAbstractSlider::SliderNoAction);
292 pressedControl = QStyle::SC_None;
294 if (tmp == QStyle::SC_ScrollBarSlider)
295 q->setSliderDown(false);
297 QStyleOptionSlider opt;
298 q->initStyleOption(&opt);
299 q->repaint(q->style()->subControlRect(QStyle::CC_ScrollBar, &opt, tmp, q));
303 Initialize \a option with the values from this QScrollBar. This method
304 is useful for subclasses when they need a QStyleOptionSlider, but don't want
305 to fill in all the information themselves.
307 \sa QStyleOption::initFrom()
309 void QScrollBar::initStyleOption(QStyleOptionSlider *option) const
314 Q_D(const QScrollBar);
315 option->initFrom(this);
316 option->subControls = QStyle::SC_None;
317 option->activeSubControls = QStyle::SC_None;
318 option->orientation = d->orientation;
319 option->minimum = d->minimum;
320 option->maximum = d->maximum;
321 option->sliderPosition = d->position;
322 option->sliderValue = d->value;
323 option->singleStep = d->singleStep;
324 option->pageStep = d->pageStep;
325 option->upsideDown = d->invertedAppearance;
326 if (d->orientation == Qt::Horizontal)
327 option->state |= QStyle::State_Horizontal;
328 if ((d->flashed || !d->transient) && style()->styleHint(QStyle::SH_ScrollBar_Transient))
329 option->state |= QStyle::State_On;
333 #define HORIZONTAL (d_func()->orientation == Qt::Horizontal)
334 #define VERTICAL !HORIZONTAL
337 Constructs a vertical scroll bar.
339 The \a parent argument is sent to the QWidget constructor.
341 The \l {QAbstractSlider::minimum} {minimum} defaults to 0, the
342 \l {QAbstractSlider::maximum} {maximum} to 99, with a
343 \l {QAbstractSlider::singleStep} {singleStep} size of 1 and a
344 \l {QAbstractSlider::pageStep} {pageStep} size of 10, and an
345 initial \l {QAbstractSlider::value} {value} of 0.
347 QScrollBar::QScrollBar(QWidget *parent)
348 : QAbstractSlider(*new QScrollBarPrivate, parent)
350 d_func()->orientation = Qt::Vertical;
355 Constructs a scroll bar with the given \a orientation.
357 The \a parent argument is passed to the QWidget constructor.
359 The \l {QAbstractSlider::minimum} {minimum} defaults to 0, the
360 \l {QAbstractSlider::maximum} {maximum} to 99, with a
361 \l {QAbstractSlider::singleStep} {singleStep} size of 1 and a
362 \l {QAbstractSlider::pageStep} {pageStep} size of 10, and an
363 initial \l {QAbstractSlider::value} {value} of 0.
365 QScrollBar::QScrollBar(Qt::Orientation orientation, QWidget *parent)
366 : QAbstractSlider(*new QScrollBarPrivate, parent)
368 d_func()->orientation = orientation;
375 Destroys the scroll bar.
377 QScrollBar::~QScrollBar()
381 void QScrollBarPrivate::init()
384 invertedControls = true;
385 pressedControl = hoverControl = QStyle::SC_None;
386 pointerOutsidePressedControl = false;
387 transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient);
389 q->setFocusPolicy(Qt::NoFocus);
390 QSizePolicy sp(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::Slider);
391 if (orientation == Qt::Vertical)
393 q->setSizePolicy(sp);
394 q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
395 q->setAttribute(Qt::WA_OpaquePaintEvent);
397 #if !defined(QT_NO_CONTEXTMENU) && defined(Q_OS_WINCE)
398 if (!q->style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, 0, q)) {
399 q->setContextMenuPolicy(Qt::PreventContextMenu);
404 #ifndef QT_NO_CONTEXTMENU
406 void QScrollBar::contextMenuEvent(QContextMenuEvent *event)
408 if (!style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, 0, this)) {
409 QAbstractSlider::contextMenuEvent(event);
414 bool horiz = HORIZONTAL;
415 QPointer<QMenu> menu = new QMenu(this);
416 QAction *actScrollHere = menu->addAction(tr("Scroll here"));
417 menu->addSeparator();
418 QAction *actScrollTop = menu->addAction(horiz ? tr("Left edge") : tr("Top"));
419 QAction *actScrollBottom = menu->addAction(horiz ? tr("Right edge") : tr("Bottom"));
420 menu->addSeparator();
421 QAction *actPageUp = menu->addAction(horiz ? tr("Page left") : tr("Page up"));
422 QAction *actPageDn = menu->addAction(horiz ? tr("Page right") : tr("Page down"));
423 menu->addSeparator();
424 QAction *actScrollUp = menu->addAction(horiz ? tr("Scroll left") : tr("Scroll up"));
425 QAction *actScrollDn = menu->addAction(horiz ? tr("Scroll right") : tr("Scroll down"));
426 QAction *actionSelected = menu->exec(event->globalPos());
428 if (actionSelected == 0)
430 else if (actionSelected == actScrollHere)
431 setValue(d_func()->pixelPosToRangeValue(horiz ? event->pos().x() : event->pos().y()));
432 else if (actionSelected == actScrollTop)
433 triggerAction(QAbstractSlider::SliderToMinimum);
434 else if (actionSelected == actScrollBottom)
435 triggerAction(QAbstractSlider::SliderToMaximum);
436 else if (actionSelected == actPageUp)
437 triggerAction(QAbstractSlider::SliderPageStepSub);
438 else if (actionSelected == actPageDn)
439 triggerAction(QAbstractSlider::SliderPageStepAdd);
440 else if (actionSelected == actScrollUp)
441 triggerAction(QAbstractSlider::SliderSingleStepSub);
442 else if (actionSelected == actScrollDn)
443 triggerAction(QAbstractSlider::SliderSingleStepAdd);
446 #endif // QT_NO_CONTEXTMENU
450 QSize QScrollBar::sizeHint() const
453 QStyleOptionSlider opt;
454 initStyleOption(&opt);
456 int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this);
457 int scrollBarSliderMin = style()->pixelMetric(QStyle::PM_ScrollBarSliderMin, &opt, this);
459 if (opt.orientation == Qt::Horizontal)
460 size = QSize(scrollBarExtent * 2 + scrollBarSliderMin, scrollBarExtent);
462 size = QSize(scrollBarExtent, scrollBarExtent * 2 + scrollBarSliderMin);
464 return style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, size, this)
465 .expandedTo(QApplication::globalStrut());
469 void QScrollBar::sliderChange(SliderChange change)
471 QAbstractSlider::sliderChange(change);
477 bool QScrollBar::event(QEvent *event)
479 switch(event->type()) {
480 case QEvent::HoverEnter:
481 case QEvent::HoverLeave:
482 case QEvent::HoverMove:
483 if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
484 d_func()->updateHoverControl(he->pos());
486 case QEvent::StyleChange:
487 d_func()->setTransient(style()->styleHint(QStyle::SH_ScrollBar_Transient));
492 return QAbstractSlider::event(event);
498 #ifndef QT_NO_WHEELEVENT
499 void QScrollBar::wheelEvent(QWheelEvent *event)
502 int delta = event->delta();
503 // scrollbar is a special case - in vertical mode it reaches minimum
504 // value in the upper position, however QSlider's minimum value is on
505 // the bottom. So we need to invert a value, but since the scrollbar is
506 // inverted by default, we need to inverse the delta value for the
507 // horizontal orientation.
508 if (event->orientation() == Qt::Horizontal)
511 if (d->scrollByDelta(event->orientation(), event->modifiers(), delta))
519 void QScrollBar::paintEvent(QPaintEvent *)
523 QStyleOptionSlider opt;
524 initStyleOption(&opt);
525 opt.subControls = QStyle::SC_All;
526 if (d->pressedControl) {
527 opt.activeSubControls = (QStyle::SubControl)d->pressedControl;
528 if (!d->pointerOutsidePressedControl)
529 opt.state |= QStyle::State_Sunken;
531 opt.activeSubControls = (QStyle::SubControl)d->hoverControl;
533 style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this);
534 if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient)) {
543 void QScrollBar::mousePressEvent(QMouseEvent *e)
547 if (d->repeatActionTimer.isActive())
548 d->stopRepeatAction();
550 bool midButtonAbsPos = style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition,
552 QStyleOptionSlider opt;
553 initStyleOption(&opt);
555 if (d->maximum == d->minimum // no range
556 || (e->buttons() & (~e->button())) // another button was clicked before
557 || !(e->button() == Qt::LeftButton || (midButtonAbsPos && e->button() == Qt::MidButton)))
560 d->pressedControl = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this);
561 d->pointerOutsidePressedControl = false;
563 QRect sr = style()->subControlRect(QStyle::CC_ScrollBar, &opt,
564 QStyle::SC_ScrollBarSlider, this);
565 QPoint click = e->pos();
566 QPoint pressValue = click - sr.center() + sr.topLeft();
567 d->pressValue = d->orientation == Qt::Horizontal ? d->pixelPosToRangeValue(pressValue.x()) :
568 d->pixelPosToRangeValue(pressValue.y());
569 if (d->pressedControl == QStyle::SC_ScrollBarSlider) {
570 d->clickOffset = HORIZONTAL ? (click.x()-sr.x()) : (click.y()-sr.y());
571 d->snapBackPosition = d->position;
574 if ((d->pressedControl == QStyle::SC_ScrollBarAddPage
575 || d->pressedControl == QStyle::SC_ScrollBarSubPage)
576 && ((midButtonAbsPos && e->button() == Qt::MidButton)
577 || (style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition, &opt, this)
578 && e->button() == Qt::LeftButton))) {
579 int sliderLength = HORIZONTAL ? sr.width() : sr.height();
580 setSliderPosition(d->pixelPosToRangeValue((HORIZONTAL ? e->pos().x()
581 : e->pos().y()) - sliderLength / 2));
582 d->pressedControl = QStyle::SC_ScrollBarSlider;
583 d->clickOffset = sliderLength / 2;
585 const int initialDelay = 500; // default threshold
586 d->activateControl(d->pressedControl, initialDelay);
589 repaint(style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this));
590 if (time.elapsed() >= initialDelay && d->repeatActionTimer.isActive()) {
591 // It took more than 500ms (the initial timer delay) to process the repaint(), we
592 // therefore need to restart the timer in case we have a pending mouse release event;
593 // otherwise we'll get a timer event right before the release event,
594 // causing the repeat action to be invoked twice on a single mouse click.
595 // 50ms is the default repeat time (see activateControl/setRepeatAction).
596 d->repeatActionTimer.start(50, this);
598 if (d->pressedControl == QStyle::SC_ScrollBarSlider)
606 void QScrollBar::mouseReleaseEvent(QMouseEvent *e)
609 if (!d->pressedControl)
612 if (e->buttons() & (~e->button())) // some other button is still pressed
615 d->stopRepeatAction();
622 void QScrollBar::mouseMoveEvent(QMouseEvent *e)
625 if (!d->pressedControl)
628 QStyleOptionSlider opt;
629 initStyleOption(&opt);
630 if (!(e->buttons() & Qt::LeftButton
631 || ((e->buttons() & Qt::MidButton)
632 && style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition, &opt, this))))
635 if (d->pressedControl == QStyle::SC_ScrollBarSlider) {
636 QPoint click = e->pos();
637 int newPosition = d->pixelPosToRangeValue((HORIZONTAL ? click.x() : click.y()) -d->clickOffset);
638 int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this);
641 r.adjust(-m, -m, m, m);
642 if (! r.contains(e->pos()))
643 newPosition = d->snapBackPosition;
645 setSliderPosition(newPosition);
646 } else if (!style()->styleHint(QStyle::SH_ScrollBar_ScrollWhenPointerLeavesControl, &opt, this)) {
648 if (style()->styleHint(QStyle::SH_ScrollBar_RollBetweenButtons, &opt, this)
649 && d->pressedControl & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) {
650 QStyle::SubControl newSc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this);
651 if (newSc == d->pressedControl && !d->pointerOutsidePressedControl)
652 return; // nothing to do
653 if (newSc & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) {
654 d->pointerOutsidePressedControl = false;
655 QRect scRect = style()->subControlRect(QStyle::CC_ScrollBar, &opt, newSc, this);
656 scRect |= style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this);
657 d->pressedControl = newSc;
658 d->activateControl(d->pressedControl, 0);
664 // stop scrolling when the mouse pointer leaves a control
665 // similar to push buttons
666 QRect pr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this);
667 if (pr.contains(e->pos()) == d->pointerOutsidePressedControl) {
668 if ((d->pointerOutsidePressedControl = !d->pointerOutsidePressedControl)) {
669 d->pointerOutsidePressedControl = true;
670 setRepeatAction(SliderNoAction);
673 d->activateControl(d->pressedControl);
680 int QScrollBarPrivate::pixelPosToRangeValue(int pos) const
682 Q_Q(const QScrollBar);
683 QStyleOptionSlider opt;
684 q->initStyleOption(&opt);
685 QRect gr = q->style()->subControlRect(QStyle::CC_ScrollBar, &opt,
686 QStyle::SC_ScrollBarGroove, q);
687 QRect sr = q->style()->subControlRect(QStyle::CC_ScrollBar, &opt,
688 QStyle::SC_ScrollBarSlider, q);
689 int sliderMin, sliderMax, sliderLength;
691 if (orientation == Qt::Horizontal) {
692 sliderLength = sr.width();
694 sliderMax = gr.right() - sliderLength + 1;
695 if (q->layoutDirection() == Qt::RightToLeft)
696 opt.upsideDown = !opt.upsideDown;
698 sliderLength = sr.height();
700 sliderMax = gr.bottom() - sliderLength + 1;
703 return QStyle::sliderValueFromPosition(minimum, maximum, pos - sliderMin,
704 sliderMax - sliderMin, opt.upsideDown);
709 void QScrollBar::hideEvent(QHideEvent *)
712 if (d->pressedControl) {
713 d->pressedControl = QStyle::SC_None;
714 setRepeatAction(SliderNoAction);
719 Returns the style option for scroll bar.
721 Q_WIDGETS_EXPORT QStyleOptionSlider qt_qscrollbarStyleOption(QScrollBar *scrollbar)
723 QStyleOptionSlider opt;
724 scrollbar->initStyleOption(&opt);
730 #endif // QT_NO_SCROLLBAR