Raven Core  3.0.0
P2P Digital Currency
transactiontablemodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
7 
8 #include "addresstablemodel.h"
9 #include "guiconstants.h"
10 #include "guiutil.h"
11 #include "optionsmodel.h"
12 #include "platformstyle.h"
13 #include "transactiondesc.h"
14 #include "transactionrecord.h"
15 #include "walletmodel.h"
16 
17 #include "core_io.h"
18 #include "validation.h"
19 #include "sync.h"
20 #include "uint256.h"
21 #include "util.h"
22 #include "wallet/wallet.h"
23 
24 #include <QColor>
25 #include <QDateTime>
26 #include <QDebug>
27 #include <QIcon>
28 #include <QList>
29 
30 // Amount column is right-aligned it contains numbers
31 static int column_alignments[] = {
32  Qt::AlignLeft|Qt::AlignVCenter, /* status */
33  Qt::AlignLeft|Qt::AlignVCenter, /* watchonly */
34  Qt::AlignLeft|Qt::AlignVCenter, /* date */
35  Qt::AlignLeft|Qt::AlignVCenter, /* type */
36  Qt::AlignLeft|Qt::AlignVCenter, /* address */
37  Qt::AlignRight|Qt::AlignVCenter, /* amount */
38  Qt::AlignLeft|Qt::AlignVCenter /* assetName */
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  {
88  cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second));
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 =
143  TransactionRecord::decomposeTransaction(wallet, mi->second);
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  for (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  for (int i = lowerIndex; i < upperIndex; i++) {
172  TransactionRecord *rec = &cachedWallet[i];
173  rec->status.needsUpdate = true;
174  }
175  break;
176  }
177  }
178 
179  int size()
180  {
181  return cachedWallet.size();
182  }
183 
185  {
186  if(idx >= 0 && idx < cachedWallet.size())
187  {
188  TransactionRecord *rec = &cachedWallet[idx];
189 
190  // Get required locks upfront. This avoids the GUI from getting
191  // stuck if the core is holding the locks for a longer time - for
192  // example, during a wallet rescan.
193  //
194  // If a status update is needed (blocks came in since last check),
195  // update the status of this transaction from the wallet. Otherwise,
196  // simply re-use the cached status.
197  TRY_LOCK(cs_main, lockMain);
198  if(lockMain)
199  {
200  TRY_LOCK(wallet->cs_wallet, lockWallet);
201  if(lockWallet && rec->statusUpdateNeeded())
202  {
203  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
204 
205  if(mi != wallet->mapWallet.end())
206  {
207  rec->updateStatus(mi->second);
208  }
209  }
210  }
211  return rec;
212  }
213  return 0;
214  }
215 
216  QString describe(TransactionRecord *rec, int unit)
217  {
218  {
219  LOCK2(cs_main, wallet->cs_wallet);
220  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
221  if(mi != wallet->mapWallet.end())
222  {
223  return TransactionDesc::toHTML(wallet, mi->second, rec, unit);
224  }
225  }
226  return QString();
227  }
228 
230  {
231  LOCK2(cs_main, wallet->cs_wallet);
232  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
233  if(mi != wallet->mapWallet.end())
234  {
235  std::string strHex = EncodeHexTx(static_cast<CTransaction>(mi->second));
236  return QString::fromStdString(strHex);
237  }
238  return QString();
239  }
240 };
241 
243  QAbstractTableModel(parent),
244  wallet(_wallet),
245  walletModel(parent),
246  priv(new TransactionTablePriv(_wallet, this)),
247  fProcessingQueuedTransactions(false),
248  platformStyle(_platformStyle)
249 {
250  columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << tr("Amount") << tr("Asset");
251 
252  priv->refreshWallet();
253 
254  connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
255 
257 }
258 
260 {
262  delete priv;
263 }
264 
267 {
269  Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
270 }
271 
272 void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
273 {
274  uint256 updated;
275  updated.SetHex(hash.toStdString());
276 
277  priv->updateWallet(updated, status, showTransaction);
278 }
279 
281 {
282  // Blocks came in since last poll.
283  // Invalidate status (number of confirmations) and (possibly) description
284  // for all rows. Qt is smart enough to only actually request the data for the
285  // visible rows.
286  Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
287  Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
288 }
289 
290 int TransactionTableModel::rowCount(const QModelIndex &parent) const
291 {
292  Q_UNUSED(parent);
293  return priv->size();
294 }
295 
296 int TransactionTableModel::columnCount(const QModelIndex &parent) const
297 {
298  Q_UNUSED(parent);
299  return columns.length();
300 }
301 
303 {
304  QString status;
305 
306  switch(wtx->status.status)
307  {
309  status = tr("Open for %n more block(s)","",wtx->status.open_for);
310  break;
312  status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
313  break;
315  status = tr("Offline");
316  break;
318  status = tr("Unconfirmed");
319  break;
321  status = tr("Abandoned");
322  break;
324  status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
325  break;
327  status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
328  break;
330  status = tr("Conflicted");
331  break;
333  status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
334  break;
336  status = tr("This block was not received by any other nodes and will probably not be accepted!");
337  break;
339  status = tr("Generated but not accepted");
340  break;
341  }
342 
343  return status;
344 }
345 
347 {
348  if(wtx->time)
349  {
350  return GUIUtil::dateTimeStr(wtx->time);
351  }
352  return QString();
353 }
354 
355 /* Look up address in address book, if found return label (address)
356  otherwise just return (address)
357  */
358 QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
359 {
360  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
361  QString description;
362  if(!label.isEmpty())
363  {
364  description += label;
365  }
366  if(label.isEmpty() || tooltip)
367  {
368  description += QString(" (") + QString::fromStdString(address) + QString(")");
369  }
370  return description;
371 }
372 
374 {
375  switch(wtx->type)
376  {
378  return tr("Received with");
380  return tr("Received from");
383  return tr("Sent to");
385  return tr("Payment to yourself");
387  return tr("Mined");
389  return tr("Asset Issued");
391  return tr("Asset Reissued");
393  return tr("Assets Received");
395  return tr("Assets Sent");
396  default:
397  return QString();
398  }
399 }
400 
402 {
403  switch(wtx->type)
404  {
406  return QIcon(":/icons/tx_mined");
409  return QIcon(":/icons/tx_input");
412  return QIcon(":/icons/tx_output");
416  return QIcon(":/icons/tx_asset_input");
418  return QIcon(":/icons/tx_asset_output");
419  default:
420  return QIcon(":/icons/tx_inout");
421  }
422 }
423 
424 QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
425 {
426  QString watchAddress;
427  if (tooltip) {
428  // Mark transactions involving watch-only addresses by adding " (watch-only)"
429  watchAddress = wtx->involvesWatchAddress ? QString(" (") + tr("watch-only") + QString(")") : "";
430  }
431 
432  switch(wtx->type)
433  {
438  return QString::fromStdString(wtx->address) + watchAddress;
440  return QString::fromStdString(wtx->address) + watchAddress;
444  return lookupAddress(wtx->address, tooltip) + watchAddress;
446  return QString::fromStdString(wtx->address) + watchAddress;
448  default:
449  return tr("(n/a)") + watchAddress;
450  }
451 }
452 
454 {
455  // Show addresses without label in a less visible color
456  switch(wtx->type)
457  {
461  {
462  QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
463  if(label.isEmpty())
464  return COLOR_BAREADDRESS;
465  } break;
467  return COLOR_BAREADDRESS;
468  default:
469  break;
470  }
471  return QVariant();
472 }
473 
474 QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, RavenUnits::SeparatorStyle separators) const
475 {
476  QString str;
477  switch(wtx->type) {
482  {
483  str = QString::fromStdString(ValueFromAmountString(wtx->credit, wtx->units));
484  } break;
485  default:
486  {
488  false, separators);
489  } break;
490  }
491  if (showUnconfirmed) {
492  if (!wtx->status.countsForBalance) {
493  str = QString("[") + str + QString("]");
494  }
495  }
496  return QString(str);
497 }
498 
500 {
501  switch(wtx->status.status)
502  {
509  return QIcon(":/icons/transaction_0");
511  return QIcon(":/icons/transaction_abandoned");
513  switch(wtx->status.depth)
514  {
515  case 1: return QIcon(":/icons/transaction_1");
516  case 2: return QIcon(":/icons/transaction_2");
517  case 3: return QIcon(":/icons/transaction_3");
518  case 4: return QIcon(":/icons/transaction_4");
519  default: return QIcon(":/icons/transaction_5");
520  };
522  return QIcon(":/icons/transaction_confirmed");
524  return QIcon(":/icons/transaction_conflicted");
526  int total = wtx->status.depth + wtx->status.matures_in;
527  int part = (wtx->status.depth * 4 / total) + 1;
528  return QIcon(QString(":/icons/transaction_%1").arg(part));
529  }
532  return QIcon(":/icons/transaction_0");
533  default:
534  return COLOR_BLACK;
535  }
536 }
537 
539 {
540  if (wtx->involvesWatchAddress)
541  return QIcon(":/icons/eye");
542  else
543  return QVariant();
544 }
545 
547 {
548  QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
551  {
552  tooltip += QString(" ") + formatTxToAddress(rec, true);
553  }
554  return tooltip;
555 }
556 
557 QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
558 {
559  if(!index.isValid())
560  return QVariant();
561  TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
562 
563  switch(role)
564  {
565  case RawDecorationRole:
566  switch(index.column())
567  {
568  case Status:
569  return txStatusDecoration(rec);
570  case Watchonly:
571  return txWatchonlyDecoration(rec);
572  case ToAddress:
573  return txAddressDecoration(rec);
574  case AssetName:
575  return QString::fromStdString(rec->assetName);
576  }
577  break;
578  case Qt::DecorationRole:
579  {
580  QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
581  return platformStyle->TextColorIcon(icon);
582  }
583  case Qt::DisplayRole:
584  switch(index.column())
585  {
586  case Date:
587  return formatTxDate(rec);
588  case Type:
589  return formatTxType(rec);
590  case ToAddress:
591  return formatTxToAddress(rec, false);
592  case Amount:
593  return formatTxAmount(rec, true, RavenUnits::separatorAlways);
594  case AssetName:
595  return QString::fromStdString(rec->assetName);
596  }
597  break;
598  case Qt::EditRole:
599  // Edit role is used for sorting, so return the unformatted values
600  switch(index.column())
601  {
602  case Status:
603  return QString::fromStdString(rec->status.sortKey);
604  case Date:
605  return rec->time;
606  case Type:
607  return formatTxType(rec);
608  case Watchonly:
609  return (rec->involvesWatchAddress ? 1 : 0);
610  case ToAddress:
611  return formatTxToAddress(rec, true);
612  case Amount:
613  return qint64(rec->credit + rec->debit);
614  case AssetName:
615  return QString::fromStdString(rec->assetName);
616  }
617  break;
618  case Qt::ToolTipRole:
619  return formatTooltip(rec);
620  case Qt::TextAlignmentRole:
621  return column_alignments[index.column()];
622  case Qt::ForegroundRole:
623  // Use the "danger" color for abandoned transactions
625  {
626  return COLOR_TX_STATUS_DANGER;
627  }
628  // Non-confirmed (but not immature) as transactions are grey
630  {
631  return COLOR_UNCONFIRMED;
632  }
633  if(index.column() == Amount && (rec->credit+rec->debit) < 0)
634  {
635  return COLOR_NEGATIVE;
636  }
637  if(index.column() == ToAddress)
638  {
639  return addressColor(rec);
640  }
641  break;
642  case TypeRole:
643  return rec->type;
644  case DateRole:
645  return QDateTime::fromTime_t(static_cast<uint>(rec->time));
646  case WatchonlyRole:
647  return rec->involvesWatchAddress;
649  return txWatchonlyDecoration(rec);
650  case LongDescriptionRole:
652  case AddressRole:
653  return QString::fromStdString(rec->address);
654  case LabelRole:
655  return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
656  case AmountRole:
657  return qint64(rec->credit + rec->debit);
658  case TxIDRole:
659  return rec->getTxID();
660  case TxHashRole:
661  return QString::fromStdString(rec->hash.ToString());
662  case TxHexRole:
663  return priv->getTxHex(rec);
664  case TxPlainTextRole:
665  {
666  QString details;
667  QDateTime date = QDateTime::fromTime_t(static_cast<uint>(rec->time));
668  QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
669 
670  details.append(date.toString("M/d/yy HH:mm"));
671  details.append(" ");
672  details.append(formatTxStatus(rec));
673  details.append(". ");
674  if(!formatTxType(rec).isEmpty()) {
675  details.append(formatTxType(rec));
676  details.append(" ");
677  }
678  if(!rec->address.empty()) {
679  if(txLabel.isEmpty())
680  details.append(tr("(no label)") + " ");
681  else {
682  details.append("(");
683  details.append(txLabel);
684  details.append(") ");
685  }
686  details.append(QString::fromStdString(rec->address));
687  details.append(" ");
688  }
689  details.append(formatTxAmount(rec, false, RavenUnits::separatorNever));
690  return details;
691  }
692  case ConfirmedRole:
693  return rec->status.countsForBalance;
694  case FormattedAmountRole:
695  // Used for copy/export, so don't include separators
696  return formatTxAmount(rec, false, RavenUnits::separatorNever);
697  case AssetNameRole:
698  {
699  QString assetName;
700  assetName.append(QString::fromStdString(rec->assetName));
701  return assetName;
702  }
703  case StatusRole:
704  return rec->status.status;
705  }
706  return QVariant();
707 }
708 
709 QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
710 {
711  if(orientation == Qt::Horizontal)
712  {
713  if(role == Qt::DisplayRole)
714  {
715  return columns[section];
716  }
717  else if (role == Qt::TextAlignmentRole)
718  {
719  return column_alignments[section];
720  } else if (role == Qt::ToolTipRole)
721  {
722  switch(section)
723  {
724  case Status:
725  return tr("Transaction status. Hover over this field to show number of confirmations.");
726  case Date:
727  return tr("Date and time that the transaction was received.");
728  case Type:
729  return tr("Type of transaction.");
730  case Watchonly:
731  return tr("Whether or not a watch-only address is involved in this transaction.");
732  case ToAddress:
733  return tr("User-defined intent/purpose of the transaction.");
734  case Amount:
735  return tr("Amount removed from or added to balance.");
736  case AssetName:
737  return tr("The asset (or RVN) removed or added to balance.");
738  }
739  }
740  }
741  return QVariant();
742 }
743 
744 QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
745 {
746  Q_UNUSED(parent);
747  TransactionRecord *data = priv->index(row);
748  if(data)
749  {
750  return createIndex(row, column, priv->index(row));
751  }
752  return QModelIndex();
753 }
754 
756 {
757  // emit dataChanged to update Amount column with the current unit
759  Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
760 }
761 
762 // queue notifications to show a non freezing progress dialog e.g. for rescan
764 {
765 public:
767  TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
768  hash(_hash), status(_status), showTransaction(_showTransaction) {}
769 
770  void invoke(QObject *ttm)
771  {
772  QString strHash = QString::fromStdString(hash.GetHex());
773  qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
774  QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
775  Q_ARG(QString, strHash),
776  Q_ARG(int, status),
777  Q_ARG(bool, showTransaction));
778  }
779 private:
783 };
784 
785 static bool fQueueNotifications = false;
786 static std::vector< TransactionNotification > vQueueNotifications;
787 
788 static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet, const uint256 &hash, ChangeType status)
789 {
790  // Find transaction in wallet
791  std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
792  // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
793  bool inWallet = mi != wallet->mapWallet.end();
794  bool showTransaction = (inWallet && TransactionRecord::showTransaction(mi->second));
795 
796  TransactionNotification notification(hash, status, showTransaction);
797 
798  if (fQueueNotifications)
799  {
800  vQueueNotifications.push_back(notification);
801  return;
802  }
803  notification.invoke(ttm);
804 }
805 
806 static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
807 {
808  if (nProgress == 0)
809  fQueueNotifications = true;
810 
811  if (nProgress == 100)
812  {
813  fQueueNotifications = false;
814  if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
815  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
816  for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
817  {
818  if (vQueueNotifications.size() - i <= 10)
819  QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
820 
821  vQueueNotifications[i].invoke(ttm);
822  }
823  std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
824  }
825 }
826 
828 {
829  // Connect signals to wallet
830  wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
831  wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
832 }
833 
835 {
836  // Disconnect signals from wallet
837  wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
838  wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
839 }
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString describe(TransactionRecord *rec, int unit)
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard, const int nAssetUnit=MIN_ASSET_UNITS - 1)
Format as string.
Definition: ravenunits.cpp:101
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:178
Not sent to any other nodes.
CCriticalSection cs_wallet
Definition: wallet.h:751
Generated (mined) transactions.
QString formatTooltip(const TransactionRecord *rec) const
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)
CCriticalSection cs_main
Global state.
Definition: validation.cpp:72
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:158
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.
#define COLOR_TX_STATUS_OFFLINE
Definition: guiconstants.h:33
static bool showTransaction(const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available */...
Definition: ravenunits.cpp:242
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, RavenUnits::SeparatorStyle separators=RavenUnits::separatorStandard) const
AddressTableModel * getAddressTableModel()
Transaction data, hex-encoded.
TransactionTableModel * parent
TransactionTableModel(const PlatformStyle *platformStyle, CWallet *wallet, WalletModel *parent=0)
void updateWallet(const uint256 &hash, int status, bool showTransaction)
TransactionTablePriv * priv
int getDisplayUnit() const
Definition: optionsmodel.h:68
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
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:1139
bool operator()(const TransactionRecord &a, const uint256 &b) const
#define LOCK2(cs1, cs2)
Definition: sync.h:177
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
QString getTxID() const
Return the unique identifier for this transaction (part)
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:35
QString labelForAddress(const QString &address) const
TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction)
bool countsForBalance
Transaction counts towards available balance.
void updateStatus(const CWalletTx &wtx)
Update status from core wallet tx.
bool statusUpdateNeeded() const
Return whether a status update is needed.
std::string ValueFromAmountString(const CAmount &amount, const int8_t units)
Definition: core_write.cpp:22
QString getTxHex(TransactionRecord *rec)
Date and time this transaction was created.
std::string ToString() const
Definition: uint256.cpp:63
#define COLOR_BLACK
Definition: guiconstants.h:37
UI model for the transaction table of a wallet.
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
Normal (sent/received) transactions.
QString lookupAddress(const std::string &address, bool tooltip) const
QVariant data(const QModelIndex &index, int role) const
256-bit opaque blob.
Definition: uint256.h:123
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
Conflicts with other transaction or mempool.
Interface to Raven wallet from Qt view code.
Definition: walletmodel.h:165
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
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:673
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:143
Label of address related to transaction.
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:818
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:1142
QString formatTxStatus(const TransactionRecord *wtx) const
QVariant addressColor(const TransactionRecord *wtx) const
#define COLOR_TX_STATUS_OPENUNTILDATE
Definition: guiconstants.h:31
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:28
static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
Abandoned from the wallet.
#define COLOR_BAREADDRESS
Definition: guiconstants.h:29
const PlatformStyle * platformStyle
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
Transaction will likely not mature because no nodes have confirmed.
OptionsModel * getOptionsModel()
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
QString formatTxDate(const TransactionRecord *wtx) const