source: trunk/src/gui/widgets/qspinbox.cpp@ 965

Last change on this file since 965 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: 36.7 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 <private/qabstractspinbox_p.h>
43#include <qspinbox.h>
44
45#ifndef QT_NO_SPINBOX
46
47#include <qlineedit.h>
48#include <qlocale.h>
49#include <qvalidator.h>
50#include <qdebug.h>
51
52#include <math.h>
53#include <float.h>
54
55QT_BEGIN_NAMESPACE
56
57//#define QSPINBOX_QSBDEBUG
58#ifdef QSPINBOX_QSBDEBUG
59# define QSBDEBUG qDebug
60#else
61# define QSBDEBUG if (false) qDebug
62#endif
63
64class QSpinBoxPrivate : public QAbstractSpinBoxPrivate
65{
66 Q_DECLARE_PUBLIC(QSpinBox)
67public:
68 QSpinBoxPrivate();
69 void emitSignals(EmitPolicy ep, const QVariant &);
70
71 virtual QVariant valueFromText(const QString &n) const;
72 virtual QString textFromValue(const QVariant &n) const;
73 QVariant validateAndInterpret(QString &input, int &pos,
74 QValidator::State &state) const;
75
76 inline void init() {
77 Q_Q(QSpinBox);
78 q->setInputMethodHints(Qt::ImhDigitsOnly);
79 setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem);
80 }
81};
82
83class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate
84{
85 Q_DECLARE_PUBLIC(QDoubleSpinBox)
86public:
87 QDoubleSpinBoxPrivate();
88 void emitSignals(EmitPolicy ep, const QVariant &);
89
90 virtual QVariant valueFromText(const QString &n) const;
91 virtual QString textFromValue(const QVariant &n) const;
92 QVariant validateAndInterpret(QString &input, int &pos,
93 QValidator::State &state) const;
94 double round(double input) const;
95 // variables
96 int decimals;
97
98 inline void init() {
99 Q_Q(QDoubleSpinBox);
100 q->setInputMethodHints(Qt::ImhFormattedNumbersOnly);
101 }
102
103 // When fiddling with the decimals property, we may lose precision in these properties.
104 double actualMin;
105 double actualMax;
106};
107
108
109/*!
110 \class QSpinBox
111 \brief The QSpinBox class provides a spin box widget.
112
113 \ingroup basicwidgets
114
115
116 QSpinBox is designed to handle integers and discrete sets of
117 values (e.g., month names); use QDoubleSpinBox for floating point
118 values.
119
120 QSpinBox allows the user to choose a value by clicking the up/down
121 buttons or pressing up/down on the keyboard to increase/decrease
122 the value currently displayed. The user can also type the value in
123 manually. The spin box supports integer values but can be extended to
124 use different strings with validate(), textFromValue() and valueFromText().
125
126 Every time the value changes QSpinBox emits the valueChanged()
127 signals. The current value can be fetched with value() and set
128 with setValue().
129
130 Clicking the up/down buttons or using the keyboard accelerator's
131 up and down arrows will increase or decrease the current value in
132 steps of size singleStep(). If you want to change this behaviour you
133 can reimplement the virtual function stepBy(). The minimum and
134 maximum value and the step size can be set using one of the
135 constructors, and can be changed later with setMinimum(),
136 setMaximum() and setSingleStep().
137
138 Most spin boxes are directional, but QSpinBox can also operate as
139 a circular spin box, i.e. if the range is 0-99 and the current
140 value is 99, clicking "up" will give 0 if wrapping() is set to
141 true. Use setWrapping() if you want circular behavior.
142
143 The displayed value can be prepended and appended with arbitrary
144 strings indicating, for example, currency or the unit of
145 measurement. See setPrefix() and setSuffix(). The text in the spin
146 box is retrieved with text() (which includes any prefix() and
147 suffix()), or with cleanText() (which has no prefix(), no suffix()
148 and no leading or trailing whitespace).
149
150 It is often desirable to give the user a special (often default)
151 choice in addition to the range of numeric values. See
152 setSpecialValueText() for how to do this with QSpinBox.
153
154 \table 100%
155 \row \o \inlineimage windowsxp-spinbox.png Screenshot of a Windows XP spin box
156 \o A spin box shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
157 \row \o \inlineimage plastique-spinbox.png Screenshot of a Plastique spin box
158 \o A spin box shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
159 \row \o \inlineimage macintosh-spinbox.png Screenshot of a Macintosh spin box
160 \o A spin box shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
161 \endtable
162
163 \section1 Subclassing QSpinBox
164
165 If using prefix(), suffix(), and specialValueText() don't provide
166 enough control, you subclass QSpinBox and reimplement
167 valueFromText() and textFromValue(). For example, here's the code
168 for a custom spin box that allows the user to enter icon sizes
169 (e.g., "32 x 32"):
170
171 \snippet examples/widgets/icons/iconsizespinbox.cpp 1
172 \codeline
173 \snippet examples/widgets/icons/iconsizespinbox.cpp 2
174
175 See the \l{widgets/icons}{Icons} example for the full source
176 code.
177
178 \sa QDoubleSpinBox, QDateTimeEdit, QSlider, {Spin Boxes Example}
179*/
180
181/*!
182 \fn void QSpinBox::valueChanged(int i)
183
184 This signal is emitted whenever the spin box's value is changed.
185 The new value's integer value is passed in \a i.
186*/
187
188/*!
189 \fn void QSpinBox::valueChanged(const QString &text)
190
191 \overload
192
193 The new value is passed literally in \a text with no prefix() or
194 suffix().
195*/
196
197/*!
198 Constructs a spin box with 0 as minimum value and 99 as maximum value, a
199 step value of 1. The value is initially set to 0. It is parented to \a
200 parent.
201
202 \sa setMinimum(), setMaximum(), setSingleStep()
203*/
204
205QSpinBox::QSpinBox(QWidget *parent)
206 : QAbstractSpinBox(*new QSpinBoxPrivate, parent)
207{
208 Q_D(QSpinBox);
209 d->init();
210}
211
212#ifdef QT3_SUPPORT
213/*!
214 Use one of the constructors that doesn't take the \a name
215 argument and then use setObjectName() instead.
216*/
217QSpinBox::QSpinBox(QWidget *parent, const char *name)
218 : QAbstractSpinBox(*new QSpinBoxPrivate, parent)
219{
220 Q_D(QSpinBox);
221 setObjectName(QString::fromAscii(name));
222 d->init();
223}
224
225/*!
226 Use one of the constructors that doesn't take the \a name
227 argument and then use setObjectName() instead.
228*/
229QSpinBox::QSpinBox(int minimum, int maximum, int step, QWidget *parent, const char *name)
230 : QAbstractSpinBox(*new QSpinBoxPrivate, parent)
231{
232 Q_D(QSpinBox);
233 d->minimum = QVariant(qMin<int>(minimum, maximum));
234 d->maximum = QVariant(qMax<int>(minimum, maximum));
235 d->singleStep = QVariant(step);
236 setObjectName(QString::fromAscii(name));
237 d->init();
238}
239
240#endif
241
242/*!
243 \property QSpinBox::value
244 \brief the value of the spin box
245
246 setValue() will emit valueChanged() if the new value is different
247 from the old one.
248*/
249
250int QSpinBox::value() const
251{
252 Q_D(const QSpinBox);
253 return d->value.toInt();
254}
255
256void QSpinBox::setValue(int value)
257{
258 Q_D(QSpinBox);
259 d->setValue(QVariant(value), EmitIfChanged);
260}
261
262/*!
263 \property QSpinBox::prefix
264 \brief the spin box's prefix
265
266 The prefix is prepended to the start of the displayed value.
267 Typical use is to display a unit of measurement or a currency
268 symbol. For example:
269
270 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 0
271
272 To turn off the prefix display, set this property to an empty
273 string. The default is no prefix. The prefix is not displayed when
274 value() == minimum() and specialValueText() is set.
275
276 If no prefix is set, prefix() returns an empty string.
277
278 \sa suffix(), setSuffix(), specialValueText(), setSpecialValueText()
279*/
280
281QString QSpinBox::prefix() const
282{
283 Q_D(const QSpinBox);
284 return d->prefix;
285}
286
287void QSpinBox::setPrefix(const QString &prefix)
288{
289 Q_D(QSpinBox);
290
291 d->prefix = prefix;
292 d->updateEdit();
293
294 d->cachedSizeHint = QSize();
295 updateGeometry();
296}
297
298/*!
299 \property QSpinBox::suffix
300 \brief the suffix of the spin box
301
302 The suffix is appended to the end of the displayed value. Typical
303 use is to display a unit of measurement or a currency symbol. For
304 example:
305
306 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 1
307
308 To turn off the suffix display, set this property to an empty
309 string. The default is no suffix. The suffix is not displayed for
310 the minimum() if specialValueText() is set.
311
312 If no suffix is set, suffix() returns an empty string.
313
314 \sa prefix(), setPrefix(), specialValueText(), setSpecialValueText()
315*/
316
317QString QSpinBox::suffix() const
318{
319 Q_D(const QSpinBox);
320
321 return d->suffix;
322}
323
324void QSpinBox::setSuffix(const QString &suffix)
325{
326 Q_D(QSpinBox);
327
328 d->suffix = suffix;
329 d->updateEdit();
330
331 d->cachedSizeHint = QSize();
332 updateGeometry();
333}
334
335/*!
336 \property QSpinBox::cleanText
337
338 \brief the text of the spin box excluding any prefix, suffix,
339 or leading or trailing whitespace.
340
341 \sa text, QSpinBox::prefix, QSpinBox::suffix
342*/
343
344QString QSpinBox::cleanText() const
345{
346 Q_D(const QSpinBox);
347
348 return d->stripped(d->edit->displayText());
349}
350
351
352/*!
353 \property QSpinBox::singleStep
354 \brief the step value
355
356 When the user uses the arrows to change the spin box's value the
357 value will be incremented/decremented by the amount of the
358 singleStep. The default value is 1. Setting a singleStep value of
359 less than 0 does nothing.
360*/
361
362int QSpinBox::singleStep() const
363{
364 Q_D(const QSpinBox);
365
366 return d->singleStep.toInt();
367}
368
369void QSpinBox::setSingleStep(int value)
370{
371 Q_D(QSpinBox);
372 if (value >= 0) {
373 d->singleStep = QVariant(value);
374 d->updateEdit();
375 }
376}
377
378/*!
379 \property QSpinBox::minimum
380
381 \brief the minimum value of the spin box
382
383 When setting this property the \l maximum is adjusted
384 if necessary to ensure that the range remains valid.
385
386 The default minimum value is 0.
387
388 \sa setRange() specialValueText
389*/
390
391int QSpinBox::minimum() const
392{
393 Q_D(const QSpinBox);
394
395 return d->minimum.toInt();
396}
397
398void QSpinBox::setMinimum(int minimum)
399{
400 Q_D(QSpinBox);
401 const QVariant m(minimum);
402 d->setRange(m, (d->variantCompare(d->maximum, m) > 0 ? d->maximum : m));
403}
404
405/*!
406 \property QSpinBox::maximum
407
408 \brief the maximum value of the spin box
409
410 When setting this property the \l minimum is adjusted
411 if necessary, to ensure that the range remains valid.
412
413 The default maximum value is 99.
414
415 \sa setRange() specialValueText
416
417*/
418
419int QSpinBox::maximum() const
420{
421 Q_D(const QSpinBox);
422
423 return d->maximum.toInt();
424}
425
426void QSpinBox::setMaximum(int maximum)
427{
428 Q_D(QSpinBox);
429 const QVariant m(maximum);
430 d->setRange((d->variantCompare(d->minimum, m) < 0 ? d->minimum : m), m);
431}
432
433/*!
434 Convenience function to set the \a minimum, and \a maximum values
435 with a single function call.
436
437 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 2
438 is equivalent to:
439 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 3
440
441 \sa minimum maximum
442*/
443
444void QSpinBox::setRange(int minimum, int maximum)
445{
446 Q_D(QSpinBox);
447 d->setRange(QVariant(minimum), QVariant(maximum));
448}
449
450/*!
451 This virtual function is used by the spin box whenever it needs to
452 display the given \a value. The default implementation returns a
453 string containing \a value printed in the standard way using
454 QWidget::locale().toString(), but with the thousand separator
455 removed. Reimplementations may return anything. (See the example
456 in the detailed description.)
457
458 Note: QSpinBox does not call this function for specialValueText()
459 and that neither prefix() nor suffix() should be included in the
460 return value.
461
462 If you reimplement this, you may also need to reimplement
463 valueFromText() and validate()
464
465 \sa valueFromText(), validate(), QLocale::groupSeparator()
466*/
467
468QString QSpinBox::textFromValue(int value) const
469{
470 QString str = locale().toString(value);
471 if (qAbs(value) >= 1000 || value == INT_MIN) {
472 str.remove(locale().groupSeparator());
473 }
474
475 return str;
476}
477
478/*!
479 \fn int QSpinBox::valueFromText(const QString &text) const
480
481 This virtual function is used by the spin box whenever it needs to
482 interpret \a text entered by the user as a value.
483
484 Subclasses that need to display spin box values in a non-numeric
485 way need to reimplement this function.
486
487 Note: QSpinBox handles specialValueText() separately; this
488 function is only concerned with the other values.
489
490 \sa textFromValue(), validate()
491*/
492
493int QSpinBox::valueFromText(const QString &text) const
494{
495 Q_D(const QSpinBox);
496
497 QString copy = text;
498 int pos = d->edit->cursorPosition();
499 QValidator::State state = QValidator::Acceptable;
500 return d->validateAndInterpret(copy, pos, state).toInt();
501}
502
503/*!
504 \reimp
505*/
506QValidator::State QSpinBox::validate(QString &text, int &pos) const
507{
508 Q_D(const QSpinBox);
509
510 QValidator::State state;
511 d->validateAndInterpret(text, pos, state);
512 return state;
513}
514
515
516/*!
517 \reimp
518*/
519void QSpinBox::fixup(QString &input) const
520{
521 input.remove(locale().groupSeparator());
522}
523
524
525// --- QDoubleSpinBox ---
526
527/*!
528 \class QDoubleSpinBox
529 \brief The QDoubleSpinBox class provides a spin box widget that
530 takes doubles.
531
532 \ingroup basicwidgets
533
534
535 QDoubleSpinBox allows the user to choose a value by clicking the
536 up and down buttons or by pressing Up or Down on the keyboard to
537 increase or decrease the value currently displayed. The user can
538 also type the value in manually. The spin box supports double
539 values but can be extended to use different strings with
540 validate(), textFromValue() and valueFromText().
541
542 Every time the value changes QDoubleSpinBox emits the
543 valueChanged() signal. The current value can be fetched with
544 value() and set with setValue().
545
546 Note: QDoubleSpinBox will round numbers so they can be displayed
547 with the current precision. In a QDoubleSpinBox with decimals set
548 to 2, calling setValue(2.555) will cause value() to return 2.56.
549
550 Clicking the up and down buttons or using the keyboard accelerator's
551 Up and Down arrows will increase or decrease the current value in
552 steps of size singleStep(). If you want to change this behavior you
553 can reimplement the virtual function stepBy(). The minimum and
554 maximum value and the step size can be set using one of the
555 constructors, and can be changed later with setMinimum(),
556 setMaximum() and setSingleStep(). The spinbox has a default
557 precision of 2 decimal places but this can be changed using
558 setDecimals().
559
560 Most spin boxes are directional, but QDoubleSpinBox can also
561 operate as a circular spin box, i.e. if the range is 0.0-99.9 and
562 the current value is 99.9, clicking "up" will give 0 if wrapping()
563 is set to true. Use setWrapping() if you want circular behavior.
564
565 The displayed value can be prepended and appended with arbitrary
566 strings indicating, for example, currency or the unit of
567 measurement. See setPrefix() and setSuffix(). The text in the spin
568 box is retrieved with text() (which includes any prefix() and
569 suffix()), or with cleanText() (which has no prefix(), no suffix()
570 and no leading or trailing whitespace).
571
572 It is often desirable to give the user a special (often default)
573 choice in addition to the range of numeric values. See
574 setSpecialValueText() for how to do this with QDoubleSpinBox.
575
576 \sa QSpinBox, QDateTimeEdit, QSlider, {Spin Boxes Example}
577*/
578
579/*!
580 \fn void QDoubleSpinBox::valueChanged(double d);
581
582 This signal is emitted whenever the spin box's value is changed.
583 The new value is passed in \a d.
584*/
585
586/*!
587 \fn void QDoubleSpinBox::valueChanged(const QString &text);
588
589 \overload
590
591 The new value is passed literally in \a text with no prefix() or
592 suffix().
593*/
594
595/*!
596 Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
597 a step value of 1.0 and a precision of 2 decimal places. The value is
598 initially set to 0.00. The spin box has the given \a parent.
599
600 \sa setMinimum(), setMaximum(), setSingleStep()
601*/
602QDoubleSpinBox::QDoubleSpinBox(QWidget *parent)
603 : QAbstractSpinBox(*new QDoubleSpinBoxPrivate, parent)
604{
605 Q_D(QDoubleSpinBox);
606 d->init();
607}
608
609/*!
610 \property QDoubleSpinBox::value
611 \brief the value of the spin box
612
613 setValue() will emit valueChanged() if the new value is different
614 from the old one.
615
616 Note: The value will be rounded so it can be displayed with the
617 current setting of decimals.
618
619 \sa decimals
620*/
621double QDoubleSpinBox::value() const
622{
623 Q_D(const QDoubleSpinBox);
624
625 return d->value.toDouble();
626}
627
628void QDoubleSpinBox::setValue(double value)
629{
630 Q_D(QDoubleSpinBox);
631 QVariant v(d->round(value));
632 d->setValue(v, EmitIfChanged);
633}
634/*!
635 \property QDoubleSpinBox::prefix
636 \brief the spin box's prefix
637
638 The prefix is prepended to the start of the displayed value.
639 Typical use is to display a unit of measurement or a currency
640 symbol. For example:
641
642 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 4
643
644 To turn off the prefix display, set this property to an empty
645 string. The default is no prefix. The prefix is not displayed when
646 value() == minimum() and specialValueText() is set.
647
648 If no prefix is set, prefix() returns an empty string.
649
650 \sa suffix(), setSuffix(), specialValueText(), setSpecialValueText()
651*/
652
653QString QDoubleSpinBox::prefix() const
654{
655 Q_D(const QDoubleSpinBox);
656
657 return d->prefix;
658}
659
660void QDoubleSpinBox::setPrefix(const QString &prefix)
661{
662 Q_D(QDoubleSpinBox);
663
664 d->prefix = prefix;
665 d->updateEdit();
666}
667
668/*!
669 \property QDoubleSpinBox::suffix
670 \brief the suffix of the spin box
671
672 The suffix is appended to the end of the displayed value. Typical
673 use is to display a unit of measurement or a currency symbol. For
674 example:
675
676 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 5
677
678 To turn off the suffix display, set this property to an empty
679 string. The default is no suffix. The suffix is not displayed for
680 the minimum() if specialValueText() is set.
681
682 If no suffix is set, suffix() returns an empty string.
683
684 \sa prefix(), setPrefix(), specialValueText(), setSpecialValueText()
685*/
686
687QString QDoubleSpinBox::suffix() const
688{
689 Q_D(const QDoubleSpinBox);
690
691 return d->suffix;
692}
693
694void QDoubleSpinBox::setSuffix(const QString &suffix)
695{
696 Q_D(QDoubleSpinBox);
697
698 d->suffix = suffix;
699 d->updateEdit();
700}
701
702/*!
703 \property QDoubleSpinBox::cleanText
704
705 \brief the text of the spin box excluding any prefix, suffix,
706 or leading or trailing whitespace.
707
708 \sa text, QDoubleSpinBox::prefix, QDoubleSpinBox::suffix
709*/
710
711QString QDoubleSpinBox::cleanText() const
712{
713 Q_D(const QDoubleSpinBox);
714
715 return d->stripped(d->edit->displayText());
716}
717
718/*!
719 \property QDoubleSpinBox::singleStep
720 \brief the step value
721
722 When the user uses the arrows to change the spin box's value the
723 value will be incremented/decremented by the amount of the
724 singleStep. The default value is 1.0. Setting a singleStep value
725 of less than 0 does nothing.
726*/
727double QDoubleSpinBox::singleStep() const
728{
729 Q_D(const QDoubleSpinBox);
730
731 return d->singleStep.toDouble();
732}
733
734void QDoubleSpinBox::setSingleStep(double value)
735{
736 Q_D(QDoubleSpinBox);
737
738 if (value >= 0) {
739 d->singleStep = value;
740 d->updateEdit();
741 }
742}
743
744/*!
745 \property QDoubleSpinBox::minimum
746
747 \brief the minimum value of the spin box
748
749 When setting this property the \l maximum is adjusted
750 if necessary to ensure that the range remains valid.
751
752 The default minimum value is 0.0.
753
754 Note: The minimum value will be rounded to match the decimals
755 property.
756
757 \sa decimals, setRange() specialValueText
758*/
759
760double QDoubleSpinBox::minimum() const
761{
762 Q_D(const QDoubleSpinBox);
763
764 return d->minimum.toDouble();
765}
766
767void QDoubleSpinBox::setMinimum(double minimum)
768{
769 Q_D(QDoubleSpinBox);
770 d->actualMin = minimum;
771 const QVariant m(d->round(minimum));
772 d->setRange(m, (d->variantCompare(d->maximum, m) > 0 ? d->maximum : m));
773}
774
775/*!
776 \property QDoubleSpinBox::maximum
777
778 \brief the maximum value of the spin box
779
780 When setting this property the \l minimum is adjusted
781 if necessary, to ensure that the range remains valid.
782
783 The default maximum value is 99.99.
784
785 Note: The maximum value will be rounded to match the decimals
786 property.
787
788 \sa decimals, setRange()
789*/
790
791double QDoubleSpinBox::maximum() const
792{
793 Q_D(const QDoubleSpinBox);
794
795 return d->maximum.toDouble();
796}
797
798void QDoubleSpinBox::setMaximum(double maximum)
799{
800 Q_D(QDoubleSpinBox);
801 d->actualMax = maximum;
802 const QVariant m(d->round(maximum));
803 d->setRange((d->variantCompare(d->minimum, m) < 0 ? d->minimum : m), m);
804}
805
806/*!
807 Convenience function to set the \a minimum and \a maximum values
808 with a single function call.
809
810 Note: The maximum and minimum values will be rounded to match the
811 decimals property.
812
813 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 6
814 is equivalent to:
815 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 7
816
817 \sa minimum maximum
818*/
819
820void QDoubleSpinBox::setRange(double minimum, double maximum)
821{
822 Q_D(QDoubleSpinBox);
823 d->actualMin = minimum;
824 d->actualMax = maximum;
825 d->setRange(QVariant(d->round(minimum)), QVariant(d->round(maximum)));
826}
827
828/*!
829 \property QDoubleSpinBox::decimals
830
831 \brief the precision of the spin box, in decimals
832
833 Sets how many decimals the spinbox will use for displaying and
834 interpreting doubles.
835
836 \warning The maximum value for \a decimals is DBL_MAX_10_EXP +
837 DBL_DIG (ie. 323) because of the limitations of the double type.
838
839 Note: The maximum, minimum and value might change as a result of
840 changing this property.
841*/
842
843int QDoubleSpinBox::decimals() const
844{
845 Q_D(const QDoubleSpinBox);
846
847 return d->decimals;
848}
849
850void QDoubleSpinBox::setDecimals(int decimals)
851{
852 Q_D(QDoubleSpinBox);
853 d->decimals = qBound(0, decimals, DBL_MAX_10_EXP + DBL_DIG);
854
855 setRange(d->actualMin, d->actualMax); // make sure values are rounded
856 setValue(value());
857}
858
859/*!
860 This virtual function is used by the spin box whenever it needs to
861 display the given \a value. The default implementation returns a string
862 containing \a value printed using QWidget::locale().toString(\a value,
863 QLatin1Char('f'), decimals()) and will remove the thousand
864 separator. Reimplementations may return anything.
865
866 Note: QDoubleSpinBox does not call this function for
867 specialValueText() and that neither prefix() nor suffix() should
868 be included in the return value.
869
870 If you reimplement this, you may also need to reimplement
871 valueFromText().
872
873 \sa valueFromText(), QLocale::groupSeparator()
874*/
875
876
877QString QDoubleSpinBox::textFromValue(double value) const
878{
879 Q_D(const QDoubleSpinBox);
880 QString str = locale().toString(value, 'f', d->decimals);
881 if (qAbs(value) >= 1000.0) {
882 str.remove(locale().groupSeparator());
883 }
884 return str;
885}
886
887/*!
888 This virtual function is used by the spin box whenever it needs to
889 interpret \a text entered by the user as a value.
890
891 Subclasses that need to display spin box values in a non-numeric
892 way need to reimplement this function.
893
894 Note: QDoubleSpinBox handles specialValueText() separately; this
895 function is only concerned with the other values.
896
897 \sa textFromValue(), validate()
898*/
899double QDoubleSpinBox::valueFromText(const QString &text) const
900{
901 Q_D(const QDoubleSpinBox);
902
903 QString copy = text;
904 int pos = d->edit->cursorPosition();
905 QValidator::State state = QValidator::Acceptable;
906 return d->validateAndInterpret(copy, pos, state).toDouble();
907}
908
909/*!
910 \reimp
911*/
912QValidator::State QDoubleSpinBox::validate(QString &text, int &pos) const
913{
914 Q_D(const QDoubleSpinBox);
915
916 QValidator::State state;
917 d->validateAndInterpret(text, pos, state);
918 return state;
919}
920
921
922/*!
923 \reimp
924*/
925void QDoubleSpinBox::fixup(QString &input) const
926{
927 input.remove(locale().groupSeparator());
928}
929
930// --- QSpinBoxPrivate ---
931
932/*!
933 \internal
934 Constructs a QSpinBoxPrivate object
935*/
936
937QSpinBoxPrivate::QSpinBoxPrivate()
938{
939 minimum = QVariant((int)0);
940 maximum = QVariant((int)99);
941 value = minimum;
942 singleStep = QVariant((int)1);
943 type = QVariant::Int;
944}
945
946/*!
947 \internal
948 \reimp
949*/
950
951void QSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
952{
953 Q_Q(QSpinBox);
954 if (ep != NeverEmit) {
955 pendingEmit = false;
956 if (ep == AlwaysEmit || value != old) {
957 emit q->valueChanged(edit->displayText());
958 emit q->valueChanged(value.toInt());
959 }
960 }
961}
962
963/*!
964 \internal
965 \reimp
966*/
967
968QString QSpinBoxPrivate::textFromValue(const QVariant &value) const
969{
970 Q_Q(const QSpinBox);
971 return q->textFromValue(value.toInt());
972}
973/*!
974 \internal
975 \reimp
976*/
977
978QVariant QSpinBoxPrivate::valueFromText(const QString &text) const
979{
980 Q_Q(const QSpinBox);
981
982 return QVariant(q->valueFromText(text));
983}
984
985
986/*!
987 \internal Multi purpose function that parses input, sets state to
988 the appropriate state and returns the value it will be interpreted
989 as.
990*/
991
992QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
993 QValidator::State &state) const
994{
995 if (cachedText == input && !input.isEmpty()) {
996 state = cachedState;
997 QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
998 << state << " and value was " << cachedValue;
999
1000 return cachedValue;
1001 }
1002 const int max = maximum.toInt();
1003 const int min = minimum.toInt();
1004
1005 QString copy = stripped(input, &pos);
1006 QSBDEBUG() << "input" << input << "copy" << copy;
1007 state = QValidator::Acceptable;
1008 int num = min;
1009
1010 if (max != min && (copy.isEmpty()
1011 || (min < 0 && copy == QLatin1String("-"))
1012 || (min >= 0 && copy == QLatin1String("+")))) {
1013 state = QValidator::Intermediate;
1014 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
1015 } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) {
1016 state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100
1017 } else {
1018 bool ok = false;
1019 num = locale.toInt(copy, &ok, 10);
1020 if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) {
1021 QString copy2 = copy;
1022 copy2.remove(locale.groupSeparator());
1023 num = locale.toInt(copy2, &ok, 10);
1024 }
1025 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
1026 if (!ok) {
1027 state = QValidator::Invalid;
1028 } else if (num >= min && num <= max) {
1029 state = QValidator::Acceptable;
1030 } else if (max == min) {
1031 state = QValidator::Invalid;
1032 } else {
1033 if ((num >= 0 && num > max) || (num < 0 && num < min)) {
1034 state = QValidator::Invalid;
1035 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1036 } else {
1037 state = QValidator::Intermediate;
1038 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate";
1039 }
1040 }
1041 }
1042 if (state != QValidator::Acceptable)
1043 num = max > 0 ? min : max;
1044 input = prefix + copy + suffix;
1045 cachedText = input;
1046 cachedState = state;
1047 cachedValue = QVariant((int)num);
1048
1049 QSBDEBUG() << "cachedText is set to '" << cachedText << "' state is set to "
1050 << state << " and value is set to " << cachedValue;
1051 return cachedValue;
1052}
1053
1054// --- QDoubleSpinBoxPrivate ---
1055
1056/*!
1057 \internal
1058 Constructs a QSpinBoxPrivate object
1059*/
1060
1061QDoubleSpinBoxPrivate::QDoubleSpinBoxPrivate()
1062{
1063 actualMin = 0.0;
1064 actualMax = 99.99;
1065 minimum = QVariant(actualMin);
1066 maximum = QVariant(actualMax);
1067 value = minimum;
1068 singleStep = QVariant(1.0);
1069 decimals = 2;
1070 type = QVariant::Double;
1071}
1072
1073/*!
1074 \internal
1075 \reimp
1076*/
1077
1078void QDoubleSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
1079{
1080 Q_Q(QDoubleSpinBox);
1081 if (ep != NeverEmit) {
1082 pendingEmit = false;
1083 if (ep == AlwaysEmit || value != old) {
1084 emit q->valueChanged(edit->displayText());
1085 emit q->valueChanged(value.toDouble());
1086 }
1087 }
1088}
1089
1090
1091/*!
1092 \internal
1093 \reimp
1094*/
1095QVariant QDoubleSpinBoxPrivate::valueFromText(const QString &f) const
1096{
1097 Q_Q(const QDoubleSpinBox);
1098 return QVariant(q->valueFromText(f));
1099}
1100
1101/*!
1102 \internal
1103 Rounds to a double value that is restricted to decimals.
1104 E.g. // decimals = 2
1105
1106 round(5.555) => 5.56
1107 */
1108
1109double QDoubleSpinBoxPrivate::round(double value) const
1110{
1111 return QString::number(value, 'f', decimals).toDouble();
1112}
1113
1114
1115/*!
1116 \internal Multi purpose function that parses input, sets state to
1117 the appropriate state and returns the value it will be interpreted
1118 as.
1119*/
1120
1121QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
1122 QValidator::State &state) const
1123{
1124 if (cachedText == input && !input.isEmpty()) {
1125 state = cachedState;
1126 QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
1127 << state << " and value was " << cachedValue;
1128 return cachedValue;
1129 }
1130 const double max = maximum.toDouble();
1131 const double min = minimum.toDouble();
1132
1133 QString copy = stripped(input, &pos);
1134 QSBDEBUG() << "input" << input << "copy" << copy;
1135 int len = copy.size();
1136 double num = min;
1137 const bool plus = max >= 0;
1138 const bool minus = min <= 0;
1139
1140 switch (len) {
1141 case 0:
1142 state = max != min ? QValidator::Intermediate : QValidator::Invalid;
1143 goto end;
1144 case 1:
1145 if (copy.at(0) == locale.decimalPoint()
1146 || (plus && copy.at(0) == QLatin1Char('+'))
1147 || (minus && copy.at(0) == QLatin1Char('-'))) {
1148 state = QValidator::Intermediate;
1149 goto end;
1150 }
1151 break;
1152 case 2:
1153 if (copy.at(1) == locale.decimalPoint()
1154 && ((plus && copy.at(0) == QLatin1Char('+')) || (minus && copy.at(0) == QLatin1Char('-')))) {
1155 state = QValidator::Intermediate;
1156 goto end;
1157 }
1158 break;
1159 default: break;
1160 }
1161
1162 if (copy.at(0) == locale.groupSeparator()) {
1163 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1164 state = QValidator::Invalid;
1165 goto end;
1166 } else if (len > 1) {
1167 const int dec = copy.indexOf(locale.decimalPoint());
1168 if (dec != -1) {
1169 if (dec + 1 < copy.size() && copy.at(dec + 1) == locale.decimalPoint() && pos == dec + 1) {
1170 copy.remove(dec + 1, 1); // typing a delimiter when you are on the delimiter
1171 } // should be treated as typing right arrow
1172
1173 if (copy.size() - dec > decimals + 1) {
1174 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1175 state = QValidator::Invalid;
1176 goto end;
1177 }
1178 for (int i=dec + 1; i<copy.size(); ++i) {
1179 if (copy.at(i).isSpace() || copy.at(i) == locale.groupSeparator()) {
1180 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1181 state = QValidator::Invalid;
1182 goto end;
1183 }
1184 }
1185 } else {
1186 const QChar &last = copy.at(len - 1);
1187 const QChar &secondLast = copy.at(len - 2);
1188 if ((last == locale.groupSeparator() || last.isSpace())
1189 && (secondLast == locale.groupSeparator() || secondLast.isSpace())) {
1190 state = QValidator::Invalid;
1191 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1192 goto end;
1193 } else if (last.isSpace() && (!locale.groupSeparator().isSpace() || secondLast.isSpace())) {
1194 state = QValidator::Invalid;
1195 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1196 goto end;
1197 }
1198 }
1199 }
1200
1201 {
1202 bool ok = false;
1203 num = locale.toDouble(copy, &ok);
1204 QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok;
1205
1206 if (!ok) {
1207 if (locale.groupSeparator().isPrint()) {
1208 if (max < 1000 && min > -1000 && copy.contains(locale.groupSeparator())) {
1209 state = QValidator::Invalid;
1210 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1211 goto end;
1212 }
1213
1214 const int len = copy.size();
1215 for (int i=0; i<len- 1; ++i) {
1216 if (copy.at(i) == locale.groupSeparator() && copy.at(i + 1) == locale.groupSeparator()) {
1217 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1218 state = QValidator::Invalid;
1219 goto end;
1220 }
1221 }
1222
1223 QString copy2 = copy;
1224 copy2.remove(locale.groupSeparator());
1225 num = locale.toDouble(copy2, &ok);
1226 QSBDEBUG() << locale.groupSeparator() << num << copy2 << ok;
1227
1228 if (!ok) {
1229 state = QValidator::Invalid;
1230 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1231 goto end;
1232 }
1233 }
1234 }
1235
1236 if (!ok) {
1237 state = QValidator::Invalid;
1238 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1239 } else if (num >= min && num <= max) {
1240 state = QValidator::Acceptable;
1241 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Acceptable";
1242 } else if (max == min) { // when max and min is the same the only non-Invalid input is max (or min)
1243 state = QValidator::Invalid;
1244 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1245 } else {
1246 if ((num >= 0 && num > max) || (num < 0 && num < min)) {
1247 state = QValidator::Invalid;
1248 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1249 } else {
1250 state = QValidator::Intermediate;
1251 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate";
1252 }
1253 }
1254 }
1255
1256end:
1257 if (state != QValidator::Acceptable) {
1258 num = max > 0 ? min : max;
1259 }
1260
1261 input = prefix + copy + suffix;
1262 cachedText = input;
1263 cachedState = state;
1264 cachedValue = QVariant(num);
1265 return QVariant(num);
1266}
1267
1268/*
1269 \internal
1270 \reimp
1271*/
1272
1273QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const
1274{
1275 Q_Q(const QDoubleSpinBox);
1276 return q->textFromValue(f.toDouble());
1277}
1278
1279/*!
1280 \fn void QSpinBox::setLineStep(int step)
1281
1282 Use setSingleStep() instead.
1283*/
1284
1285/*!
1286 \fn void QSpinBox::setMaxValue(int value)
1287
1288 Use setMaximum() instead.
1289*/
1290
1291/*!
1292 \fn void QSpinBox::setMinValue(int value)
1293
1294 Use setMinimum() instead.
1295*/
1296
1297/*!
1298 \fn int QSpinBox::maxValue() const
1299
1300 Use maximum() instead.
1301*/
1302
1303/*!
1304 \fn int QSpinBox::minValue() const
1305
1306 Use minimum() instead.
1307*/
1308
1309/*! \reimp */
1310bool QSpinBox::event(QEvent *event)
1311{
1312 Q_D(QSpinBox);
1313 if (event->type() == QEvent::StyleChange
1314#ifdef Q_WS_MAC
1315 || event->type() == QEvent::MacSizeChange
1316#endif
1317 )
1318 d->setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem);
1319 return QAbstractSpinBox::event(event);
1320}
1321
1322QT_END_NAMESPACE
1323
1324#endif // QT_NO_SPINBOX
Note: See TracBrowser for help on using the repository browser.