Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

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 <qt/addresstablemodel.h>
8 #include <qt/guiutil.h>
9 #include <qt/optionsmodel.h>
10 #include <qt/transactiondesc.h>
11 #include <qt/transactionrecord.h>
12 #include <qt/walletmodel.h>
13 
14 #include <core_io.h>
15 #include <validation.h>
16 #include <sync.h>
17 #include <uint256.h>
18 #include <util.h>
19 #include <wallet/wallet.h>
20 
21 #include <QColor>
22 #include <QDateTime>
23 #include <QDebug>
24 #include <QIcon>
25 #include <QList>
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  wallet(_wallet),
60  parent(_parent)
61  {
62  }
63 
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  {
81  for (const auto& entry : wallet->mapWallet)
82  {
83  if (TransactionRecord::showTransaction(entry.second))
85  }
86  }
87  }
88 
89  /* Update our model of the wallet incrementally, to synchronize our model of the wallet
90  with that of the core.
91 
92  Call with transaction that was added, removed or changed.
93  */
94  void updateWallet(const uint256 &hash, int status, bool showTransaction)
95  {
96  qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
97 
98  // Find bounds of this transaction in model
99  QList<TransactionRecord>::iterator lower = qLowerBound(
100  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
101  QList<TransactionRecord>::iterator upper = qUpperBound(
102  cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
103  int lowerIndex = (lower - cachedWallet.begin());
104  int upperIndex = (upper - cachedWallet.begin());
105  bool inModel = (lower != upper);
106 
107  if(status == CT_UPDATED)
108  {
109  if(showTransaction && !inModel)
110  status = CT_NEW; /* Not in model, but want to show, treat as new */
111  if(!showTransaction && inModel)
112  status = CT_DELETED; /* In model, but want to hide, treat as deleted */
113  }
114 
115  qDebug() << " inModel=" + QString::number(inModel) +
116  " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
117  " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
118 
119  switch(status)
120  {
121  case CT_NEW:
122  if(inModel)
123  {
124  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
125  break;
126  }
127  if(showTransaction)
128  {
130  // Find transaction in wallet
131  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
132  if(mi == wallet->mapWallet.end())
133  {
134  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
135  break;
136  }
137  // Added -- insert at the right position
138  QList<TransactionRecord> toInsert =
140  if(!toInsert.isEmpty()) /* only if something to insert */
141  {
142  parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
143  int insert_idx = lowerIndex;
144  for (const TransactionRecord &rec : toInsert)
145  {
146  cachedWallet.insert(insert_idx, rec);
147  insert_idx += 1;
148  }
149  parent->endInsertRows();
150  }
151  }
152  break;
153  case CT_DELETED:
154  if(!inModel)
155  {
156  qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
157  break;
158  }
159  // Removed -- remove entire transaction from table
160  parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
161  cachedWallet.erase(lower, upper);
162  parent->endRemoveRows();
163  break;
164  case CT_UPDATED:
165  // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
166  // visible transactions.
167  for (int i = lowerIndex; i < upperIndex; i++) {
168  TransactionRecord *rec = &cachedWallet[i];
169  rec->status.needsUpdate = true;
170  }
171  Q_EMIT parent->dataChanged(parent->index(lowerIndex, TransactionTableModel::Status), parent->index(upperIndex, TransactionTableModel::Status));
172  break;
173  }
174  }
175 
176  void updateAddressBook(const QString& address, const QString& label, bool isMine, const QString& purpose, int status)
177  {
178  std::string address2 = address.toStdString();
179  int index = 0;
180  for (auto& rec : cachedWallet) {
181  if (rec.strAddress == address2) {
182  rec.status.needsUpdate = true;
184  }
185  index++;
186  }
187  }
188 
189  int size()
190  {
191  return cachedWallet.size();
192  }
193 
195  {
196  if(idx >= 0 && idx < cachedWallet.size())
197  {
198  TransactionRecord *rec = &cachedWallet[idx];
199 
200  // Get required locks upfront. This avoids the GUI from getting
201  // stuck if the core is holding the locks for a longer time - for
202  // example, during a wallet rescan.
203  //
204  // If a status update is needed (blocks came in since last check),
205  // update the status of this transaction from the wallet. Otherwise,
206  // simply re-use the cached status.
207  TRY_LOCK(cs_main, lockMain);
208  if(lockMain)
209  {
210  TRY_LOCK(wallet->cs_wallet, lockWallet);
211  if(lockWallet && (rec->statusUpdateNeeded(parent->getChainLockHeight())))
212  {
213  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
214 
215  if(mi != wallet->mapWallet.end())
216  {
217  rec->updateStatus(mi->second, parent->getChainLockHeight());
218  }
219  }
220  }
221  return rec;
222  }
223  return 0;
224  }
225 
226  QString describe(TransactionRecord *rec, int unit)
227  {
228  {
230  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
231  if(mi != wallet->mapWallet.end())
232  {
233  return TransactionDesc::toHTML(wallet, mi->second, rec, unit);
234  }
235  }
236  return QString();
237  }
238 
240  {
242  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
243  if(mi != wallet->mapWallet.end())
244  {
245  std::string strHex = EncodeHexTx(*mi->second.tx);
246  return QString::fromStdString(strHex);
247  }
248  return QString();
249  }
250 };
251 
253  QAbstractTableModel(parent),
254  wallet(_wallet),
255  walletModel(parent),
256  priv(new TransactionTablePriv(_wallet, this)),
257  fProcessingQueuedTransactions(false)
258 {
259  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Address / Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
260  priv->refreshWallet();
261 
262  connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
263 
265 }
266 
268 {
270  delete priv;
271 }
272 
275 {
277  Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
278 }
279 
280 void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
281 {
282  uint256 updated;
283  updated.SetHex(hash.toStdString());
284 
285  priv->updateWallet(updated, status, showTransaction);
286 }
287 
288 void TransactionTableModel::updateAddressBook(const QString& address, const QString& label, bool isMine,
289  const QString& purpose, int status)
290 {
291  priv->updateAddressBook(address, label, isMine, purpose, status);
292 }
293 
295 {
296  // Blocks came in since last poll.
297  // Invalidate status (number of confirmations) and (possibly) description
298  // for all rows. Qt is smart enough to only actually request the data for the
299  // visible rows.
300  Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
301 }
302 
303 
305 {
306  cachedChainLockHeight = chainLockHeight;
307 }
308 
310 {
311  return cachedChainLockHeight;
312 }
313 
314 int TransactionTableModel::rowCount(const QModelIndex &parent) const
315 {
316  Q_UNUSED(parent);
317  return priv->size();
318 }
319 
320 int TransactionTableModel::columnCount(const QModelIndex &parent) const
321 {
322  Q_UNUSED(parent);
323  return columns.length();
324 }
325 
327 {
328  QString status;
329 
330  switch(wtx->status.status)
331  {
333  status = tr("Open for %n more block(s)","",wtx->status.open_for);
334  break;
336  status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
337  break;
339  status = tr("Unconfirmed");
340  break;
342  status = tr("Abandoned");
343  break;
345  status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
346  break;
348  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
349  break;
351  status = tr("Conflicted");
352  break;
354  status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
355  break;
357  status = tr("Generated but not accepted");
358  break;
359  }
360 
361  if (wtx->status.lockedByInstantSend) {
362  status += ", " + tr("verified via InstantSend");
363  }
364  if (wtx->status.lockedByChainLocks) {
365  status += ", " + tr("locked via ChainLocks");
366  }
367 
368  return status;
369 }
370 
372 {
373  if(wtx->time)
374  {
375  return GUIUtil::dateTimeStr(wtx->time);
376  }
377  return QString();
378 }
379 
380 /* If label is non-empty, return label (address)
381  otherwise just return (address)
382  */
383 QString TransactionTableModel::formatAddressLabel(const std::string &address, const QString& label, bool tooltip) const
384 {
385  QString description;
386  if(!label.isEmpty())
387  {
388  description += label;
389  }
390  if(label.isEmpty() || tooltip)
391  {
392  description += QString(" (") + QString::fromStdString(address) + QString(")");
393  }
394  return description;
395 }
396 
398 {
399  switch(wtx->type)
400  {
402  return tr("Received with");
404  return tr("Received from");
406  return tr("Received via PrivateSend");
409  return tr("Sent to");
411  return tr("Payment to yourself");
413  return tr("Mined");
414 
416  return tr("PrivateSend Denominate");
418  return tr("PrivateSend Collateral Payment");
420  return tr("PrivateSend Make Collateral Inputs");
422  return tr("PrivateSend Create Denominations");
424  return "PrivateSend";
425 
426  default:
427  return QString();
428  }
429 }
430 
432 {
433  if (wtx->status.lockedByInstantSend) {
435  }
436  return QVariant();
437 }
438 
439 QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
440 {
441  QString watchAddress;
442  if (tooltip) {
443  // Mark transactions involving watch-only addresses by adding " (watch-only)"
444  watchAddress = wtx->involvesWatchAddress ? QString(" (") + tr("watch-only") + QString(")") : "";
445  }
446 
447  switch(wtx->type)
448  {
450  return QString::fromStdString(wtx->strAddress) + watchAddress;
456  return formatAddressLabel(wtx->strAddress, wtx->status.label, tooltip) + watchAddress;
458  return QString::fromStdString(wtx->strAddress) + watchAddress;
460  default:
461  return tr("(n/a)") + watchAddress;
462  }
463 }
464 
466 {
467  // Show addresses without label in a less visible color
468  switch(wtx->type)
469  {
475  {
477  if(label.isEmpty())
479  } break;
486  default:
487  break;
488  }
490 }
491 
492 QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
493 {
494  QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
495  if(showUnconfirmed)
496  {
497  if(!wtx->status.countsForBalance)
498  {
499  str = QString("[") + str + QString("]");
500  }
501  }
502  return QString(str);
503 }
504 
506 {
507  switch (rec->type) {
524  }
526 }
527 
529 {
530  switch(wtx->status.status)
531  {
536  return GUIUtil::getIcon("transaction_0");
538  return GUIUtil::getIcon("transaction_abandoned", GUIUtil::ThemedColor::RED);
540  switch(wtx->status.depth)
541  {
542  case 1: return GUIUtil::getIcon("transaction_1", GUIUtil::ThemedColor::ORANGE);
543  case 2: return GUIUtil::getIcon("transaction_2", GUIUtil::ThemedColor::ORANGE);
544  case 3: return GUIUtil::getIcon("transaction_3", GUIUtil::ThemedColor::ORANGE);
545  case 4: return GUIUtil::getIcon("transaction_4", GUIUtil::ThemedColor::ORANGE);
546  default: return GUIUtil::getIcon("transaction_5", GUIUtil::ThemedColor::ORANGE);
547  };
553  int total = wtx->status.depth + wtx->status.matures_in;
554  int part = (wtx->status.depth * 5 / total) + 1;
555  return GUIUtil::getIcon(QString("transaction_%1").arg(part), GUIUtil::ThemedColor::ORANGE);
556  }
558  return GUIUtil::getIcon("transaction_0", GUIUtil::ThemedColor::RED);
559  default:
561  }
562 }
563 
565 {
566  if (wtx->involvesWatchAddress)
567  return GUIUtil::getIcon("eye");
568  else
569  return QVariant();
570 }
571 
573 {
574  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
577  {
578  tooltip += QString(" ") + formatTxToAddress(rec, true);
579  }
580  return tooltip;
581 }
582 
583 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
584 {
585  if(!index.isValid())
586  return QVariant();
587  TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
588 
589  switch(role)
590  {
591  case RawDecorationRole:
592  switch(index.column())
593  {
594  case Status:
595  return txStatusDecoration(rec);
596  case Watchonly:
597  return txWatchonlyDecoration(rec);
598  case ToAddress:
599  return txAddressDecoration(rec);
600  }
601  break;
602  case Qt::DecorationRole:
603  {
604  return qvariant_cast<QIcon>(index.data(RawDecorationRole));
605  }
606  case Qt::DisplayRole:
607  switch(index.column())
608  {
609  case Date:
610  return formatTxDate(rec);
611  case Type:
612  return formatTxType(rec);
613  case ToAddress:
614  return formatTxToAddress(rec, false);
615  case Amount:
617  }
618  break;
619  case Qt::EditRole:
620  // Edit role is used for sorting, so return the unformatted values
621  switch(index.column())
622  {
623  case Status:
624  return QString::fromStdString(rec->status.sortKey);
625  case Date:
626  return rec->time;
627  case Type:
628  return formatTxType(rec);
629  case Watchonly:
630  return (rec->involvesWatchAddress ? 1 : 0);
631  case ToAddress:
632  return formatTxToAddress(rec, true);
633  case Amount:
634  return qint64(rec->credit + rec->debit);
635  }
636  break;
637  case Qt::ToolTipRole:
638  return formatTooltip(rec);
639  case Qt::TextAlignmentRole:
640  return column_alignments[index.column()];
641  case Qt::ForegroundRole:
642  // Non-confirmed (but not immature) as transactions are grey
644  {
646  }
647  if (index.column() == Amount) {
648  return amountColor(rec);
649  }
650  if(index.column() == ToAddress)
651  {
652  return addressColor(rec);
653  }
655  case TypeRole:
656  return rec->type;
657  case DateRole:
658  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
659  case DateRoleInt:
660  return qint64(rec->time);
661  case WatchonlyRole:
662  return rec->involvesWatchAddress;
664  return txWatchonlyDecoration(rec);
665  case LongDescriptionRole:
667  case AddressRole:
668  return QString::fromStdString(rec->strAddress);
669  case LabelRole:
670  return rec->status.label;
671  case AmountRole:
672  return qint64(rec->credit + rec->debit);
673  case TxIDRole:
674  return rec->getTxID();
675  case TxHashRole:
676  return QString::fromStdString(rec->hash.ToString());
677  case TxHexRole:
678  return priv->getTxHex(rec);
679  case TxPlainTextRole:
680  {
681  QString details;
682  QString txLabel = rec->status.label;
683 
684  details.append(formatTxDate(rec));
685  details.append(" ");
686  details.append(formatTxStatus(rec));
687  details.append(". ");
688  if(!formatTxType(rec).isEmpty()) {
689  details.append(formatTxType(rec));
690  details.append(" ");
691  }
692  if(!rec->strAddress.empty()) {
693  if(txLabel.isEmpty())
694  details.append(tr("(no label)") + " ");
695  else {
696  details.append("(");
697  details.append(txLabel);
698  details.append(") ");
699  }
700  details.append(QString::fromStdString(rec->strAddress));
701  details.append(" ");
702  }
703  details.append(formatTxAmount(rec, false, BitcoinUnits::separatorNever));
704  return details;
705  }
706  case ConfirmedRole:
707  return rec->status.countsForBalance;
708  case FormattedAmountRole:
709  // Used for copy/export, so don't include separators
710  return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
711  case StatusRole:
712  return rec->status.status;
713  }
714  return QVariant();
715 }
716 
717 QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
718 {
719  if(orientation == Qt::Horizontal)
720  {
721  if(role == Qt::DisplayRole)
722  {
723  return columns[section];
724  }
725  else if (role == Qt::TextAlignmentRole)
726  {
727  return column_alignments[section];
728  } else if (role == Qt::ToolTipRole)
729  {
730  switch(section)
731  {
732  case Status:
733  return tr("Transaction status. Hover over this field to show number of confirmations.");
734  case Date:
735  return tr("Date and time that the transaction was received.");
736  case Type:
737  return tr("Type of transaction.");
738  case Watchonly:
739  return tr("Whether or not a watch-only address is involved in this transaction.");
740  case ToAddress:
741  return tr("User-defined intent/purpose of the transaction.");
742  case Amount:
743  return tr("Amount removed from or added to balance.");
744  }
745  }
746  }
747  return QVariant();
748 }
749 
750 QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
751 {
752  Q_UNUSED(parent);
753  TransactionRecord *data = priv->index(row);
754  if(data)
755  {
756  return createIndex(row, column, priv->index(row));
757  }
758  return QModelIndex();
759 }
760 
762 {
763  // emit dataChanged to update Amount column with the current unit
765  Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
766 }
767 
768 // queue notifications to show a non freezing progress dialog e.g. for rescan
770 {
771 public:
773  TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
774  hash(_hash), status(_status), showTransaction(_showTransaction) {}
775 
776  void invoke(QObject *ttm)
777  {
778  QString strHash = QString::fromStdString(hash.GetHex());
779  qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
780  QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
781  Q_ARG(QString, strHash),
782  Q_ARG(int, status),
783  Q_ARG(bool, showTransaction));
784  }
785 private:
789 };
790 
791 static bool fQueueNotifications = false;
792 static std::vector< TransactionNotification > vQueueNotifications;
793 
794 static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet, const uint256 &hash, ChangeType status)
795 {
796  // Find transaction in wallet
797  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
798  // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
799  bool inWallet = mi != wallet->mapWallet.end();
800  bool showTransaction = (inWallet && TransactionRecord::showTransaction(mi->second));
801 
802  TransactionNotification notification(hash, status, showTransaction);
803 
805  {
806  vQueueNotifications.push_back(notification);
807  return;
808  }
809  notification.invoke(ttm);
810 }
811 
812 static void NotifyAddressBookChanged(TransactionTableModel *ttm, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)
813 {
814  QMetaObject::invokeMethod(ttm, "updateAddressBook", Qt::QueuedConnection,
815  Q_ARG(QString, QString::fromStdString(EncodeDestination(address))),
816  Q_ARG(QString, QString::fromStdString(label)),
817  Q_ARG(bool, isMine),
818  Q_ARG(QString, QString::fromStdString(purpose)),
819  Q_ARG(int, (int)status));
820 }
821 
822 static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
823 {
824  if (nProgress == 0)
825  fQueueNotifications = true;
826 
827  if (nProgress == 100)
828  {
829  fQueueNotifications = false;
830  if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
831  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
832  for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
833  {
834  if (vQueueNotifications.size() - i <= 10)
835  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
836 
837  vQueueNotifications[i].invoke(ttm);
838  }
839  std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
840  }
841 }
842 
844 {
845  // Connect signals to wallet
846  wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
847  wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
848  wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
849 }
850 
852 {
853  // Disconnect signals from wallet
854  wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
855  wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
856  wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
857 }
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString describe(TransactionRecord *rec, int unit)
TransactionTableModel(CWallet *wallet, WalletModel *parent=0)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
Confirmed, but waiting for the recommended number of confirmations.
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
Transaction not yet final, waiting for block.
Transaction status (TransactionRecord::Status)
#define TRY_LOCK(cs, name)
Definition: sync.h:180
CCriticalSection cs_wallet
Definition: wallet.h:836
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::separatorStandard) const
Generated (mined) transactions.
static int column_alignments[]
static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet, const uint256 &hash, ChangeType status)
QString formatTooltip(const TransactionRecord *rec) const
QColor getThemedQColor(ThemedColor color)
Helper to get colors for various themes which can&#39;t be applied via css for some reason.
Definition: guiutil.cpp:204
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
std::string sortKey
Sorting key based on status.
static void NotifyAddressBookChanged(TransactionTableModel *ttm, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)
void updateTransaction(const QString &hash, int status, bool showTransaction)
CCriticalSection cs_main
Definition: validation.cpp:213
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:258
QString label
Label.
QVariant txStatusDecoration(const TransactionRecord *wtx) const
TransactionRecord * index(int idx)
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
Mined but not accepted.
Not yet mined into a block.
void updateStatus(const CWalletTx &wtx, int chainLockHeight)
Update status from core wallet tx.
static bool showTransaction(const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
AddressTableModel * getAddressTableModel()
Transaction data, hex-encoded.
TransactionTableModel * parent
Date and time this transaction was created in MSec since epoch.
void updateWallet(const uint256 &hash, int status, bool showTransaction)
TransactionTablePriv * priv
int getDisplayUnit() const
Definition: optionsmodel.h:82
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
bool lockedByChainLocks
Transaction was locked via ChainLocks.
QList< TransactionRecord > cachedWallet
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:1197
false
Definition: bls_dkg.cpp:168
bool operator()(const TransactionRecord &a, const uint256 &b) const
#define LOCK2(cs1, cs2)
Definition: sync.h:179
void updateChainLockHeight(int chainLockHeight)
CTxDestination txDest
UI model for a transaction.
TransactionStatus status
Status: can change with block chain update.
QString formatTxType(const TransactionRecord *wtx) const
TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent)
Whole transaction as plain text.
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
ChangeType
General change type (added, updated, removed).
Definition: ui_interface.h:20
static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
QString getTxID() const
Return the unique identifier for this transaction (part)
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
QIcon getIcon(const QString &strIcon, const ThemedColor color, const ThemedColor colorAlternative, const QString &strIconPath)
Helper to get an icon colorized with the given color (replaces black) and colorAlternative (replaces ...
Definition: guiutil.cpp:216
TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction)
bool countsForBalance
Transaction counts towards available balance.
QString getTxHex(TransactionRecord *rec)
Date and time this transaction was created.
std::string ToString() const
Definition: uint256.cpp:62
UI model for the transaction table of a wallet.
Normal (sent/received) transactions.
QString formatAddressLabel(const std::string &address, const QString &label, bool tooltip) const
QVariant data(const QModelIndex &index, int role) const
256-bit opaque blob.
Definition: uint256.h:123
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:130
static std::vector< TransactionNotification > vQueueNotifications
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
boost::signals2::signal< void(CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
Definition: wallet.h:1190
Conflicts with other transaction or mempool.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:100
bool lockedByInstantSend
Transaction was locked via InstantSend.
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
std::string GetHex() const
Definition: uint256.cpp:21
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:715
Label of address related to transaction.
QString labelForDestination(const CTxDestination &dest) const
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:896
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:1200
QString formatTxStatus(const TransactionRecord *wtx) const
static bool fQueueNotifications
bool statusUpdateNeeded(int chainLockHeight) const
Return whether a status update is needed.
QVariant addressColor(const TransactionRecord *wtx) const
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.
QVariant amountColor(const TransactionRecord *rec) const
void SetHex(const char *psz)
Definition: uint256.cpp:27
static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
Abandoned from the wallet.
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
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
Released under the MIT license