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