84 lines
2.6 KiB
C++
84 lines
2.6 KiB
C++
/*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
* SPDX-FileCopyrightText: 2019-2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
|
*/
|
|
|
|
#include "countervalidator.h"
|
|
|
|
#include "util.h"
|
|
|
|
namespace validators
|
|
{
|
|
std::optional<qulonglong> parseUnsignedInteger(const QString &input, const QLocale &locale)
|
|
{
|
|
bool ok = false;
|
|
|
|
auto v = locale.toULongLong(input, &ok);
|
|
if (ok) {
|
|
return std::optional<qulonglong>(v);
|
|
} else {
|
|
/*
|
|
* Fall back to parsing according to C locale for better UX.
|
|
* This simplifies copy-pasting from websites which may be a bit
|
|
* biased towards the Anglosphere.
|
|
*/
|
|
const QLocale c = QLocale::c();
|
|
v = c.toULongLong(input, &ok);
|
|
return ok ? std::optional<qulonglong>(v) : std::nullopt;
|
|
}
|
|
}
|
|
|
|
UnsignedLongValidator::UnsignedLongValidator(QObject *parent):
|
|
QValidator(parent)
|
|
{
|
|
}
|
|
|
|
void UnsignedLongValidator::fixup(QString &input) const
|
|
{
|
|
/*
|
|
* First of all: simplify the input to get rid of 'fluff' such as
|
|
* digit group separators in partial input. E.g. if the user wants
|
|
* to type the value 123456 then partial input might become "123,4"
|
|
* at some point which would be invalid.
|
|
*/
|
|
const QLocale l = locale();
|
|
const QChar c = l.groupSeparator();
|
|
QString fixed = input.replace(c, QLatin1String(""));
|
|
fixed = validators::strip_spaces(fixed);
|
|
|
|
/*
|
|
* Normalise to locale's preferred formatting if possible
|
|
* I.e. if valid, re-instate any decorative fluff like digit group
|
|
* separators depending on the locale.
|
|
*
|
|
* This may also involve switching from Latin script (C locale) to
|
|
* whatever script the configured locale uses natively.
|
|
*/
|
|
const auto v = parseUnsignedInteger(fixed, l);
|
|
if (v) {
|
|
fixed = l.toString(v.value());
|
|
}
|
|
|
|
input = fixed;
|
|
}
|
|
|
|
QValidator::State UnsignedLongValidator::validate(QString &input, int &cursor) const
|
|
{
|
|
Q_UNUSED(cursor);
|
|
// Avoid a hard error on empty string.
|
|
if (input.size() == 0) {
|
|
return QValidator::Intermediate;
|
|
} else {
|
|
|
|
const QLocale l = locale();
|
|
const auto parsed = parseUnsignedInteger(input, l);
|
|
|
|
/*
|
|
* The actual value is a don't care at this point.
|
|
* All that matters is the input can be parsed
|
|
*/
|
|
return parsed ? QValidator::Acceptable : QValidator::Invalid;
|
|
}
|
|
}
|
|
}
|