diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-04-10 12:44:20 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2017-06-20 09:53:14 +0000 |
commit | 9d23aebb271ea534a66cb3aceb2e63d9a1c870d6 (patch) | |
tree | a78a9b2739aabc594e04cb73cae3a81a24c54dd1 /src/corelib | |
parent | ccca8c94359e7f07333b710119bfdf00b25b78fd (diff) |
Add QLocale::formattedDataSize and consolidate use cases
It should be easier to translate sizes in bytes to human-readable
strings consistently rather than having to repeat this code (and the
string translations) in various places. The FileDialog in QtQuick.Controls
has a use for this, too.
[ChangeLog][QtCore][QLocale] Added QLocale::formattedDataSize() for
formatting quantities of bytes as kB, MB, GB etc.
Done-with: Edward Welbourne <edward.welbourne@qt.io>
Change-Id: I27bca146c3eba90fa7a5d52ef6626ce85723e3f0
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 71 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.h | 15 |
2 files changed, 86 insertions, 0 deletions
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 5557b5af2d..43d83db835 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -61,6 +61,7 @@ #include "qvariant.h" #include "qstringbuilder.h" #include "private/qnumeric_p.h" +#include <cmath> #ifdef Q_OS_WIN # include <qt_windows.h> # include <time.h> @@ -3781,6 +3782,76 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci } /*! + \since 5.10 + + \enum QLocale::DataSizeFormat + + Specifies the format for representation of data quantities. + + \omitvalue DataSizeBase1000 + \omitvalue DataSizeSIQuantifiers + \value DataSizeIecFormat format using base 1024 and IEC prefixes: KiB, MiB, GiB, ... + \value DataSizeTraditionalFormat format using base 1024 and SI prefixes: kB, MB, GB, ... + \value DataSizeSIFormat format using base 1000 and SI prefixes: kB, MB, GB, ... + + \sa formattedDataSize() +*/ + +/*! + \since 5.10 + + Converts a size in bytes to a human-readable localized string, expressed in + a unit for which the numeric portion is at least 1 but as low as + possible. For example if \a bytes is 16384, \a precision is 2, and \a format + is \c DataSizeIecFormat (the default), this function returns "16.00 KiB"; + for 1330409069609 bytes it returns "1.21 GiB"; and so on. If \a format is \c + DataSizeIecFormat or \c DataSizeTraditionalFormat, the given number of bytes + is divided by a power of 1024, with result less than 1024; for \c + DataSizeSIFormat, it is divided by a power of 1000, with result less than + 1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so + on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the + older SI quantifiers k, M, etc. + + \sa refresh(), caching() +*/ +QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) +{ + int power, base = 1000; + if (!bytes) { + power = 0; + } else if (format & DataSizeBase1000) { + power = int(std::log10(qAbs(bytes)) / 3); + } else { // Compute log2(bytes) / 10: + power = int((63 - qCountLeadingZeroBits(quint64(qAbs(bytes)))) / 10); + base = 1024; + } + // Only go to doubles if we'll be using a quantifier: + const QString number = power + ? toString(bytes / std::pow(double(base), power), 'f', qMin(precision, 3 * power)) + : toString(bytes); + + // We don't support sizes in units larger than exbibytes because + // the number of bytes would not fit into qint64. + Q_ASSERT(power <= 6 && power >= 0); + QString unit; + if (power > 0) { + quint16 index, size; + if (format & DataSizeSIQuantifiers) { + index = d->m_data->m_byte_si_quantified_idx; + size = d->m_data->m_byte_si_quantified_size; + } else { + index = d->m_data->m_byte_iec_quantified_idx; + size = d->m_data->m_byte_iec_quantified_size; + } + unit = getLocaleListData(byte_unit_data + index, size, power - 1); + } else { + unit = getLocaleData(byte_unit_data + d->m_data->m_byte_idx, d->m_data->m_byte_size); + } + + return number + QLatin1Char(' ') + unit; +} + +/*! \since 4.8 Returns an ordered list of locale names for translation purposes in diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index f9482a7e3a..54b1a32946 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -913,6 +913,19 @@ public: CurrencyDisplayName }; + enum DataSizeFormat { + // Single-bit values, for internal use. + DataSizeBase1000 = 1, // use factors of 1000 instead of IEC's 1024; + DataSizeSIQuantifiers = 2, // use SI quantifiers instead of IEC ones. + + // Flags values for use in API: + DataSizeIecFormat = 0, // base 1024, KiB, MiB, GiB, ... + DataSizeTraditionalFormat = DataSizeSIQuantifiers, // base 1024, kB, MB, GB, ... + DataSizeSIFormat = DataSizeBase1000 | DataSizeSIQuantifiers // base 1000, kB, MB, GB, ... + }; + Q_DECLARE_FLAGS(DataSizeFormats, DataSizeFormat) + Q_FLAG(DataSizeFormats) + QLocale(); QLocale(const QString &name); QLocale(Language language, Country country = AnyCountry); @@ -1045,6 +1058,8 @@ public: { return toCurrencyString(double(i), symbol, precision); } #endif + QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat); + QStringList uiLanguages() const; bool operator==(const QLocale &other) const; |