1 #include "transactionview.h"
3 #include "transactionfilterproxy.h"
4 #include "transactionrecord.h"
5 #include "walletmodel.h"
6 #include "addresstablemodel.h"
7 #include "transactiontablemodel.h"
9 #include "csvmodelwriter.h"
10 #include "transactiondescdialog.h"
11 #include "editaddressdialog.h"
15 #include <QDoubleValidator>
16 #include <QHBoxLayout>
17 #include <QVBoxLayout>
20 #include <QHeaderView>
21 #include <QPushButton>
22 #include <QFileDialog>
23 #include <QMessageBox>
26 #include <QApplication>
29 #include <QDateTimeEdit>
33 TransactionView::TransactionView(QWidget *parent) :
34 QWidget(parent), model(0), transactionProxyModel(0),
38 setContentsMargins(0,0,0,0);
40 QHBoxLayout *hlayout = new QHBoxLayout();
41 hlayout->setContentsMargins(0,0,0,0);
42 hlayout->setSpacing(0);
44 hlayout->addSpacing(23);
46 dateWidget = new QComboBox(this);
47 dateWidget->setMaximumWidth(120);
48 dateWidget->setMinimumWidth(120);
49 dateWidget->addItem(tr("All"), All);
50 dateWidget->addItem(tr("Today"), Today);
51 dateWidget->addItem(tr("This week"), ThisWeek);
52 dateWidget->addItem(tr("This month"), ThisMonth);
53 dateWidget->addItem(tr("Last month"), LastMonth);
54 dateWidget->addItem(tr("This year"), ThisYear);
55 dateWidget->addItem(tr("Range..."), Range);
56 hlayout->addWidget(dateWidget);
58 typeWidget = new QComboBox(this);
59 typeWidget->setMaximumWidth(120);
60 typeWidget->setMinimumWidth(120);
62 typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
63 typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
64 TransactionFilterProxy::TYPE(TransactionRecord::RecvFromIP));
65 typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
66 TransactionFilterProxy::TYPE(TransactionRecord::SendToIP));
67 typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf));
68 typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
69 typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));
71 hlayout->addWidget(typeWidget);
73 addressWidget = new QLineEdit(this);
74 #if QT_VERSION >= 0x040700
75 addressWidget->setPlaceholderText("Enter address or label to search");
77 hlayout->addWidget(addressWidget);
79 amountWidget = new QLineEdit(this);
80 #if QT_VERSION >= 0x040700
81 amountWidget->setPlaceholderText("Min amount");
83 amountWidget->setMaximumWidth(100);
84 amountWidget->setMinimumWidth(100);
85 amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
86 hlayout->addWidget(amountWidget);
88 QVBoxLayout *vlayout = new QVBoxLayout(this);
89 vlayout->setContentsMargins(0,0,0,0);
90 vlayout->setSpacing(0);
91 //vlayout->addLayout(hlayout2);
93 QTableView *view = new QTableView(this);
94 vlayout->addLayout(hlayout);
95 vlayout->addWidget(createDateRangeWidget());
96 vlayout->addWidget(view);
97 vlayout->setSpacing(0);
98 int width = view->verticalScrollBar()->sizeHint().width();
99 // Cover scroll bar width with spacing
100 hlayout->addSpacing(width);
101 // Always show scroll bar
102 view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
103 view->setTabKeyNavigation(false);
104 view->setContextMenuPolicy(Qt::CustomContextMenu);
106 transactionView = view;
109 QAction *copyAddressAction = new QAction("Copy address", this);
110 QAction *copyLabelAction = new QAction("Copy label", this);
111 QAction *editLabelAction = new QAction("Edit label", this);
112 QAction *showDetailsAction = new QAction("Show details...", this);
114 contextMenu = new QMenu();
115 contextMenu->addAction(copyAddressAction);
116 contextMenu->addAction(copyLabelAction);
117 contextMenu->addAction(editLabelAction);
118 contextMenu->addAction(showDetailsAction);
121 connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
122 connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
123 connect(addressWidget, SIGNAL(textChanged(const QString&)), this, SLOT(changedPrefix(const QString&)));
124 connect(amountWidget, SIGNAL(textChanged(const QString&)), this, SLOT(changedAmount(const QString&)));
126 connect(view, SIGNAL(doubleClicked(const QModelIndex&)), this, SIGNAL(doubleClicked(const QModelIndex&)));
129 SIGNAL(customContextMenuRequested(const QPoint &)),
131 SLOT(contextualMenu(const QPoint &)));
133 connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
134 connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
135 connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
136 connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
139 void TransactionView::setModel(WalletModel *model)
143 transactionProxyModel = new TransactionFilterProxy(this);
144 transactionProxyModel->setSourceModel(model->getTransactionTableModel());
145 transactionProxyModel->setDynamicSortFilter(true);
147 transactionProxyModel->setSortRole(Qt::EditRole);
149 transactionView->setModel(transactionProxyModel);
150 transactionView->setAlternatingRowColors(true);
151 transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
152 transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
153 transactionView->setSortingEnabled(true);
154 transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
155 transactionView->verticalHeader()->hide();
157 transactionView->horizontalHeader()->resizeSection(
158 TransactionTableModel::Status, 23);
159 transactionView->horizontalHeader()->resizeSection(
160 TransactionTableModel::Date, 120);
161 transactionView->horizontalHeader()->resizeSection(
162 TransactionTableModel::Type, 120);
163 transactionView->horizontalHeader()->setResizeMode(
164 TransactionTableModel::ToAddress, QHeaderView::Stretch);
165 transactionView->horizontalHeader()->resizeSection(
166 TransactionTableModel::Amount, 100);
170 void TransactionView::chooseDate(int idx)
172 QDate current = QDate::currentDate();
173 dateRangeWidget->setVisible(false);
174 switch(dateWidget->itemData(idx).toInt())
177 transactionProxyModel->setDateRange(
178 TransactionFilterProxy::MIN_DATE,
179 TransactionFilterProxy::MAX_DATE);
182 transactionProxyModel->setDateRange(
184 TransactionFilterProxy::MAX_DATE);
188 QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
189 transactionProxyModel->setDateRange(
190 QDateTime(startOfWeek),
191 TransactionFilterProxy::MAX_DATE);
195 transactionProxyModel->setDateRange(
196 QDateTime(QDate(current.year(), current.month(), 1)),
197 TransactionFilterProxy::MAX_DATE);
200 transactionProxyModel->setDateRange(
201 QDateTime(QDate(current.year(), current.month()-1, 1)),
202 QDateTime(QDate(current.year(), current.month(), 1)));
205 transactionProxyModel->setDateRange(
206 QDateTime(QDate(current.year(), 1, 1)),
207 TransactionFilterProxy::MAX_DATE);
210 dateRangeWidget->setVisible(true);
216 void TransactionView::chooseType(int idx)
218 transactionProxyModel->setTypeFilter(
219 typeWidget->itemData(idx).toInt());
222 void TransactionView::changedPrefix(const QString &prefix)
224 transactionProxyModel->setAddressPrefix(prefix);
227 void TransactionView::changedAmount(const QString &amount)
229 qint64 amount_parsed = 0;
230 if(GUIUtil::parseMoney(amount, &amount_parsed))
232 transactionProxyModel->setMinAmount(amount_parsed);
236 transactionProxyModel->setMinAmount(0);
240 void TransactionView::exportClicked()
242 // CSV is currently the only supported format
243 QString filename = QFileDialog::getSaveFileName(
245 tr("Export Transaction Data"),
247 tr("Comma separated file (*.csv)"));
249 if (filename.isNull()) return;
251 CSVModelWriter writer(filename);
253 // name, column, role
254 writer.setModel(transactionProxyModel);
255 writer.addColumn("Confirmed", 0, TransactionTableModel::ConfirmedRole);
256 writer.addColumn("Date", 0, TransactionTableModel::DateRole);
257 writer.addColumn("Type", TransactionTableModel::Type, Qt::EditRole);
258 writer.addColumn("Label", 0, TransactionTableModel::LabelRole);
259 writer.addColumn("Address", 0, TransactionTableModel::AddressRole);
260 writer.addColumn("Amount", 0, TransactionTableModel::FormattedAmountRole);
261 writer.addColumn("ID", 0, TransactionTableModel::TxIDRole);
265 QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
266 QMessageBox::Abort, QMessageBox::Abort);
270 void TransactionView::contextualMenu(const QPoint &point)
272 QModelIndex index = transactionView->indexAt(point);
275 contextMenu->exec(QCursor::pos());
279 void TransactionView::copyAddress()
281 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
282 if(!selection.isEmpty())
284 QApplication::clipboard()->setText(selection.at(0).data(TransactionTableModel::AddressRole).toString());
288 void TransactionView::copyLabel()
290 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
291 if(!selection.isEmpty())
293 QApplication::clipboard()->setText(selection.at(0).data(TransactionTableModel::LabelRole).toString());
297 void TransactionView::editLabel()
299 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
300 if(!selection.isEmpty())
302 AddressTableModel *addressBook = model->getAddressTableModel();
303 QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
304 if(address.isEmpty())
306 // If this transaction has no associated address, exit
309 int idx = addressBook->lookupAddress(address);
312 // Edit sending / receiving address
313 QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex());
314 // Determine type of address, launch appropriate editor dialog type
315 QString type = modelIdx.data(AddressTableModel::TypeRole).toString();
317 EditAddressDialog dlg(type==AddressTableModel::Receive
318 ? EditAddressDialog::EditReceivingAddress
319 : EditAddressDialog::EditSendingAddress,
321 dlg.setModel(addressBook);
327 // Add sending address
328 EditAddressDialog dlg(EditAddressDialog::NewSendingAddress,
335 void TransactionView::showDetails()
337 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
338 if(!selection.isEmpty())
340 TransactionDescDialog dlg(selection.at(0));
345 QWidget *TransactionView::createDateRangeWidget()
347 dateRangeWidget = new QFrame();
348 dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
349 dateRangeWidget->setContentsMargins(1,1,1,1);
350 QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
351 layout->setContentsMargins(0,0,0,0);
352 layout->addSpacing(23);
353 layout->addWidget(new QLabel("Range:"));
355 dateFrom = new QDateTimeEdit(this);
356 dateFrom->setDisplayFormat("dd/MM/yy");
357 dateFrom->setCalendarPopup(true);
358 dateFrom->setMinimumWidth(100);
359 dateFrom->setDate(QDate::currentDate().addDays(-7));
360 layout->addWidget(dateFrom);
361 layout->addWidget(new QLabel("to"));
363 dateTo = new QDateTimeEdit(this);
364 dateTo->setDisplayFormat("dd/MM/yy");
365 dateTo->setCalendarPopup(true);
366 dateTo->setMinimumWidth(100);
367 dateTo->setDate(QDate::currentDate());
368 layout->addWidget(dateTo);
369 layout->addStretch();
372 dateRangeWidget->setVisible(false);
375 connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
376 connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
378 return dateRangeWidget;
381 void TransactionView::dateRangeChanged()
383 transactionProxyModel->setDateRange(
384 QDateTime(dateFrom->date()),
385 QDateTime(dateTo->date()).addDays(1));