Dogecoin Core  1.14.2
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 "addresstablemodel.h"
8 #include "guiconstants.h"
9 #include "guiutil.h"
10 #include "optionsmodel.h"
11 #include "platformstyle.h"
12 #include "transactiondesc.h"
13 #include "transactionrecord.h"
14 #include "walletmodel.h"
15 
16 #include "core_io.h"
17 #include "validation.h"
18 #include "sync.h"
19 #include "uint256.h"
20 #include "util.h"
21 #include "wallet/wallet.h"
22 
23 #include <QColor>
24 #include <QDateTime>
25 #include <QDebug>
26 #include <QIcon>
27 #include <QList>
28 
29 #include <boost/bind/bind.hpp>
30 #include <boost/foreach.hpp>
31 
32 // Amount column is right-aligned it contains numbers
33 static int column_alignments[] = {
34  Qt::AlignLeft|Qt::AlignVCenter, /* status */
35  Qt::AlignLeft|Qt::AlignVCenter, /* watchonly */
36  Qt::AlignLeft|Qt::AlignVCenter, /* date */
37  Qt::AlignLeft|Qt::AlignVCenter, /* type */
38  Qt::AlignLeft|Qt::AlignVCenter, /* address */
39  Qt::AlignRight|Qt::AlignVCenter /* amount */
40  };
41 
42 // Comparison operator for sort/binary search of model tx list
43 struct TxLessThan
44 {
45  bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
46  {
47  return a.hash < b.hash;
48  }
49  bool operator()(const TransactionRecord &a, const uint256 &b) const
50  {
51  return a.hash < b;
52  }
53  bool operator()(const uint256 &a, const TransactionRecord &b) const
54  {
55  return a < b.hash;
56  }
57 };
58 
59 // Private implementation
61 {
62 public:
64  wallet(_wallet),
65  parent(_parent)
66  {
67  }
68 
71 
72  /* Local cache of wallet.
73  * As it is in the same order as the CWallet, by definition
74  * this is sorted by sha256.
75  */
76  QList<TransactionRecord> cachedWallet;
77 
78  /* Query entire wallet anew from core.
79  */
81  {
82  qDebug() << "TransactionTablePriv::refreshWallet";
83  cachedWallet.clear();
84  {
86  for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
87  {
90  }
91  }
92  }
93 
94  /* Update our model of the wallet incrementally, to synchronize our model of the wallet
95  with that of the core.
96 
97  Call with transaction that was added, removed or changed.
98  */
99  void updateWallet(const uint256 &hash, int status, bool showTransaction)
100  {
101  qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
102 
103  // Find bounds of this transaction in model
104  QList<TransactionRecord>::iterator lower = qLowerBound(
105  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
106  QList<TransactionRecord>::iterator upper = qUpperBound(
107  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
108  int lowerIndex = (lower - cachedWallet.begin());
109  int upperIndex = (upper - cachedWallet.begin());
110  bool inModel = (lower != upper);
111 
112  if(status == CT_UPDATED)
113  {
114  if(showTransaction && !inModel)
115  status = CT_NEW; /* Not in model, but want to show, treat as new */
116  if(!showTransaction && inModel)
117  status = CT_DELETED; /* In model, but want to hide, treat as deleted */
118  }
119 
120  qDebug() << " inModel=" + QString::number(inModel) +
121  " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
122  " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
123 
124  switch(status)
125  {
126  case CT_NEW:
127  if(inModel)
128  {
129  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
130  break;
131  }
132  if(showTransaction)
133  {
135  // Find transaction in wallet
136  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
137  if(mi == wallet->mapWallet.end())
138  {
139  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
140  break;
141  }
142  // Added -- insert at the right position
143  QList<TransactionRecord> toInsert =
145  if(!toInsert.isEmpty()) /* only if something to insert */
146  {
147  parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
148  int insert_idx = lowerIndex;
149  Q_FOREACH(const TransactionRecord &rec, toInsert)
150  {
151  cachedWallet.insert(insert_idx, rec);
152  insert_idx += 1;
153  }
154  parent->endInsertRows();
155  }
156  }
157  break;
158  case CT_DELETED:
159  if(!inModel)
160  {
161  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
162  break;
163  }
164  // Removed -- remove entire transaction from table
165  parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
166  cachedWallet.erase(lower, upper);
167  parent->endRemoveRows();
168  break;
169  case CT_UPDATED:
170  // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
171  // visible transactions.
172  break;
173  }
174  }
175 
176  int size()
177  {
178  return cachedWallet.size();
179  }
180 
182  {
183  if(idx >= 0 && idx < cachedWallet.size())
184  {
185  TransactionRecord *rec = &cachedWallet[idx];
186 
187  // Get required locks upfront. This avoids the GUI from getting
188  // stuck if the core is holding the locks for a longer time - for
189  // example, during a wallet rescan.
190  //
191  // If a status update is needed (blocks came in since last check),
192  // update the status of this transaction from the wallet. Otherwise,
193  // simply re-use the cached status.
194  TRY_LOCK(cs_main, lockMain);
195  if(lockMain)
196  {
197  TRY_LOCK(wallet->cs_wallet, lockWallet);
198  if(lockWallet && rec->statusUpdateNeeded())
199  {
200  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
201 
202  if(mi != wallet->mapWallet.end())
203  {
204  rec->updateStatus(mi->second);
205  }
206  }
207  }
208  return rec;
209  }
210  return 0;
211  }
212 
213  QString describe(TransactionRecord *rec, int unit)
214  {
215  {
217  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
218  if(mi != wallet->mapWallet.end())
219  {
220  return TransactionDesc::toHTML(wallet, mi->second, rec, unit);
221  }
222  }
223  return QString();
224  }
225 
227  {
229  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
230  if(mi != wallet->mapWallet.end())
231  {
232  std::string strHex = EncodeHexTx(static_cast<CTransaction>(mi->second));
233  return QString::fromStdString(strHex);
234  }
235  return QString();
236  }
237 };
238 
240  QAbstractTableModel(parent),
241  wallet(_wallet),
242  walletModel(parent),
243  priv(new TransactionTablePriv(_wallet, this)),
244  fProcessingQueuedTransactions(false),
245  platformStyle(_platformStyle)
246 {
247  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
248  priv->refreshWallet();
249 
250  connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
251 
253 }
254 
256 {
258  delete priv;
259 }
260 
263 {
265  Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
266 }
267 
268 void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
269 {
270  uint256 updated;
271  updated.SetHex(hash.toStdString());
272 
273  priv->updateWallet(updated, status, showTransaction);
274 }
275 
277 {
278  // Blocks came in since last poll.
279  // Invalidate status (number of confirmations) and (possibly) description
280  // for all rows. Qt is smart enough to only actually request the data for the
281  // visible rows.
282  Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
283  Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
284 }
285 
286 int TransactionTableModel::rowCount(const QModelIndex &parent) const
287 {
288  Q_UNUSED(parent);
289  return priv->size();
290 }
291 
292 int TransactionTableModel::columnCount(const QModelIndex &parent) const
293 {
294  Q_UNUSED(parent);
295  return columns.length();
296 }
297 
299 {
300  QString status;
301 
302  switch(wtx->status.status)
303  {
305  status = tr("Open for %n more block(s)","",wtx->status.open_for);
306  break;
308  status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
309  break;
311  status = tr("Offline");
312  break;
314  status = tr("Unconfirmed");
315  break;
317  status = tr("Abandoned");
318  break;
320  status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
321  break;
323  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
324  break;
326  status = tr("Conflicted");
327  break;
329  status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
330  break;
332  status = tr("This block was not received by any other nodes and will probably not be accepted!");
333  break;
335  status = tr("Generated but not accepted");
336  break;
337  }
338 
339  return status;
340 }
341 
343 {
344  if(wtx->time)
345  {
346  return GUIUtil::dateTimeStr(wtx->time);
347  }
348  return QString();
349 }
350 
351 /* Look up address in address book, if found return label (address)
352  otherwise just return (address)
353  */
354 QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
355 {
356  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
357  QString description;
358  if(!label.isEmpty())
359  {
360  description += label;
361  }
362  if(label.isEmpty() || tooltip)
363  {
364  description += QString(" (") + QString::fromStdString(address) + QString(")");
365  }
366  return description;
367 }
368 
370 {
371  switch(wtx->type)
372  {
374  return tr("Received with");
376  return tr("Received from");
379  return tr("Sent to");
381  return tr("Payment to yourself");
383  return tr("Mined");
384  default:
385  return QString();
386  }
387 }
388 
390 {
391  switch(wtx->type)
392  {
394  return QIcon(":/icons/tx_mined");
397  return QIcon(":/icons/tx_input");
400  return QIcon(":/icons/tx_output");
401  default:
402  return QIcon(":/icons/tx_inout");
403  }
404 }
405 
406 QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
407 {
408  QString watchAddress;
409  if (tooltip) {
410  // Mark transactions involving watch-only addresses by adding " (watch-only)"
411  watchAddress = wtx->involvesWatchAddress ? QString(" (") + tr("watch-only") + QString(")") : "";
412  }
413 
414  switch(wtx->type)
415  {
417  return QString::fromStdString(wtx->address) + watchAddress;
421  return lookupAddress(wtx->address, tooltip) + watchAddress;
423  return QString::fromStdString(wtx->address) + watchAddress;
425  default:
426  return tr("(n/a)") + watchAddress;
427  }
428 }
429 
431 {
432  // Show addresses without label in a less visible color
433  switch(wtx->type)
434  {
438  {
439  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
440  if(label.isEmpty())
441  return COLOR_BAREADDRESS;
442  } break;
444  return COLOR_BAREADDRESS;
445  default:
446  break;
447  }
448  return QVariant();
449 }
450 
451 QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
452 {
453  QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
454  if(showUnconfirmed)
455  {
456  if(!wtx->status.countsForBalance)
457  {
458  str = QString("[") + str + QString("]");
459  }
460  }
461  return QString(str);
462 }
463 
465 {
466  switch(wtx->status.status)
467  {
474  return QIcon(":/icons/transaction_0");
476  return QIcon(":/icons/transaction_abandoned");
478  switch(wtx->status.depth)
479  {
480  case 1: return QIcon(":/icons/transaction_1");
481  case 2: return QIcon(":/icons/transaction_2");
482  case 3: return QIcon(":/icons/transaction_3");
483  case 4: return QIcon(":/icons/transaction_4");
484  default: return QIcon(":/icons/transaction_5");
485  };
487  return QIcon(":/icons/transaction_confirmed");
489  return QIcon(":/icons/transaction_conflicted");
491  int total = wtx->status.depth + wtx->status.matures_in;
492  int part = (wtx->status.depth * 4 / total) + 1;
493  return QIcon(QString(":/icons/transaction_%1").arg(part));
494  }
497  return QIcon(":/icons/transaction_0");
498  default:
499  return COLOR_BLACK;
500  }
501 }
502 
504 {
505  if (wtx->involvesWatchAddress)
506  return QIcon(":/icons/eye");
507  else
508  return QVariant();
509 }
510 
512 {
513  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
516  {
517  tooltip += QString(" ") + formatTxToAddress(rec, true);
518  }
519  return tooltip;
520 }
521 
522 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
523 {
524  if(!index.isValid())
525  return QVariant();
526  TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
527 
528  switch(role)
529  {
530  case RawDecorationRole:
531  switch(index.column())
532  {
533  case Status:
534  return txStatusDecoration(rec);
535  case Watchonly:
536  return txWatchonlyDecoration(rec);
537  case ToAddress:
538  return txAddressDecoration(rec);
539  }
540  break;
541  case Qt::DecorationRole:
542  {
543  QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
544  return platformStyle->TextColorIcon(icon);
545  }
546  case Qt::DisplayRole:
547  switch(index.column())
548  {
549  case Date:
550  return formatTxDate(rec);
551  case Type:
552  return formatTxType(rec);
553  case ToAddress:
554  return formatTxToAddress(rec, false);
555  case Amount:
557  }
558  break;
559  case Qt::EditRole:
560  // Edit role is used for sorting, so return the unformatted values
561  switch(index.column())
562  {
563  case Status:
564  return QString::fromStdString(rec->status.sortKey);
565  case Date:
566  return rec->time;
567  case Type:
568  return formatTxType(rec);
569  case Watchonly:
570  return (rec->involvesWatchAddress ? 1 : 0);
571  case ToAddress:
572  return formatTxToAddress(rec, true);
573  case Amount:
574  return qint64(rec->credit + rec->debit);
575  }
576  break;
577  case Qt::ToolTipRole:
578  return formatTooltip(rec);
579  case Qt::TextAlignmentRole:
580  return column_alignments[index.column()];
581  case Qt::ForegroundRole:
582  // Use the "danger" color for abandoned transactions
584  {
585  return COLOR_TX_STATUS_DANGER;
586  }
587  // Non-confirmed (but not immature) as transactions are grey
589  {
590  return COLOR_UNCONFIRMED;
591  }
592  if(index.column() == Amount && (rec->credit+rec->debit) < 0)
593  {
594  return COLOR_NEGATIVE;
595  }
596  if(index.column() == ToAddress)
597  {
598  return addressColor(rec);
599  }
600  break;
601  case TypeRole:
602  return rec->type;
603  case DateRole:
604  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
605  case WatchonlyRole:
606  return rec->involvesWatchAddress;
608  return txWatchonlyDecoration(rec);
609  case LongDescriptionRole:
611  case AddressRole:
612  return QString::fromStdString(rec->address);
613  case LabelRole:
614  return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
615  case AmountRole:
616  return qint64(rec->credit + rec->debit);
617  case TxIDRole:
618  return rec->getTxID();
619  case TxHashRole:
620  return QString::fromStdString(rec->hash.ToString());
621  case TxHexRole:
622  return priv->getTxHex(rec);
623  case TxPlainTextRole:
624  {
625  QString details;
626  QDateTime date = QDateTime::fromTime_t(static_cast<uint>(rec->time));
627  QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
628 
629  details.append(date.toString("M/d/yy HH:mm"));
630  details.append(" ");
631  details.append(formatTxStatus(rec));
632  details.append(". ");
633  if(!formatTxType(rec).isEmpty()) {
634  details.append(formatTxType(rec));
635  details.append(" ");
636  }
637  if(!rec->address.empty()) {
638  if(txLabel.isEmpty())
639  details.append(tr("(no label)") + " ");
640  else {
641  details.append("(");
642  details.append(txLabel);
643  details.append(") ");
644  }
645  details.append(QString::fromStdString(rec->address));
646  details.append(" ");
647  }
648  details.append(formatTxAmount(rec, false, BitcoinUnits::separatorNever));
649  return details;
650  }
651  case ConfirmedRole:
652  return rec->status.countsForBalance;
653  case FormattedAmountRole:
654  // Used for copy/export, so don't include separators
655  return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
656  case StatusRole:
657  return rec->status.status;
658  }
659  return QVariant();
660 }
661 
662 QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
663 {
664  if(orientation == Qt::Horizontal)
665  {
666  if(role == Qt::DisplayRole)
667  {
668  return columns[section];
669  }
670  else if (role == Qt::TextAlignmentRole)
671  {
672  return column_alignments[section];
673  } else if (role == Qt::ToolTipRole)
674  {
675  switch(section)
676  {
677  case Status:
678  return tr("Transaction status. Hover over this field to show number of confirmations.");
679  case Date:
680  return tr("Date and time that the transaction was received.");
681  case Type:
682  return tr("Type of transaction.");
683  case Watchonly:
684  return tr("Whether or not a watch-only address is involved in this transaction.");
685  case ToAddress:
686  return tr("User-defined intent/purpose of the transaction.");
687  case Amount:
688  return tr("Amount removed from or added to balance.");
689  }
690  }
691  }
692  return QVariant();
693 }
694 
695 QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
696 {
697  Q_UNUSED(parent);
698  TransactionRecord *data = priv->index(row);
699  if(data)
700  {
701  return createIndex(row, column, priv->index(row));
702  }
703  return QModelIndex();
704 }
705 
707 {
708  // emit dataChanged to update Amount column with the current unit
710  Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
711 }
712 
713 // queue notifications to show a non freezing progress dialog e.g. for rescan
715 {
716 public:
718  TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
719  hash(_hash), status(_status), showTransaction(_showTransaction) {}
720 
721  void invoke(QObject *ttm)
722  {
723  QString strHash = QString::fromStdString(hash.GetHex());
724  qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
725  QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
726  Q_ARG(QString, strHash),
727  Q_ARG(int, status),
728  Q_ARG(bool, showTransaction));
729  }
730 private:
734 };
735 
736 static bool fQueueNotifications = false;
737 static std::vector< TransactionNotification > vQueueNotifications;
738 
739 static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet, const uint256 &hash, ChangeType status)
740 {
741  // Find transaction in wallet
742  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
743  // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
744  bool inWallet = mi != wallet->mapWallet.end();
745  bool showTransaction = (inWallet && TransactionRecord::showTransaction(mi->second));
746 
747  TransactionNotification notification(hash, status, showTransaction);
748 
749  if (fQueueNotifications)
750  {
751  vQueueNotifications.push_back(notification);
752  return;
753  }
754  notification.invoke(ttm);
755 }
756 
757 static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
758 {
759  if (nProgress == 0)
760  fQueueNotifications = true;
761 
762  if (nProgress == 100)
763  {
764  fQueueNotifications = false;
765  if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
766  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
767  for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
768  {
769  if (vQueueNotifications.size() - i <= 10)
770  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
771 
772  vQueueNotifications[i].invoke(ttm);
773  }
774  std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
775  }
776 }
777 
779 {
780  // Connect signals to wallet
781  wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this,
782  boost::placeholders::_1,
783  boost::placeholders::_2,
784  boost::placeholders::_3));
785  wallet->ShowProgress.connect(boost::bind(ShowProgress, this,
786  boost::placeholders::_1,
787  boost::placeholders::_2));
788 }
789 
791 {
792  // Disconnect signals from wallet
793  wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this,
794  boost::placeholders::_1,
795  boost::placeholders::_2,
796  boost::placeholders::_3));
797  wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this,
798  boost::placeholders::_1,
799  boost::placeholders::_2));
800 }
QString labelForAddress(const QString &address) const
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:308
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:493
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:614
CCriticalSection cs_wallet
Definition: wallet.h:559
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:878
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:875
int getDisplayUnit()
Definition: optionsmodel.h:65
QIcon TextColorIcon(const QString &filename) const
Colorize an icon (given filename) with the text color.
static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
UI model for a transaction.
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
TransactionStatus status
Status: can change with block chain update.
static bool showTransaction(const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
QString getTxID() const
Return the unique identifier for this transaction (part)
void updateStatus(const CWalletTx &wtx)
Update status from core wallet tx.
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
bool statusUpdateNeeded()
Return whether a status update is needed.
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
bool countsForBalance
Transaction counts towards available balance.
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
@ MaturesWarning
Transaction will likely not mature because no nodes have confirmed.
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ OpenUntilDate
Normal (sent/received) transactions.
@ Unconfirmed
Not yet mined into a block.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ OpenUntilBlock
Transaction not yet final, waiting for block.
@ Conflicted
Conflicts with other transaction or mempool.
@ Abandoned
Abandoned from the wallet.
@ Offline
Not sent to any other nodes.
std::string sortKey
Sorting key based on status.
UI model for the transaction table of a wallet.
QVariant data(const QModelIndex &index, int role) const
QVariant txStatusDecoration(const TransactionRecord *wtx) const
int rowCount(const QModelIndex &parent) const
TransactionTablePriv * priv
QVariant addressColor(const TransactionRecord *wtx) const
@ TxPlainTextRole
Whole transaction as plain text.
@ LabelRole
Label of address related to transaction.
@ LongDescriptionRole
Long description (HTML format)
@ TypeRole
Type of transaction.
@ StatusRole
Transaction status (TransactionRecord::Status)
@ DateRole
Date and time this transaction was created.
@ TxHashRole
Transaction hash.
@ TxHexRole
Transaction data, hex-encoded.
@ RawDecorationRole
Unprocessed icon.
@ TxIDRole
Unique identifier.
@ AddressRole
Address of transaction.
@ WatchonlyDecorationRole
Watch-only icon.
@ WatchonlyRole
Watch-only boolean.
@ AmountRole
Net amount of transaction.
@ ConfirmedRole
Is transaction confirmed?
@ FormattedAmountRole
Formatted amount, without brackets when unconfirmed.
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::separatorStandard) const
QString formatTooltip(const TransactionRecord *rec) const
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
void updateTransaction(const QString &hash, int status, bool showTransaction)
QString formatTxStatus(const TransactionRecord *wtx) const
TransactionTableModel(const PlatformStyle *platformStyle, CWallet *wallet, WalletModel *parent=0)
QVariant headerData(int section, Qt::Orientation orientation, int role) const
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
int columnCount(const QModelIndex &parent) const
const PlatformStyle * platformStyle
QString formatTxType(const TransactionRecord *wtx) const
QString lookupAddress(const std::string &address, bool tooltip) const
QVariant txAddressDecoration(const TransactionRecord *wtx) const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
QString formatTxDate(const TransactionRecord *wtx) const
TransactionTableModel * parent
QList< TransactionRecord > cachedWallet
void updateWallet(const uint256 &hash, int status, bool showTransaction)
QString getTxHex(TransactionRecord *rec)
TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent)
QString describe(TransactionRecord *rec, int unit)
TransactionRecord * index(int idx)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:99
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
void SetHex(const char *psz)
Definition: uint256.cpp:30
std::string ToString() const
Definition: uint256.cpp:65
std::string GetHex() const
Definition: uint256.cpp:21
256-bit opaque blob.
Definition: uint256.h:123
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:117
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:33
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:23
#define COLOR_TX_STATUS_OPENUNTILDATE
Definition: guiconstants.h:29
#define COLOR_TX_STATUS_OFFLINE
Definition: guiconstants.h:31
#define COLOR_NEGATIVE
Definition: guiconstants.h:25
#define COLOR_BLACK
Definition: guiconstants.h:35
#define COLOR_BAREADDRESS
Definition: guiconstants.h:27
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:86
TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction)
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
bool operator()(const TransactionRecord &a, const uint256 &b) const
bool operator()(const uint256 &a, const TransactionRecord &b) const
#define LOCK2(cs1, cs2)
Definition: sync.h:178
#define TRY_LOCK(cs, name)
Definition: sync.h:179
ChangeType
General change type (added, updated, removed).
Definition: ui_interface.h:22
@ CT_UPDATED
Definition: ui_interface.h:24
@ CT_DELETED
Definition: ui_interface.h:25
@ CT_NEW
Definition: ui_interface.h:23
CCriticalSection cs_main
Global state.
Definition: validation.cpp:61