File indexing completed on 2024-05-12 16:44:03

0001 /*
0002     SPDX-FileCopyrightText: 2001-2002 Michael Edwardes <mte@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2002-2017 Thomas Baumgart <tbaumgart@kde.org>
0004     SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kmymoneymoneyvalidator.h"
0009 
0010 // ----------------------------------------------------------------------------
0011 // QT Includes
0012 
0013 // ----------------------------------------------------------------------------
0014 // KDE Includes
0015 
0016 // ----------------------------------------------------------------------------
0017 // Project Includes
0018 
0019 
0020 KMyMoneyMoneyValidator::KMyMoneyMoneyValidator(QObject * parent) :
0021     QDoubleValidator(parent)
0022 {
0023     setLocale(QLocale::c());
0024 }
0025 
0026 KMyMoneyMoneyValidator::KMyMoneyMoneyValidator(double bottom, double top, int decimals,
0027         QObject * parent) :
0028     QDoubleValidator(bottom, top, decimals, parent)
0029 {
0030     setLocale(QLocale::c());
0031 }
0032 
0033 KMyMoneyMoneyValidator::~KMyMoneyMoneyValidator()
0034 {
0035 }
0036 
0037 /*
0038  * The code of the following function is taken from kdeui/knumvalidator.cpp
0039  * and adjusted to always use the monetary symbols defined in the KDE System Settings
0040  */
0041 QValidator::State KMyMoneyMoneyValidator::validate(QString & input, int & _p) const
0042 {
0043     Q_UNUSED(_p)
0044     QString s = input;
0045     // TODO: port this to kf5
0046 #if 0
0047     KLocale * l = KLocale::global();
0048     // ok, we have to re-format the number to have:
0049     // 1. decimalSymbol == '.'
0050     // 2. negativeSign  == '-'
0051     // 3. positiveSign  == <empty>
0052     // 4. thousandsSeparator() == <empty> (we don't check that there
0053     //    are exactly three decimals between each separator):
0054     QString d = l->monetaryDecimalSymbol(),
0055             n = l->negativeSign(),
0056             p = l->positiveSign(),
0057             t = l->monetaryThousandsSeparator();
0058     // first, delete p's and t's:
0059     if (!p.isEmpty())
0060         for (int idx = s.indexOf(p) ; idx >= 0 ; idx = s.indexOf(p, idx))
0061             s.remove(idx, p.length());
0062 
0063 
0064     if (!t.isEmpty())
0065         for (int idx = s.indexOf(t) ; idx >= 0 ; idx = s.indexOf(t, idx))
0066             s.remove(idx, t.length());
0067 
0068     // then, replace the d's and n's
0069     if ((!n.isEmpty() && n.indexOf('.') != -1) ||
0070             (!d.isEmpty() && d.indexOf('-') != -1)) {
0071         // make sure we don't replace something twice:
0072         qWarning() << "KDoubleValidator: decimal symbol contains '-' or "
0073                    "negative sign contains '.' -> improve algorithm" << endl;
0074         return Invalid;
0075     }
0076 
0077     if (!d.isEmpty() && d != ".")
0078         for (int idx = s.indexOf(d) ; idx >= 0 ; idx = s.indexOf(d, idx + 1))
0079             s.replace(idx, d.length(), ".");
0080 
0081     if (!n.isEmpty() && n != "-")
0082         for (int idx = s.indexOf(n) ; idx >= 0 ; idx = s.indexOf(n, idx + 1))
0083             s.replace(idx, n.length(), "-");
0084 
0085     // Take care of monetary parens around the value if selected via
0086     // the locale settings.
0087     // If the lead-in or lead-out paren is present, remove it
0088     // before passing the string to the QDoubleValidator
0089     if (l->negativeMonetarySignPosition() == KLocale::ParensAround
0090             || l->positiveMonetarySignPosition() == KLocale::ParensAround) {
0091         QRegExp regExp("^(\\()?([\\d-\\.]*)(\\))?$");
0092         if (s.indexOf(regExp) != -1) {
0093             s = regExp.cap(2);
0094         }
0095     }
0096 
0097     // check for non numeric values (QDoubleValidator allows an 'e', we don't)
0098     QRegExp nonNumeric("[^\\d-\\.]+");
0099     if (s.indexOf(nonNumeric) != -1)
0100         return Invalid;
0101 
0102     // check for minus sign trailing the number
0103     QRegExp trailingMinus("^([^-]*)\\w*-$");
0104     if (s.indexOf(trailingMinus) != -1) {
0105         s = QString("-%1").arg(trailingMinus.cap(1));
0106     }
0107 
0108     // check for the maximum allowed number of decimal places
0109     int decPos = s.indexOf('.');
0110     if (decPos != -1) {
0111         if (decimals() == 0)
0112             return Invalid;
0113         if (((int)(s.length()) - decPos) > decimals())
0114             return Invalid;
0115     }
0116 
0117     // If we have just a single minus sign, we are done
0118     if (s == QString("-"))
0119         return Acceptable;
0120 
0121     QValidator::State rc = QDoubleValidator::validate(s, _p);
0122     if (rc == Acceptable) {
0123         // If the numeric value is acceptable, we check if the parens
0124         // are ok. If only the lead-in is present, the return value
0125         // is intermediate, if only the lead-out is present then it
0126         // definitely is invalid. Nevertheless, we check for parens
0127         // only, if the locale settings have it enabled.
0128         if (l->negativeMonetarySignPosition() == KLocale::ParensAround
0129                 || l->positiveMonetarySignPosition() == KLocale::ParensAround) {
0130             int tmp = input.count('(') - input.count(')');
0131             if (tmp > 0)
0132                 rc = Intermediate;
0133             else if (tmp < 0)
0134                 rc = Invalid;
0135         }
0136     }
0137     return rc;
0138 #else
0139     return Acceptable;
0140 #endif
0141 }