File indexing completed on 2024-04-21 14:55:57

0001 /**********************************************************************
0002 **
0003 **
0004 ** KIntValidator:
0005 **   Copyright (C) 1999 Glen Parker <glenebob@nwlink.com>
0006 ** KDoubleValidator:
0007 **   Copyright (c) 2002 Marc Mutz <mutz@kde.org>
0008 **
0009 ** This library is free software; you can redistribute it and/or
0010 ** modify it under the terms of the GNU Library General Public
0011 ** License as published by the Free Software Foundation; either
0012 ** version 2 of the License, or (at your option) any later version.
0013 **
0014 ** This library is distributed in the hope that it will be useful,
0015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
0016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017 ** Library General Public License for more details.
0018 **
0019 ** You should have received a copy of the GNU Library General Public
0020 ** License along with this library; if not, write to the Free
0021 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0022 **
0023 *****************************************************************************/
0024 
0025 #include "knumvalidator.h"
0026 
0027 #include <QWidget>
0028 #include <QCharRef>
0029 
0030 #include <klocale.h>
0031 #include <kdebug.h>
0032 
0033 ///////////////////////////////////////////////////////////////
0034 //  Implementation of KIntValidator
0035 //
0036 class Q_DECL_HIDDEN KIntValidator::KIntValidatorPrivate
0037 {
0038 public:
0039     KIntValidatorPrivate()
0040         : _base(0), _min(0), _max(0)
0041     {}
0042     int _base;
0043     int _min;
0044     int _max;
0045 };
0046 
0047 KIntValidator::KIntValidator(QWidget *parent, int base)
0048     : QValidator(parent), d(new KIntValidatorPrivate)
0049 {
0050     setBase(base);
0051 }
0052 
0053 KIntValidator::KIntValidator(int bottom, int top, QWidget *parent, int base)
0054     : QValidator(parent), d(new KIntValidatorPrivate)
0055 {
0056     setBase(base);
0057     setRange(bottom, top);
0058 }
0059 
0060 KIntValidator::~KIntValidator()
0061 {
0062     delete d;
0063 }
0064 
0065 QValidator::State KIntValidator::validate(QString &str, int &) const
0066 {
0067     bool ok;
0068     int  val = 0;
0069     QString newStr;
0070 
0071     newStr = str.trimmed();
0072     if (d->_base > 10) {
0073         newStr = newStr.toUpper();
0074     }
0075 
0076     if (newStr == QLatin1String("-")) {// a special case
0077         if ((d->_min || d->_max) && d->_min >= 0) {
0078             ok = false;
0079         } else {
0080             return QValidator::Acceptable;
0081         }
0082     } else if (!newStr.isEmpty()) {
0083         val = newStr.toInt(&ok, d->_base);
0084     } else {
0085         val = 0;
0086         ok = true;
0087     }
0088 
0089     if (! ok) {
0090         return QValidator::Invalid;
0091     }
0092 
0093     if ((! d->_min && ! d->_max) || (val >= d->_min && val <= d->_max)) {
0094         return QValidator::Acceptable;
0095     }
0096 
0097     if (d->_max && d->_min >= 0 && val < 0) {
0098         return QValidator::Invalid;
0099     }
0100 
0101     return QValidator::Intermediate;
0102 }
0103 
0104 void KIntValidator::fixup(QString &str) const
0105 {
0106     int                dummy;
0107     int                val;
0108     QValidator::State  state;
0109 
0110     state = validate(str, dummy);
0111 
0112     if (state == QValidator::Invalid || state == QValidator::Acceptable) {
0113         return;
0114     }
0115 
0116     if (! d->_min && ! d->_max) {
0117         return;
0118     }
0119 
0120     val = str.toInt(nullptr, d->_base);
0121 
0122     if (val < d->_min) {
0123         val = d->_min;
0124     }
0125     if (val > d->_max) {
0126         val = d->_max;
0127     }
0128 
0129     str.setNum(val, d->_base);
0130 }
0131 
0132 void KIntValidator::setRange(int bottom, int top)
0133 {
0134     d->_min = bottom;
0135     d->_max = top;
0136 
0137     if (d->_max < d->_min) {
0138         d->_max = d->_min;
0139     }
0140 }
0141 
0142 void KIntValidator::setBase(int base)
0143 {
0144     d->_base = base;
0145     if (d->_base < 2) {
0146         d->_base = 2;
0147     }
0148     if (d->_base > 36) {
0149         d->_base = 36;
0150     }
0151 }
0152 
0153 int KIntValidator::bottom() const
0154 {
0155     return d->_min;
0156 }
0157 
0158 int KIntValidator::top() const
0159 {
0160     return d->_max;
0161 }
0162 
0163 int KIntValidator::base() const
0164 {
0165     return d->_base;
0166 }
0167 
0168 ///////////////////////////////////////////////////////////////
0169 //  Implementation of KDoubleValidator
0170 //
0171 
0172 class Q_DECL_HIDDEN KDoubleValidator::KDoubleValidatorPrivate
0173 {
0174 public:
0175     KDoubleValidatorPrivate(bool accept = true) : acceptLocalizedNumbers(accept) {}
0176 
0177     bool acceptLocalizedNumbers;
0178 };
0179 
0180 KDoubleValidator::KDoubleValidator(QObject *parent)
0181     : QDoubleValidator(parent), d(new KDoubleValidatorPrivate())
0182 {
0183 }
0184 
0185 KDoubleValidator::KDoubleValidator(double bottom, double top, int decimals,
0186                                    QObject *parent)
0187     : QDoubleValidator(bottom, top, decimals, parent), d(new KDoubleValidatorPrivate())
0188 {
0189 }
0190 
0191 KDoubleValidator::~KDoubleValidator()
0192 {
0193     delete d;
0194 }
0195 
0196 bool KDoubleValidator::acceptLocalizedNumbers() const
0197 {
0198     return d->acceptLocalizedNumbers;
0199 }
0200 
0201 void KDoubleValidator::setAcceptLocalizedNumbers(bool accept)
0202 {
0203     d->acceptLocalizedNumbers = accept;
0204 }
0205 
0206 QValidator::State KDoubleValidator::validate(QString &input, int &p) const
0207 {
0208     QString s = input;
0209     if (acceptLocalizedNumbers()) {
0210         KLocale *l = KLocale::global();
0211         // ok, we have to re-format the number to have:
0212         // 1. decimalSymbol == '.'
0213         // 2. negativeSign  == '-'
0214         // 3. positiveSign  == <empty>
0215         // 4. thousandsSeparator() == <empty> (we don't check that there
0216         //    are exactly three decimals between each separator):
0217         QString d = l->decimalSymbol(),
0218                 n = l->negativeSign(),
0219                 p = l->positiveSign(),
0220                 t = l->thousandsSeparator();
0221         // first, delete p's and t's:
0222         if (!p.isEmpty())
0223             for (int idx = s.indexOf(p); idx >= 0; idx = s.indexOf(p, idx)) {
0224                 s.remove(idx, p.length());
0225             }
0226 
0227         if (!t.isEmpty())
0228             for (int idx = s.indexOf(t); idx >= 0; idx = s.indexOf(t, idx)) {
0229                 s.remove(idx, t.length());
0230             }
0231 
0232         // then, replace the d's and n's
0233         if ((!n.isEmpty() && n.indexOf('.') != -1) ||
0234                 (!d.isEmpty() && d.indexOf('-') != -1)) {
0235             // make sure we don't replace something twice:
0236             kWarning() << "KDoubleValidator: decimal symbol contains '-' or "
0237                        "negative sign contains '.' -> improve algorithm" << endl;
0238             return Invalid;
0239         }
0240 
0241         if (!d.isEmpty() && d != ".")
0242             for (int idx = s.indexOf(d); idx >= 0; idx = s.indexOf(d, idx + 1)) {
0243                 s.replace(idx, d.length(), '.');
0244             }
0245 
0246         if (!n.isEmpty() && n != "-")
0247             for (int idx = s.indexOf(n); idx >= 0; idx = s.indexOf(n, idx + 1)) {
0248                 s.replace(idx, n.length(), '-');
0249             }
0250     }
0251 
0252     return base::validate(s, p);
0253 }
0254 
0255 #include "moc_knumvalidator.cpp"