src/gui/widgets/qabstractslider.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <qapplication.h>
       
    43 #include "qabstractslider.h"
       
    44 #include "qevent.h"
       
    45 #include "qabstractslider_p.h"
       
    46 #include "qdebug.h"
       
    47 #ifndef QT_NO_ACCESSIBILITY
       
    48 #include "qaccessible.h"
       
    49 #endif
       
    50 #ifdef QT_KEYPAD_NAVIGATION
       
    51 #include "qtabwidget.h" // Needed in inTabWidget()
       
    52 #endif // QT_KEYPAD_NAVIGATION
       
    53 #include <limits.h>
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 /*!
       
    58     \class QAbstractSlider
       
    59     \brief The QAbstractSlider class provides an integer value within a range.
       
    60 
       
    61     \ingroup abstractwidgets
       
    62 
       
    63     The class is designed as a common super class for widgets like
       
    64     QScrollBar, QSlider and QDial.
       
    65 
       
    66     Here are the main properties of the class:
       
    67 
       
    68     \list 1
       
    69 
       
    70     \i \l value: The bounded integer that QAbstractSlider maintains.
       
    71 
       
    72     \i \l minimum: The lowest possible value.
       
    73 
       
    74     \i \l maximum: The highest possible value.
       
    75 
       
    76     \i \l singleStep: The smaller of two natural steps that an
       
    77     abstract sliders provides and typically corresponds to the user
       
    78     pressing an arrow key.
       
    79 
       
    80     \i \l pageStep: The larger of two natural steps that an abstract
       
    81     slider provides and typically corresponds to the user pressing
       
    82     PageUp or PageDown.
       
    83 
       
    84     \i \l tracking: Whether slider tracking is enabled.
       
    85 
       
    86     \i \l sliderPosition: The current position of the slider. If \l
       
    87     tracking is enabled (the default), this is identical to \l value.
       
    88 
       
    89     \endlist
       
    90 
       
    91     Unity (1) may be viewed as a third step size. setValue() lets you
       
    92     set the current value to any integer in the allowed range, not
       
    93     just minimum() + \e n * singleStep() for integer values of \e n.
       
    94     Some widgets may allow the user to set any value at all; others
       
    95     may just provide multiples of singleStep() or pageStep().
       
    96 
       
    97     QAbstractSlider emits a comprehensive set of signals:
       
    98 
       
    99     \table
       
   100     \header \i Signal \i Emitted when
       
   101     \row \i \l valueChanged()
       
   102          \i the value has changed. The \l tracking
       
   103             determines whether this signal is emitted during user
       
   104             interaction.
       
   105     \row \i \l sliderPressed()
       
   106          \i the user starts to drag the slider.
       
   107     \row \i \l sliderMoved()
       
   108          \i the user drags the slider.
       
   109     \row \i \l sliderReleased()
       
   110          \i the user releases the slider.
       
   111     \row \i \l actionTriggered()
       
   112          \i a slider action was triggerd.
       
   113     \row \i \l rangeChanged()
       
   114          \i a the range has changed.
       
   115     \endtable
       
   116 
       
   117     QAbstractSlider provides a virtual sliderChange() function that is
       
   118     well suited for updating the on-screen representation of
       
   119     sliders. By calling triggerAction(), subclasses trigger slider
       
   120     actions. Two helper functions QStyle::sliderPositionFromValue() and
       
   121     QStyle::sliderValueFromPosition() help subclasses and styles to map
       
   122     screen coordinates to logical range values.
       
   123 
       
   124     \sa QAbstractSpinBox, QSlider, QDial, QScrollBar, {Sliders Example}
       
   125 */
       
   126 
       
   127 /*!
       
   128     \enum QAbstractSlider::SliderAction
       
   129 
       
   130     \value SliderNoAction
       
   131     \value SliderSingleStepAdd
       
   132     \value SliderSingleStepSub
       
   133     \value SliderPageStepAdd
       
   134     \value SliderPageStepSub
       
   135     \value SliderToMinimum
       
   136     \value SliderToMaximum
       
   137     \value SliderMove
       
   138 
       
   139 */
       
   140 
       
   141 /*!
       
   142     \fn void QAbstractSlider::valueChanged(int value)
       
   143 
       
   144     This signal is emitted when the slider value has changed, with the
       
   145     new slider \a value as argument.
       
   146 */
       
   147 
       
   148 /*!
       
   149     \fn void QAbstractSlider::sliderPressed()
       
   150 
       
   151     This signal is emitted when the user presses the slider with the
       
   152     mouse, or programmatically when setSliderDown(true) is called.
       
   153 
       
   154     \sa sliderReleased(), sliderMoved(), isSliderDown()
       
   155 */
       
   156 
       
   157 /*!
       
   158     \fn void QAbstractSlider::sliderMoved(int value)
       
   159 
       
   160     This signal is emitted when sliderDown is true and the slider moves. This
       
   161     usually happens when the user is dragging the slider. The \a value
       
   162     is the new slider position.
       
   163 
       
   164     This signal is emitted even when tracking is turned off.
       
   165 
       
   166     \sa setTracking(), valueChanged(), isSliderDown(),
       
   167     sliderPressed(), sliderReleased()
       
   168 */
       
   169 
       
   170 /*!
       
   171     \fn void QAbstractSlider::sliderReleased()
       
   172 
       
   173     This signal is emitted when the user releases the slider with the
       
   174     mouse, or programmatically when setSliderDown(false) is called.
       
   175 
       
   176     \sa sliderPressed() sliderMoved() sliderDown
       
   177 */
       
   178 
       
   179 /*!
       
   180     \fn void QAbstractSlider::rangeChanged(int min, int max)
       
   181 
       
   182     This signal is emitted when the slider range has changed, with \a
       
   183     min being the new minimum, and \a max being the new maximum.
       
   184 
       
   185     \sa minimum, maximum
       
   186 */
       
   187 
       
   188 /*!
       
   189     \fn void QAbstractSlider::actionTriggered(int action)
       
   190 
       
   191     This signal is emitted when the slider action \a action is
       
   192     triggered. Actions are \l SliderSingleStepAdd, \l
       
   193     SliderSingleStepSub, \l SliderPageStepAdd, \l SliderPageStepSub,
       
   194     \l SliderToMinimum, \l SliderToMaximum, and \l SliderMove.
       
   195 
       
   196     When the signal is emitted, the \l sliderPosition has been
       
   197     adjusted according to the action, but the \l value has not yet
       
   198     been propagated (meaning the valueChanged() signal was not yet
       
   199     emitted), and the visual display has not been updated. In slots
       
   200     connected to this signal you can thus safely adjust any action by
       
   201     calling setSliderPosition() yourself, based on both the action and
       
   202     the slider's value.
       
   203 
       
   204     \sa triggerAction()
       
   205 */
       
   206 
       
   207 /*!
       
   208     \enum QAbstractSlider::SliderChange
       
   209 
       
   210     \value SliderRangeChange
       
   211     \value SliderOrientationChange
       
   212     \value SliderStepsChange
       
   213     \value SliderValueChange
       
   214 */
       
   215 
       
   216 QAbstractSliderPrivate::QAbstractSliderPrivate()
       
   217     : minimum(0), maximum(99), singleStep(1), pageStep(10),
       
   218       value(0), position(0), pressValue(-1), offset_accumulated(0), tracking(true),
       
   219       blocktracking(false), pressed(false),
       
   220       invertedAppearance(false), invertedControls(false),
       
   221       orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction)
       
   222 {
       
   223 }
       
   224 
       
   225 QAbstractSliderPrivate::~QAbstractSliderPrivate()
       
   226 {
       
   227 }
       
   228 
       
   229 /*!
       
   230     Sets the slider's minimum to \a min and its maximum to \a max.
       
   231 
       
   232     If \a max is smaller than \a min, \a min becomes the only legal
       
   233     value.
       
   234 
       
   235     \sa minimum maximum
       
   236 */
       
   237 void QAbstractSlider::setRange(int min, int max)
       
   238 {
       
   239     Q_D(QAbstractSlider);
       
   240     int oldMin = d->minimum;
       
   241     int oldMax = d->maximum;
       
   242     d->minimum = min;
       
   243     d->maximum = qMax(min, max);
       
   244     if (oldMin != d->minimum || oldMax != d->maximum) {
       
   245         sliderChange(SliderRangeChange);
       
   246         emit rangeChanged(d->minimum, d->maximum);
       
   247         setValue(d->value); // re-bound
       
   248     }
       
   249 }
       
   250 
       
   251 
       
   252 void QAbstractSliderPrivate::setSteps(int single, int page)
       
   253 {
       
   254     Q_Q(QAbstractSlider);
       
   255     singleStep = qAbs(single);
       
   256     pageStep = qAbs(page);
       
   257     q->sliderChange(QAbstractSlider::SliderStepsChange);
       
   258 }
       
   259 
       
   260 /*!
       
   261     Constructs an abstract slider.
       
   262 
       
   263     The \a parent arguments is sent to the QWidget constructor.
       
   264 
       
   265     The \l minimum defaults to 0, the \l maximum to 99, with a \l
       
   266     singleStep size of 1 and a \l pageStep size of 10, and an initial
       
   267     \l value of 0.
       
   268 */
       
   269 QAbstractSlider::QAbstractSlider(QWidget *parent)
       
   270     :QWidget(*new QAbstractSliderPrivate, parent, 0)
       
   271 {
       
   272 }
       
   273 
       
   274 /*! \internal */
       
   275 QAbstractSlider::QAbstractSlider(QAbstractSliderPrivate &dd, QWidget *parent)
       
   276     :QWidget(dd, parent, 0)
       
   277 {
       
   278 }
       
   279 
       
   280 /*!
       
   281     Destroys the slider.
       
   282 */
       
   283 QAbstractSlider::~QAbstractSlider()
       
   284 {
       
   285 }
       
   286 
       
   287 /*!
       
   288     \property QAbstractSlider::orientation
       
   289     \brief the orientation of the slider
       
   290 
       
   291     The orientation must be \l Qt::Vertical (the default) or \l
       
   292     Qt::Horizontal.
       
   293 */
       
   294 void QAbstractSlider::setOrientation(Qt::Orientation orientation)
       
   295 {
       
   296     Q_D(QAbstractSlider);
       
   297     if (d->orientation == orientation)
       
   298         return;
       
   299 
       
   300     d->orientation = orientation;
       
   301     if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) {
       
   302         QSizePolicy sp = sizePolicy();
       
   303         sp.transpose();
       
   304         setSizePolicy(sp);
       
   305         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
       
   306     }
       
   307     update();
       
   308     updateGeometry();
       
   309 }
       
   310 
       
   311 Qt::Orientation QAbstractSlider::orientation() const
       
   312 {
       
   313     Q_D(const QAbstractSlider);
       
   314     return d->orientation;
       
   315 }
       
   316 
       
   317 
       
   318 /*!
       
   319     \property QAbstractSlider::minimum
       
   320     \brief the sliders's minimum value
       
   321 
       
   322     When setting this property, the \l maximum is adjusted if
       
   323     necessary to ensure that the range remains valid. Also the
       
   324     slider's current value is adjusted to be within the new range.
       
   325 
       
   326 */
       
   327 
       
   328 void QAbstractSlider::setMinimum(int min)
       
   329 {
       
   330     Q_D(QAbstractSlider);
       
   331     setRange(min, qMax(d->maximum, min));
       
   332 }
       
   333 
       
   334 int QAbstractSlider::minimum() const
       
   335 {
       
   336     Q_D(const QAbstractSlider);
       
   337     return d->minimum;
       
   338 }
       
   339 
       
   340 
       
   341 /*!
       
   342     \property QAbstractSlider::maximum
       
   343     \brief the slider's maximum value
       
   344 
       
   345     When setting this property, the \l minimum is adjusted if
       
   346     necessary to ensure that the range remains valid.  Also the
       
   347     slider's current value is adjusted to be within the new range.
       
   348 
       
   349 
       
   350 */
       
   351 
       
   352 void QAbstractSlider::setMaximum(int max)
       
   353 {
       
   354     Q_D(QAbstractSlider);
       
   355     setRange(qMin(d->minimum, max), max);
       
   356 }
       
   357 
       
   358 int QAbstractSlider::maximum() const
       
   359 {
       
   360     Q_D(const QAbstractSlider);
       
   361     return d->maximum;
       
   362 }
       
   363 
       
   364 
       
   365 
       
   366 /*!
       
   367     \property QAbstractSlider::singleStep
       
   368     \brief the single step.
       
   369 
       
   370     The smaller of two natural steps that an
       
   371     abstract sliders provides and typically corresponds to the user
       
   372     pressing an arrow key.
       
   373 
       
   374     \sa pageStep
       
   375 */
       
   376 
       
   377 void QAbstractSlider::setSingleStep(int step)
       
   378 {
       
   379     Q_D(QAbstractSlider);
       
   380     if (step != d->singleStep)
       
   381         d->setSteps(step, d->pageStep);
       
   382 }
       
   383 
       
   384 int QAbstractSlider::singleStep() const
       
   385 {
       
   386     Q_D(const QAbstractSlider);
       
   387     return d->singleStep;
       
   388 }
       
   389 
       
   390 
       
   391 /*!
       
   392     \property QAbstractSlider::pageStep
       
   393     \brief the page step.
       
   394 
       
   395     The larger of two natural steps that an abstract slider provides
       
   396     and typically corresponds to the user pressing PageUp or PageDown.
       
   397 
       
   398     \sa singleStep
       
   399 */
       
   400 
       
   401 void QAbstractSlider::setPageStep(int step)
       
   402 {
       
   403     Q_D(QAbstractSlider);
       
   404     if (step != d->pageStep)
       
   405         d->setSteps(d->singleStep, step);
       
   406 }
       
   407 
       
   408 int QAbstractSlider::pageStep() const
       
   409 {
       
   410     Q_D(const QAbstractSlider);
       
   411     return d->pageStep;
       
   412 }
       
   413 
       
   414 /*!
       
   415     \property QAbstractSlider::tracking
       
   416     \brief whether slider tracking is enabled
       
   417 
       
   418     If tracking is enabled (the default), the slider emits the
       
   419     valueChanged() signal while the slider is being dragged. If
       
   420     tracking is disabled, the slider emits the valueChanged() signal
       
   421     only when the user releases the slider.
       
   422 
       
   423     \sa sliderDown
       
   424 */
       
   425 void QAbstractSlider::setTracking(bool enable)
       
   426 {
       
   427     Q_D(QAbstractSlider);
       
   428     d->tracking = enable;
       
   429 }
       
   430 
       
   431 bool QAbstractSlider::hasTracking() const
       
   432 {
       
   433     Q_D(const QAbstractSlider);
       
   434     return d->tracking;
       
   435 }
       
   436 
       
   437 
       
   438 /*!
       
   439     \property QAbstractSlider::sliderDown
       
   440     \brief whether the slider is pressed down.
       
   441 
       
   442     The property is set by subclasses in order to let the abstract
       
   443     slider know whether or not \l tracking has any effect.
       
   444 
       
   445     Changing the slider down property emits the sliderPressed() and
       
   446     sliderReleased() signals.
       
   447 
       
   448 */
       
   449 void QAbstractSlider::setSliderDown(bool down)
       
   450 {
       
   451     Q_D(QAbstractSlider);
       
   452     bool doEmit = d->pressed != down;
       
   453 
       
   454     d->pressed = down;
       
   455 
       
   456     if (doEmit) {
       
   457         if (down)
       
   458             emit sliderPressed();
       
   459         else
       
   460             emit sliderReleased();
       
   461     }
       
   462 
       
   463     if (!down && d->position != d->value)
       
   464         triggerAction(SliderMove);
       
   465 }
       
   466 
       
   467 bool QAbstractSlider::isSliderDown() const
       
   468 {
       
   469     Q_D(const QAbstractSlider);
       
   470     return d->pressed;
       
   471 }
       
   472 
       
   473 
       
   474 /*!
       
   475     \property QAbstractSlider::sliderPosition
       
   476     \brief the current slider position
       
   477 
       
   478     If \l tracking is enabled (the default), this is identical to \l value.
       
   479 */
       
   480 void QAbstractSlider::setSliderPosition(int position)
       
   481 {
       
   482     Q_D(QAbstractSlider);
       
   483     position = d->bound(position);
       
   484     if (position == d->position)
       
   485         return;
       
   486     d->position = position;
       
   487     if (!d->tracking)
       
   488         update();
       
   489     if (d->pressed)
       
   490         emit sliderMoved(position);
       
   491     if (d->tracking && !d->blocktracking)
       
   492         triggerAction(SliderMove);
       
   493 }
       
   494 
       
   495 int QAbstractSlider::sliderPosition() const
       
   496 {
       
   497     Q_D(const QAbstractSlider);
       
   498     return d->position;
       
   499 }
       
   500 
       
   501 
       
   502 /*!
       
   503     \property QAbstractSlider::value
       
   504     \brief the slider's current value
       
   505 
       
   506     The slider forces the value to be within the legal range: \l
       
   507     minimum <= \c value <= \l maximum.
       
   508 
       
   509     Changing the value also changes the \l sliderPosition.
       
   510 */
       
   511 
       
   512 
       
   513 int QAbstractSlider::value() const
       
   514 {
       
   515     Q_D(const QAbstractSlider);
       
   516     return d->value;
       
   517 }
       
   518 
       
   519 void QAbstractSlider::setValue(int value)
       
   520 {
       
   521     Q_D(QAbstractSlider);
       
   522     value = d->bound(value);
       
   523     if (d->value == value && d->position == value)
       
   524         return;
       
   525     d->value = value;
       
   526     if (d->position != value) {
       
   527         d->position = value;
       
   528         if (d->pressed)
       
   529             emit sliderMoved((d->position = value));
       
   530     }
       
   531 #ifndef QT_NO_ACCESSIBILITY
       
   532     QAccessible::updateAccessibility(this, 0, QAccessible::ValueChanged);
       
   533 #endif
       
   534     sliderChange(SliderValueChange);
       
   535     emit valueChanged(value);
       
   536 }
       
   537 
       
   538 /*!
       
   539     \property QAbstractSlider::invertedAppearance
       
   540     \brief whether or not a slider shows its values inverted.
       
   541 
       
   542     If this property is false (the default), the minimum and maximum will
       
   543     be shown in its classic position for the inherited widget. If the
       
   544     value is true, the minimum and maximum appear at their opposite location.
       
   545 
       
   546     Note: This property makes most sense for sliders and dials. For
       
   547     scroll bars, the visual effect of the scroll bar subcontrols depends on
       
   548     whether or not the styles understand inverted appearance; most styles
       
   549     ignore this property for scroll bars.
       
   550 */
       
   551 
       
   552 bool QAbstractSlider::invertedAppearance() const
       
   553 {
       
   554     Q_D(const QAbstractSlider);
       
   555     return d->invertedAppearance;
       
   556 }
       
   557 
       
   558 void QAbstractSlider::setInvertedAppearance(bool invert)
       
   559 {
       
   560     Q_D(QAbstractSlider);
       
   561     d->invertedAppearance = invert;
       
   562     update();
       
   563 }
       
   564 
       
   565 
       
   566 /*!
       
   567     \property QAbstractSlider::invertedControls
       
   568     \brief whether or not the slider inverts its wheel and key events.
       
   569 
       
   570     If this property is false, scrolling the mouse wheel "up" and using keys
       
   571     like page up will increase the slider's value towards its maximum. Otherwise
       
   572     pressing page up will move value towards the slider's minimum.
       
   573 */
       
   574 
       
   575 
       
   576 bool QAbstractSlider::invertedControls() const
       
   577 {
       
   578     Q_D(const QAbstractSlider);
       
   579     return d->invertedControls;
       
   580 }
       
   581 
       
   582 void QAbstractSlider::setInvertedControls(bool invert)
       
   583 {
       
   584     Q_D(QAbstractSlider);
       
   585     d->invertedControls = invert;
       
   586 }
       
   587 
       
   588 /*!  Triggers a slider \a action.  Possible actions are \l
       
   589   SliderSingleStepAdd, \l SliderSingleStepSub, \l SliderPageStepAdd,
       
   590   \l SliderPageStepSub, \l SliderToMinimum, \l SliderToMaximum, and \l
       
   591   SliderMove.
       
   592 
       
   593   \sa actionTriggered()
       
   594  */
       
   595 void QAbstractSlider::triggerAction(SliderAction action)
       
   596 {
       
   597     Q_D(QAbstractSlider);
       
   598     d->blocktracking = true;
       
   599     switch (action) {
       
   600     case SliderSingleStepAdd:
       
   601         setSliderPosition(d->overflowSafeAdd(d->singleStep));
       
   602         break;
       
   603     case SliderSingleStepSub:
       
   604         setSliderPosition(d->overflowSafeAdd(-d->singleStep));
       
   605         break;
       
   606     case SliderPageStepAdd:
       
   607         setSliderPosition(d->overflowSafeAdd(d->pageStep));
       
   608         break;
       
   609     case SliderPageStepSub:
       
   610         setSliderPosition(d->overflowSafeAdd(-d->pageStep));
       
   611         break;
       
   612     case SliderToMinimum:
       
   613         setSliderPosition(d->minimum);
       
   614         break;
       
   615     case SliderToMaximum:
       
   616         setSliderPosition(d->maximum);
       
   617         break;
       
   618     case SliderMove:
       
   619     case SliderNoAction:
       
   620         break;
       
   621     };
       
   622     emit actionTriggered(action);
       
   623     d->blocktracking = false;
       
   624     setValue(d->position);
       
   625 }
       
   626 
       
   627 /*!  Sets action \a action to be triggered repetitively in intervals
       
   628 of \a repeatTime, after an initial delay of \a thresholdTime.
       
   629 
       
   630 \sa triggerAction() repeatAction()
       
   631  */
       
   632 void QAbstractSlider::setRepeatAction(SliderAction action, int thresholdTime, int repeatTime)
       
   633 {
       
   634     Q_D(QAbstractSlider);
       
   635     if ((d->repeatAction = action) == SliderNoAction) {
       
   636         d->repeatActionTimer.stop();
       
   637     } else {
       
   638         d->repeatActionTime = repeatTime;
       
   639         d->repeatActionTimer.start(thresholdTime, this);
       
   640     }
       
   641 }
       
   642 
       
   643 /*!
       
   644   Returns the current repeat action.
       
   645   \sa setRepeatAction()
       
   646  */
       
   647 QAbstractSlider::SliderAction QAbstractSlider::repeatAction() const
       
   648 {
       
   649     Q_D(const QAbstractSlider);
       
   650     return d->repeatAction;
       
   651 }
       
   652 
       
   653 /*!\reimp
       
   654  */
       
   655 void QAbstractSlider::timerEvent(QTimerEvent *e)
       
   656 {
       
   657     Q_D(QAbstractSlider);
       
   658     if (e->timerId() == d->repeatActionTimer.timerId()) {
       
   659         if (d->repeatActionTime) { // was threshold time, use repeat time next time
       
   660             d->repeatActionTimer.start(d->repeatActionTime, this);
       
   661             d->repeatActionTime = 0;
       
   662         }
       
   663         if (d->repeatAction == SliderPageStepAdd)
       
   664             d->setAdjustedSliderPosition(d->overflowSafeAdd(d->pageStep));
       
   665         else if (d->repeatAction == SliderPageStepSub)
       
   666             d->setAdjustedSliderPosition(d->overflowSafeAdd(-d->pageStep));
       
   667         else
       
   668             triggerAction(d->repeatAction);
       
   669     }
       
   670 }
       
   671 
       
   672 /*!
       
   673     Reimplement this virtual function to track slider changes such as
       
   674     \l SliderRangeChange, \l SliderOrientationChange, \l
       
   675     SliderStepsChange, or \l SliderValueChange. The default
       
   676     implementation only updates the display and ignores the \a change
       
   677     parameter.
       
   678  */
       
   679 void QAbstractSlider::sliderChange(SliderChange)
       
   680 {
       
   681     update();
       
   682 }
       
   683 
       
   684 
       
   685 /*!
       
   686     \reimp
       
   687 */
       
   688 #ifndef QT_NO_WHEELEVENT
       
   689 void QAbstractSlider::wheelEvent(QWheelEvent * e)
       
   690 {
       
   691     Q_D(QAbstractSlider);
       
   692     e->ignore();
       
   693     if (e->orientation() != d->orientation && !rect().contains(e->pos()))
       
   694         return;
       
   695 
       
   696     qreal currentOffset = qreal(e->delta()) / 120;
       
   697     d->offset_accumulated += currentOffset;
       
   698     if (int(d->offset_accumulated) == 0) {
       
   699         // QAbstractSlider works on integer values. So if the accumulated
       
   700         // offset is less than +/- 1, we need to wait until we get more
       
   701         // wheel events (this means that the wheel resolution is higher than 
       
   702         // 15 degrees, e.g. when using mac mighty mouse/trackpad):
       
   703         return;
       
   704     }
       
   705 
       
   706     int stepsToScroll;
       
   707     if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) {
       
   708         stepsToScroll = currentOffset > 0 ? d->pageStep : -d->pageStep;
       
   709     } else {
       
   710         // Calculate the number of steps to scroll (per 15 degrees of rotate):
       
   711 #ifdef Q_OS_MAC
       
   712         // On mac, since mouse wheel scrolling is accelerated and
       
   713         // fine tuned by the OS, we skip applying acceleration:
       
   714         stepsToScroll = int(d->offset_accumulated);
       
   715 #else
       
   716         stepsToScroll = int(d->offset_accumulated) * QApplication::wheelScrollLines() * d->singleStep;
       
   717 #endif
       
   718         stepsToScroll = qBound(-d->pageStep, stepsToScroll, d->pageStep);
       
   719     }
       
   720 
       
   721     if (d->invertedControls)
       
   722         stepsToScroll = -stepsToScroll;
       
   723 
       
   724     int prevValue = d->value;
       
   725     d->position = d->overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction()
       
   726     triggerAction(SliderMove);
       
   727 
       
   728     if (prevValue == d->value) {
       
   729         d->offset_accumulated = 0;
       
   730     } else {
       
   731         d->offset_accumulated -= int(d->offset_accumulated);
       
   732         e->accept();
       
   733     }
       
   734 }
       
   735 #endif
       
   736 #ifdef QT_KEYPAD_NAVIGATION
       
   737 /*!
       
   738     \internal
       
   739 
       
   740     Tells us if it there is currently a reachable widget by keypad navigation in
       
   741     a certain \a orientation.
       
   742     If no navigation is possible, occuring key events in that \a orientation may
       
   743     be used to interact with the value in the focussed widget, even though it
       
   744     currently has not the editFocus.
       
   745 
       
   746     \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
       
   747 */
       
   748 inline static bool canKeypadNavigate(Qt::Orientation orientation)
       
   749 {
       
   750     return orientation == Qt::Horizontal?
       
   751             (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
       
   752                     || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
       
   753             :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
       
   754                     || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
       
   755 }
       
   756 /*!
       
   757     \internal
       
   758 
       
   759     Checks, if the \a widget is inside a QTabWidget. If is is inside
       
   760     one, left/right key events will be used to switch between tabs in keypad
       
   761     navigation. If there is no QTabWidget, the horizontal key events can be used to
       
   762     interact with the value in the focussed widget, even though it currently has
       
   763     not the editFocus.
       
   764 
       
   765     \sa QWidget::hasEditFocus()
       
   766 */
       
   767 inline static bool inTabWidget(QWidget *widget)
       
   768 {
       
   769     for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
       
   770         if (qobject_cast<const QTabWidget*>(tabWidget))
       
   771             return true;
       
   772     return false;
       
   773 }
       
   774 #endif // QT_KEYPAD_NAVIGATION
       
   775 /*!
       
   776     \reimp
       
   777 */
       
   778 void QAbstractSlider::keyPressEvent(QKeyEvent *ev)
       
   779 {
       
   780     Q_D(QAbstractSlider);
       
   781     SliderAction action = SliderNoAction;
       
   782     switch (ev->key()) {
       
   783 #ifdef QT_KEYPAD_NAVIGATION
       
   784         case Qt::Key_Select:
       
   785             if (QApplication::keypadNavigationEnabled())
       
   786                 setEditFocus(!hasEditFocus());
       
   787             else
       
   788                 ev->ignore();
       
   789             break;
       
   790         case Qt::Key_Back:
       
   791             if (QApplication::keypadNavigationEnabled() && hasEditFocus()) {
       
   792                 setValue(d->origValue);
       
   793                 setEditFocus(false);
       
   794             } else
       
   795                 ev->ignore();
       
   796             break;
       
   797 #endif
       
   798 
       
   799         // It seems we need to use invertedAppearance for Left and right, otherwise, things look weird.
       
   800         case Qt::Key_Left:
       
   801 #ifdef QT_KEYPAD_NAVIGATION
       
   802             // In QApplication::KeypadNavigationDirectional, we want to change the slider
       
   803             // value if there is no left/right navigation possible and if this slider is not
       
   804             // inside a tab widget.
       
   805             if (QApplication::keypadNavigationEnabled()
       
   806                     && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder
       
   807                     || d->orientation == Qt::Vertical
       
   808                     || !hasEditFocus() && (canKeypadNavigate(Qt::Horizontal) || inTabWidget(this)))) {
       
   809                 ev->ignore();
       
   810                 return;
       
   811             }
       
   812             if (QApplication::keypadNavigationEnabled() && d->orientation == Qt::Vertical)
       
   813                 action = d->invertedControls ? SliderSingleStepSub : SliderSingleStepAdd;
       
   814             else
       
   815 #endif
       
   816             if (isRightToLeft())
       
   817                 action = d->invertedAppearance ? SliderSingleStepSub : SliderSingleStepAdd;
       
   818             else
       
   819                 action = !d->invertedAppearance ? SliderSingleStepSub : SliderSingleStepAdd;
       
   820             break;
       
   821         case Qt::Key_Right:
       
   822 #ifdef QT_KEYPAD_NAVIGATION
       
   823             // Same logic as in Qt::Key_Left
       
   824             if (QApplication::keypadNavigationEnabled()
       
   825                     && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder
       
   826                     || d->orientation == Qt::Vertical
       
   827                     || !hasEditFocus() && (canKeypadNavigate(Qt::Horizontal) || inTabWidget(this)))) {
       
   828                 ev->ignore();
       
   829                 return;
       
   830             }
       
   831             if (QApplication::keypadNavigationEnabled() && d->orientation == Qt::Vertical)
       
   832                 action = d->invertedControls ? SliderSingleStepAdd : SliderSingleStepSub;
       
   833             else
       
   834 #endif
       
   835             if (isRightToLeft())
       
   836                 action = d->invertedAppearance ? SliderSingleStepAdd : SliderSingleStepSub;
       
   837             else
       
   838                 action = !d->invertedAppearance ? SliderSingleStepAdd : SliderSingleStepSub;
       
   839             break;
       
   840         case Qt::Key_Up:
       
   841 #ifdef QT_KEYPAD_NAVIGATION
       
   842             // In QApplication::KeypadNavigationDirectional, we want to change the slider
       
   843             // value if there is no up/down navigation possible.
       
   844             if (QApplication::keypadNavigationEnabled()
       
   845                     && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder
       
   846                     || d->orientation == Qt::Horizontal
       
   847                     || !hasEditFocus() && canKeypadNavigate(Qt::Vertical))) {
       
   848                 ev->ignore();
       
   849                 break;
       
   850             }
       
   851 #endif
       
   852             action = d->invertedControls ? SliderSingleStepSub : SliderSingleStepAdd;
       
   853             break;
       
   854         case Qt::Key_Down:
       
   855 #ifdef QT_KEYPAD_NAVIGATION
       
   856             // Same logic as in Qt::Key_Up
       
   857             if (QApplication::keypadNavigationEnabled()
       
   858                     && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder
       
   859                     || d->orientation == Qt::Horizontal
       
   860                     || !hasEditFocus() && canKeypadNavigate(Qt::Vertical))) {
       
   861                 ev->ignore();
       
   862                 break;
       
   863             }
       
   864 #endif
       
   865             action = d->invertedControls ? SliderSingleStepAdd : SliderSingleStepSub;
       
   866             break;
       
   867         case Qt::Key_PageUp:
       
   868             action = d->invertedControls ? SliderPageStepSub : SliderPageStepAdd;
       
   869             break;
       
   870         case Qt::Key_PageDown:
       
   871             action = d->invertedControls ? SliderPageStepAdd : SliderPageStepSub;
       
   872             break;
       
   873         case Qt::Key_Home:
       
   874             action = SliderToMinimum;
       
   875             break;
       
   876         case Qt::Key_End:
       
   877             action = SliderToMaximum;
       
   878             break;
       
   879         default:
       
   880             ev->ignore();
       
   881             break;
       
   882     }
       
   883     if (action)
       
   884         triggerAction(action);
       
   885 }
       
   886 
       
   887 /*!
       
   888     \reimp
       
   889 */
       
   890 void QAbstractSlider::changeEvent(QEvent *ev)
       
   891 {
       
   892     Q_D(QAbstractSlider);
       
   893     switch (ev->type()) {
       
   894     case QEvent::EnabledChange:
       
   895         if (!isEnabled()) {
       
   896             d->repeatActionTimer.stop();
       
   897             setSliderDown(false);
       
   898         }
       
   899         // fall through...
       
   900     default:
       
   901         QWidget::changeEvent(ev);
       
   902     }
       
   903 }
       
   904 
       
   905 /*!
       
   906     \reimp
       
   907 */
       
   908 bool QAbstractSlider::event(QEvent *e)
       
   909 {
       
   910 #ifdef QT_KEYPAD_NAVIGATION
       
   911     Q_D(QAbstractSlider);
       
   912     switch (e->type()) {
       
   913     case QEvent::FocusIn:
       
   914         d->origValue = d->value;
       
   915         break;
       
   916     default:
       
   917         break;
       
   918     }
       
   919 #endif
       
   920 
       
   921     return QWidget::event(e);
       
   922 }
       
   923 
       
   924 /*! \fn int QAbstractSlider::minValue() const
       
   925 
       
   926     Use minimum() instead.
       
   927 */
       
   928 
       
   929 /*! \fn int QAbstractSlider::maxValue() const
       
   930 
       
   931     Use maximum() instead.
       
   932 */
       
   933 
       
   934 /*! \fn int QAbstractSlider::lineStep() const
       
   935 
       
   936     Use singleStep() instead.
       
   937 */
       
   938 
       
   939 /*! \fn void QAbstractSlider::setMinValue(int v)
       
   940 
       
   941     Use setMinimum() instead.
       
   942 */
       
   943 
       
   944 /*! \fn void QAbstractSlider::setMaxValue(int v)
       
   945 
       
   946     Use setMaximum() instead.
       
   947 */
       
   948 
       
   949 /*! \fn void QAbstractSlider::setLineStep(int v)
       
   950 
       
   951     Use setSingleStep() instead.
       
   952 */
       
   953 
       
   954 /*! \fn void QAbstractSlider::addPage()
       
   955 
       
   956     Use triggerAction(QAbstractSlider::SliderPageStepAdd) instead.
       
   957 */
       
   958 
       
   959 /*! \fn void QAbstractSlider::subtractPage()
       
   960 
       
   961     Use triggerAction(QAbstractSlider::SliderPageStepSub) instead.
       
   962 */
       
   963 
       
   964 /*! \fn void QAbstractSlider::addLine()
       
   965 
       
   966     Use triggerAction(QAbstractSlider::SliderSingleStepAdd) instead.
       
   967 */
       
   968 
       
   969 /*! \fn void QAbstractSlider::subtractLine()
       
   970 
       
   971     Use triggerAction(QAbstractSlider::SliderSingleStepSub) instead.
       
   972 */
       
   973 
       
   974 /*! \fn void QAbstractSlider::setSteps(int single, int page)
       
   975 
       
   976     Use setSingleStep(\a single) followed by setPageStep(\a page)
       
   977     instead.
       
   978 */
       
   979 
       
   980 QT_END_NAMESPACE