Fabcoin Core  0.16.2
P2P Digital Currency
fabcoinunits.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2017 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 <fabcoinunits.h>
6 
8 
9 #include <QStringList>
10 
11 FabcoinUnits::FabcoinUnits(QObject *parent):
12  QAbstractListModel(parent),
13  unitlist(availableUnits())
14 {
15 }
16 
17 QList<FabcoinUnits::Unit> FabcoinUnits::availableUnits()
18 {
19  QList<FabcoinUnits::Unit> unitlist;
20  unitlist.append(FAB);
21  unitlist.append(mFAB);
22  unitlist.append(uFAB);
23  return unitlist;
24 }
25 
26 bool FabcoinUnits::valid(int unit)
27 {
28  switch(unit)
29  {
30  case FAB:
31  case mFAB:
32  case uFAB:
33  return true;
34  default:
35  return false;
36  }
37 }
38 
39 QString FabcoinUnits::name(int unit)
40 {
41  switch(unit)
42  {
43  case FAB: return QString("FAB");
44  case mFAB: return QString("mFAB");
45  case uFAB: return QString::fromUtf8("μFAB");
46  default: return QString("???");
47  }
48 }
49 
50 QString FabcoinUnits::description(int unit)
51 {
52  switch(unit)
53  {
54  case FAB: return QString("Fabcoins");
55  case mFAB: return QString("Milli-Fabcoins (1 / 1" THIN_SP_UTF8 "000)");
56  case uFAB: return QString("Micro-Fabcoins (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
57  default: return QString("???");
58  }
59 }
60 
61 qint64 FabcoinUnits::factor(int unit)
62 {
63  switch(unit)
64  {
65  case FAB: return 100000000;
66  case mFAB: return 100000;
67  case uFAB: return 100;
68  default: return 100000000;
69  }
70 }
71 
72 int256_t FabcoinUnits::tokenFactor(int decimalUnits)
73 {
74  if(decimalUnits == 0)
75  return 0;
76  int256_t factor = 1;
77  for(int i = 0; i < decimalUnits; i++){
78  factor *= 10;
79  }
80  return factor;
81 }
83 {
84  switch(unit)
85  {
86  case FAB: return 8;
87  case mFAB: return 5;
88  case uFAB: return 2;
89  default: return 0;
90  }
91 }
92 
93 QString FabcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators)
94 {
95  // Note: not using straight sprintf here because we do NOT want
96  // localized number formatting.
97  if(!valid(unit))
98  return QString(); // Refuse to format invalid unit
99  qint64 n = (qint64)nIn;
100  qint64 coin = factor(unit);
101  int num_decimals = decimals(unit);
102  qint64 n_abs = (n > 0 ? n : -n);
103  qint64 quotient = n_abs / coin;
104  qint64 remainder = n_abs % coin;
105  QString quotient_str = QString::number(quotient);
106  QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
107 
108  // Use SI-style thin space separators as these are locale independent and can't be
109  // confused with the decimal marker.
110  QChar thin_sp(THIN_SP_CP);
111  int q_size = quotient_str.size();
112  if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
113  for (int i = 3; i < q_size; i += 3)
114  quotient_str.insert(q_size - i, thin_sp);
115 
116  if (n < 0)
117  quotient_str.insert(0, '-');
118  else if (fPlus && n > 0)
119  quotient_str.insert(0, '+');
120  return quotient_str + QString(".") + remainder_str;
121 }
122 
123 
124 // NOTE: Using formatWithUnit in an HTML context risks wrapping
125 // quantities at the thousands separator. More subtly, it also results
126 // in a standard space rather than a thin space, due to a bug in Qt's
127 // XML whitespace canonicalisation
128 //
129 // Please take care to use formatHtmlWithUnit instead, when
130 // appropriate.
131 
132 QString FabcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
133 {
134  return format(unit, amount, plussign, separators) + QString(" ") + name(unit);
135 }
136 
137 QString FabcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
138 {
139  QString str(formatWithUnit(unit, amount, plussign, separators));
140  str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
141  return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
142 }
143 
144 
145 bool FabcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
146 {
147  if(!valid(unit) || value.isEmpty())
148  return false; // Refuse to parse invalid unit or empty string
149  int num_decimals = decimals(unit);
150 
151  // Ignore spaces and thin spaces when parsing
152  QStringList parts = removeSpaces(value).split(".");
153 
154  if(parts.size() > 2)
155  {
156  return false; // More than one dot
157  }
158  QString whole = parts[0];
159  QString decimals;
160 
161  if(parts.size() > 1)
162  {
163  decimals = parts[1];
164  }
165  if(decimals.size() > num_decimals)
166  {
167  return false; // Exceeds max precision
168  }
169  bool ok = false;
170  QString str = whole + decimals.leftJustified(num_decimals, '0');
171 
172  if(str.size() > 18)
173  {
174  return false; // Longer numbers will exceed 63 bits
175  }
176  CAmount retvalue(str.toLongLong(&ok));
177  if(val_out)
178  {
179  *val_out = retvalue;
180  }
181  return ok;
182 }
183 
184 bool FabcoinUnits::parseToken(int decimal_units, const QString &value, int256_t *val_out)
185 {
186  if(value.isEmpty())
187  return false; // Refuse to parse empty string
188 
189  // Ignore spaces and thin spaces when parsing
190  QStringList parts = removeSpaces(value).split(".");
191 
192  if(parts.size() > 2)
193  {
194  return false; // More than one dot
195  }
196  QString whole = parts[0];
197  QString decimals;
198 
199  if(parts.size() > 1)
200  {
201  decimals = parts[1];
202  }
203  if(decimals.size() > decimal_units)
204  {
205  return false; // Exceeds max precision
206  }
207  bool ok = false;
208  QString str = whole + decimals.leftJustified(decimal_units, '0');
209 
210  //remove leading zeros from str
211  while (str.startsWith('0'))
212  {
213  str.remove(0,1);
214  }
215 
216  if(str.size() > 77)
217  {
218  return false; // Longer numbers will exceed 256 bits
219  }
220 
221  int256_t retvalue;
222  try
223  {
224  retvalue = int256_t(str.toStdString());
225  ok = true;
226  }
227  catch(...)
228  {
229  ok = false;
230  }
231 
232  if(val_out)
233  {
234  *val_out = retvalue;
235  }
236  return ok;
237 }
238 
239 QString FabcoinUnits::formatToken(int decimal_units, const int256_t& nIn, bool fPlus, SeparatorStyle separators)
240 {
241  int256_t n = nIn;
242  int256_t n_abs = (n > 0 ? n : -n);
243  int256_t quotient;
244  int256_t remainder;
245  QString quotient_str;
246  QString remainder_str;
247  int256_t coin = tokenFactor(decimal_units);
248  if(coin != 0)
249  {
250  quotient = n_abs / coin;
251  remainder = n_abs % coin;
252  remainder_str = QString::fromStdString(remainder.str()).rightJustified(decimal_units, '0');
253  }
254  else
255  {
256  quotient = n_abs;
257  }
258  quotient_str = QString::fromStdString(quotient.str());
259 
260  // Use SI-style thin space separators as these are locale independent and can't be
261  // confused with the decimal marker.
262  QChar thin_sp(THIN_SP_CP);
263  int q_size = quotient_str.size();
264  if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
265  for (int i = 3; i < q_size; i += 3)
266  quotient_str.insert(q_size - i, thin_sp);
267 
268  if (n < 0)
269  quotient_str.insert(0, '-');
270  else if (fPlus && n > 0)
271  quotient_str.insert(0, '+');
272  if(remainder_str.size())
273  {
274  return quotient_str + QString(".") + remainder_str;
275  }
276  return quotient_str;
277 }
278 
279 QString FabcoinUnits::formatTokenWithUnit(const QString unit, int decimals, const int256_t &amount, bool plussign, FabcoinUnits::SeparatorStyle separators)
280 {
281  return formatToken(decimals, amount, plussign, separators) + " " + unit;
282 }
283 
285 {
286  QString amountTitle = QObject::tr("Amount");
287  if (FabcoinUnits::valid(unit))
288  {
289  amountTitle += " ("+FabcoinUnits::name(unit) + ")";
290  }
291  return amountTitle;
292 }
293 
294 int FabcoinUnits::rowCount(const QModelIndex &parent) const
295 {
296  Q_UNUSED(parent);
297  return unitlist.size();
298 }
299 
300 QVariant FabcoinUnits::data(const QModelIndex &index, int role) const
301 {
302  int row = index.row();
303  if(row >= 0 && row < unitlist.size())
304  {
305  Unit unit = unitlist.at(row);
306  switch(role)
307  {
308  case Qt::EditRole:
309  case Qt::DisplayRole:
310  return QVariant(name(unit));
311  case Qt::ToolTipRole:
312  return QVariant(description(unit));
313  case UnitRole:
314  return QVariant(static_cast<int>(unit));
315  }
316  }
317  return QVariant();
318 }
319 
321 {
322  return MAX_MONEY;
323 }
#define THIN_SP_CP
Definition: fabcoinunits.h:42
Unit identifier.
Definition: fabcoinunits.h:114
static QString formatTokenWithUnit(const QString unit, int decimals, const int256_t &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format token as string.
#define THIN_SP_HTML
Definition: fabcoinunits.h:44
static bool parse(int unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
static int decimals(int unit)
Number of decimals left.
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
int64_t CAmount
Amount in lius (Can be negative)
Definition: amount.h:15
#define THIN_SP_UTF8
Definition: fabcoinunits.h:43
FabcoinUnits(QObject *parent)
static bool valid(int unit)
Is unit ID valid?
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
Unit
Fabcoin units.
Definition: fabcoinunits.h:59
QVariant data(const QModelIndex &index, int role) const
static CAmount maxMoney()
Return maximum number of base units (Satoshis)
static QString formatToken(int decimal_units, const int256_t &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format token as string.
static qint64 factor(int unit)
Number of Satoshis (1e-8) per unit.
static int256_t tokenFactor(int unit)
Token factor from decimals.
QList< FabcoinUnits::Unit > unitlist
Definition: fabcoinunits.h:134
int rowCount(const QModelIndex &parent) const
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available */...
static QString name(int unit)
Short name.
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
static QString removeSpaces(QString text)
Definition: fabcoinunits.h:120
static bool parseToken(int decimal_units, const QString &value, int256_t *val_out)
Parse string to token amount.
static QString description(int unit)
Longer description.
static QString formatHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as HTML string (with unit)