1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #include "transactionview.h"
7 #include "addresstablemodel.h"
8 #include "bitcoinunits.h"
9 #include "csvmodelwriter.h"
10 #include "editaddressdialog.h"
12 #include "optionsmodel.h"
13 #include "platformstyle.h"
14 #include "sendcoinsdialog.h"
15 #include "transactiondescdialog.h"
16 #include "transactionfilterproxy.h"
17 #include "transactionrecord.h"
18 #include "transactiontablemodel.h"
19 #include "walletmodel.h"
21 #include "ui_interface.h"
24 #include <QDateTimeEdit>
25 #include <QDesktopServices>
26 #include <QDoubleValidator>
27 #include <QHBoxLayout>
28 #include <QHeaderView>
34 #include <QSignalMapper>
38 #include <QVBoxLayout>
40 TransactionView::TransactionView(const PlatformStyle
*platformStyle
, QWidget
*parent
) :
41 QWidget(parent
), model(0), transactionProxyModel(0),
42 transactionView(0), abandonAction(0), bumpFeeAction(0), columnResizingFixer(0)
45 setContentsMargins(0,0,0,0);
47 QHBoxLayout
*hlayout
= new QHBoxLayout();
48 hlayout
->setContentsMargins(0,0,0,0);
50 if (platformStyle
->getUseExtraSpacing()) {
51 hlayout
->setSpacing(5);
52 hlayout
->addSpacing(26);
54 hlayout
->setSpacing(0);
55 hlayout
->addSpacing(23);
58 watchOnlyWidget
= new QComboBox(this);
59 watchOnlyWidget
->setFixedWidth(24);
60 watchOnlyWidget
->addItem("", TransactionFilterProxy::WatchOnlyFilter_All
);
61 watchOnlyWidget
->addItem(platformStyle
->SingleColorIcon(":/icons/eye_plus"), "", TransactionFilterProxy::WatchOnlyFilter_Yes
);
62 watchOnlyWidget
->addItem(platformStyle
->SingleColorIcon(":/icons/eye_minus"), "", TransactionFilterProxy::WatchOnlyFilter_No
);
63 hlayout
->addWidget(watchOnlyWidget
);
65 dateWidget
= new QComboBox(this);
66 if (platformStyle
->getUseExtraSpacing()) {
67 dateWidget
->setFixedWidth(121);
69 dateWidget
->setFixedWidth(120);
71 dateWidget
->addItem(tr("All"), All
);
72 dateWidget
->addItem(tr("Today"), Today
);
73 dateWidget
->addItem(tr("This week"), ThisWeek
);
74 dateWidget
->addItem(tr("This month"), ThisMonth
);
75 dateWidget
->addItem(tr("Last month"), LastMonth
);
76 dateWidget
->addItem(tr("This year"), ThisYear
);
77 dateWidget
->addItem(tr("Range..."), Range
);
78 hlayout
->addWidget(dateWidget
);
80 typeWidget
= new QComboBox(this);
81 if (platformStyle
->getUseExtraSpacing()) {
82 typeWidget
->setFixedWidth(121);
84 typeWidget
->setFixedWidth(120);
87 typeWidget
->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES
);
88 typeWidget
->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress
) |
89 TransactionFilterProxy::TYPE(TransactionRecord::RecvFromOther
));
90 typeWidget
->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress
) |
91 TransactionFilterProxy::TYPE(TransactionRecord::SendToOther
));
92 typeWidget
->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf
));
93 typeWidget
->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated
));
94 typeWidget
->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other
));
96 hlayout
->addWidget(typeWidget
);
98 addressWidget
= new QLineEdit(this);
99 #if QT_VERSION >= 0x040700
100 addressWidget
->setPlaceholderText(tr("Enter address or label to search"));
102 hlayout
->addWidget(addressWidget
);
104 amountWidget
= new QLineEdit(this);
105 #if QT_VERSION >= 0x040700
106 amountWidget
->setPlaceholderText(tr("Min amount"));
108 if (platformStyle
->getUseExtraSpacing()) {
109 amountWidget
->setFixedWidth(97);
111 amountWidget
->setFixedWidth(100);
113 amountWidget
->setValidator(new QDoubleValidator(0, 1e20
, 8, this));
114 hlayout
->addWidget(amountWidget
);
116 // Delay before filtering transactions in ms
117 static const int input_filter_delay
= 200;
119 QTimer
* amount_typing_delay
= new QTimer(this);
120 amount_typing_delay
->setSingleShot(true);
121 amount_typing_delay
->setInterval(input_filter_delay
);
123 QTimer
* prefix_typing_delay
= new QTimer(this);
124 prefix_typing_delay
->setSingleShot(true);
125 prefix_typing_delay
->setInterval(input_filter_delay
);
127 QVBoxLayout
*vlayout
= new QVBoxLayout(this);
128 vlayout
->setContentsMargins(0,0,0,0);
129 vlayout
->setSpacing(0);
131 QTableView
*view
= new QTableView(this);
132 vlayout
->addLayout(hlayout
);
133 vlayout
->addWidget(createDateRangeWidget());
134 vlayout
->addWidget(view
);
135 vlayout
->setSpacing(0);
136 int width
= view
->verticalScrollBar()->sizeHint().width();
137 // Cover scroll bar width with spacing
138 if (platformStyle
->getUseExtraSpacing()) {
139 hlayout
->addSpacing(width
+2);
141 hlayout
->addSpacing(width
);
143 // Always show scroll bar
144 view
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn
);
145 view
->setTabKeyNavigation(false);
146 view
->setContextMenuPolicy(Qt::CustomContextMenu
);
148 view
->installEventFilter(this);
150 transactionView
= view
;
151 transactionView
->setObjectName("transactionView");
154 abandonAction
= new QAction(tr("Abandon transaction"), this);
155 bumpFeeAction
= new QAction(tr("Increase transaction fee"), this);
156 bumpFeeAction
->setObjectName("bumpFeeAction");
157 QAction
*copyAddressAction
= new QAction(tr("Copy address"), this);
158 QAction
*copyLabelAction
= new QAction(tr("Copy label"), this);
159 QAction
*copyAmountAction
= new QAction(tr("Copy amount"), this);
160 QAction
*copyTxIDAction
= new QAction(tr("Copy transaction ID"), this);
161 QAction
*copyTxHexAction
= new QAction(tr("Copy raw transaction"), this);
162 QAction
*copyTxPlainText
= new QAction(tr("Copy full transaction details"), this);
163 QAction
*editLabelAction
= new QAction(tr("Edit label"), this);
164 QAction
*showDetailsAction
= new QAction(tr("Show transaction details"), this);
166 contextMenu
= new QMenu(this);
167 contextMenu
->setObjectName("contextMenu");
168 contextMenu
->addAction(copyAddressAction
);
169 contextMenu
->addAction(copyLabelAction
);
170 contextMenu
->addAction(copyAmountAction
);
171 contextMenu
->addAction(copyTxIDAction
);
172 contextMenu
->addAction(copyTxHexAction
);
173 contextMenu
->addAction(copyTxPlainText
);
174 contextMenu
->addAction(showDetailsAction
);
175 contextMenu
->addSeparator();
176 contextMenu
->addAction(bumpFeeAction
);
177 contextMenu
->addAction(abandonAction
);
178 contextMenu
->addAction(editLabelAction
);
180 mapperThirdPartyTxUrls
= new QSignalMapper(this);
183 connect(mapperThirdPartyTxUrls
, SIGNAL(mapped(QString
)), this, SLOT(openThirdPartyTxUrl(QString
)));
185 connect(dateWidget
, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
186 connect(typeWidget
, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
187 connect(watchOnlyWidget
, SIGNAL(activated(int)), this, SLOT(chooseWatchonly(int)));
188 connect(amountWidget
, SIGNAL(textChanged(QString
)), amount_typing_delay
, SLOT(start()));
189 connect(amount_typing_delay
, SIGNAL(timeout()), this, SLOT(changedAmount()));
190 connect(addressWidget
, SIGNAL(textChanged(QString
)), prefix_typing_delay
, SLOT(start()));
191 connect(prefix_typing_delay
, SIGNAL(timeout()), this, SLOT(changedPrefix()));
193 connect(view
, SIGNAL(doubleClicked(QModelIndex
)), this, SIGNAL(doubleClicked(QModelIndex
)));
194 connect(view
, SIGNAL(customContextMenuRequested(QPoint
)), this, SLOT(contextualMenu(QPoint
)));
196 connect(bumpFeeAction
, SIGNAL(triggered()), this, SLOT(bumpFee()));
197 connect(abandonAction
, SIGNAL(triggered()), this, SLOT(abandonTx()));
198 connect(copyAddressAction
, SIGNAL(triggered()), this, SLOT(copyAddress()));
199 connect(copyLabelAction
, SIGNAL(triggered()), this, SLOT(copyLabel()));
200 connect(copyAmountAction
, SIGNAL(triggered()), this, SLOT(copyAmount()));
201 connect(copyTxIDAction
, SIGNAL(triggered()), this, SLOT(copyTxID()));
202 connect(copyTxHexAction
, SIGNAL(triggered()), this, SLOT(copyTxHex()));
203 connect(copyTxPlainText
, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
204 connect(editLabelAction
, SIGNAL(triggered()), this, SLOT(editLabel()));
205 connect(showDetailsAction
, SIGNAL(triggered()), this, SLOT(showDetails()));
208 void TransactionView::setModel(WalletModel
*_model
)
210 this->model
= _model
;
213 transactionProxyModel
= new TransactionFilterProxy(this);
214 transactionProxyModel
->setSourceModel(_model
->getTransactionTableModel());
215 transactionProxyModel
->setDynamicSortFilter(true);
216 transactionProxyModel
->setSortCaseSensitivity(Qt::CaseInsensitive
);
217 transactionProxyModel
->setFilterCaseSensitivity(Qt::CaseInsensitive
);
219 transactionProxyModel
->setSortRole(Qt::EditRole
);
221 transactionView
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
222 transactionView
->setModel(transactionProxyModel
);
223 transactionView
->setAlternatingRowColors(true);
224 transactionView
->setSelectionBehavior(QAbstractItemView::SelectRows
);
225 transactionView
->setSelectionMode(QAbstractItemView::ExtendedSelection
);
226 transactionView
->setSortingEnabled(true);
227 transactionView
->sortByColumn(TransactionTableModel::Date
, Qt::DescendingOrder
);
228 transactionView
->verticalHeader()->hide();
230 transactionView
->setColumnWidth(TransactionTableModel::Status
, STATUS_COLUMN_WIDTH
);
231 transactionView
->setColumnWidth(TransactionTableModel::Watchonly
, WATCHONLY_COLUMN_WIDTH
);
232 transactionView
->setColumnWidth(TransactionTableModel::Date
, DATE_COLUMN_WIDTH
);
233 transactionView
->setColumnWidth(TransactionTableModel::Type
, TYPE_COLUMN_WIDTH
);
234 transactionView
->setColumnWidth(TransactionTableModel::Amount
, AMOUNT_MINIMUM_COLUMN_WIDTH
);
236 columnResizingFixer
= new GUIUtil::TableViewLastColumnResizingFixer(transactionView
, AMOUNT_MINIMUM_COLUMN_WIDTH
, MINIMUM_COLUMN_WIDTH
, this);
238 if (_model
->getOptionsModel())
240 // Add third party transaction URLs to context menu
241 QStringList listUrls
= _model
->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts
);
242 for (int i
= 0; i
< listUrls
.size(); ++i
)
244 QString host
= QUrl(listUrls
[i
].trimmed(), QUrl::StrictMode
).host();
247 QAction
*thirdPartyTxUrlAction
= new QAction(host
, this); // use host as menu item label
249 contextMenu
->addSeparator();
250 contextMenu
->addAction(thirdPartyTxUrlAction
);
251 connect(thirdPartyTxUrlAction
, SIGNAL(triggered()), mapperThirdPartyTxUrls
, SLOT(map()));
252 mapperThirdPartyTxUrls
->setMapping(thirdPartyTxUrlAction
, listUrls
[i
].trimmed());
257 // show/hide column Watch-only
258 updateWatchOnlyColumn(_model
->haveWatchOnly());
261 connect(_model
, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool)));
265 void TransactionView::chooseDate(int idx
)
267 if(!transactionProxyModel
)
269 QDate current
= QDate::currentDate();
270 dateRangeWidget
->setVisible(false);
271 switch(dateWidget
->itemData(idx
).toInt())
274 transactionProxyModel
->setDateRange(
275 TransactionFilterProxy::MIN_DATE
,
276 TransactionFilterProxy::MAX_DATE
);
279 transactionProxyModel
->setDateRange(
281 TransactionFilterProxy::MAX_DATE
);
285 QDate startOfWeek
= current
.addDays(-(current
.dayOfWeek()-1));
286 transactionProxyModel
->setDateRange(
287 QDateTime(startOfWeek
),
288 TransactionFilterProxy::MAX_DATE
);
292 transactionProxyModel
->setDateRange(
293 QDateTime(QDate(current
.year(), current
.month(), 1)),
294 TransactionFilterProxy::MAX_DATE
);
297 transactionProxyModel
->setDateRange(
298 QDateTime(QDate(current
.year(), current
.month(), 1).addMonths(-1)),
299 QDateTime(QDate(current
.year(), current
.month(), 1)));
302 transactionProxyModel
->setDateRange(
303 QDateTime(QDate(current
.year(), 1, 1)),
304 TransactionFilterProxy::MAX_DATE
);
307 dateRangeWidget
->setVisible(true);
313 void TransactionView::chooseType(int idx
)
315 if(!transactionProxyModel
)
317 transactionProxyModel
->setTypeFilter(
318 typeWidget
->itemData(idx
).toInt());
321 void TransactionView::chooseWatchonly(int idx
)
323 if(!transactionProxyModel
)
325 transactionProxyModel
->setWatchOnlyFilter(
326 (TransactionFilterProxy::WatchOnlyFilter
)watchOnlyWidget
->itemData(idx
).toInt());
329 void TransactionView::changedPrefix()
331 if(!transactionProxyModel
)
333 transactionProxyModel
->setAddressPrefix(addressWidget
->text());
336 void TransactionView::changedAmount()
338 if(!transactionProxyModel
)
340 CAmount amount_parsed
= 0;
341 if (BitcoinUnits::parse(model
->getOptionsModel()->getDisplayUnit(), amountWidget
->text(), &amount_parsed
)) {
342 transactionProxyModel
->setMinAmount(amount_parsed
);
346 transactionProxyModel
->setMinAmount(0);
350 void TransactionView::exportClicked()
352 if (!model
|| !model
->getOptionsModel()) {
356 // CSV is currently the only supported format
357 QString filename
= GUIUtil::getSaveFileName(this,
358 tr("Export Transaction History"), QString(),
359 tr("Comma separated file (*.csv)"), nullptr);
361 if (filename
.isNull())
364 CSVModelWriter
writer(filename
);
366 // name, column, role
367 writer
.setModel(transactionProxyModel
);
368 writer
.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole
);
369 if (model
&& model
->haveWatchOnly())
370 writer
.addColumn(tr("Watch-only"), TransactionTableModel::Watchonly
);
371 writer
.addColumn(tr("Date"), 0, TransactionTableModel::DateRole
);
372 writer
.addColumn(tr("Type"), TransactionTableModel::Type
, Qt::EditRole
);
373 writer
.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole
);
374 writer
.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole
);
375 writer
.addColumn(BitcoinUnits::getAmountColumnTitle(model
->getOptionsModel()->getDisplayUnit()), 0, TransactionTableModel::FormattedAmountRole
);
376 writer
.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole
);
378 if(!writer
.write()) {
379 Q_EMIT
message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename
),
380 CClientUIInterface::MSG_ERROR
);
383 Q_EMIT
message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename
),
384 CClientUIInterface::MSG_INFORMATION
);
388 void TransactionView::contextualMenu(const QPoint
&point
)
390 QModelIndex index
= transactionView
->indexAt(point
);
391 QModelIndexList selection
= transactionView
->selectionModel()->selectedRows(0);
392 if (selection
.empty())
395 // check if transaction can be abandoned, disable context menu action in case it doesn't
397 hash
.SetHex(selection
.at(0).data(TransactionTableModel::TxHashRole
).toString().toStdString());
398 abandonAction
->setEnabled(model
->transactionCanBeAbandoned(hash
));
399 bumpFeeAction
->setEnabled(model
->transactionCanBeBumped(hash
));
403 contextMenu
->popup(transactionView
->viewport()->mapToGlobal(point
));
407 void TransactionView::abandonTx()
409 if(!transactionView
|| !transactionView
->selectionModel())
411 QModelIndexList selection
= transactionView
->selectionModel()->selectedRows(0);
413 // get the hash from the TxHashRole (QVariant / QString)
415 QString hashQStr
= selection
.at(0).data(TransactionTableModel::TxHashRole
).toString();
416 hash
.SetHex(hashQStr
.toStdString());
418 // Abandon the wallet transaction over the walletModel
419 model
->abandonTransaction(hash
);
422 model
->getTransactionTableModel()->updateTransaction(hashQStr
, CT_UPDATED
, false);
425 void TransactionView::bumpFee()
427 if(!transactionView
|| !transactionView
->selectionModel())
429 QModelIndexList selection
= transactionView
->selectionModel()->selectedRows(0);
431 // get the hash from the TxHashRole (QVariant / QString)
433 QString hashQStr
= selection
.at(0).data(TransactionTableModel::TxHashRole
).toString();
434 hash
.SetHex(hashQStr
.toStdString());
436 // Bump tx fee over the walletModel
437 if (model
->bumpFee(hash
)) {
439 model
->getTransactionTableModel()->updateTransaction(hashQStr
, CT_UPDATED
, true);
443 void TransactionView::copyAddress()
445 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::AddressRole
);
448 void TransactionView::copyLabel()
450 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::LabelRole
);
453 void TransactionView::copyAmount()
455 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::FormattedAmountRole
);
458 void TransactionView::copyTxID()
460 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::TxIDRole
);
463 void TransactionView::copyTxHex()
465 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::TxHexRole
);
468 void TransactionView::copyTxPlainText()
470 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::TxPlainTextRole
);
473 void TransactionView::editLabel()
475 if(!transactionView
->selectionModel() ||!model
)
477 QModelIndexList selection
= transactionView
->selectionModel()->selectedRows();
478 if(!selection
.isEmpty())
480 AddressTableModel
*addressBook
= model
->getAddressTableModel();
483 QString address
= selection
.at(0).data(TransactionTableModel::AddressRole
).toString();
484 if(address
.isEmpty())
486 // If this transaction has no associated address, exit
489 // Is address in address book? Address book can miss address when a transaction is
490 // sent from outside the UI.
491 int idx
= addressBook
->lookupAddress(address
);
494 // Edit sending / receiving address
495 QModelIndex modelIdx
= addressBook
->index(idx
, 0, QModelIndex());
496 // Determine type of address, launch appropriate editor dialog type
497 QString type
= modelIdx
.data(AddressTableModel::TypeRole
).toString();
499 EditAddressDialog
dlg(
500 type
== AddressTableModel::Receive
501 ? EditAddressDialog::EditReceivingAddress
502 : EditAddressDialog::EditSendingAddress
, this);
503 dlg
.setModel(addressBook
);
509 // Add sending address
510 EditAddressDialog
dlg(EditAddressDialog::NewSendingAddress
,
512 dlg
.setModel(addressBook
);
513 dlg
.setAddress(address
);
519 void TransactionView::showDetails()
521 if(!transactionView
->selectionModel())
523 QModelIndexList selection
= transactionView
->selectionModel()->selectedRows();
524 if(!selection
.isEmpty())
526 TransactionDescDialog
*dlg
= new TransactionDescDialog(selection
.at(0));
527 dlg
->setAttribute(Qt::WA_DeleteOnClose
);
532 void TransactionView::openThirdPartyTxUrl(QString url
)
534 if(!transactionView
|| !transactionView
->selectionModel())
536 QModelIndexList selection
= transactionView
->selectionModel()->selectedRows(0);
537 if(!selection
.isEmpty())
538 QDesktopServices::openUrl(QUrl::fromUserInput(url
.replace("%s", selection
.at(0).data(TransactionTableModel::TxHashRole
).toString())));
541 QWidget
*TransactionView::createDateRangeWidget()
543 dateRangeWidget
= new QFrame();
544 dateRangeWidget
->setFrameStyle(QFrame::Panel
| QFrame::Raised
);
545 dateRangeWidget
->setContentsMargins(1,1,1,1);
546 QHBoxLayout
*layout
= new QHBoxLayout(dateRangeWidget
);
547 layout
->setContentsMargins(0,0,0,0);
548 layout
->addSpacing(23);
549 layout
->addWidget(new QLabel(tr("Range:")));
551 dateFrom
= new QDateTimeEdit(this);
552 dateFrom
->setDisplayFormat("dd/MM/yy");
553 dateFrom
->setCalendarPopup(true);
554 dateFrom
->setMinimumWidth(100);
555 dateFrom
->setDate(QDate::currentDate().addDays(-7));
556 layout
->addWidget(dateFrom
);
557 layout
->addWidget(new QLabel(tr("to")));
559 dateTo
= new QDateTimeEdit(this);
560 dateTo
->setDisplayFormat("dd/MM/yy");
561 dateTo
->setCalendarPopup(true);
562 dateTo
->setMinimumWidth(100);
563 dateTo
->setDate(QDate::currentDate());
564 layout
->addWidget(dateTo
);
565 layout
->addStretch();
568 dateRangeWidget
->setVisible(false);
571 connect(dateFrom
, SIGNAL(dateChanged(QDate
)), this, SLOT(dateRangeChanged()));
572 connect(dateTo
, SIGNAL(dateChanged(QDate
)), this, SLOT(dateRangeChanged()));
574 return dateRangeWidget
;
577 void TransactionView::dateRangeChanged()
579 if(!transactionProxyModel
)
581 transactionProxyModel
->setDateRange(
582 QDateTime(dateFrom
->date()),
583 QDateTime(dateTo
->date()).addDays(1));
586 void TransactionView::focusTransaction(const QModelIndex
&idx
)
588 if(!transactionProxyModel
)
590 QModelIndex targetIdx
= transactionProxyModel
->mapFromSource(idx
);
591 transactionView
->scrollTo(targetIdx
);
592 transactionView
->setCurrentIndex(targetIdx
);
593 transactionView
->setFocus();
596 // We override the virtual resizeEvent of the QWidget to adjust tables column
597 // sizes as the tables width is proportional to the dialogs width.
598 void TransactionView::resizeEvent(QResizeEvent
* event
)
600 QWidget::resizeEvent(event
);
601 columnResizingFixer
->stretchColumnWidth(TransactionTableModel::ToAddress
);
604 // Need to override default Ctrl+C action for amount as default behaviour is just to copy DisplayRole text
605 bool TransactionView::eventFilter(QObject
*obj
, QEvent
*event
)
607 if (event
->type() == QEvent::KeyPress
)
609 QKeyEvent
*ke
= static_cast<QKeyEvent
*>(event
);
610 if (ke
->key() == Qt::Key_C
&& ke
->modifiers().testFlag(Qt::ControlModifier
))
612 GUIUtil::copyEntryData(transactionView
, 0, TransactionTableModel::TxPlainTextRole
);
616 return QWidget::eventFilter(obj
, event
);
619 // show/hide column Watch-only
620 void TransactionView::updateWatchOnlyColumn(bool fHaveWatchOnly
)
622 watchOnlyWidget
->setVisible(fHaveWatchOnly
);
623 transactionView
->setColumnHidden(TransactionTableModel::Watchonly
, !fHaveWatchOnly
);