Anoncoin  0.9.4
P2P Digital Currency
anoncoinamountfield.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Copyright (c) 2013-2014 The Anoncoin Core developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "anoncoinamountfield.h"
7 
8 #include "anoncoinunits.h"
9 #include "guiconstants.h"
10 #include "qvaluecombobox.h"
11 
12 #include <QApplication>
13 #include <QDoubleSpinBox>
14 #include <QHBoxLayout>
15 #include <QKeyEvent>
16 #include <qmath.h> // for qPow()
17 
19  QWidget(parent),
20  amount(0),
21  currentUnit(-1)
22 {
23  nSingleStep = 100000; // satoshis
24 
25  amount = new QDoubleSpinBox(this);
26  amount->setLocale(QLocale::c());
27  amount->installEventFilter(this);
28  amount->setMaximumWidth(170);
29 
30  QHBoxLayout *layout = new QHBoxLayout(this);
31  layout->addWidget(amount);
32  unit = new QValueComboBox(this);
33  unit->setModel(new AnoncoinUnits(this));
34  layout->addWidget(unit);
35  layout->addStretch(1);
36  layout->setContentsMargins(0,0,0,0);
37 
38  setLayout(layout);
39 
40  setFocusPolicy(Qt::TabFocus);
41  setFocusProxy(amount);
42 
43  // If one if the widgets changes, the combined content changes as well
44  connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
45  connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
46 
47  // Set default based on configuration
48  unitChanged(unit->currentIndex());
49 }
50 
51 void AnoncoinAmountField::setText(const QString &text)
52 {
53  if (text.isEmpty())
54  amount->clear();
55  else
56  amount->setValue(text.toDouble());
57 }
58 
60 {
61  amount->clear();
62  unit->setCurrentIndex(0);
63 }
64 
66 {
67  bool valid = true;
68  if (amount->value() == 0.0)
69  valid = false;
70  else if (!AnoncoinUnits::parse(currentUnit, text(), 0))
71  valid = false;
72  else if (amount->value() > AnoncoinUnits::maxAmount(currentUnit))
73  valid = false;
74 
75  setValid(valid);
76 
77  return valid;
78 }
79 
81 {
82  if (valid)
83  amount->setStyleSheet("");
84  else
85  amount->setStyleSheet(STYLE_INVALID);
86 }
87 
89 {
90  if (amount->text().isEmpty())
91  return QString();
92  else
93  return amount->text();
94 }
95 
96 bool AnoncoinAmountField::eventFilter(QObject *object, QEvent *event)
97 {
98  if (event->type() == QEvent::FocusIn)
99  {
100  // Clear invalid flag on focus
101  setValid(true);
102  }
103  else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
104  {
105  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
106  if (keyEvent->key() == Qt::Key_Comma)
107  {
108  // Translate a comma into a period
109  QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
110  QApplication::sendEvent(object, &periodKeyEvent);
111  return true;
112  }
113  }
114  return QWidget::eventFilter(object, event);
115 }
116 
117 QWidget *AnoncoinAmountField::setupTabChain(QWidget *prev)
118 {
119  QWidget::setTabOrder(prev, amount);
120  QWidget::setTabOrder(amount, unit);
121  return unit;
122 }
123 
124 qint64 AnoncoinAmountField::value(bool *valid_out) const
125 {
126  qint64 val_out = 0;
127  bool valid = AnoncoinUnits::parse(currentUnit, text(), &val_out);
128  if (valid_out)
129  {
130  *valid_out = valid;
131  }
132  return val_out;
133 }
134 
136 {
138 }
139 
141 {
142  amount->setReadOnly(fReadOnly);
143  unit->setEnabled(!fReadOnly);
144 }
145 
147 {
148  // Use description tooltip for current unit for the combobox
149  unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());
150 
151  // Determine new unit ID
152  int newUnit = unit->itemData(idx, AnoncoinUnits::UnitRole).toInt();
153 
154  // Parse current value and convert to new unit
155  bool valid = false;
156  qint64 currentValue = value(&valid);
157 
158  currentUnit = newUnit;
159 
160  // Set max length after retrieving the value, to prevent truncation
162  amount->setMaximum(qPow(10, AnoncoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));
163  amount->setSingleStep((double)nSingleStep / (double)AnoncoinUnits::factor(currentUnit));
164 
165  if (valid)
166  {
167  // If value was valid, re-place it in the widget with the new unit
168  setValue(currentValue);
169  }
170  else
171  {
172  // If current value is invalid, just clear field
173  setText("");
174  }
175  setValid(true);
176 }
177 
179 {
180  unit->setValue(newUnit);
181 }
182 
184 {
185  nSingleStep = step;
186  unitChanged(unit->currentIndex());
187 }
void setText(const QString &text)
void setDisplayUnit(int unit)
Change unit used to display amount.
Anoncoin unit definitions.
Definition: anoncoinunits.h:15
void setValue(qint64 value)
void setValid(bool valid)
Mark current value as invalid in UI.
bool validate()
Perform input validation, mark field as invalid if entered value is not valid.
QValueComboBox * unit
static bool parse(int unit, const QString &value, qint64 *val_out)
Parse string to coin amount.
QDoubleSpinBox * amount
static qint64 maxAmount(int unit)
Max amount per unit.
static qint64 factor(int unit)
Number of Satoshis (1e-8) per unit.
QWidget * setupTabChain(QWidget *prev)
Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907), in these cases we have to set it up manually.
static QString format(int unit, qint64 amount, bool plussign=false)
Format as string.
static int amountDigits(int unit)
Number of amount digits (to represent max number of coins)
#define STYLE_INVALID
Definition: guiconstants.h:19
void clear()
Make field empty and ready for new input.
void setValue(const QVariant &value)
Unit identifier.
Definition: anoncoinunits.h:67
bool eventFilter(QObject *object, QEvent *event)
Intercept focus-in event and ',' key presses.
void setSingleStep(qint64 step)
Set single step in satoshis.
void setReadOnly(bool fReadOnly)
Make read-only.
static int decimals(int unit)
Number of decimals left.
AnoncoinAmountField(QWidget *parent=0)