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

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

trunk: Merged in qt 4.6.2 sources.

File size: 36.7 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 <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
452 to display the given \a value. The default implementation returns
453 a string containing \a value printed in the standard way using
454 QWidget::locale().toString(). Reimplementations may return anything. (See
455 the example in the detailed description.)
456
457 Note: QSpinBox does not call this function for specialValueText()
458 and that neither prefix() nor suffix() should be included in the
459 return value.
460
461 If you reimplement this, you may also need to reimplement
462 valueFromText() and validate()
463
464 \sa valueFromText(), validate()
465*/
466
467QString QSpinBox::textFromValue(int value) const
468{
469 QString str = locale().toString(value);
470 if (qAbs(value) >= 1000 || value == INT_MIN) {
471 str.remove(locale().groupSeparator());
472 }
473
474 return str;
475}
476
477/*!
478 \fn int QSpinBox::valueFromText(const QString &text) const
479
480 This virtual function is used by the spin box whenever it needs to
481 interpret \a text entered by the user as a value.
482
483 Subclasses that need to display spin box values in a non-numeric
484 way need to reimplement this function.
485
486 Note: QSpinBox handles specialValueText() separately; this
487 function is only concerned with the other values.
488
489 \sa textFromValue(), validate()
490*/
491
492int QSpinBox::valueFromText(const QString &text) const
493{
494 Q_D(const QSpinBox);
495
496 QString copy = text;
497 int pos = d->edit->cursorPosition();
498 QValidator::State state = QValidator::Acceptable;
499 return d->validateAndInterpret(copy, pos, state).toInt();
500}
501
502/*!
503 \reimp
504*/
505QValidator::State QSpinBox::validate(QString &text, int &pos) const
506{
507 Q_D(const QSpinBox);
508
509 QValidator::State state;
510 d->validateAndInterpret(text, pos, state);
511 return state;
512}
513
514
515/*!
516 \reimp
517*/
518void QSpinBox::fixup(QString &input) const
519{
520 input.remove(locale().groupSeparator());
521}
522
523
524// --- QDoubleSpinBox ---
525
526/*!
527 \class QDoubleSpinBox
528 \brief The QDoubleSpinBox class provides a spin box widget that
529 takes doubles.
530
531 \ingroup basicwidgets
532
533
534 QDoubleSpinBox allows the user to choose a value by clicking the
535 up and down buttons or by pressing Up or Down on the keyboard to
536 increase or decrease the value currently displayed. The user can
537 also type the value in manually. The spin box supports double
538 values but can be extended to use different strings with
539 validate(), textFromValue() and valueFromText().
540
541 Every time the value changes QDoubleSpinBox emits the
542 valueChanged() signal. The current value can be fetched with
543 value() and set with setValue().
544
545 Note: QDoubleSpinBox will round numbers so they can be displayed
546 with the current precision. In a QDoubleSpinBox with decimals set
547 to 2, calling setValue(2.555) will cause value() to return 2.56.
548
549 Clicking the up and down buttons or using the keyboard accelerator's
550 Up and Down arrows will increase or decrease the current value in
551 steps of size singleStep(). If you want to change this behavior you
552 can reimplement the virtual function stepBy(). The minimum and
553 maximum value and the step size can be set using one of the
554 constructors, and can be changed later with setMinimum(),
555 setMaximum() and setSingleStep(). The spinbox has a default
556 precision of 2 decimal places but this can be changed using
557 setDecimals().
558
559 Most spin boxes are directional, but QDoubleSpinBox can also
560 operate as a circular spin box, i.e. if the range is 0.0-99.9 and
561 the current value is 99.9, clicking "up" will give 0 if wrapping()
562 is set to true. Use setWrapping() if you want circular behavior.
563
564 The displayed value can be prepended and appended with arbitrary
565 strings indicating, for example, currency or the unit of
566 measurement. See setPrefix() and setSuffix(). The text in the spin
567 box is retrieved with text() (which includes any prefix() and
568 suffix()), or with cleanText() (which has no prefix(), no suffix()
569 and no leading or trailing whitespace).
570
571 It is often desirable to give the user a special (often default)
572 choice in addition to the range of numeric values. See
573 setSpecialValueText() for how to do this with QDoubleSpinBox.
574
575 \sa QSpinBox, QDateTimeEdit, QSlider, {Spin Boxes Example}
576*/
577
578/*!
579 \fn void QDoubleSpinBox::valueChanged(double d);
580
581 This signal is emitted whenever the spin box's value is changed.
582 The new value is passed in \a d.
583*/
584
585/*!
586 \fn void QDoubleSpinBox::valueChanged(const QString &text);
587
588 \overload
589
590 The new value is passed literally in \a text with no prefix() or
591 suffix().
592*/
593
594/*!
595 Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
596 a step value of 1.0 and a precision of 2 decimal places. The value is
597 initially set to 0.00. The spin box has the given \a parent.
598
599 \sa setMinimum(), setMaximum(), setSingleStep()
600*/
601QDoubleSpinBox::QDoubleSpinBox(QWidget *parent)
602 : QAbstractSpinBox(*new QDoubleSpinBoxPrivate, parent)
603{
604 Q_D(QDoubleSpinBox);
605 d->init();
606}
607
608/*!
609 \property QDoubleSpinBox::value
610 \brief the value of the spin box
611
612 setValue() will emit valueChanged() if the new value is different
613 from the old one.
614
615 Note: The value will be rounded so it can be displayed with the
616 current setting of decimals.
617
618 \sa decimals
619*/
620double QDoubleSpinBox::value() const
621{
622 Q_D(const QDoubleSpinBox);
623
624 return d->value.toDouble();
625}
626
627void QDoubleSpinBox::setValue(double value)
628{
629 Q_D(QDoubleSpinBox);
630 QVariant v(d->round(value));
631 d->setValue(v, EmitIfChanged);
632}
633/*!
634 \property QDoubleSpinBox::prefix
635 \brief the spin box's prefix
636
637 The prefix is prepended to the start of the displayed value.
638 Typical use is to display a unit of measurement or a currency
639 symbol. For example:
640
641 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 4
642
643 To turn off the prefix display, set this property to an empty
644 string. The default is no prefix. The prefix is not displayed when
645 value() == minimum() and specialValueText() is set.
646
647 If no prefix is set, prefix() returns an empty string.
648
649 \sa suffix(), setSuffix(), specialValueText(), setSpecialValueText()
650*/
651
652QString QDoubleSpinBox::prefix() const
653{
654 Q_D(const QDoubleSpinBox);
655
656 return d->prefix;
657}
658
659void QDoubleSpinBox::setPrefix(const QString &prefix)
660{
661 Q_D(QDoubleSpinBox);
662
663 d->prefix = prefix;
664 d->updateEdit();
665}
666
667/*!
668 \property QDoubleSpinBox::suffix
669 \brief the suffix of the spin box
670
671 The suffix is appended to the end of the displayed value. Typical
672 use is to display a unit of measurement or a currency symbol. For
673 example:
674
675 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 5
676
677 To turn off the suffix display, set this property to an empty
678 string. The default is no suffix. The suffix is not displayed for
679 the minimum() if specialValueText() is set.
680
681 If no suffix is set, suffix() returns an empty string.
682
683 \sa prefix(), setPrefix(), specialValueText(), setSpecialValueText()
684*/
685
686QString QDoubleSpinBox::suffix() const
687{
688 Q_D(const QDoubleSpinBox);
689
690 return d->suffix;
691}
692
693void QDoubleSpinBox::setSuffix(const QString &suffix)
694{
695 Q_D(QDoubleSpinBox);
696
697 d->suffix = suffix;
698 d->updateEdit();
699}
700
701/*!
702 \property QDoubleSpinBox::cleanText
703
704 \brief the text of the spin box excluding any prefix, suffix,
705 or leading or trailing whitespace.
706
707 \sa text, QDoubleSpinBox::prefix, QDoubleSpinBox::suffix
708*/
709
710QString QDoubleSpinBox::cleanText() const
711{
712 Q_D(const QDoubleSpinBox);
713
714 return d->stripped(d->edit->displayText());
715}
716
717/*!
718 \property QDoubleSpinBox::singleStep
719 \brief the step value
720
721 When the user uses the arrows to change the spin box's value the
722 value will be incremented/decremented by the amount of the
723 singleStep. The default value is 1.0. Setting a singleStep value
724 of less than 0 does nothing.
725*/
726double QDoubleSpinBox::singleStep() const
727{
728 Q_D(const QDoubleSpinBox);
729
730 return d->singleStep.toDouble();
731}
732
733void QDoubleSpinBox::setSingleStep(double value)
734{
735 Q_D(QDoubleSpinBox);
736
737 if (value >= 0) {
738 d->singleStep = value;
739 d->updateEdit();
740 }
741}
742
743/*!
744 \property QDoubleSpinBox::minimum
745
746 \brief the minimum value of the spin box
747
748 When setting this property the \l maximum is adjusted
749 if necessary to ensure that the range remains valid.
750
751 The default minimum value is 0.0.
752
753 Note: The minimum value will be rounded to match the decimals
754 property.
755
756 \sa decimals, setRange() specialValueText
757*/
758
759double QDoubleSpinBox::minimum() const
760{
761 Q_D(const QDoubleSpinBox);
762
763 return d->minimum.toDouble();
764}
765
766void QDoubleSpinBox::setMinimum(double minimum)
767{
768 Q_D(QDoubleSpinBox);
769 d->actualMin = minimum;
770 const QVariant m(d->round(minimum));
771 d->setRange(m, (d->variantCompare(d->maximum, m) > 0 ? d->maximum : m));
772}
773
774/*!
775 \property QDoubleSpinBox::maximum
776
777 \brief the maximum value of the spin box
778
779 When setting this property the \l minimum is adjusted
780 if necessary, to ensure that the range remains valid.
781
782 The default maximum value is 99.99.
783
784 Note: The maximum value will be rounded to match the decimals
785 property.
786
787 \sa decimals, setRange()
788*/
789
790double QDoubleSpinBox::maximum() const
791{
792 Q_D(const QDoubleSpinBox);
793
794 return d->maximum.toDouble();
795}
796
797void QDoubleSpinBox::setMaximum(double maximum)
798{
799 Q_D(QDoubleSpinBox);
800 d->actualMax = maximum;
801 const QVariant m(d->round(maximum));
802 d->setRange((d->variantCompare(d->minimum, m) < 0 ? d->minimum : m), m);
803}
804
805/*!
806 Convenience function to set the \a minimum and \a maximum values
807 with a single function call.
808
809 Note: The maximum and minimum values will be rounded to match the
810 decimals property.
811
812 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 6
813 is equivalent to:
814 \snippet doc/src/snippets/code/src_gui_widgets_qspinbox.cpp 7
815
816 \sa minimum maximum
817*/
818
819void QDoubleSpinBox::setRange(double minimum, double maximum)
820{
821 Q_D(QDoubleSpinBox);
822 d->actualMin = minimum;
823 d->actualMax = maximum;
824 d->setRange(QVariant(d->round(minimum)), QVariant(d->round(maximum)));
825}
826
827/*!
828 \property QDoubleSpinBox::decimals
829
830 \brief the precision of the spin box, in decimals
831
832 Sets how many decimals the spinbox will use for displaying and
833 interpreting doubles.
834
835 \warning The maximum value for \a decimals is DBL_MAX_10_EXP +
836 DBL_DIG (ie. 323) because of the limitations of the double type.
837
838 Note: The maximum, minimum and value might change as a result of
839 changing this property.
840*/
841
842int QDoubleSpinBox::decimals() const
843{
844 Q_D(const QDoubleSpinBox);
845
846 return d->decimals;
847}
848
849void QDoubleSpinBox::setDecimals(int decimals)
850{
851 Q_D(QDoubleSpinBox);
852 d->decimals = qBound(0, decimals, DBL_MAX_10_EXP + DBL_DIG);
853
854 setRange(d->actualMin, d->actualMax); // make sure values are rounded
855 setValue(value());
856}
857
858/*!
859 This virtual function is used by the spin box whenever it needs to
860 display the given \a value. The default implementation returns a string
861 containing \a value printed using QWidget::locale().toString(\a value,
862 QLatin1Char('f'), decimals()) and will remove the thousand
863 separator. Reimplementations may return anything.
864
865 Note: QDoubleSpinBox does not call this function for
866 specialValueText() and that neither prefix() nor suffix() should
867 be included in the return value.
868
869 If you reimplement this, you may also need to reimplement
870 valueFromText().
871
872 \sa valueFromText()
873*/
874
875
876QString QDoubleSpinBox::textFromValue(double value) const
877{
878 Q_D(const QDoubleSpinBox);
879 QString str = locale().toString(value, 'f', d->decimals);
880 if (qAbs(value) >= 1000.0) {
881 str.remove(locale().groupSeparator());
882 }
883 return str;
884}
885
886/*!
887 This virtual function is used by the spin box whenever it needs to
888 interpret \a text entered by the user as a value.
889
890 Subclasses that need to display spin box values in a non-numeric
891 way need to reimplement this function.
892
893 Note: QDoubleSpinBox handles specialValueText() separately; this
894 function is only concerned with the other values.
895
896 \sa textFromValue(), validate()
897*/
898double QDoubleSpinBox::valueFromText(const QString &text) const
899{
900 Q_D(const QDoubleSpinBox);
901
902 QString copy = text;
903 int pos = d->edit->cursorPosition();
904 QValidator::State state = QValidator::Acceptable;
905 return d->validateAndInterpret(copy, pos, state).toDouble();
906}
907
908/*!
909 \reimp
910*/
911QValidator::State QDoubleSpinBox::validate(QString &text, int &pos) const
912{
913 Q_D(const QDoubleSpinBox);
914
915 QValidator::State state;
916 d->validateAndInterpret(text, pos, state);
917 return state;
918}
919
920
921/*!
922 \reimp
923*/
924void QDoubleSpinBox::fixup(QString &input) const
925{
926 input.remove(locale().groupSeparator());
927}
928
929// --- QSpinBoxPrivate ---
930
931/*!
932 \internal
933 Constructs a QSpinBoxPrivate object
934*/
935
936QSpinBoxPrivate::QSpinBoxPrivate()
937{
938 minimum = QVariant((int)0);
939 maximum = QVariant((int)99);
940 value = minimum;
941 singleStep = QVariant((int)1);
942 type = QVariant::Int;
943}
944
945/*!
946 \internal
947 \reimp
948*/
949
950void QSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
951{
952 Q_Q(QSpinBox);
953 if (ep != NeverEmit) {
954 pendingEmit = false;
955 if (ep == AlwaysEmit || value != old) {
956 emit q->valueChanged(edit->displayText());
957 emit q->valueChanged(value.toInt());
958 }
959 }
960}
961
962/*!
963 \internal
964 \reimp
965*/
966
967QString QSpinBoxPrivate::textFromValue(const QVariant &value) const
968{
969 Q_Q(const QSpinBox);
970 return q->textFromValue(value.toInt());
971}
972/*!
973 \internal
974 \reimp
975*/
976
977QVariant QSpinBoxPrivate::valueFromText(const QString &text) const
978{
979 Q_Q(const QSpinBox);
980
981 return QVariant(q->valueFromText(text));
982}
983
984
985/*!
986 \internal Multi purpose function that parses input, sets state to
987 the appropriate state and returns the value it will be interpreted
988 as.
989*/
990
991QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
992 QValidator::State &state) const
993{
994 if (cachedText == input && !input.isEmpty()) {
995 state = cachedState;
996 QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
997 << state << " and value was " << cachedValue;
998
999 return cachedValue;
1000 }
1001 const int max = maximum.toInt();
1002 const int min = minimum.toInt();
1003
1004 QString copy = stripped(input, &pos);
1005 QSBDEBUG() << "input" << input << "copy" << copy;
1006 state = QValidator::Acceptable;
1007 int num = min;
1008
1009 if (max != min && (copy.isEmpty()
1010 || (min < 0 && copy == QLatin1String("-"))
1011 || (min >= 0 && copy == QLatin1String("+")))) {
1012 state = QValidator::Intermediate;
1013 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
1014 } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) {
1015 state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100
1016 } else {
1017 bool ok = false;
1018 num = locale.toInt(copy, &ok, 10);
1019 if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) {
1020 QString copy2 = copy;
1021 copy2.remove(locale.groupSeparator());
1022 num = locale.toInt(copy2, &ok, 10);
1023 }
1024 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
1025 if (!ok) {
1026 state = QValidator::Invalid;
1027 } else if (num >= min && num <= max) {
1028 state = QValidator::Acceptable;
1029 } else if (max == min) {
1030 state = QValidator::Invalid;
1031 } else {
1032 if ((num >= 0 && num > max) || (num < 0 && num < min)) {
1033 state = QValidator::Invalid;
1034 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1035 } else {
1036 state = QValidator::Intermediate;
1037 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate";
1038 }
1039 }
1040 }
1041 if (state != QValidator::Acceptable)
1042 num = max > 0 ? min : max;
1043 input = prefix + copy + suffix;
1044 cachedText = input;
1045 cachedState = state;
1046 cachedValue = QVariant((int)num);
1047
1048 QSBDEBUG() << "cachedText is set to '" << cachedText << "' state is set to "
1049 << state << " and value is set to " << cachedValue;
1050 return cachedValue;
1051}
1052
1053// --- QDoubleSpinBoxPrivate ---
1054
1055/*!
1056 \internal
1057 Constructs a QSpinBoxPrivate object
1058*/
1059
1060QDoubleSpinBoxPrivate::QDoubleSpinBoxPrivate()
1061{
1062 actualMin = 0.0;
1063 actualMax = 99.99;
1064 minimum = QVariant(actualMin);
1065 maximum = QVariant(actualMax);
1066 value = minimum;
1067 singleStep = QVariant(1.0);
1068 decimals = 2;
1069 type = QVariant::Double;
1070}
1071
1072/*!
1073 \internal
1074 \reimp
1075*/
1076
1077void QDoubleSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
1078{
1079 Q_Q(QDoubleSpinBox);
1080 if (ep != NeverEmit) {
1081 pendingEmit = false;
1082 if (ep == AlwaysEmit || value != old) {
1083 emit q->valueChanged(edit->displayText());
1084 emit q->valueChanged(value.toDouble());
1085 }
1086 }
1087}
1088
1089
1090/*!
1091 \internal
1092 \reimp
1093*/
1094QVariant QDoubleSpinBoxPrivate::valueFromText(const QString &f) const
1095{
1096 Q_Q(const QDoubleSpinBox);
1097 return QVariant(q->valueFromText(f));
1098}
1099
1100/*!
1101 \internal
1102 Rounds to a double value that is restricted to decimals.
1103 E.g. // decimals = 2
1104
1105 round(5.555) => 5.56
1106 */
1107
1108double QDoubleSpinBoxPrivate::round(double value) const
1109{
1110 return QString::number(value, 'f', decimals).toDouble();
1111}
1112
1113
1114/*!
1115 \internal Multi purpose function that parses input, sets state to
1116 the appropriate state and returns the value it will be interpreted
1117 as.
1118*/
1119
1120QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
1121 QValidator::State &state) const
1122{
1123 if (cachedText == input && !input.isEmpty()) {
1124 state = cachedState;
1125 QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
1126 << state << " and value was " << cachedValue;
1127 return cachedValue;
1128 }
1129 const double max = maximum.toDouble();
1130 const double min = minimum.toDouble();
1131
1132 QString copy = stripped(input, &pos);
1133 QSBDEBUG() << "input" << input << "copy" << copy;
1134 int len = copy.size();
1135 double num = min;
1136 const bool plus = max >= 0;
1137 const bool minus = min <= 0;
1138
1139 switch (len) {
1140 case 0:
1141 state = max != min ? QValidator::Intermediate : QValidator::Invalid;
1142 goto end;
1143 case 1:
1144 if (copy.at(0) == locale.decimalPoint()
1145 || (plus && copy.at(0) == QLatin1Char('+'))
1146 || (minus && copy.at(0) == QLatin1Char('-'))) {
1147 state = QValidator::Intermediate;
1148 goto end;
1149 }
1150 break;
1151 case 2:
1152 if (copy.at(1) == locale.decimalPoint()
1153 && ((plus && copy.at(0) == QLatin1Char('+')) || (minus && copy.at(0) == QLatin1Char('-')))) {
1154 state = QValidator::Intermediate;
1155 goto end;
1156 }
1157 break;
1158 default: break;
1159 }
1160
1161 if (copy.at(0) == locale.groupSeparator()) {
1162 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1163 state = QValidator::Invalid;
1164 goto end;
1165 } else if (len > 1) {
1166 const int dec = copy.indexOf(locale.decimalPoint());
1167 if (dec != -1) {
1168 if (dec + 1 < copy.size() && copy.at(dec + 1) == locale.decimalPoint() && pos == dec + 1) {
1169 copy.remove(dec + 1, 1); // typing a delimiter when you are on the delimiter
1170 } // should be treated as typing right arrow
1171
1172 if (copy.size() - dec > decimals + 1) {
1173 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1174 state = QValidator::Invalid;
1175 goto end;
1176 }
1177 for (int i=dec + 1; i<copy.size(); ++i) {
1178 if (copy.at(i).isSpace() || copy.at(i) == locale.groupSeparator()) {
1179 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1180 state = QValidator::Invalid;
1181 goto end;
1182 }
1183 }
1184 } else {
1185 const QChar &last = copy.at(len - 1);
1186 const QChar &secondLast = copy.at(len - 2);
1187 if ((last == locale.groupSeparator() || last.isSpace())
1188 && (secondLast == locale.groupSeparator() || secondLast.isSpace())) {
1189 state = QValidator::Invalid;
1190 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1191 goto end;
1192 } else if (last.isSpace() && (!locale.groupSeparator().isSpace() || secondLast.isSpace())) {
1193 state = QValidator::Invalid;
1194 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1195 goto end;
1196 }
1197 }
1198 }
1199
1200 {
1201 bool ok = false;
1202 num = locale.toDouble(copy, &ok);
1203 QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok;
1204
1205 if (!ok) {
1206 if (locale.groupSeparator().isPrint()) {
1207 if (max < 1000 && min > -1000 && copy.contains(locale.groupSeparator())) {
1208 state = QValidator::Invalid;
1209 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1210 goto end;
1211 }
1212
1213 const int len = copy.size();
1214 for (int i=0; i<len- 1; ++i) {
1215 if (copy.at(i) == locale.groupSeparator() && copy.at(i + 1) == locale.groupSeparator()) {
1216 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1217 state = QValidator::Invalid;
1218 goto end;
1219 }
1220 }
1221
1222 QString copy2 = copy;
1223 copy2.remove(locale.groupSeparator());
1224 num = locale.toDouble(copy2, &ok);
1225 QSBDEBUG() << locale.groupSeparator() << num << copy2 << ok;
1226
1227 if (!ok) {
1228 state = QValidator::Invalid;
1229 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1230 goto end;
1231 }
1232 }
1233 }
1234
1235 if (!ok) {
1236 state = QValidator::Invalid;
1237 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1238 } else if (num >= min && num <= max) {
1239 state = QValidator::Acceptable;
1240 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Acceptable";
1241 } else if (max == min) { // when max and min is the same the only non-Invalid input is max (or min)
1242 state = QValidator::Invalid;
1243 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1244 } else {
1245 if ((num >= 0 && num > max) || (num < 0 && num < min)) {
1246 state = QValidator::Invalid;
1247 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
1248 } else {
1249 state = QValidator::Intermediate;
1250 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate";
1251 }
1252 }
1253 }
1254
1255end:
1256 if (state != QValidator::Acceptable) {
1257 num = max > 0 ? min : max;
1258 }
1259
1260 input = prefix + copy + suffix;
1261 cachedText = input;
1262 cachedState = state;
1263 cachedValue = QVariant(num);
1264 return QVariant(num);
1265}
1266
1267/*
1268 \internal
1269 \reimp
1270*/
1271
1272QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const
1273{
1274 Q_Q(const QDoubleSpinBox);
1275 return q->textFromValue(f.toDouble());
1276}
1277
1278/*!
1279 \fn void QSpinBox::setLineStep(int step)
1280
1281 Use setSingleStep() instead.
1282*/
1283
1284/*!
1285 \fn void QSpinBox::setMaxValue(int value)
1286
1287 Use setMaximum() instead.
1288*/
1289
1290/*!
1291 \fn void QSpinBox::setMinValue(int value)
1292
1293 Use setMinimum() instead.
1294*/
1295
1296/*!
1297 \fn int QSpinBox::maxValue() const
1298
1299 Use maximum() instead.
1300*/
1301
1302/*!
1303 \fn int QSpinBox::minValue() const
1304
1305 Use minimum() instead.
1306*/
1307
1308/*! \reimp */
1309bool QSpinBox::event(QEvent *event)
1310{
1311 Q_D(QSpinBox);
1312 if (event->type() == QEvent::StyleChange
1313#ifdef Q_WS_MAC
1314 || event->type() == QEvent::MacSizeChange
1315#endif
1316 )
1317 d->setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem);
1318 return QAbstractSpinBox::event(event);
1319}
1320
1321QT_END_NAMESPACE
1322
1323#endif // QT_NO_SPINBOX
Note: See TracBrowser for help on using the repository browser.