Use standard C99 (and Qt) types for 64-bit integers
[novacoin.git] / src / qt / bitcoinunits.cpp
1 #include "bitcoinunits.h"
2
3 #include <QtGlobal>
4 #include <QStringList>
5
6 BitcoinUnits::BitcoinUnits(QObject *parent):
7         QAbstractListModel(parent),
8         unitlist(availableUnits())
9 {
10 }
11
12 QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
13 {
14     QList<BitcoinUnits::Unit> unitlist;
15     unitlist.append(BTC);
16     unitlist.append(mBTC);
17     unitlist.append(uBTC);
18     return unitlist;
19 }
20
21 bool BitcoinUnits::valid(int unit)
22 {
23     switch(unit)
24     {
25     case BTC:
26     case mBTC:
27     case uBTC:
28         return true;
29     default:
30         return false;
31     }
32 }
33
34 QString BitcoinUnits::name(int unit)
35 {
36     switch(unit)
37     {
38     case BTC: return QString("BTC");
39     case mBTC: return QString("mBTC");
40     case uBTC: return QString::fromUtf8("μBTC");
41     default: return QString("???");
42     }
43 }
44
45 QString BitcoinUnits::description(int unit)
46 {
47     switch(unit)
48     {
49     case BTC: return QString("Bitcoins");
50     case mBTC: return QString("Milli-Bitcoins (1 / 1,000)");
51     case uBTC: return QString("Micro-Bitcoins (1 / 1,000,000)");
52     default: return QString("???");
53     }
54 }
55
56 qint64 BitcoinUnits::factor(int unit)
57 {
58     switch(unit)
59     {
60     case BTC:  return 100000000;
61     case mBTC: return 100000;
62     case uBTC: return 100;
63     default:   return 100000000;
64     }
65 }
66
67 int BitcoinUnits::amountDigits(int unit)
68 {
69     switch(unit)
70     {
71     case BTC: return 8; // 21,000,000 (# digits, without commas)
72     case mBTC: return 11; // 21,000,000,000
73     case uBTC: return 14; // 21,000,000,000,000
74     default: return 0;
75     }
76 }
77
78 int BitcoinUnits::decimals(int unit)
79 {
80     switch(unit)
81     {
82     case BTC: return 8;
83     case mBTC: return 5;
84     case uBTC: return 2;
85     default: return 0;
86     }
87 }
88
89 QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
90 {
91     // Note: not using straight sprintf here because we do NOT want
92     // localized number formatting.
93     if(!valid(unit))
94         return QString(); // Refuse to format invalid unit
95     qint64 coin = factor(unit);
96     int num_decimals = decimals(unit);
97     qint64 n_abs = (n > 0 ? n : -n);
98     qint64 quotient = n_abs / coin;
99     qint64 remainder = n_abs % coin;
100     QString quotient_str = QString::number(quotient);
101     QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
102
103     // Right-trim excess 0's after the decimal point
104     int nTrim = 0;
105     for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
106         ++nTrim;
107     remainder_str.chop(nTrim);
108
109     if (n < 0)
110         quotient_str.insert(0, '-');
111     else if (fPlus && n > 0)
112         quotient_str.insert(0, '+');
113     return quotient_str + QString(".") + remainder_str;
114 }
115
116 QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
117 {
118     return format(unit, amount, plussign) + QString(" ") + name(unit);
119 }
120
121 bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
122 {
123     if(!valid(unit) || value.isEmpty())
124         return false; // Refuse to parse invalid unit or empty string
125     int num_decimals = decimals(unit);
126     QStringList parts = value.split(".");
127
128     if(parts.size() > 2)
129     {
130         return false; // More than one dot
131     }
132     QString whole = parts[0];
133     QString decimals;
134
135     if(parts.size() > 1)
136     {
137         decimals = parts[1];
138     }
139     if(decimals.size() > num_decimals)
140     {
141         return false; // Exceeds max precision
142     }
143     bool ok = false;
144     QString str = whole + decimals.leftJustified(num_decimals, '0');
145
146     if(str.size() > 18)
147     {
148         return false; // Longer numbers will exceed 63 bits
149     }
150     qint64 retvalue = str.toLongLong(&ok);
151     if(val_out)
152     {
153         *val_out = retvalue;
154     }
155     return ok;
156 }
157
158 int BitcoinUnits::rowCount(const QModelIndex &parent) const
159 {
160     Q_UNUSED(parent);
161     return unitlist.size();
162 }
163
164 QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
165 {
166     int row = index.row();
167     if(row >= 0 && row < unitlist.size())
168     {
169         Unit unit = unitlist.at(row);
170         switch(role)
171         {
172         case Qt::EditRole:
173         case Qt::DisplayRole:
174             return QVariant(name(unit));
175         case Qt::ToolTipRole:
176             return QVariant(description(unit));
177         case UnitRole:
178             return QVariant(static_cast<int>(unit));
179         }
180     }
181     return QVariant();
182 }