Bitcoin ABC 0.32.4
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 <core_io.h>
10#include <qt/clientmodel.h>
11#include <qt/guiconstants.h>
12#include <qt/guiutil.h>
13#include <qt/optionsmodel.h>
14#include <qt/platformstyle.h>
15#include <qt/transactiondesc.h>
17#include <qt/walletmodel.h>
18#include <uint256.h>
19
20#include <algorithm>
21#include <functional>
22
23#include <QColor>
24#include <QDateTime>
25#include <QDebug>
26#include <QIcon>
27#include <QList>
28
29// Amount column is right-aligned it contains numbers
30static int column_alignments[] = {
31 Qt::AlignLeft | Qt::AlignVCenter, /* status */
32 Qt::AlignLeft | Qt::AlignVCenter, /* watchonly */
33 Qt::AlignLeft | Qt::AlignVCenter, /* date */
34 Qt::AlignLeft | Qt::AlignVCenter, /* type */
35 Qt::AlignLeft | Qt::AlignVCenter, /* address */
36 Qt::AlignRight | Qt::AlignVCenter /* amount */
37};
38
39// Comparison operator for sort/binary search of model tx list
40struct TxLessThan {
42 const TransactionRecord &b) const {
43 return a.txid < b.txid;
44 }
45 bool operator()(const TransactionRecord &a, const TxId &b) const {
46 return a.txid < b;
47 }
48 bool operator()(const TxId &a, const TransactionRecord &b) const {
49 return a < b.txid;
50 }
51};
52
53// queue notifications to show a non freezing progress dialog e.g. for rescan
55public:
58 bool _showTransaction)
59 : txid(_txid), status(_status), showTransaction(_showTransaction) {}
60
61 void invoke(QObject *ttm) {
62 QString strHash = QString::fromStdString(txid.GetHex());
63 qDebug() << "NotifyTransactionChanged: " + strHash +
64 " status= " + QString::number(status);
65 bool invoked = QMetaObject::invokeMethod(
66 ttm, "updateTransaction", Qt::QueuedConnection,
67 Q_ARG(QString, strHash), Q_ARG(int, status),
68 Q_ARG(bool, showTransaction));
69 assert(invoked);
70 }
71
72private:
76};
77
78// Private implementation
80public:
82 : parent(_parent) {}
83
85
86 /* Local cache of wallet.
87 * As it is in the same order as the CWallet, by definition this is sorted
88 * by sha256.
89 */
90 QList<TransactionRecord> cachedWallet;
91
92 bool fQueueNotifications = false;
93 std::vector<TransactionNotification> vQueueNotifications;
94
95 void NotifyTransactionChanged(const TxId &txidc, ChangeType status);
96 void ShowProgress(const std::string &title, int nProgress);
97
102 qDebug() << "TransactionTablePriv::refreshWallet";
103 cachedWallet.clear();
104 for (const auto &wtx : wallet.getWalletTxs()) {
106 cachedWallet.append(
108 }
109 }
110 }
111
117 void updateWallet(interfaces::Wallet &wallet, const TxId &txid, int status,
118 bool showTransaction) {
119 qDebug() << "TransactionTablePriv::updateWallet: " +
120 QString::fromStdString(txid.ToString()) + " " +
121 QString::number(status);
122
123 // Find bounds of this transaction in model
124 QList<TransactionRecord>::iterator lower = std::lower_bound(
125 cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
126 QList<TransactionRecord>::iterator upper = std::upper_bound(
127 cachedWallet.begin(), cachedWallet.end(), txid, TxLessThan());
128 int lowerIndex = (lower - cachedWallet.begin());
129 int upperIndex = (upper - cachedWallet.begin());
130 bool inModel = (lower != upper);
131
132 if (status == CT_UPDATED) {
133 // Not in model, but want to show, treat as new.
134 if (showTransaction && !inModel) {
135 status = CT_NEW;
136 }
137 // In model, but want to hide, treat as deleted.
138 if (!showTransaction && inModel) {
139 status = CT_DELETED;
140 }
141 }
142
143 qDebug() << " inModel=" + QString::number(inModel) +
144 " Index=" + QString::number(lowerIndex) + "-" +
145 QString::number(upperIndex) +
146 " showTransaction=" + QString::number(showTransaction) +
147 " derivedStatus=" + QString::number(status);
148
149 switch (status) {
150 case CT_NEW:
151 if (inModel) {
152 qWarning() << "TransactionTablePriv::updateWallet: "
153 "Warning: Got CT_NEW, but transaction is "
154 "already in model";
155 break;
156 }
157 if (showTransaction) {
158 // Find transaction in wallet
159 interfaces::WalletTx wtx = wallet.getWalletTx(txid);
160 if (!wtx.tx) {
161 qWarning() << "TransactionTablePriv::updateWallet: "
162 "Warning: Got CT_NEW, but transaction is "
163 "not in wallet";
164 break;
165 }
166 // Added -- insert at the right position
167 QList<TransactionRecord> toInsert =
169 /* only if something to insert */
170 if (!toInsert.isEmpty()) {
171 parent->beginInsertRows(QModelIndex(), lowerIndex,
172 lowerIndex + toInsert.size() -
173 1);
174 int insert_idx = lowerIndex;
175 for (const TransactionRecord &rec : toInsert) {
176 cachedWallet.insert(insert_idx, rec);
177 insert_idx += 1;
178 }
179 parent->endInsertRows();
180 }
181 }
182 break;
183 case CT_DELETED:
184 if (!inModel) {
185 qWarning() << "TransactionTablePriv::updateWallet: "
186 "Warning: Got CT_DELETED, but transaction is "
187 "not in model";
188 break;
189 }
190 // Removed -- remove entire transaction from table
191 parent->beginRemoveRows(QModelIndex(), lowerIndex,
192 upperIndex - 1);
193 cachedWallet.erase(lower, upper);
194 parent->endRemoveRows();
195 break;
196 case CT_UPDATED:
197 // Miscellaneous updates -- nothing to do, status update will
198 // take care of this, and is only computed for visible
199 // transactions.
200 break;
201 }
202 }
203
204 int size() { return cachedWallet.size(); }
205
207 const BlockHash &cur_block_hash, const int idx) {
208 if (idx >= 0 && idx < cachedWallet.size()) {
209 TransactionRecord *rec = &cachedWallet[idx];
210
211 // If a status update is needed (blocks came in since last check),
212 // try to update the status of this transaction from the wallet.
213 // Otherwise, simply re-use the cached status.
215 int numBlocks;
216 int64_t block_time;
217 if (!cur_block_hash.IsNull() &&
218 rec->statusUpdateNeeded(cur_block_hash) &&
219 wallet.tryGetTxStatus(rec->txid, wtx, numBlocks, block_time)) {
220 rec->updateStatus(wtx, cur_block_hash, numBlocks, block_time);
221 }
222 return rec;
223 }
224 return nullptr;
225 }
226
228 TransactionRecord *rec, int unit) {
229 return TransactionDesc::toHTML(node, wallet, rec, unit);
230 }
231
233 auto tx = wallet.getTx(rec->txid);
234 if (tx) {
235 std::string strHex = EncodeHexTx(*tx);
236 return QString::fromStdString(strHex);
237 }
238 return QString();
239 }
240};
241
243 const PlatformStyle *_platformStyle, WalletModel *parent)
244 : QAbstractTableModel(parent), walletModel(parent),
245 priv(new TransactionTablePriv(this)),
246 fProcessingQueuedTransactions(false), platformStyle(_platformStyle) {
247 columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label")
251
254
256}
257
260 delete priv;
261}
262
268 Q_EMIT headerDataChanged(Qt::Horizontal, Amount, Amount);
269}
270
271void TransactionTableModel::updateTransaction(const QString &hash, int status,
272 bool showTransaction) {
273 TxId updated;
274 updated.SetHex(hash.toStdString());
275
276 priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
277}
278
280 // Blocks came in since last poll.
281 // Invalidate status (number of confirmations) and (possibly) description
282 // for all rows. Qt is smart enough to only actually request the data for
283 // the visible rows.
284 Q_EMIT dataChanged(index(0, Status), index(priv->size() - 1, Status));
285 Q_EMIT dataChanged(index(0, ToAddress), index(priv->size() - 1, ToAddress));
286}
287
288int TransactionTableModel::rowCount(const QModelIndex &parent) const {
289 Q_UNUSED(parent);
290 return priv->size();
291}
292
293int TransactionTableModel::columnCount(const QModelIndex &parent) const {
294 Q_UNUSED(parent);
295 return columns.length();
296}
297
298QString
300 QString status;
301
302 switch (wtx->status.status) {
304 status = tr("Unconfirmed");
305 break;
307 status = tr("Abandoned");
308 break;
310 status = tr("Confirming (%1 of %2 recommended confirmations)")
311 .arg(wtx->status.depth)
313 break;
315 status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
316 break;
318 status = tr("Conflicted");
319 break;
321 status =
322 tr("Immature (%1 confirmations, will be available after %2)")
323 .arg(wtx->status.depth)
324 .arg(wtx->status.depth + wtx->status.matures_in);
325 break;
327 status = tr("Generated but not accepted");
328 break;
329 }
330
331 return status;
332}
333
334QString
336 if (wtx->time) {
337 return GUIUtil::dateTimeStr(wtx->time);
338 }
339 return QString();
340}
341
346QString TransactionTableModel::lookupAddress(const std::string &address,
347 bool tooltip) const {
349 QString::fromStdString(address));
350 QString description;
351 if (!label.isEmpty()) {
352 description += label;
353 }
354 if (label.isEmpty() || tooltip) {
355 description +=
356 QString(" (") + QString::fromStdString(address) + QString(")");
357 }
358 return description;
359}
360
361QString
363 switch (wtx->type) {
365 return tr("Received with");
367 return tr("Received from");
370 return tr("Sent to");
372 return tr("Payment to yourself");
374 return tr("Mined");
375 default:
376 return QString();
377 }
378}
379
380QVariant
382 switch (wtx->type) {
384 return QIcon(":/icons/tx_mined");
387 return QIcon(":/icons/tx_input");
390 return QIcon(":/icons/tx_output");
391 default:
392 return QIcon(":/icons/tx_inout");
393 }
394}
395
397 bool tooltip) const {
398 QString watchAddress;
399 if (tooltip) {
400 // Mark transactions involving watch-only addresses by adding "
401 // (watch-only)"
402 watchAddress = wtx->involvesWatchAddress
403 ? QString(" (") + tr("watch-only") + QString(")")
404 : "";
405 }
406
407 switch (wtx->type) {
409 return QString::fromStdString(wtx->address) + watchAddress;
413 return lookupAddress(wtx->address, tooltip) + watchAddress;
415 return QString::fromStdString(wtx->address) + watchAddress;
417 return lookupAddress(wtx->address, tooltip) + watchAddress;
418 default:
419 return tr("(n/a)") + watchAddress;
420 }
421}
422
423QVariant
425 // Show addresses without label in a less visible color
426 switch (wtx->type) {
430 QString label =
432 QString::fromStdString(wtx->address));
433 if (label.isEmpty()) {
434 return COLOR_BAREADDRESS;
435 }
436 } break;
438 return COLOR_BAREADDRESS;
439 default:
440 break;
441 }
442 return QVariant();
443}
444
446 const TransactionRecord *wtx, bool showUnconfirmed,
447 BitcoinUnits::SeparatorStyle separators) const {
448 QString str =
450 wtx->credit + wtx->debit, false, separators);
451 if (showUnconfirmed) {
452 if (!wtx->status.countsForBalance) {
453 str = QString("[") + str + QString("]");
454 }
455 }
456 return QString(str);
457}
458
459QVariant
461 switch (wtx->status.status) {
463 return QIcon(":/icons/transaction_0");
465 return QIcon(":/icons/transaction_abandoned");
467 switch (wtx->status.depth) {
468 case 1:
469 return QIcon(":/icons/transaction_1");
470 case 2:
471 return QIcon(":/icons/transaction_2");
472 case 3:
473 return QIcon(":/icons/transaction_3");
474 case 4:
475 return QIcon(":/icons/transaction_4");
476 default:
477 return QIcon(":/icons/transaction_5");
478 };
480 return QIcon(":/icons/transaction_confirmed");
482 return QIcon(":/icons/transaction_conflicted");
484 int total = wtx->status.depth + wtx->status.matures_in;
485 int part = (wtx->status.depth * 4 / total) + 1;
486 return QIcon(QString(":/icons/transaction_%1").arg(part));
487 }
489 return QIcon(":/icons/transaction_0");
490 default:
491 return COLOR_BLACK;
492 }
493}
494
496 const TransactionRecord *wtx) const {
497 if (wtx->involvesWatchAddress) {
498 return QIcon(":/icons/eye");
499 }
500
501 return QVariant();
502}
503
504QString
506 QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
511 tooltip += QString(" ") + formatTxToAddress(rec, true);
512 }
513 return tooltip;
514}
515
516QVariant TransactionTableModel::data(const QModelIndex &index, int role) const {
517 if (!index.isValid()) {
518 return QVariant();
519 }
520
521 TransactionRecord *rec =
522 static_cast<TransactionRecord *>(index.internalPointer());
523
524 switch (role) {
526 switch (index.column()) {
527 case Status:
528 return txStatusDecoration(rec);
529 case Watchonly:
530 return txWatchonlyDecoration(rec);
531 case ToAddress:
532 return txAddressDecoration(rec);
533 }
534 break;
535 case Qt::DecorationRole: {
536 QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
537 return platformStyle->TextColorIcon(icon);
538 }
539 case Qt::DisplayRole:
540 switch (index.column()) {
541 case Date:
542 return formatTxDate(rec);
543 case Type:
544 return formatTxType(rec);
545 case ToAddress:
546 return formatTxToAddress(rec, false);
547 case Amount:
548 return formatTxAmount(rec, true,
550 }
551 break;
552 case Qt::EditRole:
553 // Edit role is used for sorting, so return the unformatted values
554 switch (index.column()) {
555 case Status:
556 return QString::fromStdString(rec->status.sortKey);
557 case Date:
558 return rec->time;
559 case Type:
560 return formatTxType(rec);
561 case Watchonly:
562 return (rec->involvesWatchAddress ? 1 : 0);
563 case ToAddress:
564 return formatTxToAddress(rec, true);
565 case Amount:
566 return qint64((rec->credit + rec->debit) / SATOSHI);
567 }
568 break;
569 case Qt::ToolTipRole:
570 return formatTooltip(rec);
571 case Qt::TextAlignmentRole:
572 return column_alignments[index.column()];
573 case Qt::ForegroundRole:
574 // Use the "danger" color for abandoned transactions
577 }
578 // Non-confirmed (but not immature) as transactions are grey
579 if (!rec->status.countsForBalance &&
581 return COLOR_UNCONFIRMED;
582 }
583 if (index.column() == Amount &&
584 (rec->credit + rec->debit) < ::Amount::zero()) {
585 return COLOR_NEGATIVE;
586 }
587 if (index.column() == ToAddress) {
588 return addressColor(rec);
589 }
590 break;
591 case TypeRole:
592 return rec->type;
593 case DateRole:
594 return QDateTime::fromSecsSinceEpoch(rec->time);
595 case WatchonlyRole:
596 return rec->involvesWatchAddress;
598 return txWatchonlyDecoration(rec);
600 return priv->describe(
603 case AddressRole:
604 return QString::fromStdString(rec->address);
605 case LabelRole:
607 QString::fromStdString(rec->address));
608 case AmountRole:
609 return qint64((rec->credit + rec->debit) / SATOSHI);
610 case TxIDRole:
611 return rec->getTxID();
612 case TxHashRole:
613 return QString::fromStdString(rec->txid.ToString());
614 case TxHexRole:
615 return priv->getTxHex(walletModel->wallet(), rec);
616 case TxPlainTextRole: {
617 QString details;
618 QDateTime date = QDateTime::fromSecsSinceEpoch(rec->time);
619 QString txLabel =
621 QString::fromStdString(rec->address));
622
623 details.append(date.toString("M/d/yy HH:mm"));
624 details.append(" ");
625 details.append(formatTxStatus(rec));
626 details.append(". ");
627 if (!formatTxType(rec).isEmpty()) {
628 details.append(formatTxType(rec));
629 details.append(" ");
630 }
631 if (!rec->address.empty()) {
632 if (txLabel.isEmpty()) {
633 details.append(tr("(no label)") + " ");
634 } else {
635 details.append("(");
636 details.append(txLabel);
637 details.append(") ");
638 }
639 details.append(QString::fromStdString(rec->address));
640 details.append(" ");
641 }
642 details.append(formatTxAmount(rec, false,
644 return details;
645 }
646 case ConfirmedRole:
647 return rec->status.status ==
648 TransactionStatus::Status::Confirming ||
649 rec->status.status == TransactionStatus::Status::Confirmed;
651 // Used for copy/export, so don't include separators
652 return formatTxAmount(rec, false,
654 case StatusRole:
655 return rec->status.status;
656 }
657 return QVariant();
658}
659
661 Qt::Orientation orientation,
662 int role) const {
663 if (orientation == Qt::Horizontal) {
664 if (role == Qt::DisplayRole) {
665 return columns[section];
666 } else if (role == Qt::TextAlignmentRole) {
667 return column_alignments[section];
668 } else if (role == Qt::ToolTipRole) {
669 switch (section) {
670 case Status:
671 return tr("Transaction status. Hover over this field to "
672 "show number of confirmations.");
673 case Date:
674 return tr(
675 "Date and time that the transaction was received.");
676 case Type:
677 return tr("Type of transaction.");
678 case Watchonly:
679 return tr("Whether or not a watch-only address is involved "
680 "in this transaction.");
681 case ToAddress:
682 return tr(
683 "User-defined intent/purpose of the transaction.");
684 case Amount:
685 return tr("Amount removed from or added to balance.");
686 }
687 }
688 }
689 return QVariant();
690}
691
692QModelIndex TransactionTableModel::index(int row, int column,
693 const QModelIndex &parent) const {
694 Q_UNUSED(parent);
697 if (data) {
698 return createIndex(row, column, data);
699 }
700 return QModelIndex();
701}
702
704 // emit dataChanged to update Amount column with the current unit
706 Q_EMIT dataChanged(index(0, Amount), index(priv->size() - 1, Amount));
707}
708
710 ChangeType status) {
711 // Find transaction in wallet
712 // Determine whether to show transaction or not (determine this here so that
713 // no relocking is needed in GUI thread)
714 bool showTransaction = TransactionRecord::showTransaction();
715
716 TransactionNotification notification(txid, status, showTransaction);
717
719 vQueueNotifications.push_back(notification);
720 return;
721 }
722 notification.invoke(parent);
723}
724
725void TransactionTablePriv::ShowProgress(const std::string &title,
726 int nProgress) {
727 if (nProgress == 0) {
728 fQueueNotifications = true;
729 }
730
731 if (nProgress == 100) {
732 fQueueNotifications = false;
733 if (vQueueNotifications.size() > 10) {
734 // prevent balloon spam, show maximum 10 balloons
735 bool invoked = QMetaObject::invokeMethod(
736 parent, "setProcessingQueuedTransactions", Qt::QueuedConnection,
737 Q_ARG(bool, true));
738 assert(invoked);
739 }
740
741 for (size_t i = 0; i < vQueueNotifications.size(); ++i) {
742 if (vQueueNotifications.size() - i <= 10) {
743 bool invoked = QMetaObject::invokeMethod(
744 parent, "setProcessingQueuedTransactions",
745 Qt::QueuedConnection, Q_ARG(bool, false));
746 assert(invoked);
747 }
748
749 vQueueNotifications[i].invoke(parent);
750 }
751 vQueueNotifications.clear();
752 }
753}
754
756 // Connect signals to wallet
760 std::placeholders::_1, std::placeholders::_2));
763 std::placeholders::_1, std::placeholders::_2));
764}
765
767 // Disconnect signals from wallet
768 m_handler_transaction_changed->disconnect();
769 m_handler_show_progress->disconnect();
770}
static constexpr Amount SATOSHI
Definition: amount.h:143
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
static QString format(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
int getDisplayUnit() const
Definition: optionsmodel.h:97
void displayUnitChanged(int unit)
QIcon TextColorIcon(const QIcon &icon) const
Colorize an icon (given object) with the text color.
static QString toHTML(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
UI model for a transaction.
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
Decompose CWallet transaction to model transaction records.
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
static bool showTransaction()
Decompose CWallet transaction to model transaction records.
TransactionStatus status
Status: can change with block chain update.
void updateStatus(const interfaces::WalletTxStatus &wtx, const BlockHash &block_hash, int numBlocks, int64_t block_time)
Update status from core wallet tx.
bool statusUpdateNeeded(const BlockHash &block_hash) const
Return whether a status update is needed.
QString getTxID() const
Return the unique identifier for this transaction (part)
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
bool countsForBalance
Transaction counts towards available balance.
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ Unconfirmed
Normal (sent/received) transactions.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ Conflicted
Conflicts with other transaction or mempool.
@ Abandoned
Abandoned from the wallet.
std::string sortKey
Sorting key based on status.
UI model for the transaction table of a wallet.
QVariant txStatusDecoration(const TransactionRecord *wtx) 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 formatTooltip(const TransactionRecord *rec) const
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::SeparatorStyle::STANDARD) const
QVariant data(const QModelIndex &index, int role) const override
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
void updateTransaction(const QString &hash, int status, bool showTransaction)
New transaction, or transaction changed status.
QString formatTxStatus(const TransactionRecord *wtx) const
std::unique_ptr< interfaces::Handler > m_handler_transaction_changed
int columnCount(const QModelIndex &parent) const override
std::unique_ptr< interfaces::Handler > m_handler_show_progress
TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent=nullptr)
int rowCount(const QModelIndex &parent) const override
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
const PlatformStyle * platformStyle
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QString formatTxType(const TransactionRecord *wtx) const
QString lookupAddress(const std::string &address, bool tooltip) const
Look up address in address book, if found return label (address) otherwise just return (address)
QVariant txAddressDecoration(const TransactionRecord *wtx) const
QString formatTxDate(const TransactionRecord *wtx) const
QString getTxHex(interfaces::Wallet &wallet, TransactionRecord *rec)
void updateWallet(interfaces::Wallet &wallet, const TxId &txid, int status, bool showTransaction)
Update our model of the wallet incrementally, to synchronize our model of the wallet with that of the...
TransactionTablePriv(TransactionTableModel *_parent)
TransactionTableModel * parent
QList< TransactionRecord > cachedWallet
std::vector< TransactionNotification > vQueueNotifications
void refreshWallet(interfaces::Wallet &wallet)
Query entire wallet anew from core.
QString describe(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
void ShowProgress(const std::string &title, int nProgress)
void NotifyTransactionChanged(const TxId &txidc, ChangeType status)
TransactionRecord * index(interfaces::Wallet &wallet, const BlockHash &cur_block_hash, const int idx)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
interfaces::Node & node() const
Definition: walletmodel.h:149
BlockHash getLastBlockProcessed() const
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
void SetHex(const char *psz)
Definition: uint256.cpp:24
std::string ToString() const
Definition: uint256.h:80
bool IsNull() const
Definition: uint256.h:32
std::string GetHex() const
Definition: uint256.cpp:16
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:59
Interface for accessing a wallet.
Definition: wallet.h:60
virtual std::unique_ptr< Handler > handleShowProgress(ShowProgressFn fn)=0
virtual std::unique_ptr< Handler > handleTransactionChanged(TransactionChangedFn fn)=0
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:173
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:34
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:28
#define COLOR_NEGATIVE
Definition: guiconstants.h:30
#define COLOR_BLACK
Definition: guiconstants.h:36
#define COLOR_BAREADDRESS
Definition: guiconstants.h:32
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:83
Definition: init.h:31
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
TransactionNotification()=default
TransactionNotification(TxId _txid, ChangeType _status, bool _showTransaction)
A TxId is the identifier of a transaction.
Definition: txid.h:14
bool operator()(const TransactionRecord &a, const TxId &b) const
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
bool operator()(const TxId &a, const TransactionRecord &b) const
CTransactionRef tx
Definition: wallet.h:376
Updated transaction status.
Definition: wallet.h:390
static int column_alignments[]
ChangeType
General change type (added, updated, removed).
Definition: ui_change_type.h:9
@ CT_UPDATED
Definition: ui_change_type.h:9
@ CT_DELETED
Definition: ui_change_type.h:9
@ CT_NEW
Definition: ui_change_type.h:9
assert(!tx.IsCoinBase())