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 }