QtUI code cleanup / comment improvements
[novacoin.git] / src / qt / bitcoinamountfield.cpp
1 #include "bitcoinamountfield.h"
2 #include "qvalidatedlineedit.h"
3 #include "qvaluecombobox.h"
4 #include "bitcoinunits.h"
5
6 #include <QLabel>
7 #include <QLineEdit>
8 #include <QRegExpValidator>
9 #include <QHBoxLayout>
10 #include <QKeyEvent>
11 #include <QComboBox>
12
13 BitcoinAmountField::BitcoinAmountField(QWidget *parent):
14         QWidget(parent), amount(0), decimals(0), currentUnit(-1)
15 {
16     amount = new QValidatedLineEdit(this);
17     amount->setValidator(new QRegExpValidator(QRegExp("[0-9]*"), this));
18     amount->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
19     amount->installEventFilter(this);
20     amount->setMaximumWidth(75);
21     decimals = new QValidatedLineEdit(this);
22     decimals->setValidator(new QRegExpValidator(QRegExp("[0-9]+"), this));
23     decimals->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
24     decimals->setMaximumWidth(75);
25
26     QHBoxLayout *layout = new QHBoxLayout(this);
27     layout->setSpacing(0);
28     layout->addWidget(amount);
29     layout->addWidget(new QLabel(QString("<b>.</b>")));
30     layout->addWidget(decimals);
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(textChanged(QString)), this, SIGNAL(textChanged()));
44     connect(decimals, SIGNAL(textChanged(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 BitcoinAmountField::setText(const QString &text)
52 {
53     const QStringList parts = text.split(QString("."));
54     if(parts.size() == 2)
55     {
56         amount->setText(parts[0]);
57         decimals->setText(parts[1]);
58     }
59     else
60     {
61         amount->setText(QString());
62         decimals->setText(QString());
63     }
64 }
65
66 void BitcoinAmountField::clear()
67 {
68     amount->clear();
69     decimals->clear();
70     unit->setCurrentIndex(0);
71 }
72
73 bool BitcoinAmountField::validate()
74 {
75     bool valid = true;
76     if(decimals->text().isEmpty())
77     {
78         decimals->setValid(false);
79         valid = false;
80     }
81     if(!BitcoinUnits::parse(currentUnit, text(), 0))
82     {
83         setValid(false);
84         valid = false;
85     }
86
87     return valid;
88 }
89
90 void BitcoinAmountField::setValid(bool valid)
91 {
92     amount->setValid(valid);
93     decimals->setValid(valid);
94 }
95
96 QString BitcoinAmountField::text() const
97 {
98     if(decimals->text().isEmpty() && amount->text().isEmpty())
99     {
100         return QString();
101     }
102     return amount->text() + QString(".") + decimals->text();
103 }
104
105 // Intercept '.' and ',' keys, if pressed focus a specified widget
106 bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
107 {
108     Q_UNUSED(object);
109     if(event->type() == QEvent::KeyPress)
110     {
111         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
112         if(keyEvent->key() == Qt::Key_Period || keyEvent->key() == Qt::Key_Comma)
113         {
114             decimals->setFocus();
115             decimals->selectAll();
116         }
117     }
118     return false;
119 }
120
121 QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
122 {
123     QWidget::setTabOrder(prev, amount);
124     QWidget::setTabOrder(amount, decimals);
125     return decimals;
126 }
127
128 qint64 BitcoinAmountField::value(bool *valid_out) const
129 {
130     qint64 val_out = 0;
131     bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out);
132     if(valid_out)
133     {
134         *valid_out = valid;
135     }
136     return val_out;
137 }
138
139 void BitcoinAmountField::setValue(qint64 value)
140 {
141     setText(BitcoinUnits::format(currentUnit, value));
142 }
143
144 void BitcoinAmountField::unitChanged(int idx)
145 {
146     // Use description tooltip for current unit for the combobox
147     unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());
148
149     // Determine new unit ID
150     int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();
151
152     // Parse current value and convert to new unit
153     bool valid = false;
154     qint64 currentValue = value(&valid);
155
156     currentUnit = newUnit;
157
158     // Set max length after retrieving the value, to prevent truncation
159     amount->setMaxLength(BitcoinUnits::amountDigits(currentUnit));
160     decimals->setMaxLength(BitcoinUnits::decimals(currentUnit));
161
162     if(valid)
163     {
164         setValue(currentValue);
165     }
166     else
167     {
168         // If current value is invalid, just clear field
169         setText("");
170     }
171     setValid(true);
172 }
173
174 void BitcoinAmountField::setDisplayUnit(int newUnit)
175 {
176     unit->setValue(newUnit);
177 }