PRCYCoin  2.0.0.7rc1
P2P Digital Currency
bitcoinunits.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Copyright (c) 2014-2015 The Dash developers
3 // Copyright (c) 2015-2018 The PIVX developers
4 // Copyright (c) 2018-2020 The DAPS Project developers
5 // Distributed under the MIT/X11 software license, see the accompanying
6 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 
8 #include "amount.h"
9 #include "bitcoinunits.h"
10 #include "chainparams.h"
11 #include "primitives/transaction.h"
12 
13 #include <QSettings>
14 #include <QStringList>
15 
16 BitcoinUnits::BitcoinUnits(QObject* parent) : QAbstractListModel(parent),
17  unitlist(availableUnits())
18 {
19 }
20 
21 QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
22 {
23  QList<BitcoinUnits::Unit> unitlist;
24  unitlist.append(PRCY);
25  unitlist.append(mPRCY);
26  unitlist.append(uPRCY);
27  return unitlist;
28 }
29 
30 bool BitcoinUnits::valid(int unit)
31 {
32  switch (unit) {
33  case PRCY:
34  case mPRCY:
35  case uPRCY:
36  return true;
37  default:
38  return false;
39  }
40 }
41 
42 QString BitcoinUnits::id(int unit)
43 {
44  switch (unit) {
45  case PRCY:
46  return QString("prcycoin");
47  case mPRCY:
48  return QString("mprcycoin");
49  case uPRCY:
50  return QString::fromUtf8("uprcycoin");
51  default:
52  return QString("???");
53  }
54 }
55 
56 QString BitcoinUnits::name(int unit)
57 {
58  const QString CURR_UNIT = QString(CURRENCY_UNIT.c_str());
59  if (Params().NetworkID() == CBaseChainParams::MAIN) {
60  switch (unit) {
61  case PRCY:
62  return CURR_UNIT;
63  case mPRCY:
64  return QString("m") + CURR_UNIT;
65  case uPRCY:
66  return QString::fromUtf8("μ") + CURR_UNIT;
67  default:
68  return QString("???");
69  }
70  } else {
71  switch (unit) {
72  case PRCY:
73  return QString("t") + CURR_UNIT;
74  case mPRCY:
75  return QString("mt") + CURR_UNIT;
76  case uPRCY:
77  return QString::fromUtf8("μt") + CURR_UNIT;
78  default:
79  return QString("???");
80  }
81  }
82 }
83 
84 QString BitcoinUnits::description(int unit)
85 {
86  const QString CURR_UNIT = QString(CURRENCY_UNIT.c_str());
87  if (Params().NetworkID() == CBaseChainParams::MAIN) {
88  switch (unit) {
89  case PRCY:
90  return CURR_UNIT;
91  case mPRCY:
92  return QString("Milli-") + CURR_UNIT + QString(" (1 / 1" THIN_SP_UTF8 "000)");
93  case uPRCY:
94  return QString("Micro-") + CURR_UNIT + QString(" (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
95  default:
96  return QString("???");
97  }
98  } else {
99  switch (unit) {
100  case PRCY:
101  return QString("Test") + CURR_UNIT;
102  case mPRCY:
103  return QString("Milli-Test") + CURR_UNIT + QString(" (1 / 1" THIN_SP_UTF8 "000)");
104  case uPRCY:
105  return QString("Micro-Test") + CURR_UNIT + QString(" (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
106  default:
107  return QString("???");
108  }
109  }
110 }
111 
112 qint64 BitcoinUnits::factor(int unit)
113 {
114  switch (unit) {
115  case PRCY:
116  return 100000000;
117  case mPRCY:
118  return 100000;
119  case uPRCY:
120  return 100;
121  default:
122  return 100000000;
123  }
124 }
125 
127 {
128  switch (unit) {
129  case PRCY:
130  return 8;
131  case mPRCY:
132  return 5;
133  case uPRCY:
134  return 2;
135  default:
136  return 0;
137  }
138 }
139 
140 QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators)
141 {
142  // Note: not using straight sprintf here because we do NOT want
143  // localized number formatting.
144  if (!valid(unit))
145  return QString(); // Refuse to format invalid unit
146  qint64 n = (qint64)nIn;
147  qint64 coin = factor(unit);
148  int num_decimals = decimals(unit);
149  qint64 n_abs = (n > 0 ? n : -n);
150  qint64 quotient = n_abs / coin;
151  qint64 remainder = n_abs % coin;
152  QString quotient_str = QString::number(quotient);
153  QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
154 
155  // Use SI-style thin space separators as these are locale independent and can't be
156  // confused with the decimal marker.
157  QChar thin_sp(THIN_SP_CP);
158  int q_size = quotient_str.size();
159  if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
160  for (int i = 3; i < q_size; i += 3)
161  quotient_str.insert(q_size - i, thin_sp);
162 
163  if (n < 0)
164  quotient_str.insert(0, '-');
165  else if (fPlus && n > 0)
166  quotient_str.insert(0, '+');
167 
168  if (num_decimals <= 0)
169  return quotient_str;
170 
171  return quotient_str + QString(".") + remainder_str;
172 }
173 
174 
175 // TODO: Review all remaining calls to BitcoinUnits::formatWithUnit to
176 // TODO: determine whether the output is used in a plain text context
177 // TODO: or an HTML context (and replace with
178 // TODO: BtcoinUnits::formatHtmlWithUnit in the latter case). Hopefully
179 // TODO: there aren't instances where the result could be used in
180 // TODO: either context.
181 
182 // NOTE: Using formatWithUnit in an HTML context risks wrapping
183 // quantities at the thousands separator. More subtly, it also results
184 // in a standard space rather than a thin space, due to a bug in Qt's
185 // XML whitespace canonicalisation
186 //
187 // Please take care to use formatHtmlWithUnit instead, when
188 // appropriate.
189 
190 QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
191 {
192  return format(unit, amount, plussign, separators) + QString(" ") + name(unit);
193 }
194 
195 QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
196 {
197  QString str(formatWithUnit(unit, amount, plussign, separators));
198  str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
199  return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
200 }
201 
202 QString BitcoinUnits::floorWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
203 {
204  QSettings settings;
205  int digits = settings.value("digits").toInt();
206 
207  QString result = format(unit, amount, plussign, separators);
208  if (decimals(unit) > digits) result.chop(decimals(unit) - digits);
209 
210  return result + QString(" ") + name(unit);
211 }
212 
213 QString BitcoinUnits::floorHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
214 {
215  QString str(floorWithUnit(unit, amount, plussign, separators));
216  str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
217  return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
218 }
219 
220 bool BitcoinUnits::parse(int unit, const QString& value, CAmount* val_out)
221 {
222  if (!valid(unit) || value.isEmpty())
223  return false; // Refuse to parse invalid unit or empty string
224  int num_decimals = decimals(unit);
225 
226  // Ignore spaces and thin spaces when parsing
227  QStringList parts = removeSpaces(value).split(".");
228 
229  if (parts.size() > 2) {
230  return false; // More than one dot
231  }
232  QString whole = parts[0];
233  QString decimals;
234 
235  if (parts.size() > 1) {
236  decimals = parts[1];
237  }
238  if (decimals.size() > num_decimals) {
239  return false; // Exceeds max precision
240  }
241  bool ok = false;
242  QString str = whole + decimals.leftJustified(num_decimals, '0');
243 
244  if (str.size() > 18) {
245  return false; // Longer numbers will exceed 63 bits
246  }
247  CAmount retvalue(str.toLongLong(&ok));
248  if (val_out) {
249  *val_out = retvalue;
250  }
251  return ok;
252 }
253 
255 {
256  QString amountTitle = QObject::tr("Amount");
257  if (BitcoinUnits::valid(unit)) {
258  amountTitle += " (" + BitcoinUnits::name(unit) + ")";
259  }
260  return amountTitle;
261 }
262 
263 int BitcoinUnits::rowCount(const QModelIndex& parent) const
264 {
265  Q_UNUSED(parent);
266  return unitlist.size();
267 }
268 
269 QVariant BitcoinUnits::data(const QModelIndex& index, int role) const
270 {
271  int row = index.row();
272  if (row >= 0 && row < unitlist.size()) {
273  Unit unit = unitlist.at(row);
274  switch (role) {
275  case Qt::EditRole:
276  case Qt::DisplayRole:
277  return QVariant(name(unit));
278  case Qt::ToolTipRole:
279  return QVariant(description(unit));
280  case UnitRole:
281  return QVariant(static_cast<int>(unit));
282  }
283  }
284  return QVariant();
285 }
286 
288 {
289  return MAX_MONEY_OUT;
290 }
BitcoinUnits::id
static QString id(int unit)
Identifier, e.g. for image names.
Definition: bitcoinunits.cpp:42
BitcoinUnits::rowCount
int rowCount(const QModelIndex &parent) const
Definition: bitcoinunits.cpp:263
BitcoinUnits::floorWithUnit
static QString floorWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit) but floor value up to "digits" settings.
Definition: bitcoinunits.cpp:202
transaction.h
BitcoinUnits::decimals
static int decimals(int unit)
Number of decimals left.
Definition: bitcoinunits.cpp:126
BitcoinUnits::data
QVariant data(const QModelIndex &index, int role) const
Definition: bitcoinunits.cpp:269
BitcoinUnits::formatWithUnit
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
Definition: bitcoinunits.cpp:190
BitcoinUnits::maxMoney
static CAmount maxMoney()
Return maximum number of base units (Satoshis)
Definition: bitcoinunits.cpp:287
THIN_SP_UTF8
#define THIN_SP_UTF8
Definition: bitcoinunits.h:44
chainparams.h
BitcoinUnits::factor
static qint64 factor(int unit)
Number of Satoshis (1e-8) per unit.
Definition: bitcoinunits.cpp:112
BitcoinUnits::parse
static bool parse(int unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
Definition: bitcoinunits.cpp:220
BitcoinUnits::valid
static bool valid(int unit)
Is unit ID valid?
Definition: bitcoinunits.cpp:30
BitcoinUnits::description
static QString description(int unit)
Longer description.
Definition: bitcoinunits.cpp:84
BitcoinUnits::removeSpaces
static QString removeSpaces(QString text)
Definition: bitcoinunits.h:116
BitcoinUnits::availableUnits
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
Definition: bitcoinunits.cpp:21
THIN_SP_CP
#define THIN_SP_CP
Definition: bitcoinunits.h:43
BitcoinUnits::PRCY
@ PRCY
Definition: bitcoinunits.h:61
BitcoinUnits::unitlist
QList< BitcoinUnits::Unit > unitlist
Definition: bitcoinunits.h:130
CBaseChainParams::MAIN
@ MAIN
Definition: chainparamsbase.h:19
CAmount
int64_t CAmount
Amount in PRCY (Can be negative)
Definition: amount.h:17
BitcoinUnits::SeparatorStyle
SeparatorStyle
Definition: bitcoinunits.h:66
THIN_SP_HTML
#define THIN_SP_HTML
Definition: bitcoinunits.h:45
BitcoinUnits::separatorStandard
@ separatorStandard
Definition: bitcoinunits.h:68
BitcoinUnits::format
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
Definition: bitcoinunits.cpp:140
BitcoinUnits::separatorAlways
@ separatorAlways
Definition: bitcoinunits.h:69
BitcoinUnits::getAmountColumnTitle
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
Definition: bitcoinunits.cpp:254
BitcoinUnits::Unit
Unit
PRCY units.
Definition: bitcoinunits.h:60
BitcoinUnits::mPRCY
@ mPRCY
Definition: bitcoinunits.h:62
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:463
bitcoinunits.h
BitcoinUnits::formatHtmlWithUnit
static QString formatHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Definition: bitcoinunits.cpp:195
BitcoinUnits::uPRCY
@ uPRCY
Definition: bitcoinunits.h:63
CURRENCY_UNIT
const std::string CURRENCY_UNIT
Definition: amount.cpp:10
BitcoinUnits::floorHtmlWithUnit
static QString floorHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Definition: bitcoinunits.cpp:213
BitcoinUnits::name
static QString name(int unit)
Short name.
Definition: bitcoinunits.cpp:56
BitcoinUnits::BitcoinUnits
BitcoinUnits(QObject *parent)
Definition: bitcoinunits.cpp:16
amount.h
BitcoinUnits::UnitRole
@ UnitRole
Unit identifier.
Definition: bitcoinunits.h:110