Bitcoin ABC  0.22.13
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 
22 #include <QColor>
23 #include <QDateTime>
24 #include <QDebug>
25 #include <QIcon>
26 #include <QList>
27 
28 // Amount column is right-aligned it contains numbers
29 static int column_alignments[] = {
30  Qt::AlignLeft | Qt::AlignVCenter, /* status */
31  Qt::AlignLeft | Qt::AlignVCenter, /* watchonly */
32  Qt::AlignLeft | Qt::AlignVCenter, /* date */
33  Qt::AlignLeft | Qt::AlignVCenter, /* type */
34  Qt::AlignLeft | Qt::AlignVCenter, /* address */
35  Qt::AlignRight | Qt::AlignVCenter /* amount */
36 };
37 
38 // Comparison operator for sort/binary search of model tx list
39 struct TxLessThan {
41  const TransactionRecord &b) const {
42  return a.txid < b.txid;
43  }
44  bool operator()(const TransactionRecord &a, const TxId &b) const {
45  return a.txid < b;
46  }
47  bool operator()(const TxId &a, const TransactionRecord &b) const {
48  return a < b.txid;
49  }
50 };
51 
52 // Private implementation
54 public:
56  : parent(_parent) {}
57 
59 
60  /* Local cache of wallet.
61  * As it is in the same order as the CWallet, by definition this is sorted
62  * by sha256.
63  */
64  QList<TransactionRecord> cachedWallet;
65 
70  qDebug() << "TransactionTablePriv::refreshWallet";
71  cachedWallet.clear();
72  for (const auto &wtx : wallet.getWalletTxs()) {
74  cachedWallet.append(
76  }
77  }
78  }
79 
85  void updateWallet(interfaces::Wallet &wallet, const TxId &txid, int status,
86  bool showTransaction) {
87  qDebug() << "TransactionTablePriv::updateWallet: " +
88  QString::fromStdString(txid.ToString()) + " " +
89  QString::number(status);
90 
91  // Find bounds of this transaction in model
92  QList<TransactionRecord>::iterator lower = std::lower_bound(
93  cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
94  QList<TransactionRecord>::iterator upper = std::upper_bound(
95  cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
96  int lowerIndex = (lower - cachedWallet.begin());
97  int upperIndex = (upper - cachedWallet.begin());
98  bool inModel = (lower != upper);
99 
100  if (status == CT_UPDATED) {
101  // Not in model, but want to show, treat as new.
102  if (showTransaction && !inModel) {
103  status = CT_NEW;
104  }
105  // In model, but want to hide, treat as deleted.
106  if (!showTransaction && inModel) {
107  status = CT_DELETED;
108  }
109  }
110 
111  qDebug() << " inModel=" + QString::number(inModel) +
112  " Index=" + QString::number(lowerIndex) + "-" +
113  QString::number(upperIndex) +
114  " showTransaction=" + QString::number(showTransaction) +
115  " derivedStatus=" + QString::number(status);
116 
117  switch (status) {
118  case CT_NEW:
119  if (inModel) {
120  qWarning() << "TransactionTablePriv::updateWallet: "
121  "Warning: Got CT_NEW, but transaction is "
122  "already in model";
123  break;
124  }
125  if (showTransaction) {
126  // Find transaction in wallet
127  interfaces::WalletTx wtx = wallet.getWalletTx(txid);
128  if (!wtx.tx) {
129  qWarning() << "TransactionTablePriv::updateWallet: "
130  "Warning: Got CT_NEW, but transaction is "
131  "not in wallet";
132  break;
133  }
134  // Added -- insert at the right position
135  QList<TransactionRecord> toInsert =
137  /* only if something to insert */
138  if (!toInsert.isEmpty()) {
139  parent->beginInsertRows(QModelIndex(), lowerIndex,
140  lowerIndex + toInsert.size() -
141  1);
142  int insert_idx = lowerIndex;
143  for (const TransactionRecord &rec : toInsert) {
144  cachedWallet.insert(insert_idx, rec);
145  insert_idx += 1;
146  }
147  parent->endInsertRows();
148  }
149  }
150  break;
151  case CT_DELETED:
152  if (!inModel) {
153  qWarning() << "TransactionTablePriv::updateWallet: "
154  "Warning: Got CT_DELETED, but transaction is "
155  "not in model";
156  break;
157  }
158  // Removed -- remove entire transaction from table
159  parent->beginRemoveRows(QModelIndex(), lowerIndex,
160  upperIndex - 1);
161  cachedWallet.erase(lower, upper);
162  parent->endRemoveRows();
163  break;
164  case CT_UPDATED:
165  // Miscellaneous updates -- nothing to do, status update will
166  // take care of this, and is only computed for visible
167  // transactions.
168  break;
169  }
170  }
171 
172  int size() { return cachedWallet.size(); }
173 
175  const int cur_num_blocks, const int idx) {
176  if (idx >= 0 && idx < cachedWallet.size()) {
177  TransactionRecord *rec = &cachedWallet[idx];
178 
179  // Get required locks upfront. This avoids the GUI from getting
180  // stuck if the core is holding the locks for a longer time - for
181  // example, during a wallet rescan.
182  //
183  // If a status update is needed (blocks came in since last check),
184  // update the status of this transaction from the wallet. Otherwise,
185  // simply re-use the cached status.
187  int numBlocks;
188  int64_t block_time;
189  if (rec->statusUpdateNeeded(cur_num_blocks) &&
190  wallet.tryGetTxStatus(rec->txid, wtx, numBlocks, block_time)) {
191  rec->updateStatus(wtx, numBlocks, block_time);
192  }
193  return rec;
194  }
195  return nullptr;
196  }
197 
199  TransactionRecord *rec, int unit) {
200  return TransactionDesc::toHTML(node, wallet, rec, unit);
201  }
202 
204  auto tx = wallet.getTx(rec->txid);
205  if (tx) {
206  std::string strHex = EncodeHexTx(*tx);
207  return QString::fromStdString(strHex);
208  }
209  return QString();
210  }
211 };
212 
214  const PlatformStyle *_platformStyle, WalletModel *parent)
215  : QAbstractTableModel(parent), walletModel(parent),
216  priv(new TransactionTablePriv(this)),
217  fProcessingQueuedTransactions(false), platformStyle(_platformStyle) {
218  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label")
222 
225 
227 }
228 
231  delete priv;
232 }
233 
239  Q_EMIT headerDataChanged(Qt::Horizontal, Amount, Amount);
240 }
241 
242 void TransactionTableModel::updateTransaction(const QString &hash, int status,
243  bool showTransaction) {
244  TxId updated;
245  updated.SetHex(hash.toStdString());
246 
247  priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
248 }
249 
251  // Blocks came in since last poll.
252  // Invalidate status (number of confirmations) and (possibly) description
253  // for all rows. Qt is smart enough to only actually request the data for
254  // the visible rows.
255  Q_EMIT dataChanged(index(0, Status), index(priv->size() - 1, Status));
256  Q_EMIT dataChanged(index(0, ToAddress), index(priv->size() - 1, ToAddress));
257 }
258 
259 int TransactionTableModel::rowCount(const QModelIndex &parent) const {
260  Q_UNUSED(parent);
261  return priv->size();
262 }
263 
264 int TransactionTableModel::columnCount(const QModelIndex &parent) const {
265  Q_UNUSED(parent);
266  return columns.length();
267 }
268 
269 QString
271  QString status;
272 
273  switch (wtx->status.status) {
275  status = tr("Open for %n more block(s)", "", wtx->status.open_for);
276  break;
278  status = tr("Open until %1")
280  break;
282  status = tr("Unconfirmed");
283  break;
285  status = tr("Abandoned");
286  break;
288  status = tr("Confirming (%1 of %2 recommended confirmations)")
289  .arg(wtx->status.depth)
291  break;
293  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
294  break;
296  status = tr("Conflicted");
297  break;
299  status =
300  tr("Immature (%1 confirmations, will be available after %2)")
301  .arg(wtx->status.depth)
302  .arg(wtx->status.depth + wtx->status.matures_in);
303  break;
305  status = tr("Generated but not accepted");
306  break;
307  }
308 
309  return status;
310 }
311 
312 QString
314  if (wtx->time) {
315  return GUIUtil::dateTimeStr(wtx->time);
316  }
317  return QString();
318 }
319 
324 QString TransactionTableModel::lookupAddress(const std::string &address,
325  bool tooltip) const {
327  QString::fromStdString(address));
328  QString description;
329  if (!label.isEmpty()) {
330  description += label;
331  }
332  if (label.isEmpty() || tooltip) {
333  description +=
334  QString(" (") + QString::fromStdString(address) + QString(")");
335  }
336  return description;
337 }
338 
339 QString
341  switch (wtx->type) {
343  return tr("Received with");
345  return tr("Received from");
348  return tr("Sent to");
350  return tr("Payment to yourself");
352  return tr("Mined");
353  default:
354  return QString();
355  }
356 }
357 
358 QVariant
360  switch (wtx->type) {
362  return QIcon(":/icons/tx_mined");
365  return QIcon(":/icons/tx_input");
368  return QIcon(":/icons/tx_output");
369  default:
370  return QIcon(":/icons/tx_inout");
371  }
372 }
373 
375  bool tooltip) const {
376  QString watchAddress;
377  if (tooltip) {
378  // Mark transactions involving watch-only addresses by adding "
379  // (watch-only)"
380  watchAddress = wtx->involvesWatchAddress
381  ? QString(" (") + tr("watch-only") + QString(")")
382  : "";
383  }
384 
385  switch (wtx->type) {
387  return QString::fromStdString(wtx->address) + watchAddress;
391  return lookupAddress(wtx->address, tooltip) + watchAddress;
393  return QString::fromStdString(wtx->address) + watchAddress;
395  return lookupAddress(wtx->address, tooltip) + watchAddress;
396  default:
397  return tr("(n/a)") + watchAddress;
398  }
399 }
400 
401 QVariant
403  // Show addresses without label in a less visible color
404  switch (wtx->type) {
408  QString label =
410  QString::fromStdString(wtx->address));
411  if (label.isEmpty()) {
412  return COLOR_BAREADDRESS;
413  }
414  } break;
416  return COLOR_BAREADDRESS;
417  default:
418  break;
419  }
420  return QVariant();
421 }
422 
424  const TransactionRecord *wtx, bool showUnconfirmed,
425  BitcoinUnits::SeparatorStyle separators) const {
426  QString str =
428  wtx->credit + wtx->debit, false, separators);
429  if (showUnconfirmed) {
430  if (!wtx->status.countsForBalance) {
431  str = QString("[") + str + QString("]");
432  }
433  }
434  return QString(str);
435 }
436 
437 QVariant
439  switch (wtx->status.status) {
444  return QIcon(":/icons/transaction_0");
446  return QIcon(":/icons/transaction_abandoned");
448  switch (wtx->status.depth) {
449  case 1:
450  return QIcon(":/icons/transaction_1");
451  case 2:
452  return QIcon(":/icons/transaction_2");
453  case 3:
454  return QIcon(":/icons/transaction_3");
455  case 4:
456  return QIcon(":/icons/transaction_4");
457  default:
458  return QIcon(":/icons/transaction_5");
459  };
461  return QIcon(":/icons/transaction_confirmed");
463  return QIcon(":/icons/transaction_conflicted");
465  int total = wtx->status.depth + wtx->status.matures_in;
466  int part = (wtx->status.depth * 4 / total) + 1;
467  return QIcon(QString(":/icons/transaction_%1").arg(part));
468  }
470  return QIcon(":/icons/transaction_0");
471  default:
472  return COLOR_BLACK;
473  }
474 }
475 
477  const TransactionRecord *wtx) const {
478  if (wtx->involvesWatchAddress) {
479  return QIcon(":/icons/eye");
480  }
481 
482  return QVariant();
483 }
484 
485 QString
487  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
492  tooltip += QString(" ") + formatTxToAddress(rec, true);
493  }
494  return tooltip;
495 }
496 
497 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const {
498  if (!index.isValid()) {
499  return QVariant();
500  }
501 
502  TransactionRecord *rec =
503  static_cast<TransactionRecord *>(index.internalPointer());
504 
505  switch (role) {
506  case RawDecorationRole:
507  switch (index.column()) {
508  case Status:
509  return txStatusDecoration(rec);
510  case Watchonly:
511  return txWatchonlyDecoration(rec);
512  case ToAddress:
513  return txAddressDecoration(rec);
514  }
515  break;
516  case Qt::DecorationRole: {
517  QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
518  return platformStyle->TextColorIcon(icon);
519  }
520  case Qt::DisplayRole:
521  switch (index.column()) {
522  case Date:
523  return formatTxDate(rec);
524  case Type:
525  return formatTxType(rec);
526  case ToAddress:
527  return formatTxToAddress(rec, false);
528  case Amount:
529  return formatTxAmount(rec, true,
531  }
532  break;
533  case Qt::EditRole:
534  // Edit role is used for sorting, so return the unformatted values
535  switch (index.column()) {
536  case Status:
537  return QString::fromStdString(rec->status.sortKey);
538  case Date:
539  return rec->time;
540  case Type:
541  return formatTxType(rec);
542  case Watchonly:
543  return (rec->involvesWatchAddress ? 1 : 0);
544  case ToAddress:
545  return formatTxToAddress(rec, true);
546  case Amount:
547  return qint64((rec->credit + rec->debit) / SATOSHI);
548  }
549  break;
550  case Qt::ToolTipRole:
551  return formatTooltip(rec);
552  case Qt::TextAlignmentRole:
553  return column_alignments[index.column()];
554  case Qt::ForegroundRole:
555  // Use the "danger" color for abandoned transactions
557  return COLOR_TX_STATUS_DANGER;
558  }
559  // Non-confirmed (but not immature) as transactions are grey
560  if (!rec->status.countsForBalance &&
562  return COLOR_UNCONFIRMED;
563  }
564  if (index.column() == Amount &&
565  (rec->credit + rec->debit) < ::Amount::zero()) {
566  return COLOR_NEGATIVE;
567  }
568  if (index.column() == ToAddress) {
569  return addressColor(rec);
570  }
571  break;
572  case TypeRole:
573  return rec->type;
574  case DateRole:
575  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
576  case WatchonlyRole:
577  return rec->involvesWatchAddress;
579  return txWatchonlyDecoration(rec);
580  case LongDescriptionRole:
581  return priv->describe(
582  walletModel->node(), walletModel->wallet(), rec,
584  case AddressRole:
585  return QString::fromStdString(rec->address);
586  case LabelRole:
588  QString::fromStdString(rec->address));
589  case AmountRole:
590  return qint64((rec->credit + rec->debit) / SATOSHI);
591  case TxIDRole:
592  return rec->getTxID();
593  case TxHashRole:
594  return QString::fromStdString(rec->txid.ToString());
595  case TxHexRole:
596  return priv->getTxHex(walletModel->wallet(), rec);
597  case TxPlainTextRole: {
598  QString details;
599  QDateTime date =
600  QDateTime::fromTime_t(static_cast<uint>(rec->time));
601  QString txLabel =
603  QString::fromStdString(rec->address));
604 
605  details.append(date.toString("M/d/yy HH:mm"));
606  details.append(" ");
607  details.append(formatTxStatus(rec));
608  details.append(". ");
609  if (!formatTxType(rec).isEmpty()) {
610  details.append(formatTxType(rec));
611  details.append(" ");
612  }
613  if (!rec->address.empty()) {
614  if (txLabel.isEmpty()) {
615  details.append(tr("(no label)") + " ");
616  } else {
617  details.append("(");
618  details.append(txLabel);
619  details.append(") ");
620  }
621  details.append(QString::fromStdString(rec->address));
622  details.append(" ");
623  }
624  details.append(
626  return details;
627  }
628  case ConfirmedRole:
629  return rec->status.countsForBalance;
630  case FormattedAmountRole:
631  // Used for copy/export, so don't include separators
632  return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
633  case StatusRole:
634  return rec->status.status;
635  }
636  return QVariant();
637 }
638 
640  Qt::Orientation orientation,
641  int role) const {
642  if (orientation == Qt::Horizontal) {
643  if (role == Qt::DisplayRole) {
644  return columns[section];
645  } else if (role == Qt::TextAlignmentRole) {
646  return column_alignments[section];
647  } else if (role == Qt::ToolTipRole) {
648  switch (section) {
649  case Status:
650  return tr("Transaction status. Hover over this field to "
651  "show number of confirmations.");
652  case Date:
653  return tr(
654  "Date and time that the transaction was received.");
655  case Type:
656  return tr("Type of transaction.");
657  case Watchonly:
658  return tr("Whether or not a watch-only address is involved "
659  "in this transaction.");
660  case ToAddress:
661  return tr(
662  "User-defined intent/purpose of the transaction.");
663  case Amount:
664  return tr("Amount removed from or added to balance.");
665  }
666  }
667  }
668  return QVariant();
669 }
670 
671 QModelIndex TransactionTableModel::index(int row, int column,
672  const QModelIndex &parent) const {
673  Q_UNUSED(parent);
676  if (data) {
677  return createIndex(row, column, data);
678  }
679  return QModelIndex();
680 }
681 
683  // emit dataChanged to update Amount column with the current unit
685  Q_EMIT dataChanged(index(0, Amount), index(priv->size() - 1, Amount));
686 }
687 
688 // queue notifications to show a non freezing progress dialog e.g. for rescan
690 public:
693  bool _showTransaction)
694  : txid(_txid), status(_status), showTransaction(_showTransaction) {}
695 
696  void invoke(QObject *ttm) {
697  QString strHash = QString::fromStdString(txid.GetHex());
698  qDebug() << "NotifyTransactionChanged: " + strHash +
699  " status= " + QString::number(status);
700  bool invoked = QMetaObject::invokeMethod(
701  ttm, "updateTransaction", Qt::QueuedConnection,
702  Q_ARG(QString, strHash), Q_ARG(int, status),
703  Q_ARG(bool, showTransaction));
704  assert(invoked);
705  }
706 
707 private:
711 };
712 
713 static bool fQueueNotifications = false;
714 static std::vector<TransactionNotification> vQueueNotifications;
715 
717  const TxId &txid, ChangeType status) {
718  // Find transaction in wallet
719  // Determine whether to show transaction or not (determine this here so that
720  // no relocking is needed in GUI thread)
721  bool showTransaction = TransactionRecord::showTransaction();
722 
723  TransactionNotification notification(txid, status, showTransaction);
724 
725  if (fQueueNotifications) {
726  vQueueNotifications.push_back(notification);
727  return;
728  }
729  notification.invoke(ttm);
730 }
731 
732 static void ShowProgress(TransactionTableModel *ttm, const std::string &title,
733  int nProgress) {
734  if (nProgress == 0) {
735  fQueueNotifications = true;
736  }
737 
738  if (nProgress == 100) {
739  fQueueNotifications = false;
740  if (vQueueNotifications.size() > 10) {
741  // prevent balloon spam, show maximum 10 balloons
742  bool invoked = QMetaObject::invokeMethod(
743  ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection,
744  Q_ARG(bool, true));
745  assert(invoked);
746  }
747 
748  for (size_t i = 0; i < vQueueNotifications.size(); ++i) {
749  if (vQueueNotifications.size() - i <= 10) {
750  bool invoked = QMetaObject::invokeMethod(
751  ttm, "setProcessingQueuedTransactions",
752  Qt::QueuedConnection, Q_ARG(bool, false));
753  assert(invoked);
754  }
755 
756  vQueueNotifications[i].invoke(ttm);
757  }
758 
759  // clear
760  std::vector<TransactionNotification>().swap(vQueueNotifications);
761  }
762 }
763 
765  // Connect signals to wallet
768  std::bind(NotifyTransactionChanged, this, std::placeholders::_1,
769  std::placeholders::_2));
772  ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
773 }
774 
776  // Disconnect signals from wallet
777  m_handler_transaction_changed->disconnect();
778  m_handler_show_progress->disconnect();
779 }
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
bool statusUpdateNeeded(int numBlocks) const
Return whether a status update is needed.
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
Confirmed, but waiting for the recommended number of confirmations.
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
static constexpr Amount zero()
Definition: amount.h:35
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
Transaction not yet final, waiting for block.
Transaction status (TransactionRecord::Status)
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::separatorStandard) const
Generated (mined) transactions.
static int column_alignments[]
QString formatTooltip(const TransactionRecord *rec) const
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
std::string sortKey
Sorting key based on status.
void updateTransaction(const QString &hash, int status, bool showTransaction)
New transaction, or transaction changed status.
QString describe(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:66
Definition: amount.h:17
TransactionTablePriv(TransactionTableModel *_parent)
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
Decompose CWallet transaction to model transaction records.
bool operator()(const TxId &a, const TransactionRecord &b) const
static std::vector< TransactionNotification > vQueueNotifications
QVariant txStatusDecoration(const TransactionRecord *wtx) const
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
Mined but not accepted.
Not yet mined into a block.
static QString toHTML(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
static constexpr Amount SATOSHI
Definition: amount.h:151
int columnCount(const QModelIndex &parent) const override
CTransactionRef tx
Definition: wallet.h:341
QIcon TextColorIcon(const QIcon &icon) const
Colorize an icon (given object) with the text color.
AddressTableModel * getAddressTableModel()
Transaction data, hex-encoded.
TransactionTableModel * parent
int rowCount(const QModelIndex &parent) const override
TransactionTablePriv * priv
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...
int getDisplayUnit() const
Definition: optionsmodel.h:96
*static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available...
QList< TransactionRecord > cachedWallet
virtual std::unique_ptr< Handler > handleTransactionChanged(TransactionChangedFn fn)=0
UI model for a transaction.
TransactionStatus status
Status: can change with block chain update.
QString formatTxType(const TransactionRecord *wtx) const
virtual std::unique_ptr< Handler > handleShowProgress(ShowProgressFn fn)=0
Whole transaction as plain text.
std::unique_ptr< interfaces::Handler > m_handler_transaction_changed
virtual CTransactionRef getTx(const TxId &txid)=0
Get a transaction.
static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
QString getTxID() const
Return the unique identifier for this transaction (part)
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:33
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
Interface for accessing a wallet.
Definition: wallet.h:56
bool countsForBalance
Transaction counts towards available balance.
TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent=nullptr)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
virtual bool tryGetTxStatus(const TxId &txid, WalletTxStatus &tx_status, int &num_blocks, int64_t &block_time)=0
Try to get updated status for a particular transaction, if possible without blocking.
Date and time this transaction was created.
std::string ToString() const
Definition: uint256.h:74
bool operator()(const TransactionRecord &a, const TxId &b) const
static void NotifyTransactionChanged(TransactionTableModel *ttm, const TxId &txid, ChangeType status)
#define COLOR_BLACK
Definition: guiconstants.h:35
interfaces::Node & node() const
Definition: walletmodel.h:149
void displayUnitChanged(int unit)
UI model for the transaction table of a wallet.
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
virtual WalletTx getWalletTx(const TxId &txid)=0
Get transaction information.
void refreshWallet(interfaces::Wallet &wallet)
Query entire wallet anew from core.
Normal (sent/received) transactions.
static QString format(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
QString lookupAddress(const std::string &address, bool tooltip) const
Look up address in address book, if found return label (address) otherwise just return (address) ...
std::unique_ptr< interfaces::Handler > m_handler_show_progress
static bool showTransaction()
Decompose CWallet transaction to model transaction records.
TransactionNotification(TxId _txid, ChangeType _status, bool _showTransaction)
virtual std::vector< WalletTx > getWalletTxs()=0
Get list of all wallet transactions.
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
void updateStatus(const interfaces::WalletTxStatus &wtx, int numBlocks, int64_t block_time)
Update status from core wallet tx.
Conflicts with other transaction or mempool.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
A TxId is the identifier of a transaction.
Definition: txid.h:14
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
QString getTxHex(interfaces::Wallet &wallet, TransactionRecord *rec)
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:172
Label of address related to transaction.
QString formatTxStatus(const TransactionRecord *wtx) const
static bool fQueueNotifications
QVariant addressColor(const TransactionRecord *wtx) const
int getNumBlocks() const
#define COLOR_TX_STATUS_OPENUNTILDATE
Definition: guiconstants.h:31
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
QVariant txAddressDecoration(const TransactionRecord *wtx) const
TransactionRecord * index(interfaces::Wallet &wallet, const int cur_num_blocks, const int idx)
Formatted amount, without brackets when unconfirmed.
QVariant data(const QModelIndex &index, int role) const override
ChangeType
General change type (added, updated, removed).
Definition: ui_change_type.h:9
void SetHex(const char *psz)
Definition: uint256.cpp:21
Abandoned from the wallet.
#define COLOR_BAREADDRESS
Definition: guiconstants.h:29
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:45
const PlatformStyle * platformStyle
Updated transaction status.
Definition: wallet.h:355
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
OptionsModel * getOptionsModel()
ClientModel & clientModel() const
Definition: walletmodel.h:151
QString formatTxDate(const TransactionRecord *wtx) const