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

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

File size: 28.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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 [email protected].
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{
223 firstRepeat.invalidate();
224#else
225{
226#endif
227
228}
229
230QAbstractSliderPrivate::~QAbstractSliderPrivate()
231{
232}
233
234/*!
235 Sets the slider's minimum to \a min and its maximum to \a max.
236
237 If \a max is smaller than \a min, \a min becomes the only legal
238 value.
239
240 \sa minimum maximum
241*/
242void QAbstractSlider::setRange(int min, int max)
243{
244 Q_D(QAbstractSlider);
245 int oldMin = d->minimum;
246 int oldMax = d->maximum;
247 d->minimum = min;
248 d->maximum = qMax(min, max);
249 if (oldMin != d->minimum || oldMax != d->maximum) {
250 sliderChange(SliderRangeChange);
251 emit rangeChanged(d->minimum, d->maximum);
252 setValue(d->value); // re-bound
253 }
254}
255
256
257void QAbstractSliderPrivate::setSteps(int single, int page)
258{
259 Q_Q(QAbstractSlider);
260 singleStep = qAbs(single);
261 pageStep = qAbs(page);
262 q->sliderChange(QAbstractSlider::SliderStepsChange);
263}
264
265/*!
266 Constructs an abstract slider.
267
268 The \a parent arguments is sent to the QWidget constructor.
269
270 The \l minimum defaults to 0, the \l maximum to 99, with a \l
271 singleStep size of 1 and a \l pageStep size of 10, and an initial
272 \l value of 0.
273*/
274QAbstractSlider::QAbstractSlider(QWidget *parent)
275 :QWidget(*new QAbstractSliderPrivate, parent, 0)
276{
277}
278
279/*! \internal */
280QAbstractSlider::QAbstractSlider(QAbstractSliderPrivate &dd, QWidget *parent)
281 :QWidget(dd, parent, 0)
282{
283}
284
285/*!
286 Destroys the slider.
287*/
288QAbstractSlider::~QAbstractSlider()
289{
290}
291
292/*!
293 \property QAbstractSlider::orientation
294 \brief the orientation of the slider
295
296 The orientation must be \l Qt::Vertical (the default) or \l
297 Qt::Horizontal.
298*/
299void QAbstractSlider::setOrientation(Qt::Orientation orientation)
300{
301 Q_D(QAbstractSlider);
302 if (d->orientation == orientation)
303 return;
304
305 d->orientation = orientation;
306 if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) {
307 QSizePolicy sp = sizePolicy();
308 sp.transpose();
309 setSizePolicy(sp);
310 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
311 }
312 update();
313 updateGeometry();
314}
315
316Qt::Orientation QAbstractSlider::orientation() const
317{
318 Q_D(const QAbstractSlider);
319 return d->orientation;
320}
321
322
323/*!
324 \property QAbstractSlider::minimum
325 \brief the sliders's minimum value
326
327 When setting this property, the \l maximum is adjusted if
328 necessary to ensure that the range remains valid. Also the
329 slider's current value is adjusted to be within the new range.
330
331*/
332
333void QAbstractSlider::setMinimum(int min)
334{
335 Q_D(QAbstractSlider);
336 setRange(min, qMax(d->maximum, min));
337}
338
339int QAbstractSlider::minimum() const
340{
341 Q_D(const QAbstractSlider);
342 return d->minimum;
343}
344
345
346/*!
347 \property QAbstractSlider::maximum
348 \brief the slider's maximum value
349
350 When setting this property, the \l minimum is adjusted if
351 necessary to ensure that the range remains valid. Also the
352 slider's current value is adjusted to be within the new range.
353
354
355*/
356
357void QAbstractSlider::setMaximum(int max)
358{
359 Q_D(QAbstractSlider);
360 setRange(qMin(d->minimum, max), max);
361}
362
363int QAbstractSlider::maximum() const
364{
365 Q_D(const QAbstractSlider);
366 return d->maximum;
367}
368
369
370
371/*!
372 \property QAbstractSlider::singleStep
373 \brief the single step.
374
375 The smaller of two natural steps that an
376 abstract sliders provides and typically corresponds to the user
377 pressing an arrow key.
378
379 If the property is modified during an auto repeating key event, behavior
380 is undefined.
381
382 \sa pageStep
383*/
384
385void QAbstractSlider::setSingleStep(int step)
386{
387 Q_D(QAbstractSlider);
388 if (step != d->singleStep)
389 d->setSteps(step, d->pageStep);
390}
391
392int QAbstractSlider::singleStep() const
393{
394 Q_D(const QAbstractSlider);
395 return d->singleStep;
396}
397
398
399/*!
400 \property QAbstractSlider::pageStep
401 \brief the page step.
402
403 The larger of two natural steps that an abstract slider provides
404 and typically corresponds to the user pressing PageUp or PageDown.
405
406 \sa singleStep
407*/
408
409void QAbstractSlider::setPageStep(int step)
410{
411 Q_D(QAbstractSlider);
412 if (step != d->pageStep)
413 d->setSteps(d->singleStep, step);
414}
415
416int QAbstractSlider::pageStep() const
417{
418 Q_D(const QAbstractSlider);
419 return d->pageStep;
420}
421
422/*!
423 \property QAbstractSlider::tracking
424 \brief whether slider tracking is enabled
425
426 If tracking is enabled (the default), the slider emits the
427 valueChanged() signal while the slider is being dragged. If
428 tracking is disabled, the slider emits the valueChanged() signal
429 only when the user releases the slider.
430
431 \sa sliderDown
432*/
433void QAbstractSlider::setTracking(bool enable)
434{
435 Q_D(QAbstractSlider);
436 d->tracking = enable;
437}
438
439bool QAbstractSlider::hasTracking() const
440{
441 Q_D(const QAbstractSlider);
442 return d->tracking;
443}
444
445
446/*!
447 \property QAbstractSlider::sliderDown
448 \brief whether the slider is pressed down.
449
450 The property is set by subclasses in order to let the abstract
451 slider know whether or not \l tracking has any effect.
452
453 Changing the slider down property emits the sliderPressed() and
454 sliderReleased() signals.
455
456*/
457void QAbstractSlider::setSliderDown(bool down)
458{
459 Q_D(QAbstractSlider);
460 bool doEmit = d->pressed != down;
461
462 d->pressed = down;
463
464 if (doEmit) {
465 if (down)
466 emit sliderPressed();
467 else
468 emit sliderReleased();
469 }
470
471 if (!down && d->position != d->value)
472 triggerAction(SliderMove);
473}
474
475bool QAbstractSlider::isSliderDown() const
476{
477 Q_D(const QAbstractSlider);
478 return d->pressed;
479}
480
481
482/*!
483 \property QAbstractSlider::sliderPosition
484 \brief the current slider position
485
486 If \l tracking is enabled (the default), this is identical to \l value.
487*/
488void QAbstractSlider::setSliderPosition(int position)
489{
490 Q_D(QAbstractSlider);
491 position = d->bound(position);
492 if (position == d->position)
493 return;
494 d->position = position;
495 if (!d->tracking)
496 update();
497 if (d->pressed)
498 emit sliderMoved(position);
499 if (d->tracking && !d->blocktracking)
500 triggerAction(SliderMove);
501}
502
503int QAbstractSlider::sliderPosition() const
504{
505 Q_D(const QAbstractSlider);
506 return d->position;
507}
508
509
510/*!
511 \property QAbstractSlider::value
512 \brief the slider's current value
513
514 The slider forces the value to be within the legal range: \l
515 minimum <= \c value <= \l maximum.
516
517 Changing the value also changes the \l sliderPosition.
518*/
519
520
521int QAbstractSlider::value() const
522{
523 Q_D(const QAbstractSlider);
524 return d->value;
525}
526
527void QAbstractSlider::setValue(int value)
528{
529 Q_D(QAbstractSlider);