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 <algorithm>
21 
22 #include <QColor>
23 #include <QDateTime>
24 #include <QDebug>
25 #include <QIcon>
26 #include <QList>
27 
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
41 {
42  bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
43  {
44  return a.hash < b.hash;
45  }
46  bool operator()(const TransactionRecord &a, const uint256 &b) const
47  {
48  return a.hash < b;
49  }
50  bool operator()(const uint256 &a, const TransactionRecord &b) const
51  {
52  return a < b.hash;
53  }
54 };
55 
56 // Private implementation
58 {
59 public:
61  parent(_parent)
62  {
63  }
64 
66 
67  /* Local cache of wallet.
68  * As it is in the same order as the CWallet, by definition
69  * this is sorted by sha256.
70  */
71  QList<TransactionRecord> cachedWallet;
72 
73  /* Query entire wallet anew from core.
74  */
76  {
77  qDebug() << "TransactionTablePriv::refreshWallet";
78  cachedWallet.clear();
79  {
80  for (const auto& wtx : wallet.getWalletTxs()) {
82  cachedWallet.append(TransactionRecord::decomposeTransaction(wtx));
83  }
84  }
85  }
86  }
87 
88  /* Update our model of the wallet incrementally, to synchronize our model of the wallet
89  with that of the core.
90 
91  Call with transaction that was added, removed or changed.
92  */
93  void updateWallet(interfaces::Wallet& wallet, const uint256 &hash, int status, bool showTransaction)
94  {
95  qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
96 
97  // Find bounds of this transaction in model
98  QList<TransactionRecord>::iterator lower = std::lower_bound(
99  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
100  QList<TransactionRecord>::iterator upper = std::upper_bound(
101  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
102  int lowerIndex = (lower - cachedWallet.begin());
103  int upperIndex = (upper - cachedWallet.begin());
104  bool inModel = (lower != upper);
105 
106  if(status == CT_UPDATED)
107  {
108  if(showTransaction && !inModel)
109  status = CT_NEW; /* Not in model, but want to show, treat as new */
110  if(!showTransaction && inModel)
111  status = CT_DELETED; /* In model, but want to hide, treat as deleted */
112  }
113 
114  qDebug() << " inModel=" + QString::number(inModel) +
115  " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
116  " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
117 
118  switch(status)
119  {
120  case CT_NEW:
121  if(inModel)
122  {
123  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
124  break;
125  }
126  if(showTransaction)
127  {
128  // Find transaction in wallet
129  interfaces::WalletTx wtx = wallet.getWalletTx(hash);
130  if(!wtx.tx)
131  {
132  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
133  break;
134  }
135  // Added -- insert at the right position
136  QList<TransactionRecord> toInsert =
138  if(!toInsert.isEmpty()) /* only if something to insert */
139  {
140  parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
141  int insert_idx = lowerIndex;
142  for (const TransactionRecord &rec : toInsert)
143  {
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  {
154  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
155  break;
156  }
157  // Removed -- remove entire transaction from table
158  parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
159  cachedWallet.erase(lower, upper);
160  parent->endRemoveRows();
161  break;
162  case CT_UPDATED:
163  // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
164  // visible transactions.
165  for (int i = lowerIndex; i < upperIndex; i++) {
166  TransactionRecord *rec = &cachedWallet[i];
167  rec->status.needsUpdate = true;
168  }
169  break;
170  }
171  }
172 
173  int size()
174  {
175  return cachedWallet.size();
176  }
177 
179  {
180  if(idx >= 0 && idx < cachedWallet.size())
181  {
182  TransactionRecord *rec = &cachedWallet[idx];
183 
184  // Get required locks upfront. This avoids the GUI from getting
185  // stuck if the core is holding the locks for a longer time - for
186  // example, during a wallet rescan.
187  //
188  // If a status update is needed (blocks came in since last check),
189  // update the status of this transaction from the wallet. Otherwise,
190  // simply re-use the cached status.
192  int numBlocks;
193  int64_t block_time;
194  if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time) && rec->statusUpdateNeeded(numBlocks)) {
195  rec->updateStatus(wtx, numBlocks, block_time);
196  }
197  return rec;
198  }
199  return nullptr;
200  }
201 
202  QString describe(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
203  {
204  return TransactionDesc::toHTML(node, wallet, rec, unit);
205  }
206 
208  {
209  auto tx = wallet.getTx(rec->hash);
210  if (tx) {
211  std::string strHex = EncodeHexTx(*tx);
212  return QString::fromStdString(strHex);
213  }
214  return QString();
215  }
216 };
217 
219  QAbstractTableModel(parent),
220  walletModel(parent),
221  priv(new TransactionTablePriv(this)),
222  fProcessingQueuedTransactions(false),
223  platformStyle(_platformStyle)
224 {
225  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
227 
229 
231 }
232 
234 {
236  delete priv;
237 }
238 
241 {
243  Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
244 }
245 
246 void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
247 {
248  uint256 updated;
249  updated.SetHex(hash.toStdString());
250 
251  priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
252 }
253 
255 {
256  // Blocks came in since last poll.
257  // Invalidate status (number of confirmations) and (possibly) description
258  // for all rows. Qt is smart enough to only actually request the data for the
259  // visible rows.
260  Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
261  Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
262 }
263 
264 int TransactionTableModel::rowCount(const QModelIndex &parent) const
265 {
266  Q_UNUSED(parent);
267  return priv->size();
268 }
269 
270 int TransactionTableModel::columnCount(const QModelIndex &parent) const
271 {
272  Q_UNUSED(parent);
273  return columns.length();
274 }
275 
277 {
278  QString status;
279 
280  switch(wtx->status.status)
281  {
283  status = tr("Open for %n more block(s)","",wtx->status.open_for);
284  break;
286  status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
287  break;
289  status = tr("Unconfirmed");
290  break;
292  status = tr("Abandoned");
293  break;
295  status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
296  break;
298  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
299  break;
301  status = tr("Conflicted");
302  break;
304  status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
305  break;
307  status = tr("Generated but not accepted");
308  break;
309  }
310 
311  return status;
312 }
313 
315 {
316  if(wtx->time)
317  {
318  return GUIUtil::dateTimeStr(wtx->time);
319  }
320  return QString();
321 }
322 
323 /* Look up address in address book, if found return label (address)
324  otherwise just return (address)
325  */
326 QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
327 {
328  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
329  QString description;
330  if(!label.isEmpty())
331  {
332  description += label;
333  }
334  if(label.isEmpty() || tooltip)
335  {
336  description += QString(" (") + QString::fromStdString(address) + QString(")");
337  }
338  return description;
339 }
340 
342 {
343  switch(wtx->type)
344  {
346  return tr("Received with");
348  return tr("Received from");
351  return tr("Sent to");
353  return tr("Payment to yourself");
355  return tr("Mined");
356  default:
357  return QString();
358  }
359 }
360 
362 {
363  switch(wtx->type)
364  {
366  return QIcon(":/icons/tx_mined");
369  return QIcon(":/icons/tx_input");
372  return QIcon(":/icons/tx_output");
373  default:
374  return QIcon(":/icons/tx_inout");
375  }
376 }
377 
378 QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
379 {
380  QString watchAddress;
381  if (tooltip) {
382  // Mark transactions involving watch-only addresses by adding " (watch-only)"
383  watchAddress = wtx->involvesWatchAddress ? QString(" (") + tr("watch-only") + QString(")") : "";
384  }
385 
386  switch(wtx->type)
387  {
389  return QString::fromStdString(wtx->address) + watchAddress;
393  return lookupAddress(wtx->address, tooltip) + watchAddress;
395  return QString::fromStdString(wtx->address) + watchAddress;
397  default:
398  return tr("(n/a)") + watchAddress;
399  }
400 }
401 
403 {
404  // Show addresses without label in a less visible color
405  switch(wtx->type)
406  {
410  {
411  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
412  if(label.isEmpty())
413  return COLOR_BAREADDRESS;
414  } break;
416  return COLOR_BAREADDRESS;
417  default:
418  break;
419  }
420  return QVariant();
421 }
422 
423 QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
424 {
425  QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
426  if(showUnconfirmed)
427  {
428  if(!wtx->status.countsForBalance)
429  {
430  str = QString("[") + str + QString("]");
431  }
432  }
433  return QString(str);
434 }
435 
437 {
438  switch(wtx->status.status)
439  {
444  return QIcon(":/icons/transaction_0");
446  return QIcon(":/icons/transaction_abandoned");
448  switch(wtx->status.depth)
449  {
450  case 1: return QIcon(":/icons/transaction_1");
451  case 2: return QIcon(":/icons/transaction_2");
452  case 3: return QIcon(":/icons/transaction_3");
453  case 4: return QIcon(":/icons/transaction_4");
454  default: return QIcon(":/icons/transaction_5");
455  };
457  return QIcon(":/icons/transaction_confirmed");
459  return QIcon(":/icons/transaction_conflicted");
461  int total = wtx->status.depth + wtx->status.matures_in;
462  int part = (wtx->status.depth * 4 / total) + 1;
463  return QIcon(QString(":/icons/transaction_%1").arg(part));
464  }
466  return QIcon(":/icons/transaction_0");
467  default:
468  return COLOR_BLACK;
469  }
470 }
471 
473 {
474  if (wtx->involvesWatchAddress)
475  return QIcon(":/icons/eye");
476  else
477  return QVariant();
478 }
479 
481 {
482  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
485  {
486  tooltip += QString(" ") + formatTxToAddress(rec, true);
487  }
488  return tooltip;
489 }
490 
491 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
492 {
493  if(!index.isValid())
494  return QVariant();
495  TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
496 
497  switch(role)
498  {
499  case RawDecorationRole:
500  switch(index.column())
501  {
502  case Status:
503  return txStatusDecoration(rec);
504  case Watchonly:
505  return txWatchonlyDecoration(rec);
506  case ToAddress:
507  return txAddressDecoration(rec);
508  }
509  break;
510  case Qt::DecorationRole:
511  {
512  QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
513  return platformStyle->TextColorIcon(icon);
514  }
515  case Qt::DisplayRole:
516  switch(index.column())
517  {
518  case Date:
519  return formatTxDate(rec);
520  case Type:
521  return formatTxType(rec);
522  case ToAddress:
523  return formatTxToAddress(rec, false);
524  case Amount:
526  }
527  break;
528  case Qt::EditRole:
529  // Edit role is used for sorting, so return the unformatted values
530  switch(index.column())
531  {
532  case Status:
533  return QString::fromStdString(rec->status.sortKey);
534  case Date:
535  return rec->time;
536  case Type:
537  return formatTxType(rec);
538  case Watchonly:
539  return (rec->involvesWatchAddress ? 1 : 0);
540  case ToAddress:
541  return formatTxToAddress(rec, true);
542  case Amount:
543  return qint64(rec->credit + rec->debit);
544  }
545  break;
546  case Qt::ToolTipRole:
547  return formatTooltip(rec);
548  case Qt::TextAlignmentRole:
549  return column_alignments[index.column()];
550  case Qt::ForegroundRole:
551  // Use the "danger" color for abandoned transactions
553  {
554  return COLOR_TX_STATUS_DANGER;
555  }
556  // Non-confirmed (but not immature) as transactions are grey
558  {
559  return COLOR_UNCONFIRMED;
560  }
561  if(index.column() == Amount && (rec->credit+rec->debit) < 0)
562  {
563  return COLOR_NEGATIVE;
564  }
565  if(index.column() == ToAddress)
566  {
567  return addressColor(rec);
568  }
569  break;
570  case TypeRole:
571  return rec->type;
572  case DateRole:
573  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
574  case WatchonlyRole:
575  return rec->involvesWatchAddress;
577  return txWatchonlyDecoration(rec);
578  case LongDescriptionRole:
580  case AddressRole:
581  return QString::fromStdString(rec->address);
582  case LabelRole:
583  return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
584  case AmountRole:
585  return qint64(rec->credit + rec->debit);
586  case TxHashRole:
587  return rec->getTxHash();
588  case TxHexRole:
589  return priv->getTxHex(walletModel->wallet(), rec);
590  case TxPlainTextRole:
591  {
592  QString details;
593  QDateTime date = QDateTime::fromTime_t(static_cast<uint>(rec->time));
594  QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
595 
596  details.append(date.toString("M/d/yy HH:mm"));
597  details.append(" ");
598  details.append(formatTxStatus(rec));
599  details.append(". ");
600  if(!formatTxType(rec).isEmpty()) {
601  details.append(formatTxType(rec));
602  details.append(" ");
603  }
604  if(!rec->address.empty()) {
605  if(txLabel.isEmpty())
606  details.append(tr("(no label)") + " ");
607  else {
608  details.append("(");
609  details.append(txLabel);
610  details.append(") ");
611  }
612  details.append(QString::fromStdString(rec->address));
613  details.append(" ");
614  }
615  details.append(formatTxAmount(rec, false, BitcoinUnits::separatorNever));
616  return details;
617  }
618  case ConfirmedRole:
619  return rec->status.countsForBalance;
620  case FormattedAmountRole:
621  // Used for copy/export, so don't include separators
622  return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
623  case StatusRole:
624  return rec->status.status;
625  }
626  return QVariant();
627 }
628 
629 QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
630 {
631  if(orientation == Qt::Horizontal)
632  {
633  if(role == Qt::DisplayRole)
634  {
635  return columns[section];
636  }
637  else if (role == Qt::TextAlignmentRole)
638  {
639  return column_alignments[section];
640  } else if (role == Qt::ToolTipRole)
641  {
642  switch(section)
643  {
644  case Status:
645  return tr("Transaction status. Hover over this field to show number of confirmations.");
646  case Date:
647  return tr("Date and time that the transaction was received.");
648  case Type:
649  return tr("Type of transaction.");
650  case Watchonly:
651  return tr("Whether or not a watch-only address is involved in this transaction.");
652  case ToAddress:
653  return tr("User-defined intent/purpose of the transaction.");
654  case Amount:
655  return tr("Amount removed from or added to balance.");
656  }
657  }
658  }
659  return QVariant();
660 }
661 
662 QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
663 {
664  Q_UNUSED(parent);
666  if(data)
667  {
668  return createIndex(row, column, priv->index(walletModel->wallet(), row));
669  }
670  return QModelIndex();
671 }
672 
674 {
675  // emit dataChanged to update Amount column with the current unit
677  Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
678 }
679 
680 // queue notifications to show a non freezing progress dialog e.g. for rescan
682 {
683 public:
685  TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
686  hash(_hash), status(_status), showTransaction(_showTransaction) {}
687 
688  void invoke(QObject *ttm)
689  {
690  QString strHash = QString::fromStdString(hash.GetHex());
691  qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
692  bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
693  Q_ARG(QString, strHash),
694  Q_ARG(int, status),
695  Q_ARG(bool, showTransaction));
696  assert(invoked);
697  }
698 private:
702 };
703 
704 static bool fQueueNotifications = false;
705 static std::vector< TransactionNotification > vQueueNotifications;
706 
707 static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 &hash, ChangeType status)
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(ttm);
721 }
722 
723 static void ShowProgress(TransactionTableModel *ttm, 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(ttm, "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(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
739  assert(invoked);
740  }
741 
742  vQueueNotifications[i].invoke(ttm);
743  }
744  std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
745  }
746 }
747 
749 {
750  // Connect signals to wallet
751  m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2));
752  m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(ShowProgress, this, 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)
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)
static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 &hash, ChangeType 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.
static int column_alignments[]
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:333
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
static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
#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:47
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:61
#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
static std::vector< TransactionNotification > vQueueNotifications
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
static bool fQueueNotifications
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:347
#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