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