File indexing completed on 2024-04-28 05:50:09
0001 /* 0002 * SPDX-License-Identifier: GPL-3.0-or-later 0003 * SPDX-FileCopyrightText: 2019-2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com> 0004 */ 0005 0006 #include "countervalidator.h" 0007 0008 #include "util.h" 0009 0010 namespace validators 0011 { 0012 std::optional<qulonglong> parseUnsignedInteger(const QString &input, const QLocale &locale) 0013 { 0014 bool ok = false; 0015 0016 auto v = locale.toULongLong(input, &ok); 0017 if (ok) { 0018 return std::optional<qulonglong>(v); 0019 } else { 0020 /* 0021 * Fall back to parsing according to C locale for better UX. 0022 * This simplifies copy-pasting from websites which may be a bit 0023 * biased towards the Anglosphere. 0024 */ 0025 const QLocale c = QLocale::c(); 0026 v = c.toULongLong(input, &ok); 0027 return ok ? std::optional<qulonglong>(v) : std::nullopt; 0028 } 0029 } 0030 0031 UnsignedLongValidator::UnsignedLongValidator(QObject *parent): 0032 QValidator(parent) 0033 { 0034 } 0035 0036 void UnsignedLongValidator::fixup(QString &input) const 0037 { 0038 /* 0039 * First of all: simplify the input to get rid of 'fluff' such as 0040 * digit group separators in partial input. E.g. if the user wants 0041 * to type the value 123456 then partial input might become "123,4" 0042 * at some point which would be invalid. 0043 */ 0044 const QLocale l = locale(); 0045 const auto c = l.groupSeparator(); 0046 QString fixed = input.replace(c, QLatin1String("")); 0047 fixed = validators::strip_spaces(fixed); 0048 0049 /* 0050 * Normalise to locale's preferred formatting if possible 0051 * I.e. if valid, re-instate any decorative fluff like digit group 0052 * separators depending on the locale. 0053 * 0054 * This may also involve switching from Latin script (C locale) to 0055 * whatever script the configured locale uses natively. 0056 */ 0057 const auto v = parseUnsignedInteger(fixed, l); 0058 if (v) { 0059 fixed = l.toString(v.value()); 0060 } 0061 0062 input = fixed; 0063 } 0064 0065 QValidator::State UnsignedLongValidator::validate(QString &input, int &cursor) const 0066 { 0067 Q_UNUSED(cursor); 0068 // Avoid a hard error on empty string. 0069 if (input.size() == 0) { 0070 return QValidator::Intermediate; 0071 } else { 0072 0073 const QLocale l = locale(); 0074 const auto parsed = parseUnsignedInteger(input, l); 0075 0076 /* 0077 * The actual value is a don't care at this point. 0078 * All that matters is the input can be parsed 0079 */ 0080 return parsed ? QValidator::Acceptable : QValidator::Invalid; 0081 } 0082 } 0083 }