Bitcoin ABC  0.26.3
P2P Digital Currency
transactiontablemodel.cpp
Go to the documentation of this file.
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.
4 
6 
7 #include <core_io.h>
8 #include <interfaces/handler.h>
9 #include <qt/addresstablemodel.h>
10 #include <qt/clientmodel.h>
11 #include <qt/guiconstants.h>
12 #include <qt/guiutil.h>
13 #include <qt/optionsmodel.h>
14 #include <qt/platformstyle.h>
15 #include <qt/transactiondesc.h>
16 #include <qt/transactionrecord.h>
17 #include <qt/walletmodel.h>
18 #include <uint256.h>
19 
20 #include <algorithm>
21 #include <functional>
22 
23 #include <QColor>
24 #include <QDateTime>
25 #include <QDebug>
26 #include <QIcon>
27 #include <QList>
28 
29 // Amount column is right-aligned it contains numbers
30 static int column_alignments[] = {
31  Qt::AlignLeft | Qt::AlignVCenter, /* status */
32  Qt::AlignLeft | Qt::AlignVCenter, /* watchonly */
33  Qt::AlignLeft | Qt::AlignVCenter, /* date */
34  Qt::AlignLeft | Qt::AlignVCenter, /* type */
35  Qt::AlignLeft | Qt::AlignVCenter, /* address */
36  Qt::AlignRight | Qt::AlignVCenter /* amount */
37 };
38 
39 // Comparison operator for sort/binary search of model tx list
40 struct TxLessThan {
42  const TransactionRecord &b) const {
43  return a.txid < b.txid;
44  }
45  bool operator()(const TransactionRecord &a, const TxId &b) const {
46  return a.txid < b;
47  }
48  bool operator()(const TxId &a, const TransactionRecord &b) const {
49  return a < b.txid;
50  }
51 };
52 
53 // queue notifications to show a non freezing progress dialog e.g. for rescan
55 public:
58  bool _showTransaction)
59  : txid(_txid), status(_status), showTransaction(_showTransaction) {}
60 
61  void invoke(QObject *ttm) {
62  QString strHash = QString::fromStdString(txid.GetHex());
63  qDebug() << "NotifyTransactionChanged: " + strHash +
64  " status= " + QString::number(status);
65  bool invoked = QMetaObject::invokeMethod(
66  ttm, "updateTransaction", Qt::QueuedConnection,
67  Q_ARG(QString, strHash), Q_ARG(int, status),
68  Q_ARG(bool, showTransaction));
69  assert(invoked);
70  }
71 
72 private:
76 };
77 
78 // Private implementation
80 public:
82  : parent(_parent) {}
83 
85 
86  /* Local cache of wallet.
87  * As it is in the same order as the CWallet, by definition this is sorted
88  * by sha256.
89  */
90  QList<TransactionRecord> cachedWallet;
91 
92  bool fQueueNotifications = false;
93  std::vector<TransactionNotification> vQueueNotifications;
94 
95  void NotifyTransactionChanged(const TxId &txidc, ChangeType status);
96  void ShowProgress(const std::string &title, int nProgress);
97 
102  qDebug() << "TransactionTablePriv::refreshWallet";
103  cachedWallet.clear();
104  for (const auto &wtx : wallet.getWalletTxs()) {
106  cachedWallet.append(
108  }
109  }
110  }
111 
117  void updateWallet(interfaces::Wallet &wallet, const TxId &txid, int status,
118  bool showTransaction) {
119  qDebug() << "TransactionTablePriv::updateWallet: " +
120  QString::fromStdString(txid.ToString()) + " " +
121  QString::number(status);
122 
123  // Find bounds of this transaction in model
124  QList<TransactionRecord>::iterator lower = std::lower_bound(
125  cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
126  QList<TransactionRecord>::iterator upper = std::upper_bound(
127  cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
128  int lowerIndex = (lower - cachedWallet.begin());
129  int upperIndex = (upper - cachedWallet.begin());
130  bool inModel = (lower != upper);
131 
132  if (status == CT_UPDATED) {
133  // Not in model, but want to show, treat as new.
134  if (showTransaction && !inModel) {
135  status = CT_NEW;
136  }
137  // In model, but want to hide, treat as deleted.
138  if (!showTransaction && inModel) {
139  status = CT_DELETED;
140  }
141  }
142 
143  qDebug() << " inModel=" + QString::number(inModel) +
144  " Index=" + QString::number(lowerIndex) + "-" +
145  QString::number(upperIndex) +
146  " showTransaction=" + QString::number(showTransaction) +
147  " derivedStatus=" + QString::number(status);
148 
149  switch (status) {
150  case CT_NEW:
151  if (inModel) {
152  qWarning() << "TransactionTablePriv::updateWallet: "
153  "Warning: Got CT_NEW, but transaction is "
154  "already in model";
155  break;
156  }
157  if (showTransaction) {
158  // Find transaction in wallet
159  interfaces::WalletTx wtx = wallet.getWalletTx(txid);
160  if (!wtx.tx) {
161  qWarning() << "TransactionTablePriv::updateWallet: "
162  "Warning: Got CT_NEW, but transaction is "
163  "not in wallet";
164  break;
165  }
166  // Added -- insert at the right position
167  QList<TransactionRecord> toInsert =
169  /* only if something to insert */
170  if (!toInsert.isEmpty()) {
171  parent->beginInsertRows(QModelIndex(), lowerIndex,
172  lowerIndex + toInsert.size() -
173  1);
174  int insert_idx = lowerIndex;
175  for (const TransactionRecord &rec : toInsert) {
176  cachedWallet.insert(insert_idx, rec);
177  insert_idx += 1;
178  }
179  parent->endInsertRows();
180  }
181  }
182  break;
183  case CT_DELETED:
184  if (!inModel) {
185  qWarning() << "TransactionTablePriv::updateWallet: "
186  "Warning: Got CT_DELETED, but transaction is "
187  "not in model";
188  break;
189  }
190  // Removed -- remove entire transaction from table
191  parent->beginRemoveRows(QModelIndex(), lowerIndex,
192  upperIndex - 1);
193  cachedWallet.erase(lower, upper);
194  parent->endRemoveRows();
195  break;
196  case CT_UPDATED:
197  // Miscellaneous updates -- nothing to do, status update will
198  // take care of this, and is only computed for visible
199  // transactions.
200  break;
201  }
202  }
203 
204  int size() { return cachedWallet.size(); }
205 
207  const BlockHash &cur_block_hash, const int idx) {
208  if (idx >= 0 && idx < cachedWallet.size()) {
209  TransactionRecord *rec = &cachedWallet[idx];
210 
211  // If a status update is needed (blocks came in since last check),
212  // try to update the status of this transaction from the wallet.
213  // Otherwise, simply re-use the cached status.
215  int numBlocks;
216  int64_t block_time;
217  if (!cur_block_hash.IsNull() &&
218  rec->statusUpdateNeeded(cur_block_hash) &&
219  wallet.tryGetTxStatus(rec->txid, wtx, numBlocks, block_time)) {
220  rec->updateStatus(wtx, cur_block_hash, numBlocks, block_time);
221  }
222  return rec;
223  }
224  return nullptr;
225  }
226 
228  TransactionRecord *rec, int unit) {
229  return TransactionDesc::toHTML(node, wallet, rec, unit);
230  }
231 
233  auto tx = wallet.getTx(rec->txid);
234  if (tx) {
235  std::string strHex = EncodeHexTx(*tx);
236  return QString::fromStdString(strHex);
237  }
238  return QString();
239  }
240 };
241 
243  const PlatformStyle *_platformStyle, WalletModel *parent)
244  : QAbstractTableModel(parent), walletModel(parent),
245  priv(new TransactionTablePriv(this)),
246  fProcessingQueuedTransactions(false), platformStyle(_platformStyle) {
247  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label")
251 
254 
256 }
257 
260  delete priv;
261 }
262 
268  Q_EMIT headerDataChanged(Qt::Horizontal, Amount, Amount);
269 }
270 
271 void TransactionTableModel::updateTransaction(const QString &hash, int status,
272  bool showTransaction) {
273  TxId updated;
274  updated.SetHex(hash.toStdString());
275 
276  priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
277 }
278 
280  // Blocks came in since last poll.
281  // Invalidate status (number of confirmations) and (possibly) description
282  // for all rows. Qt is smart enough to only actually request the data for
283  // the visible rows.
284  Q_EMIT dataChanged(index(0, Status), index(priv->size() - 1, Status));
285  Q_EMIT dataChanged(index(0, ToAddress), index(priv->size() - 1, ToAddress));
286 }
287 
288 int TransactionTableModel::rowCount(const QModelIndex &parent) const {
289  Q_UNUSED(parent);
290  return priv->size();
291 }
292 
293 int TransactionTableModel::columnCount(const QModelIndex &parent) const {
294  Q_UNUSED(parent);
295  return columns.length();
296 }
297 
298 QString
300  QString status;
301 
302  switch (wtx->status.status) {
304  status = tr("Unconfirmed");
305  break;
307  status = tr("Abandoned");
308  break;
310  status = tr("Confirming (%1 of %2 recommended confirmations)")
311  .arg(wtx->status.depth)
313  break;
315  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
316  break;
318  status = tr("Conflicted");
319  break;
321  status =
322  tr("Immature (%1 confirmations, will be available after %2)")
323  .arg(wtx->status.depth)
324  .arg(wtx->status.depth + wtx->status.matures_in);
325  break;
327  status = tr("Generated but not accepted");
328  break;
329  }
330 
331  return status;
332 }
333 
334 QString
336  if (wtx->time) {
337  return GUIUtil::dateTimeStr(wtx->time);
338  }
339  return QString();
340 }
341 
346 QString TransactionTableModel::lookupAddress(const std::string &address,
347  bool tooltip) const {
349  QString::fromStdString(address));
350  QString description;
351  if (!label.isEmpty()) {
352  description += label;
353  }
354  if (label.isEmpty() || tooltip) {
355  description +=
356  QString(" (") + QString::fromStdString(address) + QString(")");
357  }
358  return description;
359 }
360 
361 QString
363  switch (wtx->type) {
365  return tr("Received with");
367  return tr("Received from");
370  return tr("Sent to");
372  return tr("Payment to yourself");
374  return tr("Mined");
375  default:
376  return QString();
377  }
378 }
379 
380 QVariant
382  switch (wtx->type) {
384  return QIcon(":/icons/tx_mined");
387  return QIcon(":/icons/tx_input");
390  return QIcon(":/icons/tx_output");
391  default:
392  return QIcon(":/icons/tx_inout");
393  }
394 }
395 
397  bool tooltip) const {
398  QString watchAddress;
399  if (tooltip) {
400  // Mark transactions involving watch-only addresses by adding "
401  // (watch-only)"
402  watchAddress = wtx->involvesWatchAddress
403  ? QString(" (") + tr("watch-only") + QString(")")
404  : "";
405  }
406 
407  switch (wtx->type) {
409  return QString::fromStdString(wtx->address) + watchAddress;
413  return lookupAddress(wtx->address, tooltip) + watchAddress;
415  return QString::fromStdString(wtx->address) + watchAddress;
417  return lookupAddress(wtx->address, tooltip) + watchAddress;
418  default:
419  return tr("(n/a)") + watchAddress;
420  }
421 }
422 
423 QVariant
425  // Show addresses without label in a less visible color
426  switch (wtx->type) {
430  QString label =
432  QString::fromStdString(wtx->address));
433  if (label.isEmpty()) {
434  return COLOR_BAREADDRESS;
435  }
436  } break;
438  return COLOR_BAREADDRESS;
439  default:
440  break;
441  }
442  return QVariant();
443 }
444 
446  const TransactionRecord *wtx, bool showUnconfirmed,
447  BitcoinUnits::SeparatorStyle separators) const {
448  QString str =
450  wtx->credit + wtx->debit, false, separators);
451  if (showUnconfirmed) {
452  if (!wtx->status.countsForBalance) {
453  str = QString("[") + str + QString("]");
454  }
455  }
456  return QString(str);
457 }
458 
459 QVariant
461  switch (wtx->status.status) {
463  return QIcon(":/icons/transaction_0");
465  return QIcon(":/icons/transaction_abandoned");
467  switch (wtx->status.depth) {
468  case 1:
469  return QIcon(":/icons/transaction_1");
470  case 2:
471  return QIcon(":/icons/transaction_2");
472  case 3:
473  return QIcon(":/icons/transaction_3");
474  case 4:
475  return QIcon(":/icons/transaction_4");
476  default:
477  return QIcon(":/icons/transaction_5");
478  };
480  return QIcon(":/icons/transaction_confirmed");
482  return QIcon(":/icons/transaction_conflicted");
484  int total = wtx->status.depth + wtx->status.matures_in;
485  int part = (wtx->status.depth * 4 / total) + 1;
486  return QIcon(QString(":/icons/transaction_%1").arg(part));
487  }
489  return QIcon(":/icons/transaction_0");
490  default:
491  return COLOR_BLACK;
492  }
493 }
494 
496  const TransactionRecord *wtx) const {
497  if (wtx->involvesWatchAddress) {
498  return QIcon(":/icons/eye");
499  }
500 
501  return QVariant();
502 }
503 
504 QString
506  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
511  tooltip += QString(" ") + formatTxToAddress(rec, true);
512  }
513  return tooltip;
514 }
515 
516 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const {
517  if (!index.isValid()) {
518  return QVariant();
519  }
520 
521  TransactionRecord *rec =
522  static_cast<TransactionRecord *>(index.internalPointer());
523 
524  switch (role) {
525  case RawDecorationRole:
526  switch (index.column()) {
527  case Status:
528  return txStatusDecoration(rec);
529  case Watchonly:
530  return txWatchonlyDecoration(rec);
531  case ToAddress:
532  return txAddressDecoration(rec);
533  }
534  break;
535  case Qt::DecorationRole: {
536  QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
537  return platformStyle->TextColorIcon(icon);
538  }
539  case Qt::DisplayRole:
540  switch (index.column()) {
541  case Date:
542  return formatTxDate(rec);
543  case Type:
544  return formatTxType(rec);
545  case ToAddress:
546  return formatTxToAddress(rec, false);
547  case Amount:
548  return formatTxAmount(rec, true,
550  }
551  break;
552  case Qt::EditRole:
553  // Edit role is used for sorting, so return the unformatted values
554  switch (index.column()) {
555  case Status:
556  return QString::fromStdString(rec->status.sortKey);
557  case Date:
558  return rec->time;
559  case Type:
560  return formatTxType(rec);
561  case Watchonly:
562  return (rec->involvesWatchAddress ? 1 : 0);
563  case ToAddress:
564  return formatTxToAddress(rec, true);
565  case Amount:
566  return qint64((rec->credit + rec->debit) / SATOSHI);
567  }
568  break;
569  case Qt::ToolTipRole:
570  return formatTooltip(rec);
571  case Qt::TextAlignmentRole:
572  return column_alignments[index.column()];
573  case Qt::ForegroundRole:
574  // Use the "danger" color for abandoned transactions
576  return COLOR_TX_STATUS_DANGER;
577  }
578  // Non-confirmed (but not immature) as transactions are grey
579  if (!rec->status.countsForBalance &&
581  return COLOR_UNCONFIRMED;
582  }
583  if (index.column() == Amount &&
584  (rec->credit + rec->debit) < ::Amount::zero()) {
585  return COLOR_NEGATIVE;
586  }
587  if (index.column() == ToAddress) {
588  return addressColor(rec);
589  }
590  break;
591  case TypeRole:
592  return rec->type;
593  case DateRole:
594  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
595  case WatchonlyRole:
596  return rec->involvesWatchAddress;
598  return txWatchonlyDecoration(rec);
599  case LongDescriptionRole:
600  return priv->describe(
601  walletModel->node(), walletModel->wallet(), rec,
603  case AddressRole:
604  return QString::fromStdString(rec->address);
605  case LabelRole:
607  QString::fromStdString(rec->address));
608  case AmountRole:
609  return qint64((rec->credit + rec->debit) / SATOSHI);
610  case TxIDRole:
611  return rec->getTxID();
612  case TxHashRole:
613  return QString::fromStdString(rec->txid.ToString());
614  case TxHexRole:
615  return priv->getTxHex(walletModel->wallet(), rec);
616  case TxPlainTextRole: {
617  QString details;
618  QDateTime date =
619  QDateTime::fromTime_t(static_cast<uint>(rec->time));
620  QString txLabel =
622  QString::fromStdString(rec->address));
623 
624  details.append(date.toString("M/d/yy HH:mm"));
625  details.append(" ");
626  details.append(formatTxStatus(rec));
627  details.append(". ");
628  if (!formatTxType(rec).isEmpty()) {
629  details.append(formatTxType(rec));
630  details.append(" ");
631  }
632  if (!rec->address.empty()) {
633  if (txLabel.isEmpty()) {
634  details.append(tr("(no label)") + " ");
635  } else {
636  details.append("(");
637  details.append(txLabel);
638  details.append(") ");
639  }
640  details.append(QString::fromStdString(rec->address));
641  details.append(" ");
642  }
643  details.append(formatTxAmount(rec, false,
645  return details;
646  }
647  case ConfirmedRole:
648  return rec->status.status ==
649  TransactionStatus::Status::Confirming ||
650  rec->status.status == TransactionStatus::Status::Confirmed;
651  case FormattedAmountRole:
652  // Used for copy/export, so don't include separators
653  return formatTxAmount(rec, false,
655  case StatusRole:
656  return rec->status.status;
657  }
658  return QVariant();
659 }
660 
662  Qt::Orientation orientation,
663  int role) const {
664  if (orientation == Qt::Horizontal) {
665  if (role == Qt::DisplayRole) {
666  return columns[section];
667  } else if (role == Qt::TextAlignmentRole) {
668  return column_alignments[section];
669  } else if (role == Qt::ToolTipRole) {
670  switch (section) {
671  case Status:
672  return tr("Transaction status. Hover over this field to "
673  "show number of confirmations.");
674  case Date:
675  return tr(
676  "Date and time that the transaction was received.");
677  case Type:
678  return tr("Type of transaction.");
679  case Watchonly:
680  return tr("Whether or not a watch-only address is involved "
681  "in this transaction.");
682  case ToAddress:
683  return tr(
684  "User-defined intent/purpose of the transaction.");
685  case Amount:
686  return tr("Amount removed from or added to balance.");
687  }
688  }
689  }
690  return QVariant();
691 }
692 
693 QModelIndex TransactionTableModel::index(int row, int column,
694  const QModelIndex &parent) const {
695  Q_UNUSED(parent);
698  if (data) {
699  return createIndex(row, column, data);
700  }
701  return QModelIndex();
702 }
703 
705  // emit dataChanged to update Amount column with the current unit
707  Q_EMIT dataChanged(index(0, Amount), index(priv->size() - 1, Amount));
708 }
709 
711  ChangeType status) {
712  // Find transaction in wallet
713  // Determine whether to show transaction or not (determine this here so that
714  // no relocking is needed in GUI thread)
715  bool showTransaction = TransactionRecord::showTransaction();
716 
717  TransactionNotification notification(txid, status, showTransaction);
718 
719  if (fQueueNotifications) {
720  vQueueNotifications.push_back(notification);
721  return;
722  }
723  notification.invoke(parent);
724 }
725 
726 void TransactionTablePriv::ShowProgress(const std::string &title,
727  int nProgress) {
728  if (nProgress == 0) {
729  fQueueNotifications = true;
730  }
731 
732  if (nProgress == 100) {
733  fQueueNotifications = false;
734  if (vQueueNotifications.size() > 10) {
735  // prevent balloon spam, show maximum 10 balloons
736  bool invoked = QMetaObject::invokeMethod(
737  parent, "setProcessingQueuedTransactions", Qt::QueuedConnection,
738  Q_ARG(bool, true));
739  assert(invoked);
740  }
741 
742  for (size_t i = 0; i < vQueueNotifications.size(); ++i) {
743  if (vQueueNotifications.size() - i <= 10) {
744  bool invoked = QMetaObject::invokeMethod(
745  parent, "setProcessingQueuedTransactions",
746  Qt::QueuedConnection, Q_ARG(bool, false));
747  assert(invoked);
748  }
749 
750  vQueueNotifications[i].invoke(parent);
751  }
752  vQueueNotifications.clear();
753  }
754 }
755 
757  // Connect signals to wallet
761  std::placeholders::_1, std::placeholders::_2));
764  std::placeholders::_1, std::placeholders::_2));
765 }
766 
768  // Disconnect signals from wallet
769  m_handler_transaction_changed->disconnect();
770  m_handler_show_progress->disconnect();
771 }
static constexpr Amount SATOSHI
Definition: amount.h:153
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
static QString format(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
int getDisplayUnit() const
Definition: optionsmodel.h:97
void displayUnitChanged(int unit)
QIcon TextColorIcon(const QIcon &icon) const
Colorize an icon (given object) with the text color.
static QString toHTML(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
UI model for a transaction.
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
Decompose CWallet transaction to model transaction records.
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
static bool showTransaction()
Decompose CWallet transaction to model transaction records.
TransactionStatus status
Status: can change with block chain update.
void updateStatus(const interfaces::WalletTxStatus &wtx, const BlockHash &block_hash, int numBlocks, int64_t block_time)
Update status from core wallet tx.
bool statusUpdateNeeded(const BlockHash &block_hash) const
Return whether a status update is needed.
QString getTxID() const
Return the unique identifier for this transaction (part)
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
bool countsForBalance
Transaction counts towards available balance.
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ Unconfirmed
Normal (sent/received) transactions.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ Conflicted
Conflicts with other transaction or mempool.
@ Abandoned
Abandoned from the wallet.
std::string sortKey
Sorting key based on status.
UI model for the transaction table of a wallet.
QVariant txStatusDecoration(const TransactionRecord *wtx) const
TransactionTablePriv * priv
QVariant addressColor(const TransactionRecord *wtx) const
@ TxPlainTextRole
Whole transaction as plain text.
@ LabelRole
Label of address related to transaction.
@ LongDescriptionRole
Long description (HTML format)
@ TypeRole
Type of transaction.
@ StatusRole
Transaction status (TransactionRecord::Status)
@ DateRole
Date and time this transaction was created.
@ TxHashRole
Transaction hash.
@ TxHexRole
Transaction data, hex-encoded.
@ RawDecorationRole
Unprocessed icon.
@ TxIDRole
Unique identifier.
@ AddressRole
Address of transaction.
@ WatchonlyDecorationRole
Watch-only icon.
@ WatchonlyRole
Watch-only boolean.
@ AmountRole
Net amount of transaction.
@ ConfirmedRole
Is transaction confirmed?
@ FormattedAmountRole
Formatted amount, without brackets when unconfirmed.
QString formatTooltip(const TransactionRecord *rec) const
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::SeparatorStyle::STANDARD) const
QVariant data(const QModelIndex &index, int role) const override
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
void updateTransaction(const QString &hash, int status, bool showTransaction)
New transaction, or transaction changed status.
QString formatTxStatus(const TransactionRecord *wtx) const
std::unique_ptr< interfaces::Handler > m_handler_transaction_changed
int columnCount(const QModelIndex &parent) const override
std::unique_ptr< interfaces::Handler > m_handler_show_progress
TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent=nullptr)
int rowCount(const QModelIndex &parent) const override
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
const PlatformStyle * platformStyle
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QString formatTxType(const TransactionRecord *wtx) const
QString lookupAddress(const std::string &address, bool tooltip) const
Look up address in address book, if found return label (address) otherwise just return (address)
QVariant txAddressDecoration(const TransactionRecord *wtx) const
QString formatTxDate(const TransactionRecord *wtx) const
QString getTxHex(interfaces::Wallet &wallet, TransactionRecord *rec)
void updateWallet(interfaces::Wallet &wallet, const TxId &txid, int status, bool showTransaction)
Update our model of the wallet incrementally, to synchronize our model of the wallet with that of the...
TransactionRecord * index(interfaces::Wallet &wallet, const BlockHash &cur_block_hash, const int idx)
TransactionTablePriv(TransactionTableModel *_parent)
TransactionTableModel * parent
QList< TransactionRecord > cachedWallet
std::vector< TransactionNotification > vQueueNotifications
void refreshWallet(interfaces::Wallet &wallet)
Query entire wallet anew from core.
QString describe(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
void ShowProgress(const std::string &title, int nProgress)
void NotifyTransactionChanged(const TxId &txidc, ChangeType status)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
BlockHash getLastBlockProcessed() const
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
interfaces::Node & node() const
Definition: walletmodel.h:149
void SetHex(const char *psz)
Definition: uint256.cpp:24
std::string ToString() const
Definition: uint256.h:78
bool IsNull() const
Definition: uint256.h:30
std::string GetHex() const
Definition: uint256.cpp:16
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:57
Interface for accessing a wallet.
Definition: wallet.h:59
virtual std::unique_ptr< Handler > handleShowProgress(ShowProgressFn fn)=0
virtual std::unique_ptr< Handler > handleTransactionChanged(TransactionChangedFn fn)=0
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:169
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:31
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
#define COLOR_BLACK
Definition: guiconstants.h:33
#define COLOR_BAREADDRESS
Definition: guiconstants.h:29
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:70
Definition: init.h:28
Definition: amount.h:19
static constexpr Amount zero()
Definition: amount.h:42
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
TransactionNotification(TxId _txid, ChangeType _status, bool _showTransaction)
A TxId is the identifier of a transaction.
Definition: txid.h:14
bool operator()(const TransactionRecord &a, const TxId &b) const
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
bool operator()(const TxId &a, const TransactionRecord &b) const
CTransactionRef tx
Definition: wallet.h:373
Updated transaction status.
Definition: wallet.h:387
static int column_alignments[]
ChangeType
General change type (added, updated, removed).
Definition: ui_change_type.h:9
@ CT_UPDATED
Definition: ui_change_type.h:9
@ CT_DELETED
Definition: ui_change_type.h:9
@ CT_NEW
Definition: ui_change_type.h:9
assert(!tx.IsCoinBase())