aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qt/bitcoin.cpp3
-rw-r--r--src/qt/bitcoinamountfield.cpp15
-rw-r--r--src/qt/bitcoinamountfield.h4
-rw-r--r--src/qt/bitcoinunits.cpp103
-rw-r--r--src/qt/bitcoinunits.h11
-rw-r--r--src/qt/guiutil.cpp5
6 files changed, 94 insertions, 47 deletions
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 7887a31b6..adfcf3eb1 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -121,6 +121,9 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
// 1) System default language
QString lang_territory = GetLangTerritory();
+ // Set default locale for amount and date formatting according to the selected language
+ QLocale::setDefault(QLocale(lang_territory));
+
// Convert to "de" only by truncating "_DE"
QString lang = lang_territory;
lang.truncate(lang_territory.lastIndexOf('_'));
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 1033bf1a0..5e8150a56 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -25,7 +25,7 @@ public:
explicit AmountSpinBox(QWidget *parent):
QAbstractSpinBox(parent),
currentUnit(BitcoinUnits::BTC),
- singleStep(100000000) // koinu
+ singleStep(COIN) // koinu
{
setAlignment(Qt::AlignRight);
@@ -48,7 +48,7 @@ public:
CAmount val = parse(input, &valid);
if(valid)
{
- input = BitcoinUnits::format(currentUnit, val, false, BitcoinUnits::separatorAlways);
+ input = BitcoinUnits::format(currentUnit, val, false, true);
lineEdit()->setText(input);
}
}
@@ -60,7 +60,7 @@ public:
void setValue(const CAmount& value)
{
- lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, BitcoinUnits::separatorAlways));
+ lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, true));
emit valueChanged();
}
@@ -195,7 +195,6 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
amount(0)
{
amount = new AmountSpinBox(this);
- amount->setLocale(QLocale::c());
amount->installEventFilter(this);
amount->setMaximumWidth(170);
@@ -220,6 +219,14 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
unitChanged(unit->currentIndex());
}
+void BitcoinAmountField::setText(const QString &text)
+{
+ if (text.isEmpty())
+ amount->clear();
+ else
+ amount->setValue(QLocale().toDouble(text));
+}
+
void BitcoinAmountField::clear()
{
amount->clear();
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index b047e6c51..8b5880b0d 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -15,6 +15,8 @@ QT_BEGIN_NAMESPACE
class QValueComboBox;
QT_END_NAMESPACE
+class AmountSpinBox;
+
/** Widget for entering bitcoin amounts.
*/
class BitcoinAmountField: public QWidget
@@ -67,6 +69,8 @@ private:
AmountSpinBox *amount;
QValueComboBox *unit;
+ void setText(const QString &text);
+ QString text() const;
private slots:
void unitChanged(int idx);
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index 08c2bfa17..a4430c4ce 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -7,6 +7,7 @@
#include "primitives/transaction.h"
#include <QStringList>
+#include <QLocale>
BitcoinUnits::BitcoinUnits(QObject *parent):
QAbstractListModel(parent),
@@ -69,6 +70,17 @@ qint64 BitcoinUnits::factor(int unit)
}
}
+qint64 BitcoinUnits::maxAmount(int unit)
+{
+ switch(unit)
+ {
+ case BTC: return Q_INT64_C(900000000000); //less than the coin supply until the year 2170
+ case mBTC: return Q_INT64_C(900000000000000);
+ case uBTC: return Q_INT64_C(900000000000000000); // Slightly under max value for int64
+ default: return 0;
+ }
+}
+
int BitcoinUnits::decimals(int unit)
{
switch(unit)
@@ -80,37 +92,42 @@ int BitcoinUnits::decimals(int unit)
}
}
-QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators)
+QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, bool fTrim, const QLocale &locale_in)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
if(!valid(unit))
return QString(); // Refuse to format invalid unit
qint64 n = (qint64)nIn;
+ QLocale locale(locale_in);
qint64 coin = factor(unit);
int num_decimals = decimals(unit);
+
qint64 n_abs = (n > 0 ? n : -n);
qint64 quotient = n_abs / coin;
qint64 remainder = n_abs % coin;
- QString quotient_str = QString::number(quotient);
- QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
+ // Quotient has group (decimal) separators if locale has this enabled
+ QString quotient_str = locale.toString(quotient);
+ // Remainder does not have group separators
+ locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
+ QString remainder_str = locale.toString(remainder).rightJustified(num_decimals, '0');
- // Use SI-style thin space separators as these are locale independent and can't be
- // confused with the decimal marker.
- QChar thin_sp(THIN_SP_CP);
- int q_size = quotient_str.size();
- if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
- for (int i = 3; i < q_size; i += 3)
- quotient_str.insert(q_size - i, thin_sp);
+ if(fTrim)
+ {
+ // Right-trim excess zeros after the decimal point
+ int nTrim = 0;
+ for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
+ ++nTrim;
+ remainder_str.chop(nTrim);
+ }
if (n < 0)
quotient_str.insert(0, '-');
else if (fPlus && n > 0)
quotient_str.insert(0, '+');
- return quotient_str + QString(".") + remainder_str;
+ return quotient_str + locale.decimalPoint() + remainder_str;
}
-
// TODO: Review all remaining calls to BitcoinUnits::formatWithUnit to
// TODO: determine whether the output is used in a plain text context
// TODO: or an HTML context (and replace with
@@ -126,54 +143,64 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
// Please take care to use formatHtmlWithUnit instead, when
// appropriate.
-QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
+QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, bool trim, const QLocale &locale)
{
- return format(unit, amount, plussign, separators) + QString(" ") + name(unit);
+ return format(unit, amount, plussign, trim) + QString(" ") + name(unit);
}
-QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
+QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, bool trim, const QLocale &locale)
{
- QString str(formatWithUnit(unit, amount, plussign, separators));
+ QString str(formatWithUnit(unit, amount, plussign, trim, locale));
str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
}
-bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
+bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out, const QLocale &locale_in)
{
if(!valid(unit) || value.isEmpty())
return false; // Refuse to parse invalid unit or empty string
+
+ QLocale locale(locale_in);
+ qint64 coin = factor(unit);
int num_decimals = decimals(unit);
- // Ignore spaces and thin spaces when parsing
- QStringList parts = removeSpaces(value).split(".");
+ QStringList parts = value.split(locale.decimalPoint());
+ bool ok = false;
if(parts.size() > 2)
- {
- return false; // More than one dot
- }
- QString whole = parts[0];
- QString decimals;
-
+ return false; // More than one decimal point
+
+ // Parse whole part (may include locale-specific group separators)
+#if QT_VERSION < 0x050000
+ qint64 whole = locale.toLongLong(parts[0], &ok, 10);
+#else
+ qint64 whole = locale.toLongLong(parts[0], &ok);
+#endif
+ if(!ok)
+ return false; // Parse error
+ if(whole > maxAmount(unit) || whole < 0)
+ return false; // Overflow or underflow
+
+ // Parse decimals part (if present, may not include group separators)
+ qint64 decimals = 0;
if(parts.size() > 1)
{
- decimals = parts[1];
+ if(parts[1].size() > num_decimals)
+ return false; // Exceeds max precision
+ locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
+#if QT_VERSION < 0x050000
+ decimals = locale.toLongLong(parts[1].leftJustified(num_decimals, '0'), &ok, 10);
+#else
+ decimals = locale.toLongLong(parts[1].leftJustified(num_decimals, '0'), &ok);
+#endif
+ if(!ok || decimals < 0)
+ return false; // Parse error
}
- if(decimals.size() > num_decimals)
- {
- return false; // Exceeds max precision
- }
- bool ok = false;
- QString str = whole + decimals.leftJustified(num_decimals, '0');
- if(str.size() > 18)
- {
- return false; // Longer numbers will exceed 63 bits
- }
- CAmount retvalue(str.toLongLong(&ok));
if(val_out)
{
- *val_out = retvalue;
+ *val_out = whole * coin + decimals;
}
return ok;
}
diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h
index 1871c33a7..afc066aac 100644
--- a/src/qt/bitcoinunits.h
+++ b/src/qt/bitcoinunits.h
@@ -9,6 +9,7 @@
#include <QAbstractListModel>
#include <QString>
+#include <QLocale>
// U+2009 THIN SPACE = UTF-8 E2 80 89
#define REAL_THIN_SP_CP 0x2009
@@ -82,15 +83,17 @@ public:
static QString description(int unit);
//! Number of Satoshis (1e-8) per unit
static qint64 factor(int unit);
+ //! Max amount per unit
+ static qint64 maxAmount(int unit);
//! Number of decimals left
static int decimals(int unit);
//! Format as string
- static QString format(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
+ static QString format(int unit, const CAmount& amount, bool plussign=false, bool trim=true, const QLocale &locale=QLocale());
//! Format as string (with unit)
- static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
- static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
+ static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, bool trim=true, const QLocale &locale=QLocale());
+ static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, bool trim=true, const QLocale &locale=QLocale());
//! Parse string to coin amount
- static bool parse(int unit, const QString &value, CAmount *val_out);
+ static bool parse(int unit, const QString &value, CAmount *val_out, const QLocale &locale=QLocale());
//! Gets title for amount column including current display unit if optionsModel reference available */
static QString getAmountColumnTitle(int unit);
///@}
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index b928cebf1..13fd63274 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -161,7 +161,10 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
if(!i->second.isEmpty())
{
- if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
+ // Parse amount in C locale with no number separators
+ QLocale locale(QLocale::c());
+ locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
+ if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount, locale))
{
return false;
}