1 /**********************************************************************
2 **
3 **
4 ** KIntValidator:
5 ** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com>
6 ** KDoubleValidator:
7 ** Copyright (c) 2002 Marc Mutz <mutz@kde.org>
8 **
9 ** This library is free software; you can redistribute it and/or
10 ** modify it under the terms of the GNU Library General Public
11 ** License as published by the Free Software Foundation; either
12 ** version 2 of the License, or (at your option) any later version.
13 **
14 ** This library is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ** Library General Public License for more details.
18 **
19 ** You should have received a copy of the GNU Library General Public
20 ** License along with this library; if not, write to the Free
21 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 **
23 *****************************************************************************/
24
25 #include "knumvalidator.h"
26
27 #include <QWidget>
28 #include <QCharRef>
29
30 #include <klocale.h>
31 #include <kdebug.h>
32
33 ///////////////////////////////////////////////////////////////
34 // Implementation of KIntValidator
35 //
36 class Q_DECL_HIDDEN KIntValidator::KIntValidatorPrivate
37 {
38 public:
KIntValidatorPrivate()39 KIntValidatorPrivate()
40 : _base(0), _min(0), _max(0)
41 {}
42 int _base;
43 int _min;
44 int _max;
45 };
46
KIntValidator(QWidget * parent,int base)47 KIntValidator::KIntValidator(QWidget *parent, int base)
48 : QValidator(parent), d(new KIntValidatorPrivate)
49 {
50 setBase(base);
51 }
52
KIntValidator(int bottom,int top,QWidget * parent,int base)53 KIntValidator::KIntValidator(int bottom, int top, QWidget *parent, int base)
54 : QValidator(parent), d(new KIntValidatorPrivate)
55 {
56 setBase(base);
57 setRange(bottom, top);
58 }
59
~KIntValidator()60 KIntValidator::~KIntValidator()
61 {
62 delete d;
63 }
64
validate(QString & str,int &) const65 QValidator::State KIntValidator::validate(QString &str, int &) const
66 {
67 bool ok;
68 int val = 0;
69 QString newStr;
70
71 newStr = str.trimmed();
72 if (d->_base > 10) {
73 newStr = newStr.toUpper();
74 }
75
76 if (newStr == QLatin1String("-")) {// a special case
77 if ((d->_min || d->_max) && d->_min >= 0) {
78 ok = false;
79 } else {
80 return QValidator::Acceptable;
81 }
82 } else if (!newStr.isEmpty()) {
83 val = newStr.toInt(&ok, d->_base);
84 } else {
85 val = 0;
86 ok = true;
87 }
88
89 if (! ok) {
90 return QValidator::Invalid;
91 }
92
93 if ((! d->_min && ! d->_max) || (val >= d->_min && val <= d->_max)) {
94 return QValidator::Acceptable;
95 }
96
97 if (d->_max && d->_min >= 0 && val < 0) {
98 return QValidator::Invalid;
99 }
100
101 return QValidator::Intermediate;
102 }
103
fixup(QString & str) const104 void KIntValidator::fixup(QString &str) const
105 {
106 int dummy;
107 int val;
108 QValidator::State state;
109
110 state = validate(str, dummy);
111
112 if (state == QValidator::Invalid || state == QValidator::Acceptable) {
113 return;
114 }
115
116 if (! d->_min && ! d->_max) {
117 return;
118 }
119
120 val = str.toInt(nullptr, d->_base);
121
122 if (val < d->_min) {
123 val = d->_min;
124 }
125 if (val > d->_max) {
126 val = d->_max;
127 }
128
129 str.setNum(val, d->_base);
130 }
131
setRange(int bottom,int top)132 void KIntValidator::setRange(int bottom, int top)
133 {
134 d->_min = bottom;
135 d->_max = top;
136
137 if (d->_max < d->_min) {
138 d->_max = d->_min;
139 }
140 }
141
setBase(int base)142 void KIntValidator::setBase(int base)
143 {
144 d->_base = base;
145 if (d->_base < 2) {
146 d->_base = 2;
147 }
148 if (d->_base > 36) {
149 d->_base = 36;
150 }
151 }
152
bottom() const153 int KIntValidator::bottom() const
154 {
155 return d->_min;
156 }
157
top() const158 int KIntValidator::top() const
159 {
160 return d->_max;
161 }
162
base() const163 int KIntValidator::base() const
164 {
165 return d->_base;
166 }
167
168 ///////////////////////////////////////////////////////////////
169 // Implementation of KDoubleValidator
170 //
171
172 class Q_DECL_HIDDEN KDoubleValidator::KDoubleValidatorPrivate
173 {
174 public:
KDoubleValidatorPrivate(bool accept=true)175 KDoubleValidatorPrivate(bool accept = true) : acceptLocalizedNumbers(accept) {}
176
177 bool acceptLocalizedNumbers;
178 };
179
KDoubleValidator(QObject * parent)180 KDoubleValidator::KDoubleValidator(QObject *parent)
181 : QDoubleValidator(parent), d(new KDoubleValidatorPrivate())
182 {
183 }
184
KDoubleValidator(double bottom,double top,int decimals,QObject * parent)185 KDoubleValidator::KDoubleValidator(double bottom, double top, int decimals,
186 QObject *parent)
187 : QDoubleValidator(bottom, top, decimals, parent), d(new KDoubleValidatorPrivate())
188 {
189 }
190
~KDoubleValidator()191 KDoubleValidator::~KDoubleValidator()
192 {
193 delete d;
194 }
195
acceptLocalizedNumbers() const196 bool KDoubleValidator::acceptLocalizedNumbers() const
197 {
198 return d->acceptLocalizedNumbers;
199 }
200
setAcceptLocalizedNumbers(bool accept)201 void KDoubleValidator::setAcceptLocalizedNumbers(bool accept)
202 {
203 d->acceptLocalizedNumbers = accept;
204 }
205
validate(QString & input,int & p) const206 QValidator::State KDoubleValidator::validate(QString &input, int &p) const
207 {
208 QString s = input;
209 if (acceptLocalizedNumbers()) {
210 KLocale *l = KLocale::global();
211 // ok, we have to re-format the number to have:
212 // 1. decimalSymbol == '.'
213 // 2. negativeSign == '-'
214 // 3. positiveSign == <empty>
215 // 4. thousandsSeparator() == <empty> (we don't check that there
216 // are exactly three decimals between each separator):
217 QString d = l->decimalSymbol(),
218 n = l->negativeSign(),
219 p = l->positiveSign(),
220 t = l->thousandsSeparator();
221 // first, delete p's and t's:
222 if (!p.isEmpty())
223 for (int idx = s.indexOf(p); idx >= 0; idx = s.indexOf(p, idx)) {
224 s.remove(idx, p.length());
225 }
226
227 if (!t.isEmpty())
228 for (int idx = s.indexOf(t); idx >= 0; idx = s.indexOf(t, idx)) {
229 s.remove(idx, t.length());
230 }
231
232 // then, replace the d's and n's
233 if ((!n.isEmpty() && n.indexOf('.') != -1) ||
234 (!d.isEmpty() && d.indexOf('-') != -1)) {
235 // make sure we don't replace something twice:
236 kWarning() << "KDoubleValidator: decimal symbol contains '-' or "
237 "negative sign contains '.' -> improve algorithm" << endl;
238 return Invalid;
239 }
240
241 if (!d.isEmpty() && d != ".")
242 for (int idx = s.indexOf(d); idx >= 0; idx = s.indexOf(d, idx + 1)) {
243 s.replace(idx, d.length(), '.');
244 }
245
246 if (!n.isEmpty() && n != "-")
247 for (int idx = s.indexOf(n); idx >= 0; idx = s.indexOf(n, idx + 1)) {
248 s.replace(idx, n.length(), '-');
249 }
250 }
251
252 return base::validate(s, p);
253 }
254
255