Bitcoin Core  31.0.0
P2P Digital Currency
transactionview.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-present 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.
4 
5 #include <qt/transactionview.h>
6 
7 #include <qt/addresstablemodel.h>
8 #include <qt/bitcoinunits.h>
9 #include <qt/csvmodelwriter.h>
10 #include <qt/editaddressdialog.h>
11 #include <qt/guiutil.h>
12 #include <qt/optionsmodel.h>
13 #include <qt/platformstyle.h>
16 #include <qt/transactionrecord.h>
18 #include <qt/walletmodel.h>
19 
20 #include <node/interface_ui.h>
21 
22 #include <chrono>
23 #include <optional>
24 
25 #include <QApplication>
26 #include <QComboBox>
27 #include <QDateTimeEdit>
28 #include <QDesktopServices>
29 #include <QDoubleValidator>
30 #include <QHBoxLayout>
31 #include <QHeaderView>
32 #include <QLabel>
33 #include <QLineEdit>
34 #include <QMenu>
35 #include <QPoint>
36 #include <QScrollBar>
37 #include <QSettings>
38 #include <QTableView>
39 #include <QTimer>
40 #include <QUrl>
41 #include <QVBoxLayout>
42 
43 TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent)
44  : QWidget(parent), m_platform_style{platformStyle}
45 {
46  // Build filter row
47  setContentsMargins(0,0,0,0);
48 
49  QHBoxLayout *hlayout = new QHBoxLayout();
50  hlayout->setContentsMargins(0,0,0,0);
51 
52  if (platformStyle->getUseExtraSpacing()) {
53  hlayout->setSpacing(5);
54  hlayout->addSpacing(26);
55  } else {
56  hlayout->setSpacing(0);
57  hlayout->addSpacing(23);
58  }
59 
60  dateWidget = new QComboBox(this);
61  if (platformStyle->getUseExtraSpacing()) {
62  dateWidget->setFixedWidth(121);
63  } else {
64  dateWidget->setFixedWidth(120);
65  }
66  dateWidget->addItem(tr("All"), All);
67  dateWidget->addItem(tr("Today"), Today);
68  dateWidget->addItem(tr("This week"), ThisWeek);
69  dateWidget->addItem(tr("This month"), ThisMonth);
70  dateWidget->addItem(tr("Last month"), LastMonth);
71  dateWidget->addItem(tr("This year"), ThisYear);
72  dateWidget->addItem(tr("Range…"), Range);
73  hlayout->addWidget(dateWidget);
74 
75  typeWidget = new QComboBox(this);
76  if (platformStyle->getUseExtraSpacing()) {
77  typeWidget->setFixedWidth(121);
78  } else {
79  typeWidget->setFixedWidth(120);
80  }
81 
82  typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
83  typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
85  typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
87  typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
88  typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));
89 
90  hlayout->addWidget(typeWidget);
91 
92  search_widget = new QLineEdit(this);
93  search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search"));
94  hlayout->addWidget(search_widget);
95 
96  amountWidget = new QLineEdit(this);
97  amountWidget->setPlaceholderText(tr("Min amount"));
98  if (platformStyle->getUseExtraSpacing()) {
99  amountWidget->setFixedWidth(97);
100  } else {
101  amountWidget->setFixedWidth(100);
102  }
103  QDoubleValidator *amountValidator = new QDoubleValidator(0, 1e20, 8, this);
104  QLocale amountLocale(QLocale::C);
105  amountLocale.setNumberOptions(QLocale::RejectGroupSeparator);
106  amountValidator->setLocale(amountLocale);
107  amountWidget->setValidator(amountValidator);
108  hlayout->addWidget(amountWidget);
109 
110  // Delay before filtering transactions
111  static constexpr auto input_filter_delay{200ms};
112 
113  QTimer* amount_typing_delay = new QTimer(this);
114  amount_typing_delay->setSingleShot(true);
115  amount_typing_delay->setInterval(input_filter_delay);
116 
117  QTimer* prefix_typing_delay = new QTimer(this);
118  prefix_typing_delay->setSingleShot(true);
119  prefix_typing_delay->setInterval(input_filter_delay);
120 
121  QVBoxLayout *vlayout = new QVBoxLayout(this);
122  vlayout->setContentsMargins(0,0,0,0);
123  vlayout->setSpacing(0);
124 
125  transactionView = new QTableView(this);
126  transactionView->setObjectName("transactionView");
127  vlayout->addLayout(hlayout);
128  vlayout->addWidget(createDateRangeWidget());
129  vlayout->addWidget(transactionView);
130  vlayout->setSpacing(0);
131  int width = transactionView->verticalScrollBar()->sizeHint().width();
132  // Cover scroll bar width with spacing
133  if (platformStyle->getUseExtraSpacing()) {
134  hlayout->addSpacing(width+2);
135  } else {
136  hlayout->addSpacing(width);
137  }
138  transactionView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
139  transactionView->setTabKeyNavigation(false);
140  transactionView->setContextMenuPolicy(Qt::CustomContextMenu);
141  transactionView->installEventFilter(this);
142  transactionView->setAlternatingRowColors(true);
143  transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
144  transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
145  transactionView->setSortingEnabled(true);
146  transactionView->verticalHeader()->hide();
147 
148  QSettings settings;
149  if (!transactionView->horizontalHeader()->restoreState(settings.value("TransactionViewHeaderState-2025").toByteArray())) {
150  transactionView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH);
151  transactionView->setColumnWidth(TransactionTableModel::Date, DATE_COLUMN_WIDTH);
152  transactionView->setColumnWidth(TransactionTableModel::Type, TYPE_COLUMN_WIDTH);
153  transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
154  transactionView->horizontalHeader()->setMinimumSectionSize(MINIMUM_COLUMN_WIDTH);
155  transactionView->horizontalHeader()->setStretchLastSection(true);
156  }
157 
158  contextMenu = new QMenu(this);
159  contextMenu->setObjectName("contextMenu");
160  copyAddressAction = contextMenu->addAction(tr("&Copy address"), this, &TransactionView::copyAddress);
161  copyLabelAction = contextMenu->addAction(tr("Copy &label"), this, &TransactionView::copyLabel);
162  contextMenu->addAction(tr("Copy &amount"), this, &TransactionView::copyAmount);
163  contextMenu->addAction(tr("Copy transaction &ID"), this, &TransactionView::copyTxID);
164  contextMenu->addAction(tr("Copy &raw transaction"), this, &TransactionView::copyTxHex);
165  contextMenu->addAction(tr("Copy full transaction &details"), this, &TransactionView::copyTxPlainText);
166  contextMenu->addAction(tr("&Show transaction details"), this, &TransactionView::showDetails);
167  contextMenu->addSeparator();
168  bumpFeeAction = contextMenu->addAction(tr("Increase transaction &fee"));
169  GUIUtil::ExceptionSafeConnect(bumpFeeAction, &QAction::triggered, this, &TransactionView::bumpFee);
170  bumpFeeAction->setObjectName("bumpFeeAction");
171  abandonAction = contextMenu->addAction(tr("A&bandon transaction"), this, &TransactionView::abandonTx);
172  contextMenu->addAction(tr("&Edit address label"), this, &TransactionView::editLabel);
173 
174  connect(dateWidget, qOverload<int>(&QComboBox::activated), this, &TransactionView::chooseDate);
175  connect(typeWidget, qOverload<int>(&QComboBox::activated), this, &TransactionView::chooseType);
176  connect(amountWidget, &QLineEdit::textChanged, amount_typing_delay, qOverload<>(&QTimer::start));
177  connect(amount_typing_delay, &QTimer::timeout, this, &TransactionView::changedAmount);
178  connect(search_widget, &QLineEdit::textChanged, prefix_typing_delay, qOverload<>(&QTimer::start));
179  connect(prefix_typing_delay, &QTimer::timeout, this, &TransactionView::changedSearch);
180 
181  connect(transactionView, &QTableView::doubleClicked, this, &TransactionView::doubleClicked);
182  connect(transactionView, &QTableView::customContextMenuRequested, this, &TransactionView::contextualMenu);
183 
184  // Double-clicking on a transaction on the transaction history page shows details
186  // Highlight transaction after fee bump
187  connect(this, &TransactionView::bumpedFee, [this](const Txid& txid) {
188  focusTransaction(txid);
189  });
190 }
191 
193 {
194  QSettings settings;
195  // Rename this cache when adding or removing columns.
196  settings.setValue("TransactionViewHeaderState-2025", transactionView->horizontalHeader()->saveState());
197 }
198 
200 {
201  this->model = _model;
202  if(_model)
203  {
205  transactionProxyModel->setSourceModel(_model->getTransactionTableModel());
206  transactionProxyModel->setDynamicSortFilter(true);
207  transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
208  transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
209  transactionProxyModel->setSortRole(Qt::EditRole);
211  transactionView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder);
212 
213  if (_model->getOptionsModel())
214  {
215  // Add third party transaction URLs to context menu
216  QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", Qt::SkipEmptyParts);
217  bool actions_created = false;
218  for (int i = 0; i < listUrls.size(); ++i)
219  {
220  QString url = listUrls[i].trimmed();
221  QString host = QUrl(url, QUrl::StrictMode).host();
222  if (!host.isEmpty())
223  {
224  if (!actions_created) {
225  contextMenu->addSeparator();
226  actions_created = true;
227  }
228  /*: Transactions table context menu action to show the
229  selected transaction in a third-party block explorer.
230  %1 is a stand-in argument for the URL of the explorer. */
231  contextMenu->addAction(tr("Show in %1").arg(host), [this, url] { openThirdPartyTxUrl(url); });
232  }
233  }
234  }
235  }
236 }
237 
239 {
240  QWidget::changeEvent(e);
241 }
242 
244 {
245  if (!transactionProxyModel) return;
246  QDate current = QDate::currentDate();
247  dateRangeWidget->setVisible(false);
248  switch(dateWidget->itemData(idx).toInt())
249  {
250  case All:
252  std::nullopt,
253  std::nullopt);
254  break;
255  case Today:
257  GUIUtil::StartOfDay(current),
258  std::nullopt);
259  break;
260  case ThisWeek: {
261  // Find last Monday
262  QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
264  GUIUtil::StartOfDay(startOfWeek),
265  std::nullopt);
266 
267  } break;
268  case ThisMonth:
270  GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1)),
271  std::nullopt);
272  break;
273  case LastMonth:
275  GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1).addMonths(-1)),
276  GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1)));
277  break;
278  case ThisYear:
280  GUIUtil::StartOfDay(QDate(current.year(), 1, 1)),
281  std::nullopt);
282  break;
283  case Range:
284  dateRangeWidget->setVisible(true);
286  break;
287  }
288 }
289 
291 {
293  return;
295  typeWidget->itemData(idx).toInt());
296 }
297 
299 {
301  return;
303 }
304 
306 {
308  return;
309  CAmount amount_parsed = 0;
310  if (BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amountWidget->text(), &amount_parsed)) {
311  transactionProxyModel->setMinAmount(amount_parsed);
312  }
313  else
314  {
316  }
317 }
318 
320 {
321  if (!model || !model->getOptionsModel()) {
322  return;
323  }
324 
325  // CSV is currently the only supported format
326  QString filename = GUIUtil::getSaveFileName(this,
327  tr("Export Transaction History"), QString(),
328  /*: Expanded name of the CSV file format.
329  See: https://en.wikipedia.org/wiki/Comma-separated_values. */
330  tr("Comma separated file") + QLatin1String(" (*.csv)"), nullptr);
331 
332  if (filename.isNull())
333  return;
334 
335  CSVModelWriter writer(filename);
336 
337  // name, column, role
339  writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
340  writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
341  writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
342  writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole);
343  writer.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole);
345  writer.addColumn(tr("ID"), 0, TransactionTableModel::TxHashRole);
346 
347  if(!writer.write()) {
348  Q_EMIT message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename),
350  }
351  else {
352  Q_EMIT message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename),
354  }
355 }
356 
357 void TransactionView::contextualMenu(const QPoint &point)
358 {
359  QModelIndex index = transactionView->indexAt(point);
360  QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
361  if (selection.empty())
362  return;
363 
364  // If the hash from the TxHashRole (QVariant / QString) is invalid, exit
365  QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
366  std::optional<Txid> maybeHash = Txid::FromHex(hashQStr.toStdString());
367  if (!maybeHash)
368  return;
369 
370  Txid hash = *maybeHash;
371  abandonAction->setEnabled(model->wallet().transactionCanBeAbandoned(hash));
372  bumpFeeAction->setEnabled(model->wallet().transactionCanBeBumped(hash));
375 
376  if (index.isValid()) {
377  GUIUtil::PopupMenu(contextMenu, transactionView->viewport()->mapToGlobal(point));
378  }
379 }
380 
382 {
383  if(!transactionView || !transactionView->selectionModel())
384  return;
385  QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
386 
387  // get the hash from the TxHashRole (QVariant / QString)
388  QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
389  Txid hash = Txid::FromHex(hashQStr.toStdString()).value();
390 
391  // Abandon the wallet transaction over the walletModel
393 }
394 
395 void TransactionView::bumpFee([[maybe_unused]] bool checked)
396 {
397  if(!transactionView || !transactionView->selectionModel())
398  return;
399  QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
400 
401  // get the hash from the TxHashRole (QVariant / QString)
402  QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
403  Txid hash = Txid::FromHex(hashQStr.toStdString()).value();
404 
405  // Bump tx fee over the walletModel
406  Txid newHash;
407  if (model->bumpFee(hash, newHash)) {
408  // Update the table
409  transactionView->selectionModel()->clearSelection();
411 
412  qApp->processEvents();
413  Q_EMIT bumpedFee(newHash);
414  }
415 }
416 
418 {
420 }
421 
423 {
425 }
426 
428 {
430 }
431 
433 {
435 }
436 
438 {
440 }
441 
443 {
445 }
446 
448 {
449  if(!transactionView->selectionModel() ||!model)
450  return;
451  QModelIndexList selection = transactionView->selectionModel()->selectedRows();
452  if(!selection.isEmpty())
453  {
454  AddressTableModel *addressBook = model->getAddressTableModel();
455  if(!addressBook)
456  return;
457  QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
458  if(address.isEmpty())
459  {
460  // If this transaction has no associated address, exit
461  return;
462  }
463  // Is address in address book? Address book can miss address when a transaction is
464  // sent from outside the UI.
465  int idx = addressBook->lookupAddress(address);
466  if(idx != -1)
467  {
468  // Edit sending / receiving address
469  QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex());
470  // Determine type of address, launch appropriate editor dialog type
471  QString type = modelIdx.data(AddressTableModel::TypeRole).toString();
472 
473  auto dlg = new EditAddressDialog(
477  dlg->setModel(addressBook);
478  dlg->loadRow(idx);
480  }
481  else
482  {
483  // Add sending address
485  this);
486  dlg->setModel(addressBook);
487  dlg->setAddress(address);
489  }
490  }
491 }
492 
494 {
495  if(!transactionView->selectionModel())
496  return;
497  QModelIndexList selection = transactionView->selectionModel()->selectedRows();
498  if(!selection.isEmpty())
499  {
500  TransactionDescDialog *dlg = new TransactionDescDialog(selection.at(0));
501  dlg->setAttribute(Qt::WA_DeleteOnClose);
502  m_opened_dialogs.append(dlg);
503  connect(dlg, &QObject::destroyed, [this, dlg] {
504  m_opened_dialogs.removeOne(dlg);
505  });
506  dlg->show();
507  }
508 }
509 
511 {
512  if(!transactionView || !transactionView->selectionModel())
513  return;
514  QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
515  if(!selection.isEmpty())
516  QDesktopServices::openUrl(QUrl::fromUserInput(url.replace("%s", selection.at(0).data(TransactionTableModel::TxHashRole).toString())));
517 }
518 
520 {
521  dateRangeWidget = new QFrame();
522  dateRangeWidget->setFrameStyle(static_cast<int>(QFrame::Panel) | static_cast<int>(QFrame::Raised));
523  dateRangeWidget->setContentsMargins(1,1,1,1);
524  QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
525  layout->setContentsMargins(0,0,0,0);
526  layout->addSpacing(23);
527  layout->addWidget(new QLabel(tr("Range:")));
528 
529  dateFrom = new QDateTimeEdit(this);
530  dateFrom->setDisplayFormat("dd/MM/yy");
531  dateFrom->setCalendarPopup(true);
532  dateFrom->setMinimumWidth(100);
533  dateFrom->setDate(QDate::currentDate().addDays(-7));
534  layout->addWidget(dateFrom);
535  layout->addWidget(new QLabel(tr("to")));
536 
537  dateTo = new QDateTimeEdit(this);
538  dateTo->setDisplayFormat("dd/MM/yy");
539  dateTo->setCalendarPopup(true);
540  dateTo->setMinimumWidth(100);
541  dateTo->setDate(QDate::currentDate());
542  layout->addWidget(dateTo);
543  layout->addStretch();
544 
545  // Hide by default
546  dateRangeWidget->setVisible(false);
547 
548  // Notify on change
549  connect(dateFrom, &QDateTimeEdit::dateChanged, this, &TransactionView::dateRangeChanged);
550  connect(dateTo, &QDateTimeEdit::dateChanged, this, &TransactionView::dateRangeChanged);
551 
552  return dateRangeWidget;
553 }
554 
556 {
558  return;
560  GUIUtil::StartOfDay(dateFrom->date()),
561  GUIUtil::StartOfDay(dateTo->date()).addDays(1));
562 }
563 
564 void TransactionView::focusTransaction(const QModelIndex &idx)
565 {
567  return;
568  QModelIndex targetIdx = transactionProxyModel->mapFromSource(idx);
569  transactionView->scrollTo(targetIdx);
570  transactionView->setCurrentIndex(targetIdx);
571  transactionView->setFocus();
572 }
573 
575 {
577  return;
578 
579  const QModelIndexList results = this->model->getTransactionTableModel()->match(
580  this->model->getTransactionTableModel()->index(0,0),
582  QString::fromStdString(txid.ToString()), -1);
583 
584  transactionView->setFocus();
585  transactionView->selectionModel()->clearSelection();
586  for (const QModelIndex& index : results) {
587  const QModelIndex targetIndex = transactionProxyModel->mapFromSource(index);
588  transactionView->selectionModel()->select(
589  targetIndex,
590  QItemSelectionModel::Rows | QItemSelectionModel::Select);
591  // Called once per destination to ensure all results are in view, unless
592  // transactions are not ordered by (ascending or descending) date.
593  transactionView->scrollTo(targetIndex);
594  // scrollTo() does not scroll far enough the first time when transactions
595  // are ordered by ascending date.
596  if (index == results[0]) transactionView->scrollTo(targetIndex);
597  }
598 }
599 
600 // Need to override default Ctrl+C action for amount as default behaviour is just to copy DisplayRole text
601 bool TransactionView::eventFilter(QObject *obj, QEvent *event)
602 {
603  if (event->type() == QEvent::KeyPress)
604  {
605  QKeyEvent *ke = static_cast<QKeyEvent *>(event);
606  if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
607  {
609  return true;
610  }
611  }
612  if (event->type() == QEvent::EnabledChange) {
613  if (!isEnabled()) {
615  }
616  }
617  return QWidget::eventFilter(obj, event);
618 }
619 
621 {
622  // close all dialogs opened from this view
623  for (QDialog* dlg : m_opened_dialogs) {
624  dlg->close();
625  }
626  m_opened_dialogs.clear();
627 }
QVariant data(const QModelIndex &index, int role) const override
void addColumn(const QString &title, int column, int role=Qt::EditRole)
QDateTime StartOfDay(const QDate &date)
Returns the start-moment of the day in local time.
Definition: guiutil.cpp:950
TransactionRecord * index(interfaces::Wallet &wallet, const uint256 &cur_block_hash, const int idx)
Predefined combinations for certain default usage cases.
Definition: interface_ui.h:66
OptionsModel * getOptionsModel() const
void openThirdPartyTxUrl(QString url)
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
QWidget * createDateRangeWidget()
int lookupAddress(const QString &address) const
Dialog showing transaction details.
void PopupMenu(QMenu *menu, const QPoint &point, QAction *at_action)
Call QMenu::popup() only on supported QT_QPA_PLATFORM.
Definition: guiutil.cpp:943
QAction * abandonAction
void updateTransaction(const QString &hash, int status, bool showTransaction)
void bumpFee(bool checked)
TransactionTableModel * getTransactionTableModel() const
void focusTransaction(const QModelIndex &)
void setTypeFilter(quint32 modes)
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
QTableView * transactionView
static bool parse(Unit unit, const QString &value, CAmount *val_out)
Parse string to coin amount.
void bumpedFee(const Txid &txid)
void ShowModalDialogAsynchronously(QDialog *dialog)
Shows a QDialog instance asynchronously, and deletes it on close.
Definition: guiutil.cpp:978
Export a Qt table model to a CSV file.
Transaction data, hex-encoded.
TransactionTableModel * parent
static quint32 TYPE(int type)
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
QDateTimeEdit * dateTo
const char * url
Definition: rpcconsole.cpp:61
Whole transaction as plain text.
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
std::string ToString() const
auto ExceptionSafeConnect(Sender sender, Signal signal, Receiver receiver, Slot method, Qt::ConnectionType type=Qt::AutoConnection)
A drop-in replacement of QObject::connect function (see: https://doc.qt.io/qt-5/qobject.html#connect-3), that guaranties that all exceptions are handled within the slot.
Definition: guiutil.h:369
bool hasEntryData(const QAbstractItemView *view, int column, int role)
Returns true if the specified field of the currently selected view entry is not empty.
Definition: guiutil.cpp:284
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Date and time this transaction was created.
bool eventFilter(QObject *obj, QEvent *event) override
void copyEntryData(const QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
Definition: guiutil.cpp:264
Qt model of the address book in the core.
void setMinAmount(const CAmount &minimum)
TransactionFilterProxy * transactionProxyModel
QString getThirdPartyTxUrls() const
Definition: optionsmodel.h:104
QAction * copyLabelAction
void chooseDate(int idx)
void setModel(const QAbstractItemModel *model)
void setModel(WalletModel *model)
QLineEdit * amountWidget
QComboBox * typeWidget
Filter the transaction list according to pre-specified rules.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:48
QList< TransactionDescDialog * > m_opened_dialogs
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:313
static const QString Receive
Specifies receive address.
Dialog for editing an address and associated information.
bool bumpFee(Txid hash, Txid &new_hash)
QFrame * dateRangeWidget
Label of address related to transaction.
static const quint32 ALL_TYPES
Type filter bit field (all types)
static QString getAmountColumnTitle(Unit unit)
Gets title for amount column including current display unit if optionsModel reference available */...
void setSearchString(const QString &)
TransactionView(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
AddressTableModel * getAddressTableModel() const
QAction * copyAddressAction
virtual bool transactionCanBeAbandoned(const Txid &txid)=0
Return whether transaction can be abandoned.
void contextualMenu(const QPoint &)
void changeEvent(QEvent *e) override
Formatted amount, without brackets when unconfirmed.
virtual bool abandonTransaction(const Txid &txid)=0
Abandon transaction.
void chooseType(int idx)
QAction * bumpFeeAction
QDateTimeEdit * dateFrom
QModelIndex index(int row, int column, const QModelIndex &parent) const override
bool write()
Perform export of the model to CSV.
void doubleClicked(const QModelIndex &)
static std::optional< transaction_identifier > FromHex(std::string_view hex)
void setDateRange(const std::optional< QDateTime > &from, const std::optional< QDateTime > &to)
Filter transactions between date range.
Type of address (Send or Receive)
WalletModel * model
virtual bool transactionCanBeBumped(const Txid &txid)=0
Return whether transaction can be bumped.
QComboBox * dateWidget
QLineEdit * search_widget