keysmith/src/validators/countervalidator.cpp

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;
}
}
}