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

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

trunk: Merged in qt 4.6.1 sources.

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