Dash Core  0.12.2.1
P2P Digital Currency
transactiontablemodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2015 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/foreach.hpp>
30 
31 // Amount column is right-aligned it contains numbers
32 static int column_alignments[] = {
33  Qt::AlignLeft|Qt::AlignVCenter, /* status */
34  Qt::AlignLeft|Qt::AlignVCenter, /* watchonly */
35  Qt::AlignLeft|Qt::AlignVCenter, /* date */
36  Qt::AlignLeft|Qt::AlignVCenter, /* type */
37  Qt::AlignLeft|Qt::AlignVCenter, /* address */
38  Qt::AlignRight|Qt::AlignVCenter /* amount */
39  };
40 
41 // Comparison operator for sort/binary search of model tx list
42 struct TxLessThan
43 {
44  bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
45  {
46  return a.hash < b.hash;
47  }
48  bool operator()(const TransactionRecord &a, const uint256 &b) const
49  {
50  return a.hash < b;
51  }
52  bool operator()(const uint256 &a, const TransactionRecord &b) const
53  {
54  return a < b.hash;
55  }
56 };
57 
58 // Private implementation
60 {
61 public:
63  wallet(wallet),
64  parent(parent)
65  {
66  }
67 
70 
71  /* Local cache of wallet.
72  * As it is in the same order as the CWallet, by definition
73  * this is sorted by sha256.
74  */
75  QList<TransactionRecord> cachedWallet;
76 
77  /* Query entire wallet anew from core.
78  */
80  {
81  qDebug() << "TransactionTablePriv::refreshWallet";
82  cachedWallet.clear();
83  {
84  LOCK2(cs_main, wallet->cs_wallet);
85  for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
86  {
89  }
90  }
91  }
92 
93  /* Update our model of the wallet incrementally, to synchronize our model of the wallet
94  with that of the core.
95 
96  Call with transaction that was added, removed or changed.
97  */
98  void updateWallet(const uint256 &hash, int status, bool showTransaction)
99  {
100  qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
101 
102  // Find bounds of this transaction in model
103  QList<TransactionRecord>::iterator lower = qLowerBound(
104  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
105  QList<TransactionRecord>::iterator upper = qUpperBound(
106  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
107  int lowerIndex = (lower - cachedWallet.begin());
108  int upperIndex = (upper - cachedWallet.begin());
109  bool inModel = (lower != upper);
110 
111  if(status == CT_UPDATED)
112  {
113  if(showTransaction && !inModel)
114  status = CT_NEW; /* Not in model, but want to show, treat as new */
115  if(!showTransaction && inModel)
116  status = CT_DELETED; /* In model, but want to hide, treat as deleted */
117  }
118 
119  qDebug() << " inModel=" + QString::number(inModel) +
120  " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
121  " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
122 
123  switch(status)
124  {
125  case CT_NEW:
126  if(inModel)
127  {
128  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
129  break;
130  }
131  if(showTransaction)
132  {
133  LOCK2(cs_main, wallet->cs_wallet);
134  // Find transaction in wallet
135  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
136  if(mi == wallet->mapWallet.end())
137  {
138  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
139  break;
140  }
141  // Added -- insert at the right position
142  QList<TransactionRecord> toInsert =
144  if(!toInsert.isEmpty()) /* only if something to insert */
145  {
146  parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
147  int insert_idx = lowerIndex;
148  Q_FOREACH(const TransactionRecord &rec, toInsert)
149  {
150  cachedWallet.insert(insert_idx, rec);
151  insert_idx += 1;
152  }
153  parent->endInsertRows();
154  }
155  }
156  break;
157  case CT_DELETED:
158  if(!inModel)
159  {
160  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
161  break;
162  }
163  // Removed -- remove entire transaction from table
164  parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
165  cachedWallet.erase(lower, upper);
166  parent->endRemoveRows();
167  break;
168  case CT_UPDATED:
169  // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
170  // visible transactions.
171  break;
172  }
173  }
174 
175  int size()
176  {
177  return cachedWallet.size();
178  }
179 
181  {
182  if(idx >= 0 && idx < cachedWallet.size())
183  {
184  TransactionRecord *rec = &cachedWallet[idx];
185 
186  // Get required locks upfront. This avoids the GUI from getting
187  // stuck if the core is holding the locks for a longer time - for
188  // example, during a wallet rescan.
189  //
190  // If a status update is needed (blocks came in since last check),
191  // update the status of this transaction from the wallet. Otherwise,
192  // simply re-use the cached status.
193  TRY_LOCK(cs_main, lockMain);
194  if(lockMain)
195  {
196  TRY_LOCK(wallet->cs_wallet, lockWallet);
197  if(lockWallet && rec->statusUpdateNeeded())
198  {
199  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
200 
201  if(mi != wallet->mapWallet.end())
202  {
203  rec->updateStatus(mi->second);
204  }
205  }
206  }
207  return rec;
208  }
209  return 0;
210  }
211 
212  QString describe(TransactionRecord *rec, int unit)
213  {
214  {
215  LOCK2(cs_main, wallet->cs_wallet);
216  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
217  if(mi != wallet->mapWallet.end())
218  {
219  return TransactionDesc::toHTML(wallet, mi->second, rec, unit);
220  }
221  }
222  return QString();
223  }
224 
226  {
227  LOCK2(cs_main, wallet->cs_wallet);
228  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
229  if(mi != wallet->mapWallet.end())
230  {
231  std::string strHex = EncodeHexTx(static_cast<CTransaction>(mi->second));
232  return QString::fromStdString(strHex);
233  }
234  return QString();
235  }
236 };
237 
239  QAbstractTableModel(parent),
240  wallet(wallet),
241  walletModel(parent),
242  priv(new TransactionTablePriv(wallet, this)),
243  fProcessingQueuedTransactions(false),
244  platformStyle(platformStyle)
245 {
246  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Address / Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
247  priv->refreshWallet();
248 
249  connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
250 
252 }
253 
255 {
257  delete priv;
258 }
259 
262 {
264  Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
265 }
266 
267 void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
268 {
269  uint256 updated;
270  updated.SetHex(hash.toStdString());
271 
272  priv->updateWallet(updated, status, showTransaction);
273 }
274 
276 {
277  // Blocks came in since last poll.
278  // Invalidate status (number of confirmations) and (possibly) description
279  // for all rows. Qt is smart enough to only actually request the data for the
280  // visible rows.
281  Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
282  Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
283 }
284 
285 int TransactionTableModel::rowCount(const QModelIndex &parent) const
286 {
287  Q_UNUSED(parent);
288  return priv->size();
289 }
290 
291 int TransactionTableModel::columnCount(const QModelIndex &parent) const
292 {
293  Q_UNUSED(parent);
294  return columns.length();
295 }
296 
298 {
299  QString status;
300 
301  switch(wtx->status.status)
302  {
304  status = tr("Open for %n more block(s)","",wtx->status.open_for);
305  break;
307  status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
308  break;
310  status = tr("Offline");
311  break;
313  status = tr("Unconfirmed");
314  break;
316  status = tr("Abandoned");
317  break;
319  status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
320  break;
322  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
323  break;
325  status = tr("Conflicted");
326  break;
328  status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
329  break;
331  status = tr("This block was not received by any other nodes and will probably not be accepted!");
332  break;
334  status = tr("Generated but not accepted");
335  break;
336  }
337 
338  return status;
339 }
340 
342 {
343  if(wtx->time)
344  {
345  return GUIUtil::dateTimeStr(wtx->time);
346  }
347  return QString();
348 }
349 
350 /* Look up address in address book, if found return label (address)
351  otherwise just return (address)
352  */
353 QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
354 {
355  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
356  QString description;
357  if(!label.isEmpty())
358  {
359  description += label;
360  }
361  if(label.isEmpty() || tooltip)
362  {
363  description += QString(" (") + QString::fromStdString(address) + QString(")");
364  }
365  return description;
366 }
367 
369 {
370  switch(wtx->type)
371  {
373  return tr("Received with");
375  return tr("Received from");
377  return tr("Received via PrivateSend");
380  return tr("Sent to");
382  return tr("Payment to yourself");
384  return tr("Mined");
385 
387  return tr("PrivateSend Denominate");
389  return tr("PrivateSend Collateral Payment");
391  return tr("PrivateSend Make Collateral Inputs");
393  return tr("PrivateSend Create Denominations");
395  return tr("PrivateSend");
396 
397  default:
398  return QString();
399  }
400 }
401 
403 {
404  QString theme = GUIUtil::getThemeName();
405  switch(wtx->type)
406  {
408  return QIcon(":/icons/" + theme + "/tx_mined");
412  return QIcon(":/icons/" + theme + "/tx_input");
415  return QIcon(":/icons/" + theme + "/tx_output");
416  default:
417  return QIcon(":/icons/" + theme + "/tx_inout");
418  }
419 }
420 
421 QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
422 {
423  QString watchAddress;
424  if (tooltip) {
425  // Mark transactions involving watch-only addresses by adding " (watch-only)"
426  watchAddress = wtx->involvesWatchAddress ? QString(" (") + tr("watch-only") + QString(")") : "";
427  }
428 
429  switch(wtx->type)
430  {
432  return QString::fromStdString(wtx->address) + watchAddress;
438  return lookupAddress(wtx->address, tooltip) + watchAddress;
440  return QString::fromStdString(wtx->address) + watchAddress;
442  default:
443  return tr("(n/a)") + watchAddress;
444  }
445 }
446 
448 {
449  // Show addresses without label in a less visible color
450  switch(wtx->type)
451  {
457  {
458  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
459  if(label.isEmpty())
460  return COLOR_BAREADDRESS;
461  } break;
467  return COLOR_BAREADDRESS;
468  default:
469  break;
470  }
471  return QVariant();
472 }
473 
474 QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
475 {
476  QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
477  if(showUnconfirmed)
478  {
479  if(!wtx->status.countsForBalance)
480  {
481  str = QString("[") + str + QString("]");
482  }
483  }
484  return QString(str);
485 }
486 
488 {
489  QString theme = GUIUtil::getThemeName();
490  switch(wtx->status.status)
491  {
498  return QIcon(":/icons/" + theme + "/transaction_0");
500  return QIcon(":/icons/" + theme + "/transaction_abandoned");
502  switch(wtx->status.depth)
503  {
504  case 1: return QIcon(":/icons/" + theme + "/transaction_1");
505  case 2: return QIcon(":/icons/" + theme + "/transaction_2");
506  case 3: return QIcon(":/icons/" + theme + "/transaction_3");
507  case 4: return QIcon(":/icons/" + theme + "/transaction_4");
508  default: return QIcon(":/icons/" + theme + "/transaction_5");
509  };
511  return QIcon(":/icons/" + theme + "/transaction_confirmed");
513  return QIcon(":/icons/" + theme + "/transaction_conflicted");
515  int total = wtx->status.depth + wtx->status.matures_in;
516  int part = (wtx->status.depth * 4 / total) + 1;
517  return QIcon(QString(":/icons/" + theme + "/transaction_%1").arg(part));
518  }
521  return QIcon(":/icons/" + theme + "/transaction_0");
522  default:
523  return COLOR_BLACK;
524  }
525 }
526 
528 {
529  QString theme = GUIUtil::getThemeName();
530  if (wtx->involvesWatchAddress)
531  return QIcon(":/icons/" + theme + "/eye");
532  else
533  return QVariant();
534 }
535 
537 {
538  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
541  {
542  tooltip += QString(" ") + formatTxToAddress(rec, true);
543  }
544  return tooltip;
545 }
546 
547 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
548 {
549  if(!index.isValid())
550  return QVariant();
551  TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
552 
553  switch(role)
554  {
555  case RawDecorationRole:
556  switch(index.column())
557  {
558  case Status:
559  return txStatusDecoration(rec);
560  case Watchonly:
561  return txWatchonlyDecoration(rec);
562  case ToAddress:
563  return txAddressDecoration(rec);
564  }
565  break;
566  case Qt::DecorationRole:
567  {
568  return qvariant_cast<QIcon>(index.data(RawDecorationRole));
569  }
570  case Qt::DisplayRole:
571  switch(index.column())
572  {
573  case Date:
574  return formatTxDate(rec);
575  case Type:
576  return formatTxType(rec);
577  case ToAddress:
578  return formatTxToAddress(rec, false);
579  case Amount:
581  }
582  break;
583  case Qt::EditRole:
584  // Edit role is used for sorting, so return the unformatted values
585  switch(index.column())
586  {
587  case Status:
588  return QString::fromStdString(rec->status.sortKey);
589  case Date:
590  return rec->time;
591  case Type:
592  return formatTxType(rec);
593  case Watchonly:
594  return (rec->involvesWatchAddress ? 1 : 0);
595  case ToAddress:
596  return formatTxToAddress(rec, true);
597  case Amount:
598  return qint64(rec->credit + rec->debit);
599  }
600  break;
601  case Qt::ToolTipRole:
602  return formatTooltip(rec);
603  case Qt::TextAlignmentRole:
604  return column_alignments[index.column()];
605  case Qt::ForegroundRole:
606  // Use the "danger" color for abandoned transactions
608  {
609  return COLOR_TX_STATUS_DANGER;
610  }
611  // Non-confirmed (but not immature) as transactions are grey
613  {
614  return COLOR_UNCONFIRMED;
615  }
616  if(index.column() == Amount && (rec->credit+rec->debit) < 0)
617  {
618  return COLOR_NEGATIVE;
619  }
620  if(index.column() == ToAddress)
621  {
622  return addressColor(rec);
623  }
624  break;
625  case TypeRole:
626  return rec->type;
627  case DateRole:
628  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
629  case WatchonlyRole:
630  return rec->involvesWatchAddress;
632  return txWatchonlyDecoration(rec);
633  case LongDescriptionRole:
635  case AddressRole:
636  return QString::fromStdString(rec->address);
637  case LabelRole:
638  return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
639  case AmountRole:
640  return qint64(rec->credit + rec->debit);
641  case TxIDRole:
642  return rec->getTxID();
643  case TxHashRole:
644  return QString::fromStdString(rec->hash.ToString());
645  case TxHexRole:
646  return priv->getTxHex(rec);
647  case TxPlainTextRole:
648  {
649  QString details;
650  QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
651 
652  details.append(formatTxDate(rec));
653  details.append(" ");
654  details.append(formatTxStatus(rec));
655  details.append(". ");
656  if(!formatTxType(rec).isEmpty()) {
657  details.append(formatTxType(rec));
658  details.append(" ");
659  }
660  if(!rec->address.empty()) {
661  if(txLabel.isEmpty())
662  details.append(tr("(no label)") + " ");
663  else {
664  details.append("(");
665  details.append(txLabel);
666  details.append(") ");
667  }
668  details.append(QString::fromStdString(rec->address));
669  details.append(" ");
670  }
671  details.append(formatTxAmount(rec, false, BitcoinUnits::separatorNever));
672  return details;
673  }
674  case ConfirmedRole:
675  return rec->status.countsForBalance;
676  case FormattedAmountRole:
677  // Used for copy/export, so don't include separators
678  return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
679  case StatusRole:
680  return rec->status.status;
681  }
682  return QVariant();
683 }
684 
685 QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
686 {
687  if(orientation == Qt::Horizontal)
688  {
689  if(role == Qt::DisplayRole)
690  {
691  return columns[section];
692  }
693  else if (role == Qt::TextAlignmentRole)
694  {
695  return column_alignments[section];
696  } else if (role == Qt::ToolTipRole)
697  {
698  switch(section)
699  {
700  case Status:
701  return tr("Transaction status. Hover over this field to show number of confirmations.");
702  case Date:
703  return tr("Date and time that the transaction was received.");
704  case Type:
705  return tr("Type of transaction.");
706  case Watchonly:
707  return tr("Whether or not a watch-only address is involved in this transaction.");
708  case ToAddress:
709  return tr("User-defined intent/purpose of the transaction.");
710  case Amount:
711  return tr("Amount removed from or added to balance.");
712  }
713  }
714  }
715  return QVariant();
716 }
717 
718 QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
719 {
720  Q_UNUSED(parent);
721  TransactionRecord *data = priv->index(row);
722  if(data)
723  {
724  return createIndex(row, column, priv->index(row));
725  }
726  return QModelIndex();
727 }
728 
730 {
731  // emit dataChanged to update Amount column with the current unit
733  Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
734 }
735 
736 // queue notifications to show a non freezing progress dialog e.g. for rescan
738 {
739 public:
743 
744  void invoke(QObject *ttm)
745  {
746  QString strHash = QString::fromStdString(hash.GetHex());
747  qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
748  QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
749  Q_ARG(QString, strHash),
750  Q_ARG(int, status),
751  Q_ARG(bool, showTransaction));
752  }
753 private:
757 };
758 
759 static bool fQueueNotifications = false;
760 static std::vector< TransactionNotification > vQueueNotifications;
761 
763 {
764  // Find transaction in wallet
765  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
766  // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
767  bool inWallet = mi != wallet->mapWallet.end();
768  bool showTransaction = (inWallet && TransactionRecord::showTransaction(mi->second));
769 
770  TransactionNotification notification(hash, status, showTransaction);
771 
773  {
774  vQueueNotifications.push_back(notification);
775  return;
776  }
777  notification.invoke(ttm);
778 }
779 
780 static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
781 {
782  if (nProgress == 0)
783  fQueueNotifications = true;
784 
785  if (nProgress == 100)
786  {
787  fQueueNotifications = false;
788  if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
789  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
790  for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
791  {
792  if (vQueueNotifications.size() - i <= 10)
793  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
794 
795  vQueueNotifications[i].invoke(ttm);
796  }
797  std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
798  }
799 }
800 
802 {
803  // Connect signals to wallet
804  wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
805  wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
806 }
807 
809 {
810  // Disconnect signals from wallet
811  wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
812  wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
813 }
void updateStatus(const CWalletTx &wtx)
TransactionTableModel(const PlatformStyle *platformStyle, CWallet *wallet, WalletModel *parent=0)
#define TRY_LOCK(cs, name)
Definition: sync.h:170
Normal (sent/received) transactions.
QVariant data(const QModelIndex &index, int role) const
void updateWallet(const uint256 &hash, int status, bool showTransaction)
QVariant headerData(int section, Qt::Orientation orientation, int role) const
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
static int column_alignments[]
static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet, const uint256 &hash, ChangeType status)
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::separatorStandard) const
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available */...
static bool showTransaction(const CWalletTx &wtx)
CCriticalSection cs_main
Definition: validation.cpp:62
QVariant txAddressDecoration(const TransactionRecord *wtx) const
std::string sortKey
Sorting key based on status.
#define COLOR_TX_STATUS_OFFLINE
Definition: guiconstants.h:32
bool operator()(const TransactionRecord &a, const uint256 &b) const
TransactionStatus status
void updateTransaction(const QString &hash, int status, bool showTransaction)
#define LOCK2(cs1, cs2)
Definition: sync.h:169
QString formatTxStatus(const TransactionRecord *wtx) const
description
Definition: setup.py:4
ChangeType
Definition: ui_interface.h:21
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
QString labelForAddress(const QString &address) const
static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
QVariant txStatusDecoration(const TransactionRecord *wtx) const
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:34
int columnCount(const QModelIndex &parent) const
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
static const int RecommendedNumConfirmations
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
OptionsModel * getOptionsModel()
std::string ToString() const
Definition: uint256.cpp:65
#define COLOR_BLACK
Definition: guiconstants.h:36
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:24
Definition: wallet.py:1
QString lookupAddress(const std::string &address, bool tooltip) const
QString formatTxType(const TransactionRecord *wtx) const
QString getTxHex(TransactionRecord *rec)
QString formatTooltip(const TransactionRecord *rec) const
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:119
TransactionTableModel * parent
TransactionNotification(uint256 hash, ChangeType status, bool showTransaction)
static std::vector< TransactionNotification > vQueueNotifications
Generated (mined) transactions.
QString getTxID() const
TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent)
QString getThemeName()
Definition: guiutil.cpp:902
TransactionRecord * index(int idx)
std::string GetHex() const
Definition: uint256.cpp:21
QString describe(TransactionRecord *rec, int unit)
int getDisplayUnit()
Definition: optionsmodel.h:73
bool operator()(const uint256 &a, const TransactionRecord &b) const
bool countsForBalance
Transaction counts towards available balance.
static bool fQueueNotifications
int rowCount(const QModelIndex &parent) const
#define COLOR_TX_STATUS_OPENUNTILDATE
Definition: guiconstants.h:30
TransactionTablePriv * priv
void SetHex(const char *psz)
Definition: uint256.cpp:30
AddressTableModel * getAddressTableModel()
#define COLOR_BAREADDRESS
Definition: guiconstants.h:28
#define COLOR_NEGATIVE
Definition: guiconstants.h:26
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
QVariant addressColor(const TransactionRecord *wtx) const
QString formatTxDate(const TransactionRecord *wtx) const
QList< TransactionRecord > cachedWallet
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:87