Fabcoin Core  0.16.2
P2P Digital Currency
tokenamountfield.cpp
Go to the documentation of this file.
1 #include <tokenamountfield.h>
2 
3 #include <fabcoinunits.h>
4 #include <styleSheet.h>
5 #include <qvaluecombobox.h>
6 
7 #include <QApplication>
8 #include <QAbstractSpinBox>
9 #include <QKeyEvent>
10 #include <QLineEdit>
11 #include <QHBoxLayout>
12 
16 class TokenAmountSpinBox: public QAbstractSpinBox
17 {
18  Q_OBJECT
19 
20 public:
21  explicit TokenAmountSpinBox(QWidget *parent):
22  QAbstractSpinBox(parent),
23  decimalUnits(0),
24  totalSupply(0),
25  singleStep(0),
26  minAmount(0)
27  {
28  setAlignment(Qt::AlignRight);
29 
30  connect(lineEdit(), SIGNAL(textEdited(QString)), this, SIGNAL(valueChanged()));
31  }
32 
33  QValidator::State validate(QString &text, int &pos) const
34  {
35  if(text.isEmpty())
36  return QValidator::Intermediate;
37  bool valid = false;
38  parse(text, &valid);
39  /* Make sure we return Intermediate so that fixup() is called on defocus */
40  return valid ? QValidator::Intermediate : QValidator::Invalid;
41  }
42 
43  void fixup(QString &input) const
44  {
45  bool valid = false;
46  int256_t val = parse(input, &valid);
47  val = getMax(val, minAmount);
48  if(valid)
49  {
51  lineEdit()->setText(input);
52  }
53  }
54 
55  int256_t value(bool *valid_out=0) const
56  {
57  return parse(text(), valid_out);
58  }
59 
60  void setValue(const int256_t& value)
61  {
62  int256_t val = getMax(value, minAmount);
63  lineEdit()->setText(FabcoinUnits::formatToken(decimalUnits, val, false, FabcoinUnits::separatorAlways));
64  Q_EMIT valueChanged();
65  }
66 
67  void stepBy(int steps)
68  {
69  bool valid = false;
70  int256_t val = value(&valid);
71  val = val + steps * singleStep;
72  val = getMin(getMax(val, minAmount), totalSupply);
73  setValue(val);
74  }
75 
76  int256_t minimum() const
77  {
78  return minAmount;
79  }
80 
81  void setMinimum(const int256_t& min)
82  {
83  minAmount = min;
84  Q_EMIT valueChanged();
85  }
86 
87  void setTotalSupply(const int256_t &value)
88  {
90  }
91 
93  {
95  setSingleStep();
96  }
97 
98 private:
99  int decimalUnits; // Token decimal units
100  int256_t totalSupply; // Token total supply
101  int256_t singleStep;
102  int256_t minAmount;
103 
109  int256_t parse(const QString &text, bool *valid_out=0) const
110  {
111  int256_t val = 0;
112  bool valid = FabcoinUnits::parseToken(decimalUnits, text, &val);
113  if(valid)
114  {
115  if(val < 0 || val > totalSupply)
116  valid = false;
117  }
118  if(valid_out)
119  *valid_out = valid;
120  return valid ? val : 0;
121  }
122 
124  {
125  int256_t step = 1;
126  for(int i = 1; i < decimalUnits; i++)
127  {
128  step *= 10;
129  }
130  singleStep = step;
131  }
132 
133  int256_t getMax(int256_t a, int256_t b) const{
134  return a > b ? a : b;
135  }
136 
137  int256_t getMin(int256_t a, int256_t b) const{
138  return a > b ? b : a;
139  }
140 
141 protected:
142  bool event(QEvent *event)
143  {
144  if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
145  {
146  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
147  if (keyEvent->key() == Qt::Key_Comma)
148  {
149  // Translate a comma into a period
150  QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
151  return QAbstractSpinBox::event(&periodKeyEvent);
152  }
153  }
154  return QAbstractSpinBox::event(event);
155  }
156 
157  StepEnabled stepEnabled() const
158  {
159  if (isReadOnly()) // Disable steps when TokenAmountSpinBox is read-only
160  return StepNone;
161  if (text().isEmpty()) // Allow step-up with empty field
162  return StepUpEnabled;
163 
164  StepEnabled rv = 0;
165  bool valid = false;
166  int256_t val = value(&valid);
167  if(valid)
168  {
169  if(val > minAmount)
170  rv |= StepDownEnabled;
171  if(val < totalSupply)
172  rv |= StepUpEnabled;
173  }
174  return rv;
175  }
176 
177 Q_SIGNALS:
178  void valueChanged();
179 };
180 
181 #include <tokenamountfield.moc>
182 
184  QWidget(parent),
185  amount(0)
186 {
187  amount = new TokenAmountSpinBox(this);
188  amount->setLocale(QLocale::c());
189  amount->installEventFilter(this);
190 
191  QHBoxLayout *layout = new QHBoxLayout(this);
192  layout->addWidget(amount);
193 
194  layout->setContentsMargins(0,0,0,0);
195 
196  setLayout(layout);
197  connect(amount, SIGNAL(valueChanged()), this, SIGNAL(valueChanged()));
198 }
199 
201 {
202  amount->clear();
203 }
204 
205 void TokenAmountField::setEnabled(bool fEnabled)
206 {
207  amount->setEnabled(fEnabled);
208 }
209 
211 {
212  bool valid = false;
213  value(&valid);
214  setValid(valid);
215  return valid;
216 }
217 
219 {
220  if (valid)
221  amount->setStyleSheet("");
222  else
223  SetObjectStyleSheet(amount, StyleSheetNames::Invalid);
224 }
225 
226 bool TokenAmountField::eventFilter(QObject *object, QEvent *event)
227 {
228  if (event->type() == QEvent::FocusIn)
229  {
230  // Clear invalid flag on focus
231  setValid(true);
232  }
233  return QWidget::eventFilter(object, event);
234 }
235 
236 int256_t TokenAmountField::value(bool *valid_out) const
237 {
238  return amount->value(valid_out);
239 }
240 
241 void TokenAmountField::setValue(const int256_t& value)
242 {
243  amount->setValue(value);
244 }
245 
246 void TokenAmountField::setReadOnly(bool fReadOnly)
247 {
248  amount->setReadOnly(fReadOnly);
249 }
250 
252 {
253  return amount->minimum();
254 }
255 
256 void TokenAmountField::setMinimum(const int256_t& min)
257 {
258  amount->setMinimum(min);
259 }
260 
262 {
263  amount->setTotalSupply(value);
264 }
265 
267 {
268  amount->setDecimalUnits(value);
269 }
270 
271 QString TokenAmountField::text() const
272 {
273  return QString::fromStdString(value().str());
274 }
void setDecimalUnits(int value)
void setTotalSupply(const int256_t &value)
void setTotalSupply(const int256_t &value)
#define SetObjectStyleSheet(object, name)
Definition: styleSheet.h:10
QSpinBox that uses fixed-point numbers internally and uses our own formatting/parsing functions...
QValidator::State validate(QString &text, int &pos) const
void setValue(const int256_t &value)
void setValue(const int256_t &value)
TokenAmountField(QWidget *parent=0)
#define c(i)
StepEnabled stepEnabled() const
bool eventFilter(QObject *object, QEvent *event)
Intercept focus-in event and &#39;,&#39; key presses.
TokenAmountSpinBox * amount
int256_t parse(const QString &text, bool *valid_out=0) const
Parse a string into a number of base monetary units and return validity.
ExecStats::duration min
Definition: ExecStats.cpp:35
void clear()
Make field empty and ready for new input.
int256_t value(bool *valid_out=0) const
void setDecimalUnits(int value)
void setMinimum(const int256_t &min)
bool validate()
Perform input validation, mark field as invalid if entered value is not valid.
void setReadOnly(bool fReadOnly)
Make read-only.
#define a(i)
int256_t getMin(int256_t a, int256_t b) const
void fixup(QString &input) const
void setMinimum(const int256_t &min)
void setValid(bool valid)
Mark current value as invalid in UI.
#define b(i, j)
int256_t getMax(int256_t a, int256_t b) const
static QString formatToken(int decimal_units, const int256_t &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format token as string.
bool event(QEvent *event)
void stepBy(int steps)
TokenAmountSpinBox(QWidget *parent)
QString text() const
static bool parseToken(int decimal_units, const QString &value, int256_t *val_out)
Parse string to token amount.
void setEnabled(bool fEnabled)
Enable/Disable.
int256_t minimum() const
int256_t minimum() const