source: trunk/src/gui/widgets/qabstractslider.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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