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>
31 TransactionView::TransactionView(QWidget *parent) :
32 QWidget(parent), model(0), transactionProxyModel(0),
36 setContentsMargins(0,0,0,0);
38 QHBoxLayout *hlayout = new QHBoxLayout();
39 hlayout->setContentsMargins(0,0,0,0);
40 hlayout->setSpacing(0);
42 hlayout->addSpacing(23);
44 dateWidget = new QComboBox(this);
45 dateWidget->setMaximumWidth(120);
46 dateWidget->setMinimumWidth(120);
47 dateWidget->addItem(tr("All"), All);
48 dateWidget->addItem(tr("Today"), Today);
49 dateWidget->addItem(tr("This week"), ThisWeek);
50 dateWidget->addItem(tr("This month"), ThisMonth);
51 dateWidget->addItem(tr("Last month"), LastMonth);
52 dateWidget->addItem(tr("This year"), ThisYear);
53 dateWidget->addItem(tr("Range..."), Range);
54 hlayout->addWidget(dateWidget);
56 typeWidget = new QComboBox(this);
57 typeWidget->setMaximumWidth(120);
58 typeWidget->setMinimumWidth(120);
60 typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
61 typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
62 TransactionFilterProxy::TYPE(TransactionRecord::RecvFromIP));
63 typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
64 TransactionFilterProxy::TYPE(TransactionRecord::SendToIP));
65 typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf));
66 typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
67 typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));
69 hlayout->addWidget(typeWidget);
71 addressWidget = new QLineEdit(this);
72 #if QT_VERSION >= 0x040700
73 addressWidget->setPlaceholderText("Enter address or label to search");
75 hlayout->addWidget(addressWidget);
77 amountWidget = new QLineEdit(this);
78 #if QT_VERSION >= 0x040700
79 amountWidget->setPlaceholderText("Min amount");
81 amountWidget->setMaximumWidth(100);
82 amountWidget->setMinimumWidth(100);
83 amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
84 hlayout->addWidget(amountWidget);
86 QVBoxLayout *vlayout = new QVBoxLayout(this);
87 vlayout->setContentsMargins(0,0,0,0);
88 vlayout->setSpacing(0);
89 //vlayout->addLayout(hlayout2);
91 QTableView *view = new QTableView(this);
92 vlayout->addLayout(hlayout);
93 vlayout->addWidget(view);
94 vlayout->setSpacing(0);
95 int width = view->verticalScrollBar()->sizeHint().width();
96 // Cover scroll bar width with spacing
97 hlayout->addSpacing(width);
98 // Always show scroll bar
99 view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
100 view->setTabKeyNavigation(false);
101 view->setContextMenuPolicy(Qt::CustomContextMenu);
103 transactionView = view;
106 QAction *copyAddressAction = new QAction("Copy address", this);
107 QAction *copyLabelAction = new QAction("Copy label", this);
108 QAction *editLabelAction = new QAction("Edit label", this);
109 QAction *showDetailsAction = new QAction("Show details...", this);
111 contextMenu = new QMenu();
112 contextMenu->addAction(copyAddressAction);
113 contextMenu->addAction(copyLabelAction);
114 contextMenu->addAction(editLabelAction);
115 contextMenu->addAction(showDetailsAction);
118 connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
119 connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
120 connect(addressWidget, SIGNAL(textChanged(const QString&)), this, SLOT(changedPrefix(const QString&)));
121 connect(amountWidget, SIGNAL(textChanged(const QString&)), this, SLOT(changedAmount(const QString&)));
123 connect(view, SIGNAL(doubleClicked(const QModelIndex&)), this, SIGNAL(doubleClicked(const QModelIndex&)));
126 SIGNAL(customContextMenuRequested(const QPoint &)),
128 SLOT(contextualMenu(const QPoint &)));
130 connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
131 connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
132 connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
133 connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
136 void TransactionView::setModel(WalletModel *model)
140 transactionProxyModel = new TransactionFilterProxy(this);
141 transactionProxyModel->setSourceModel(model->getTransactionTableModel());
142 transactionProxyModel->setDynamicSortFilter(true);
144 transactionProxyModel->setSortRole(Qt::EditRole);
146 transactionView->setModel(transactionProxyModel);
147 transactionView->setAlternatingRowColors(true);
148 transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
149 transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
150 transactionView->setSortingEnabled(true);
151 transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
152 transactionView->verticalHeader()->hide();
154 transactionView->horizontalHeader()->resizeSection(
155 TransactionTableModel::Status, 23);
156 transactionView->horizontalHeader()->resizeSection(
157 TransactionTableModel::Date, 120);
158 transactionView->horizontalHeader()->resizeSection(
159 TransactionTableModel::Type, 120);
160 transactionView->horizontalHeader()->setResizeMode(
161 TransactionTableModel::ToAddress, QHeaderView::Stretch);
162 transactionView->horizontalHeader()->resizeSection(
163 TransactionTableModel::Amount, 100);
167 void TransactionView::chooseDate(int idx)
169 QDate current = QDate::currentDate();
170 switch(dateWidget->itemData(idx).toInt())
173 transactionProxyModel->setDateRange(
174 TransactionFilterProxy::MIN_DATE,
175 TransactionFilterProxy::MAX_DATE);
178 transactionProxyModel->setDateRange(
180 TransactionFilterProxy::MAX_DATE);
184 QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
185 transactionProxyModel->setDateRange(
186 QDateTime(startOfWeek),
187 TransactionFilterProxy::MAX_DATE);
191 transactionProxyModel->setDateRange(
192 QDateTime(QDate(current.year(), current.month(), 1)),
193 TransactionFilterProxy::MAX_DATE);
196 transactionProxyModel->setDateRange(
197 QDateTime(QDate(current.year(), current.month()-1, 1)),
198 QDateTime(QDate(current.year(), current.month(), 1)));
201 transactionProxyModel->setDateRange(
202 QDateTime(QDate(current.year(), 1, 1)),
203 TransactionFilterProxy::MAX_DATE);
206 // TODO ask specific range
212 void TransactionView::chooseType(int idx)
214 transactionProxyModel->setTypeFilter(
215 typeWidget->itemData(idx).toInt());
218 void TransactionView::changedPrefix(const QString &prefix)
220 transactionProxyModel->setAddressPrefix(prefix);
223 void TransactionView::changedAmount(const QString &amount)
225 qint64 amount_parsed = 0;
226 if(GUIUtil::parseMoney(amount, &amount_parsed))
228 transactionProxyModel->setMinAmount(amount_parsed);
232 transactionProxyModel->setMinAmount(0);
236 void TransactionView::exportClicked()
238 // CSV is currently the only supported format
239 QString filename = QFileDialog::getSaveFileName(
241 tr("Export Transaction Data"),
243 tr("Comma separated file (*.csv)"));
245 if (filename.isNull()) return;
247 CSVModelWriter writer(filename);
249 // name, column, role
250 writer.setModel(transactionProxyModel);
251 writer.addColumn("Confirmed", 0, TransactionTableModel::ConfirmedRole);
252 writer.addColumn("Date", 0, TransactionTableModel::DateRole);
253 writer.addColumn("Type", TransactionTableModel::Type, Qt::EditRole);
254 writer.addColumn("Label", 0, TransactionTableModel::LabelRole);
255 writer.addColumn("Address", 0, TransactionTableModel::AddressRole);
256 writer.addColumn("Amount", 0, TransactionTableModel::FormattedAmountRole);
257 writer.addColumn("ID", 0, TransactionTableModel::TxIDRole);
261 QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
262 QMessageBox::Abort, QMessageBox::Abort);
266 void TransactionView::contextualMenu(const QPoint &point)
268 QModelIndex index = transactionView->indexAt(point);
271 contextMenu->exec(QCursor::pos());
275 void TransactionView::copyAddress()
277 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
278 if(!selection.isEmpty())
280 QApplication::clipboard()->setText(selection.at(0).data(TransactionTableModel::AddressRole).toString());
284 void TransactionView::copyLabel()
286 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
287 if(!selection.isEmpty())
289 QApplication::clipboard()->setText(selection.at(0).data(TransactionTableModel::LabelRole).toString());
293 void TransactionView::editLabel()
295 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
296 if(!selection.isEmpty())
298 AddressTableModel *addressBook = model->getAddressTableModel();
299 QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
300 if(address.isEmpty())
302 // If this transaction has no associated address, exit
305 int idx = addressBook->lookupAddress(address);
308 // Edit sending / receiving address
309 QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex());
310 // Determine type of address, launch appropriate editor dialog type
311 QString type = modelIdx.data(AddressTableModel::TypeRole).toString();
313 EditAddressDialog dlg(type==AddressTableModel::Receive
314 ? EditAddressDialog::EditReceivingAddress
315 : EditAddressDialog::EditSendingAddress,
317 dlg.setModel(addressBook);
323 // Add sending address
324 EditAddressDialog dlg(EditAddressDialog::NewSendingAddress,
331 void TransactionView::showDetails()
333 QModelIndexList selection = transactionView->selectionModel()->selectedRows();
334 if(!selection.isEmpty())
336 TransactionDescDialog dlg(selection.at(0));