make send coins dialog more user friendly (better checking)
[novacoin.git] / gui / src / bitcoingui.cpp
1 /*
2  * Qt4 bitcoin GUI.
3  *
4  * W.J. van der Laan 2011
5  */
6 #include "bitcoingui.h"
7 #include "transactiontablemodel.h"
8 #include "addressbookdialog.h"
9 #include "sendcoinsdialog.h"
10 #include "optionsdialog.h"
11 #include "aboutdialog.h"
12
13 #include <QApplication>
14 #include <QMainWindow>
15 #include <QMenuBar>
16 #include <QMenu>
17 #include <QIcon>
18 #include <QTabWidget>
19 #include <QVBoxLayout>
20 #include <QWidget>
21 #include <QToolBar>
22 #include <QStatusBar>
23 #include <QLabel>
24 #include <QTableView>
25 #include <QLineEdit>
26 #include <QPushButton>
27 #include <QHeaderView>
28 #include <QLocale>
29 #include <QSortFilterProxyModel>
30 #include <QClipboard>
31
32 #include <QDebug>
33
34 #include <iostream>
35
36 BitcoinGUI::BitcoinGUI(QWidget *parent):
37     QMainWindow(parent), trayIcon(0)
38 {
39     resize(850, 550);
40     setWindowTitle(tr("Bitcoin"));
41     setWindowIcon(QIcon(":icons/bitcoin"));
42
43     createActions();
44
45     /* Menus */
46     QMenu *file = menuBar()->addMenu("&File");
47     file->addAction(sendcoins);
48     file->addSeparator();
49     file->addAction(quit);
50     
51     QMenu *settings = menuBar()->addMenu("&Settings");
52     settings->addAction(receiving_addresses);
53     settings->addAction(options);
54
55     QMenu *help = menuBar()->addMenu("&Help");
56     help->addAction(about);
57     
58     /* Toolbar */
59     QToolBar *toolbar = addToolBar("Main toolbar");
60     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
61     toolbar->addAction(sendcoins);
62     toolbar->addAction(addressbook);
63
64     /* Address: <address>: New... : Paste to clipboard */
65     QHBoxLayout *hbox_address = new QHBoxLayout();
66     hbox_address->addWidget(new QLabel(tr("Your Bitcoin Address:")));
67     address = new QLineEdit();
68     address->setReadOnly(true);
69     hbox_address->addWidget(address);
70     
71     QPushButton *button_new = new QPushButton(tr("&New..."));
72     QPushButton *button_clipboard = new QPushButton(tr("&Copy to clipboard"));
73     hbox_address->addWidget(button_new);
74     hbox_address->addWidget(button_clipboard);
75     
76     /* Balance: <balance> */
77     QHBoxLayout *hbox_balance = new QHBoxLayout();
78     hbox_balance->addWidget(new QLabel(tr("Balance:")));
79     hbox_balance->addSpacing(5);/* Add some spacing between the label and the text */
80
81     labelBalance = new QLabel();
82     labelBalance->setFont(QFont("Teletype"));
83     hbox_balance->addWidget(labelBalance);
84     hbox_balance->addStretch(1);
85     
86     QVBoxLayout *vbox = new QVBoxLayout();
87     vbox->addLayout(hbox_address);
88     vbox->addLayout(hbox_balance);
89     
90     transaction_model = new TransactionTableModel(this);
91
92     vbox->addWidget(createTabs());
93
94     QWidget *centralwidget = new QWidget(this);
95     centralwidget->setLayout(vbox);
96     setCentralWidget(centralwidget);
97     
98     /* Create status bar */
99     statusBar();
100     
101     labelConnections = new QLabel();
102     labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken);
103     labelConnections->setMinimumWidth(130);
104     
105     labelBlocks = new QLabel();
106     labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken);
107     labelBlocks->setMinimumWidth(130);
108     
109     labelTransactions = new QLabel();
110     labelTransactions->setFrameStyle(QFrame::Panel | QFrame::Sunken);
111     labelTransactions->setMinimumWidth(130);
112     
113     statusBar()->addPermanentWidget(labelConnections);
114     statusBar()->addPermanentWidget(labelBlocks);
115     statusBar()->addPermanentWidget(labelTransactions);
116      
117     /* Action bindings */
118     connect(button_new, SIGNAL(clicked()), this, SLOT(newAddressClicked()));
119     connect(button_clipboard, SIGNAL(clicked()), this, SLOT(copyClipboardClicked()));
120
121     createTrayIcon();
122 }
123
124 void BitcoinGUI::createActions()
125 {
126     quit = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this);
127     sendcoins = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
128     addressbook = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
129     about = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this);
130     receiving_addresses = new QAction(QIcon(":/icons/receiving-addresses"), tr("Your &Receiving Addresses..."), this);
131     options = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
132     openBitCoin = new QAction(QIcon(":/icons/bitcoin"), "Open Bitcoin", this);
133
134     connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
135     connect(sendcoins, SIGNAL(triggered()), this, SLOT(sendcoinsClicked()));
136     connect(addressbook, SIGNAL(triggered()), this, SLOT(addressbookClicked()));
137     connect(receiving_addresses, SIGNAL(triggered()), this, SLOT(receivingAddressesClicked()));
138     connect(options, SIGNAL(triggered()), this, SLOT(optionsClicked()));
139     connect(about, SIGNAL(triggered()), this, SLOT(aboutClicked()));
140 }
141
142 void BitcoinGUI::createTrayIcon()
143 {
144     QMenu *trayIconMenu = new QMenu(this);
145     trayIconMenu->addAction(openBitCoin);
146     trayIconMenu->addAction(sendcoins);
147     trayIconMenu->addAction(options);
148     trayIconMenu->addSeparator();
149     trayIconMenu->addAction(quit);
150
151     trayIcon = new QSystemTrayIcon(this);
152     trayIcon->setContextMenu(trayIconMenu);
153     trayIcon->setIcon(QIcon(":/icons/toolbar"));
154     trayIcon->show();
155 }
156
157 QWidget *BitcoinGUI::createTabs()
158 {
159     QStringList tab_filters, tab_labels;
160     tab_filters << "^."
161             << "^["+TransactionTableModel::Sent+TransactionTableModel::Received+"]"
162             << "^["+TransactionTableModel::Sent+"]"
163             << "^["+TransactionTableModel::Received+"]";
164     tab_labels  << tr("All transactions")
165                 << tr("Sent/Received")
166                 << tr("Sent")
167                 << tr("Received");
168     QTabWidget *tabs = new QTabWidget(this);
169
170     for(int i = 0; i < tab_labels.size(); ++i)
171     {
172         QSortFilterProxyModel *proxy_model = new QSortFilterProxyModel(this);
173         proxy_model->setSourceModel(transaction_model);
174         proxy_model->setDynamicSortFilter(true);
175         proxy_model->setFilterRole(Qt::UserRole);
176         proxy_model->setFilterKeyColumn(TransactionTableModel::Type);
177         proxy_model->setFilterRegExp(QRegExp(tab_filters.at(i)));
178
179         QTableView *transaction_table = new QTableView(this);
180         transaction_table->setModel(proxy_model);
181         transaction_table->setSelectionBehavior(QAbstractItemView::SelectRows);
182         transaction_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
183         transaction_table->verticalHeader()->hide();
184
185         transaction_table->horizontalHeader()->resizeSection(
186                 TransactionTableModel::Status, 112);
187         transaction_table->horizontalHeader()->resizeSection(
188                 TransactionTableModel::Date, 112);
189         transaction_table->horizontalHeader()->setResizeMode(
190                 TransactionTableModel::Description, QHeaderView::Stretch);
191         transaction_table->horizontalHeader()->resizeSection(
192                 TransactionTableModel::Debit, 79);
193         transaction_table->horizontalHeader()->resizeSection(
194                 TransactionTableModel::Credit, 79);
195         transaction_table->setColumnHidden(TransactionTableModel::Type, true);
196
197         tabs->addTab(transaction_table, tab_labels.at(i));
198     }
199     return tabs;
200 }
201
202 void BitcoinGUI::sendcoinsClicked()
203 {
204     qDebug() << "Send coins clicked";
205     SendCoinsDialog dlg;
206     dlg.exec();
207 }
208
209 void BitcoinGUI::addressbookClicked()
210 {
211     qDebug() << "Address book clicked";
212     AddressBookDialog dlg;
213     dlg.setTab(AddressBookDialog::SendingTab);
214     /* if an address accepted, do a 'send' to specified address */
215     if(dlg.exec())
216     {
217         SendCoinsDialog send(0, dlg.getReturnValue());
218         send.exec();
219     }
220 }
221
222 void BitcoinGUI::receivingAddressesClicked()
223 {
224     qDebug() << "Receiving addresses clicked";
225     AddressBookDialog dlg;
226     dlg.setTab(AddressBookDialog::ReceivingTab);
227     dlg.exec();
228 }
229
230 void BitcoinGUI::optionsClicked()
231 {
232     qDebug() << "Options clicked";
233     OptionsDialog dlg;
234     dlg.exec();
235 }
236
237 void BitcoinGUI::aboutClicked()
238 {
239     qDebug() << "About clicked";
240     AboutDialog dlg;
241     dlg.exec();
242 }
243
244 void BitcoinGUI::newAddressClicked()
245 {
246     qDebug() << "New address clicked";
247     /* TODO: generate new address */
248 }
249
250 void BitcoinGUI::copyClipboardClicked()
251 {
252     qDebug() << "Copy to clipboard";
253     /* Copy text in address to clipboard */
254     QApplication::clipboard()->setText(address->text());
255 }
256
257 void BitcoinGUI::setBalance(double balance)
258 {
259     labelBalance->setText(QLocale::system().toString(balance, 8));
260 }
261
262 void BitcoinGUI::setAddress(const QString &addr)
263 {
264     address->setText(addr);
265 }
266
267 void BitcoinGUI::setNumConnections(int count)
268 {
269     labelConnections->setText(QLocale::system().toString(count)+" "+tr("connections"));
270 }
271
272 void BitcoinGUI::setNumBlocks(int count)
273 {
274     labelBlocks->setText(QLocale::system().toString(count)+" "+tr("blocks"));
275 }
276
277 void BitcoinGUI::setNumTransactions(int count)
278 {
279     labelTransactions->setText(QLocale::system().toString(count)+" "+tr("transactions"));
280 }