Bitcoin ABC  0.22.13
P2P Digital Currency
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 <network.h>
8 
9 #include <QStringList>
10 
12  : QAbstractListModel(parent), unitlist(availableUnits()) {}
13 
14 QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits() {
15  QList<BitcoinUnits::Unit> unitlist;
16  unitlist.append(BCH);
17  unitlist.append(mBCH);
18  unitlist.append(uBCH);
19  unitlist.append(SAT);
20  return unitlist;
21 }
22 
23 bool BitcoinUnits::valid(int unit) {
24  switch (unit) {
25  case BCH:
26  case mBCH:
27  case uBCH:
28  case SAT:
29  return true;
30  default:
31  return false;
32  }
33 }
34 
35 QString BitcoinUnits::longName(int unit) {
36  switch (unit) {
37  case BCH:
38  return QString(CURRENCY_UNIT.c_str());
39  case mBCH:
40  return QString("m") + QString(CURRENCY_UNIT.c_str());
41  case uBCH:
42  return QString::fromUtf8("μ") + QString(CURRENCY_UNIT.c_str());
43  case SAT:
44  return QString("Satoshi (sat)");
45  default:
46  return QString("???");
47  }
48 }
49 
50 QString BitcoinUnits::shortName(int unit) {
51  switch (unit) {
52  case SAT:
53  return QString("sat");
54  default:
55  return longName(unit);
56  }
57 }
58 
59 QString BitcoinUnits::description(int unit) {
60  switch (unit) {
61  case BCH:
62  return QString("Bitcoins");
63  case mBCH:
64  return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)");
65  case uBCH:
66  return QString("Micro-Bitcoins (1 / 1" THIN_SP_UTF8
67  "000" THIN_SP_UTF8 "000)");
68  case SAT:
69  return QString("Satoshi (sat) (1 / 100" THIN_SP_UTF8
70  "000" THIN_SP_UTF8 "000)");
71  default:
72  return QString("???");
73  }
74 }
75 
76 qint64 BitcoinUnits::factor(int unit) {
77  switch (unit) {
78  case BCH:
79  return 100000000;
80  case mBCH:
81  return 100000;
82  case uBCH:
83  return 100;
84  case SAT:
85  return 1;
86  default:
87  return 100000000;
88  }
89 }
90 
91 int BitcoinUnits::decimals(int unit) {
92  switch (unit) {
93  case BCH:
94  return 8;
95  case mBCH:
96  return 5;
97  case uBCH:
98  return 2;
99  case SAT:
100  return 0;
101  default:
102  return 0;
103  }
104 }
105 
106 QString BitcoinUnits::format(int unit, const Amount nIn, bool fPlus,
107  SeparatorStyle separators) {
108  // Note: not using straight sprintf here because we do NOT want
109  // localized number formatting.
110  if (!valid(unit)) {
111  // Refuse to format invalid unit
112  return QString();
113  }
114  qint64 n = qint64(nIn / SATOSHI);
115  qint64 coin = factor(unit);
116  int num_decimals = decimals(unit);
117  qint64 n_abs = (n > 0 ? n : -n);
118  qint64 quotient = n_abs / coin;
119  QString quotient_str = QString::number(quotient);
120 
121  // Use SI-style thin space separators as these are locale independent and
122  // can't be confused with the decimal marker.
123  QChar thin_sp(THIN_SP_CP);
124  int q_size = quotient_str.size();
125  if (separators == separatorAlways ||
126  (separators == separatorStandard && q_size > 4)) {
127  for (int i = 3; i < q_size; i += 3) {
128  quotient_str.insert(q_size - i, thin_sp);
129  }
130  }
131 
132  if (n < 0) {
133  quotient_str.insert(0, '-');
134  } else if (fPlus && n > 0) {
135  quotient_str.insert(0, '+');
136  }
137 
138  if (num_decimals > 0) {
139  qint64 remainder = n_abs % coin;
140  QString remainder_str =
141  QString::number(remainder).rightJustified(num_decimals, '0');
142  return quotient_str + QString(".") + remainder_str;
143  } else {
144  return quotient_str;
145  }
146 }
147 
148 // NOTE: Using formatWithUnit in an HTML context risks wrapping
149 // quantities at the thousands separator. More subtly, it also results
150 // in a standard space rather than a thin space, due to a bug in Qt's
151 // XML whitespace canonicalisation
152 //
153 // Please take care to use formatHtmlWithUnit instead, when
154 // appropriate.
155 
156 QString BitcoinUnits::formatWithUnit(int unit, const Amount amount,
157  bool plussign, SeparatorStyle separators) {
158  return format(unit, amount, plussign, separators) + QString(" ") +
159  shortName(unit);
160 }
161 
162 QString BitcoinUnits::formatHtmlWithUnit(int unit, const Amount amount,
163  bool plussign,
164  SeparatorStyle separators) {
165  QString str(formatWithUnit(unit, amount, plussign, separators));
166  str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
167  return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
168 }
169 
170 bool BitcoinUnits::parse(int unit, const QString &value, Amount *val_out) {
171  if (!valid(unit) || value.isEmpty()) {
172  // Refuse to parse invalid unit or empty string
173  return false;
174  }
175  int num_decimals = decimals(unit);
176 
177  // Ignore spaces and thin spaces when parsing
178  QStringList parts = removeSpaces(value).split(".");
179 
180  if (parts.size() > 2) {
181  // More than one dot
182  return false;
183  }
184  QString whole = parts[0];
185  QString decimals;
186 
187  if (parts.size() > 1) {
188  decimals = parts[1];
189  }
190  if (decimals.size() > num_decimals) {
191  // Exceeds max precision
192  return false;
193  }
194  bool ok = false;
195  QString str = whole + decimals.leftJustified(num_decimals, '0');
196 
197  if (str.size() > 18) {
198  // Longer numbers will exceed 63 bits
199  return false;
200  }
201  Amount retvalue(int64_t(str.toLongLong(&ok)) * SATOSHI);
202  if (val_out) {
203  *val_out = retvalue;
204  }
205  return ok;
206 }
207 
209  QString amountTitle = QObject::tr("Amount");
210  if (BitcoinUnits::valid(unit)) {
211  amountTitle += " (" + BitcoinUnits::shortName(unit) + ")";
212  }
213  return amountTitle;
214 }
215 
216 int BitcoinUnits::rowCount(const QModelIndex &parent) const {
217  Q_UNUSED(parent);
218  return unitlist.size();
219 }
220 
221 QVariant BitcoinUnits::data(const QModelIndex &index, int role) const {
222  int row = index.row();
223  if (row >= 0 && row < unitlist.size()) {
224  Unit unit = unitlist.at(row);
225  switch (role) {
226  case Qt::EditRole:
227  case Qt::DisplayRole:
228  return QVariant(longName(unit));
229  case Qt::ToolTipRole:
230  return QVariant(description(unit));
231  case UnitRole:
232  return QVariant(static_cast<int>(unit));
233  }
234  }
235  return QVariant();
236 }
237 
239  return MAX_MONEY;
240 }
static QString formatWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
const std::string CURRENCY_UNIT
Definition: network.cpp:8
QList< BitcoinUnits::Unit > unitlist
Definition: bitcoinunits.h:104
Unit
Bitcoin units (Bitcoin Cash unit work the same as Bitoin).
Definition: bitcoinunits.h:43
Definition: amount.h:17
static bool valid(int unit)
Is unit ID valid?
#define THIN_SP_HTML
Definition: bitcoinunits.h:26
static constexpr Amount SATOSHI
Definition: amount.h:151
static const Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:165
static QString longName(int unit)
Long name.
*static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available...
BitcoinUnits(QObject *parent)
static QString description(int unit)
Longer description.
static QString shortName(int unit)
Short name.
#define THIN_SP_UTF8
Definition: bitcoinunits.h:25
static qint64 factor(int unit)
Number of Satoshis (1e-8) per unit.
Unit identifier.
Definition: bitcoinunits.h:88
static Amount maxMoney()
Return maximum number of base units (Satoshis)
static QString format(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
int rowCount(const QModelIndex &parent) const override
static QString formatHtmlWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as HTML string (with unit)
static QString removeSpaces(QString text)
Definition: bitcoinunits.h:94
QVariant data(const QModelIndex &index, int role) const override
static bool parse(int unit, const QString &value, Amount *val_out)
Parse string to coin amount.
#define THIN_SP_CP
Definition: bitcoinunits.h:24
static int decimals(int unit)
Number of decimals left.