Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
bitcoinunits.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2016 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <qt/bitcoinunits.h>
6
7#include <common/args.h>
8#include <consensus/amount.h>
9#include <currencyunit.h>
10
11#include <QStringList>
12
13#include <cassert>
14
15// clang-format off
17 std::map<
19 std::tuple<
20 QString /* longname */,
21 QString /* description */
22 >
23 >;
24static const unitNameMap xecUnits = {
26 {"XEC",
27 "eCash"}},
29 {"Satoshi (sat)",
30 "Satoshi (sat) (1 / 100)"}},
31};
32static const unitNameMap bchUnits = {
34 {"BCHA",
35 "Bitcoins"}},
37 {"Satoshi (sat)",
38 "Satoshi (sat) (1 / 100" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)"}},
39};
40// clang-format on
41
43 return gArgs.GetBoolArg("-ecash", DEFAULT_ECASH) ? xecUnits : bchUnits;
44}
45
47 : QAbstractListModel(parent), unitlist(availableUnits()) {}
48
55
56bool BitcoinUnits::valid(int unit) {
57 switch (unit) {
58 case base:
59 case sub:
60 return true;
61 default:
62 return false;
63 }
64}
65
67 const auto &units = getUnitsAtRuntime();
68 auto it = units.find(BitcoinUnits::Unit(unit));
69 return it != units.end() ? std::get<0>(it->second) : "???";
70}
71
73 if (unit == sub) {
74 return QString("sat");
75 }
76 return longName(unit);
77}
78
80 const auto &units = getUnitsAtRuntime();
81 auto it = units.find(BitcoinUnits::Unit(unit));
82 return it != units.end() ? std::get<1>(it->second) : "???";
83}
84
86 const auto &currency = Currency::get();
87 switch (unit) {
88 case base:
89 return currency.baseunit;
90 case sub:
91 return currency.subunit;
92 default:
93 assert(false && "non-existent BitcoinUnits::Unit");
94 }
95}
96
98 switch (unit) {
99 case base:
100 return Currency::get().decimals;
101 case sub:
102 return 0;
103 default:
104 assert(false && "non-existent BitcoinUnits::Unit");
105 }
106}
107
108QString BitcoinUnits::format(int unit, const Amount nIn, bool fPlus,
110 // Note: not using straight sprintf here because we do NOT want
111 // localized number formatting.
112 if (!valid(unit)) {
113 // Refuse to format invalid unit
114 return QString();
115 }
116 qint64 n = qint64(nIn / SATOSHI);
117 qint64 coin = factor(unit) / SATOSHI;
118 int num_decimals = decimals(unit);
119 qint64 n_abs = (n > 0 ? n : -n);
120 qint64 quotient = n_abs / coin;
121 QString quotient_str = QString::number(quotient);
122 if (justify) {
123 quotient_str = quotient_str.rightJustified(16 - num_decimals, ' ');
124 }
125
126 // Use SI-style thin space separators as these are locale independent and
127 // can't be confused with the decimal marker.
129 int q_size = quotient_str.size();
132 for (int i = 3; i < q_size; i += 3) {
133 quotient_str.insert(q_size - i, thin_sp);
134 }
135 }
136
137 if (n < 0) {
138 quotient_str.insert(0, '-');
139 } else if (fPlus && n > 0) {
140 quotient_str.insert(0, '+');
141 }
142
143 if (num_decimals > 0) {
144 qint64 remainder = n_abs % coin;
146 QString::number(remainder).rightJustified(num_decimals, '0');
147 return quotient_str + QString(".") + remainder_str;
148 } else {
149 return quotient_str;
150 }
151}
152
153// NOTE: Using formatWithUnit in an HTML context risks wrapping
154// quantities at the thousands separator. More subtly, it also results
155// in a standard space rather than a thin space, due to a bug in Qt's
156// XML whitespace canonicalisation
157//
158// Please take care to use formatHtmlWithUnit instead, when
159// appropriate.
160
163 return format(unit, amount, plussign, separators) + QString(" ") +
164 shortName(unit);
165}
166
168 bool plussign,
170 QString str(formatWithUnit(unit, amount, plussign, separators));
171 str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
172 return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
173}
174
177 bool privacy) {
178 assert(amount >= Amount::zero());
179 QString value;
180 if (privacy) {
181 value = format(unit, Amount::zero(), false, separators, true)
182 .replace('0', '#');
183 } else {
184 value = format(unit, amount, false, separators, true);
185 }
186 return value + QString(" ") + shortName(unit);
187}
188
189bool BitcoinUnits::parse(int unit, const QString &value, Amount *val_out) {
190 if (!valid(unit) || value.isEmpty()) {
191 // Refuse to parse invalid unit or empty string
192 return false;
193 }
194 int num_decimals = decimals(unit);
195
196 // Ignore spaces and thin spaces when parsing
197 QStringList parts = removeSpaces(value).split(".");
198
199 if (parts.size() > 2) {
200 // More than one dot
201 return false;
202 }
203 QString whole = parts[0];
205
206 if (parts.size() > 1) {
207 decimals = parts[1];
208 }
209 if (decimals.size() > num_decimals) {
210 // Exceeds max precision
211 return false;
212 }
213 bool ok = false;
214 QString str = whole + decimals.leftJustified(num_decimals, '0');
215
216 if (str.size() > 18) {
217 // Longer numbers will exceed 63 bits
218 return false;
219 }
220 Amount retvalue(int64_t(str.toLongLong(&ok)) * SATOSHI);
221 if (val_out) {
222 *val_out = retvalue;
223 }
224 return ok;
225}
226
228 QString amountTitle = QObject::tr("Amount");
229 if (BitcoinUnits::valid(unit)) {
230 amountTitle += " (" + BitcoinUnits::shortName(unit) + ")";
231 }
232 return amountTitle;
233}
234
235int BitcoinUnits::rowCount(const QModelIndex &parent) const {
236 Q_UNUSED(parent);
237 return unitlist.size();
238}
239
240QVariant BitcoinUnits::data(const QModelIndex &index, int role) const {
241 int row = index.row();
242 if (row >= 0 && row < unitlist.size()) {
243 Unit unit = unitlist.at(row);
244 switch (role) {
245 case Qt::EditRole:
246 case Qt::DisplayRole:
247 return QVariant(longName(unit));
248 case Qt::ToolTipRole:
249 return QVariant(description(unit));
250 case UnitRole:
251 return QVariant(static_cast<int>(unit));
252 }
253 }
254 return QVariant();
255}
256
static constexpr Amount SATOSHI
Definition amount.h:143
static constexpr Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition amount.h:165
ArgsManager gArgs
Definition args.cpp:38
static const unitNameMap xecUnits
static const unitNameMap bchUnits
std::map< BitcoinUnits::Unit, std::tuple< QString, QString > > unitNameMap
static const unitNameMap & getUnitsAtRuntime()
#define THIN_SP_CP
#define THIN_SP_HTML
#define THIN_SP_UTF8
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition args.cpp:556
@ UnitRole
Unit identifier.
int rowCount(const QModelIndex &parent) const override
QList< BitcoinUnits::Unit > unitlist
static QString formatWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
static int decimals(int unit)
Number of decimals left.
QVariant data(const QModelIndex &index, int role) const override
static Amount factor(int unit)
Number of Satoshis (1e-8) per unit.
static bool valid(int unit)
Is unit ID valid?
static QString formatWithPrivacy(int unit, const Amount &amount, SeparatorStyle separators, bool privacy)
Format as string (with unit) of fixed length to preserve privacy, if it is set.
static QString description(int unit)
Longer description.
static QString removeSpaces(QString text)
static QString longName(int unit)
Long name.
static Amount maxMoney()
Return maximum number of base units (Satoshis)
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
static QString format(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
static bool parse(int unit, const QString &value, Amount *val_out)
Parse string to coin amount.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
Unit
Currency units Please add only sensible ones.
BitcoinUnits(QObject *parent)
static QString shortName(int unit)
Short name.
static QString formatHtmlWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as HTML string (with unit)
constexpr bool DEFAULT_ECASH
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
static constexpr Amount zero() noexcept
Definition amount.h:32
static const Currency & get()
Definition amount.cpp:18
uint8_t decimals
Definition amount.h:149
assert(!tx.IsCoinBase())