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