Expose formattedDataSize() in QML Locale type
This was added to qtbase in 9d23aeb. Qt Quick Dialogs needs it to display file sizes in FileDialog. [ChangeLog][QML][Locale] Added formattedDataSize() for formatting quantities of bytes as kB, MB, GB etc. Fixes: QTBUG-91283 Change-Id: I8ea64f961c04d4900d18fa45398670df89882c56 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
acf3a16800
commit
d61ececdb8
|
@ -495,6 +495,41 @@ ReturnedValue QQmlLocaleData::method_set_numberOptions(const QV4::FunctionObject
|
|||
return Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue QQmlLocaleData::method_get_formattedDataSize(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
|
||||
{
|
||||
QV4::Scope scope(b);
|
||||
const QLocale *locale = getThisLocale(scope, thisObject);
|
||||
if (!locale)
|
||||
return Encode::undefined();
|
||||
|
||||
if (argc < 1 || argc > 3) {
|
||||
THROW_ERROR(QString::fromLatin1(
|
||||
"Locale: formattedDataSize(): Expected 1-3 arguments, but received %1").arg(argc).toLatin1());
|
||||
}
|
||||
|
||||
const qint64 bytes = static_cast<qint64>(argv[0].toInteger());
|
||||
if (argc == 1)
|
||||
RETURN_RESULT(scope.engine->newString(locale->formattedDataSize(bytes)));
|
||||
|
||||
int precision = 0;
|
||||
if (argc >= 2) {
|
||||
if (!argv[1].isInteger())
|
||||
THROW_ERROR("Locale: formattedDataSize(): Invalid argument ('precision' must be an int)");
|
||||
|
||||
precision = argv[1].toInt32();
|
||||
if (argc == 2)
|
||||
RETURN_RESULT(scope.engine->newString(locale->formattedDataSize(bytes, precision)));
|
||||
}
|
||||
|
||||
// argc >= 3
|
||||
if (!argv[2].isNumber())
|
||||
THROW_ERROR("Locale: formattedDataSize(): Invalid argument ('format' must be DataSizeFormat)");
|
||||
|
||||
const quint32 intFormat = argv[2].toUInt32();
|
||||
const auto format = QLocale::DataSizeFormats(intFormat);
|
||||
RETURN_RESULT(scope.engine->newString(locale->formattedDataSize(bytes, precision, format)));
|
||||
}
|
||||
|
||||
ReturnedValue QQmlLocaleData::method_get_measurementSystem(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
|
||||
{
|
||||
QV4::Scope scope(b);
|
||||
|
@ -701,6 +736,7 @@ QV4LocaleDataDeletable::QV4LocaleDataDeletable(QV4::ExecutionEngine *engine)
|
|||
o->defineDefaultProperty(QStringLiteral("monthName"), QQmlLocaleData::method_monthName, 0);
|
||||
o->defineDefaultProperty(QStringLiteral("currencySymbol"), QQmlLocaleData::method_currencySymbol, 0);
|
||||
o->defineDefaultProperty(QStringLiteral("dateTimeFormat"), QQmlLocaleData::method_dateTimeFormat, 0);
|
||||
o->defineDefaultProperty(QStringLiteral("formattedDataSize"), QQmlLocaleData::method_get_formattedDataSize, 0);
|
||||
o->defineAccessorProperty(QStringLiteral("name"), QQmlLocaleData::method_get_name, nullptr);
|
||||
o->defineAccessorProperty(QStringLiteral("positiveSign"), QQmlLocaleData::method_get_positiveSign, nullptr);
|
||||
o->defineAccessorProperty(QStringLiteral("uiLanguages"), QQmlLocaleData::method_get_uiLanguages, nullptr);
|
||||
|
@ -950,6 +986,20 @@ ReturnedValue QQmlLocale::method_localeCompare(const QV4::FunctionObject *b, con
|
|||
\sa Date
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlmethod string QtQml::Locale::formattedDataSize(int bytes, int precision, DataSizeFormat format)
|
||||
\since 6.2
|
||||
|
||||
Converts a size in \a bytes to a human-readable localized string, comprising a
|
||||
number and a quantified unit.
|
||||
|
||||
The \a precision and \a format arguments are optional.
|
||||
|
||||
For more information, see \l QLocale::formattedDataSize().
|
||||
|
||||
\sa QLocale::DataSizeFormats
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlmethod string QtQml::Locale::monthName(month, type)
|
||||
|
||||
|
|
|
@ -139,6 +139,15 @@ namespace QQmlLocale
|
|||
};
|
||||
Q_ENUM_NS(NumberOptions)
|
||||
|
||||
enum DataSizeFormat {
|
||||
DataSizeBase1000 = QLocale::DataSizeBase1000,
|
||||
DataSizeSIQuantifiers = QLocale::DataSizeSIQuantifiers,
|
||||
DataSizeIecFormat = QLocale::DataSizeIecFormat,
|
||||
DataSizeTraditionalFormat = QLocale::DataSizeTraditionalFormat,
|
||||
DataSizeSIFormat = QLocale::DataSizeSIFormat
|
||||
};
|
||||
Q_ENUM_NS(DataSizeFormat)
|
||||
|
||||
Q_QML_PRIVATE_EXPORT QV4::ReturnedValue locale(QV4::ExecutionEngine *engine, const QString &localeName);
|
||||
Q_QML_PRIVATE_EXPORT QV4::ReturnedValue wrap(QV4::ExecutionEngine *engine, const QLocale &locale);
|
||||
Q_QML_PRIVATE_EXPORT void registerStringLocaleCompare(QV4::ExecutionEngine *engine);
|
||||
|
@ -205,6 +214,8 @@ struct QQmlLocaleData : public QV4::Object
|
|||
|
||||
static QV4::ReturnedValue method_get_numberOptions(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
|
||||
static QV4::ReturnedValue method_set_numberOptions(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
|
||||
|
||||
static QV4::ReturnedValue method_get_formattedDataSize(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
property var locale: Qt.locale()
|
||||
|
||||
// TODO: Workaround for not being able to use "Locale" in QQmlExpression (QTBUG-91747).
|
||||
property var localeType: Locale
|
||||
|
||||
function setLocale(l) {
|
||||
locale = Qt.locale(l)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <QDebug>
|
||||
|
||||
#include <QtQml/qqmlengine.h>
|
||||
#include <QtQml/qqmlexpression.h>
|
||||
#include <QtQml/qqmlcomponent.h>
|
||||
#include <QtQml/qqmlcontext.h>
|
||||
#include <QtCore/QDateTime>
|
||||
|
@ -76,6 +77,8 @@ private slots:
|
|||
#if defined(Q_OS_UNIX) && QT_CONFIG(timezone)
|
||||
void timeZoneUpdated();
|
||||
#endif
|
||||
void formattedDataSize_data();
|
||||
void formattedDataSize();
|
||||
|
||||
void dateToLocaleString_data();
|
||||
void dateToLocaleString();
|
||||
|
@ -118,6 +121,7 @@ private:
|
|||
void addDateTimeFormatData(const QString &l);
|
||||
void addDateFormatData(const QString &l);
|
||||
void addTimeFormatData(const QString &l);
|
||||
void addFormattedDataSizeDataForLocale(const QString &l);
|
||||
QQmlEngine engine;
|
||||
};
|
||||
|
||||
|
@ -629,6 +633,112 @@ void tst_qqmllocale::timeFormat()
|
|||
QCOMPARE(val.toString(), l.timeFormat(format));
|
||||
}
|
||||
|
||||
void tst_qqmllocale::addFormattedDataSizeDataForLocale(const QString &localeStr)
|
||||
{
|
||||
const QByteArray localeByteArray = localeStr.toLatin1();
|
||||
QString functionCallScript;
|
||||
QString expectedResult;
|
||||
QString expectedErrorMessage;
|
||||
|
||||
const QLocale locale(localeStr);
|
||||
|
||||
const auto makeTag = [&](){
|
||||
QRegularExpression argRegex("formattedDataSize\\((.*)\\)");
|
||||
QString tag = functionCallScript;
|
||||
const auto match = argRegex.match(functionCallScript);
|
||||
if (match.hasMatch())
|
||||
tag = match.captured(1);
|
||||
return localeStr + QLatin1String(", ") + tag;
|
||||
};
|
||||
|
||||
functionCallScript = QLatin1String("locale.formattedDataSize(1000000)");
|
||||
expectedResult = locale.formattedDataSize(1000000);
|
||||
QTest::newRow(qPrintable(makeTag())) << localeStr << functionCallScript << expectedResult << expectedErrorMessage;
|
||||
|
||||
functionCallScript = QLatin1String("locale.formattedDataSize(1000000, 3)");
|
||||
expectedResult = locale.formattedDataSize(1000000, 3);
|
||||
QTest::newRow(qPrintable(makeTag())) << localeStr << functionCallScript << expectedResult << expectedErrorMessage;
|
||||
|
||||
functionCallScript = QLatin1String("locale.formattedDataSize(1000000, 3, localeType.DataSizeIecFormat)");
|
||||
expectedResult = locale.formattedDataSize(1000000, 3, QLocale::DataSizeIecFormat);
|
||||
QTest::newRow(qPrintable(makeTag())) << localeStr << functionCallScript << expectedResult << expectedErrorMessage;
|
||||
|
||||
functionCallScript = QLatin1String("locale.formattedDataSize(1000000, 3, localeType.DataSizeTraditionalFormat)");
|
||||
expectedResult = locale.formattedDataSize(1000000, 3, QLocale::DataSizeTraditionalFormat);
|
||||
QTest::newRow(qPrintable(makeTag())) << localeStr << functionCallScript << expectedResult << expectedErrorMessage;
|
||||
|
||||
functionCallScript = QLatin1String("locale.formattedDataSize(1000000, 3, localeType.DataSizeSIFormat)");
|
||||
expectedResult = locale.formattedDataSize(1000000, 3, QLocale::DataSizeSIFormat);
|
||||
QTest::newRow(qPrintable(makeTag())) << localeStr << functionCallScript << expectedResult << expectedErrorMessage;
|
||||
}
|
||||
|
||||
void tst_qqmllocale::formattedDataSize_data()
|
||||
{
|
||||
QTest::addColumn<QString>("localeStr");
|
||||
QTest::addColumn<QString>("functionCallScript");
|
||||
QTest::addColumn<QString>("expectedResult");
|
||||
QTest::addColumn<QString>("expectedErrorMessagePattern");
|
||||
|
||||
addFormattedDataSizeDataForLocale("en_US");
|
||||
addFormattedDataSizeDataForLocale("de_DE");
|
||||
addFormattedDataSizeDataForLocale("ar_SA");
|
||||
addFormattedDataSizeDataForLocale("hi_IN");
|
||||
addFormattedDataSizeDataForLocale("zh_CN");
|
||||
addFormattedDataSizeDataForLocale("th_TH");
|
||||
|
||||
// Test error conditions (which aren't locale-specific).
|
||||
QString functionCallScript = "locale.formattedDataSize()";
|
||||
QString errorMessage = ".*Locale: formattedDataSize\\(\\): Expected 1-3 arguments, but received 0";
|
||||
QTest::newRow("too few args") << "en_AU" << functionCallScript << QString() << errorMessage;
|
||||
|
||||
functionCallScript = "locale.formattedDataSize(10, 1, localeType.DataSizeIecFormat, \"foo\")";
|
||||
errorMessage = ".*Locale: formattedDataSize\\(\\): Expected 1-3 arguments, but received 4";
|
||||
QTest::newRow("too many args") << "en_AU" << functionCallScript << QString() << errorMessage;
|
||||
|
||||
functionCallScript = "locale.formattedDataSize(10, \"no\")";
|
||||
errorMessage = ".*Locale: formattedDataSize\\(\\): Invalid argument \\('precision' must be an int\\)";
|
||||
QTest::newRow("precision wrong type") << "en_AU" << functionCallScript << QString() << errorMessage;
|
||||
|
||||
functionCallScript = "locale.formattedDataSize(10, 1, \"no\")";
|
||||
errorMessage = ".*Locale: formattedDataSize\\(\\): Invalid argument \\('format' must be DataSizeFormat\\)";
|
||||
QTest::newRow("format wrong type") << "en_AU" << functionCallScript << QString() << errorMessage;
|
||||
}
|
||||
|
||||
void tst_qqmllocale::formattedDataSize()
|
||||
{
|
||||
QFETCH(QString, localeStr);
|
||||
QFETCH(QString, functionCallScript);
|
||||
QFETCH(QString, expectedResult);
|
||||
QFETCH(QString, expectedErrorMessagePattern);
|
||||
|
||||
QQmlComponent component(&engine, testFileUrl("functions.qml"));
|
||||
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
|
||||
|
||||
QScopedPointer<QObject> object(component.create());
|
||||
QVERIFY(object);
|
||||
|
||||
QLocale locale(localeStr);
|
||||
QVariant returnValue;
|
||||
|
||||
QVERIFY(QMetaObject::invokeMethod(object.data(), "setLocale", Qt::DirectConnection,
|
||||
Q_ARG(QVariant, QVariant(localeStr))));
|
||||
|
||||
QQmlExpression qmlExpression(engine.rootContext(), object.data(), functionCallScript);
|
||||
const QVariant evaluationResult = qmlExpression.evaluate();
|
||||
if (expectedErrorMessagePattern.isEmpty()) {
|
||||
QVERIFY2(!qmlExpression.hasError(), qPrintable(qmlExpression.error().toString()));
|
||||
QVERIFY(evaluationResult.canConvert<QString>());
|
||||
QCOMPARE(evaluationResult.toString(), expectedResult);
|
||||
} else {
|
||||
QVERIFY(qmlExpression.hasError());
|
||||
QRegularExpression errorRegex(expectedErrorMessagePattern);
|
||||
QVERIFY(errorRegex.isValid());
|
||||
QVERIFY2(errorRegex.match(qmlExpression.error().toString()).hasMatch(),
|
||||
qPrintable(QString::fromLatin1("Mismatch in actual vs expected error message:\n Actual: %1\n Expected: %2")
|
||||
.arg(qmlExpression.error().toString()).arg(expectedErrorMessagePattern)));
|
||||
}
|
||||
}
|
||||
|
||||
void tst_qqmllocale::dateToLocaleString_data()
|
||||
{
|
||||
addStandardFormatData();
|
||||
|
|
Loading…
Reference in New Issue