Bitcoin Core 28.99.0
P2P Digital Currency
transactiontablemodel.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2022 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
8#include <qt/bitcoinunits.h>
9#include <qt/clientmodel.h>
10#include <qt/guiconstants.h>
11#include <qt/guiutil.h>
12#include <qt/optionsmodel.h>
13#include <qt/platformstyle.h>
14#include <qt/transactiondesc.h>
16#include <qt/walletmodel.h>
17
18#include <core_io.h>
19#include <interfaces/handler.h>
20#include <tinyformat.h>
21#include <uint256.h>
22
23#include <algorithm>
24#include <functional>
25
26#include <QColor>
27#include <QDateTime>
28#include <QDebug>
29#include <QIcon>
30#include <QLatin1Char>
31#include <QLatin1String>
32#include <QList>
33
34
35// Amount column is right-aligned it contains numbers
36static int column_alignments[] = {
37 Qt::AlignLeft|Qt::AlignVCenter, /*status=*/
38 Qt::AlignLeft|Qt::AlignVCenter, /*watchonly=*/
39 Qt::AlignLeft|Qt::AlignVCenter, /*date=*/
40 Qt::AlignLeft|Qt::AlignVCenter, /*type=*/
41 Qt::AlignLeft|Qt::AlignVCenter, /*address=*/
42 Qt::AlignRight|Qt::AlignVCenter /* amount */
43 };
44
45// Comparison operator for sort/binary search of model tx list
47{
48 bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
49 {
50 return a.hash < b.hash;
51 }
52 bool operator()(const TransactionRecord &a, const uint256 &b) const
53 {
54 return a.hash < b;
55 }
56 bool operator()(const uint256 &a, const TransactionRecord &b) const
57 {
58 return a < b.hash;
59 }
60};
61
62// queue notifications to show a non freezing progress dialog e.g. for rescan
64{
65public:
67 TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
68 hash(_hash), status(_status), showTransaction(_showTransaction) {}
69
70 void invoke(QObject *ttm)
71 {
72 QString strHash = QString::fromStdString(hash.GetHex());
73 qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
74 bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
75 Q_ARG(QString, strHash),
76 Q_ARG(int, status),
77 Q_ARG(bool, showTransaction));
78 assert(invoked);
79 }
80private:
84};
85
86// Private implementation
88{
89public:
91 parent(_parent)
92 {
93 }
94
96
98 QList<TransactionRecord> cachedWallet;
99
101 bool m_loaded = false;
103 bool m_loading = false;
104 std::vector< TransactionNotification > vQueueNotifications;
105
106 void NotifyTransactionChanged(const uint256 &hash, ChangeType status);
108
109 /* Query entire wallet anew from core.
110 */
112 {
114 {
115 for (const auto& wtx : wallet.getWalletTxs()) {
118 }
119 }
120 }
121 m_loaded = true;
123 }
124
125 /* Update our model of the wallet incrementally, to synchronize our model of the wallet
126 with that of the core.
127
128 Call with transaction that was added, removed or changed.
129 */
130 void updateWallet(interfaces::Wallet& wallet, const uint256 &hash, int status, bool showTransaction)
131 {
132 qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
133
134 // Find bounds of this transaction in model
135 QList<TransactionRecord>::iterator lower = std::lower_bound(
136 cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
137 QList<TransactionRecord>::iterator upper = std::upper_bound(
138 cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
139 int lowerIndex = (lower - cachedWallet.begin());
140 int upperIndex = (upper - cachedWallet.begin());
141 bool inModel = (lower != upper);
142
143 if(status == CT_UPDATED)
144 {
145 if(showTransaction && !inModel)
146 status = CT_NEW; /* Not in model, but want to show, treat as new */
147 if(!showTransaction && inModel)
148 status = CT_DELETED; /* In model, but want to hide, treat as deleted */
149 }
150
151 qDebug() << " inModel=" + QString::number(inModel) +
152 " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
153 " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
154
155 switch(status)
156 {
157 case CT_NEW:
158 if(inModel)
159 {
160 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
161 break;
162 }
163 if(showTransaction)
164 {
165 // Find transaction in wallet
166 interfaces::WalletTx wtx = wallet.getWalletTx(hash);
167 if(!wtx.tx)
168 {
169 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
170 break;
171 }
172 // Added -- insert at the right position
173 QList<TransactionRecord> toInsert =
175 if(!toInsert.isEmpty()) /* only if something to insert */
176 {
177 parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
178 int insert_idx = lowerIndex;
179 for (const TransactionRecord &rec : toInsert)
180 {
181 cachedWallet.insert(insert_idx, rec);
182 insert_idx += 1;
183 }
184 parent->endInsertRows();
185 }
186 }
187 break;
188 case CT_DELETED:
189 if(!inModel)
190 {
191 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
192 break;
193 }
194 // Removed -- remove entire transaction from table
195 parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
196 cachedWallet.erase(lower, upper);
197 parent->endRemoveRows();
198 break;
199 case CT_UPDATED:
200 // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
201 // visible transactions.
202 for (int i = lowerIndex; i < upperIndex; i++) {
204 rec->status.needsUpdate = true;
205 }
206 break;
207 }
208 }
209
210 int size()
211 {
212 return cachedWallet.size();
213 }
214
215 TransactionRecord* index(interfaces::Wallet& wallet, const uint256& cur_block_hash, const int idx)
216 {
217 if (idx >= 0 && idx < cachedWallet.size()) {
218 TransactionRecord *rec = &cachedWallet[idx];
219
220 // If a status update is needed (blocks came in since last check),
221 // try to update the status of this transaction from the wallet.
222 // Otherwise, simply reuse the cached status.
224 int numBlocks;
225 int64_t block_time;
226 if (!cur_block_hash.IsNull() && rec->statusUpdateNeeded(cur_block_hash) && wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time)) {
227 rec->updateStatus(wtx, cur_block_hash, numBlocks, block_time);
228 }
229 return rec;
230 }
231 return nullptr;
232 }
233
235 {
236 return TransactionDesc::toHTML(node, wallet, rec, unit);
237 }
238
240 {
241 auto tx = wallet.getTx(rec->hash);
242 if (tx) {
243 std::string strHex = EncodeHexTx(*tx);
244 return QString::fromStdString(strHex);
245 }
246 return QString();
247 }
248};
249
251 QAbstractTableModel(parent),
252 walletModel(parent),
253 priv(new TransactionTablePriv(this)),
254 platformStyle(_platformStyle)
255{
257
258 columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
260
262}
263
265{
267 delete priv;
268}
269
272{
274 Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
275}
276
277void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
278{
279 uint256 updated;
280 updated.SetHexDeprecated(hash.toStdString());
281
282 priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
283}
284
286{
287 // Blocks came in since last poll.
288 // Invalidate status (number of confirmations) and (possibly) description
289 // for all rows. Qt is smart enough to only actually request the data for the
290 // visible rows.
291 Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
292 Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
293}
294
295int TransactionTableModel::rowCount(const QModelIndex &parent) const
296{
297 if (parent.isValid()) {
298 return 0;
299 }
300 return priv->size();
301}
302
303int TransactionTableModel::columnCount(const QModelIndex &parent) const
304{
305 if (parent.isValid()) {
306 return 0;
307 }
308 return columns.length();
309}
310
312{
313 QString status;
314
315 switch(wtx->status.status)
316 {
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("Generated but not accepted");
337 break;
338 }
339
340 return status;
341}
342
344{
345 if(wtx->time)
346 {
347 return GUIUtil::dateTimeStr(wtx->time);
348 }
349 return QString();
350}
351
352/* Look up address in address book, if found return label (address)
353 otherwise just return (address)
354 */
355QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
356{
357 QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
358 QString description;
359 if(!label.isEmpty())
360 {
361 description += label;
362 }
363 if(label.isEmpty() || tooltip)
364 {
365 description += QString(" (") + QString::fromStdString(address) + QString(")");
366 }
367 return description;
368}
369
371{
372 switch(wtx->type)
373 {
375 return tr("Received with");
377 return tr("Received from");
380 return tr("Sent to");
382 return tr("Mined");
383 default:
384 return QString();
385 }
386}
387
389{
390 switch(wtx->type)
391 {
393 return QIcon(":/icons/tx_mined");
396 return QIcon(":/icons/tx_input");
399 return QIcon(":/icons/tx_output");
400 default:
401 return QIcon(":/icons/tx_inout");
402 }
403}
404
405QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
406{
407 QString watchAddress;
408 if (tooltip && wtx->involvesWatchAddress) {
409 // Mark transactions involving watch-only addresses by adding " (watch-only)"
410 watchAddress = QLatin1String(" (") + tr("watch-only") + QLatin1Char(')');
411 }
412
413 switch(wtx->type)
414 {
416 return QString::fromStdString(wtx->address) + watchAddress;
420 return lookupAddress(wtx->address, tooltip) + watchAddress;
422 return QString::fromStdString(wtx->address) + watchAddress;
423 default:
424 return tr("(n/a)") + watchAddress;
425 }
426}
427
429{
430 // Show addresses without label in a less visible color
431 switch(wtx->type)
432 {
436 {
437 QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
438 if(label.isEmpty())
439 return COLOR_BAREADDRESS;
440 } break;
441 default:
442 break;
443 }
444 return QVariant();
445}
446
447QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
448{
449 QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
450 if(showUnconfirmed)
451 {
452 if(!wtx->status.countsForBalance)
453 {
454 str = QString("[") + str + QString("]");
455 }
456 }
457 return QString(str);
458}
459
461{
462 switch(wtx->status.status)
463 {
465 return QIcon(":/icons/transaction_0");
467 return QIcon(":/icons/transaction_abandoned");
469 switch(wtx->status.depth)
470 {
471 case 1: return QIcon(":/icons/transaction_1");
472 case 2: return QIcon(":/icons/transaction_2");
473 case 3: return QIcon(":/icons/transaction_3");
474 case 4: return QIcon(":/icons/transaction_4");
475 default: return QIcon(":/icons/transaction_5");
476 };
478 return QIcon(":/icons/transaction_confirmed");
480 return QIcon(":/icons/transaction_conflicted");
482 int total = wtx->status.depth + wtx->status.matures_in;
483 int part = (wtx->status.depth * 4 / total) + 1;
484 return QIcon(QString(":/icons/transaction_%1").arg(part));
485 }
487 return QIcon(":/icons/transaction_0");
488 default:
489 return COLOR_BLACK;
490 }
491}
492
494{
495 if (wtx->involvesWatchAddress)
496 return QIcon(":/icons/eye");
497 else
498 return QVariant();
499}
500
502{
503 QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
506 {
507 tooltip += QString(" ") + formatTxToAddress(rec, true);
508 }
509 return tooltip;
510}
511
512QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
513{
514 if(!index.isValid())
515 return QVariant();
516 TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
517
518 const auto column = static_cast<ColumnIndex>(index.column());
519 switch (role) {
521 switch (column) {
522 case Status:
523 return txStatusDecoration(rec);
524 case Watchonly:
525 return txWatchonlyDecoration(rec);
526 case Date: return {};
527 case Type: return {};
528 case ToAddress:
529 return txAddressDecoration(rec);
530 case Amount: return {};
531 } // no default case, so the compiler can warn about missing cases
532 assert(false);
533 case Qt::DecorationRole:
534 {
535 QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
536 return platformStyle->TextColorIcon(icon);
537 }
538 case Qt::DisplayRole:
539 switch (column) {
540 case Status: return {};
541 case Watchonly: return {};
542 case Date:
543 return formatTxDate(rec);
544 case Type:
545 return formatTxType(rec);
546 case ToAddress:
547 return formatTxToAddress(rec, false);
548 case Amount:
550 } // no default case, so the compiler can warn about missing cases
551 assert(false);
552 case Qt::EditRole:
553 // Edit role is used for sorting, so return the unformatted values
554 switch (column) {
555 case Status:
556 return QString::fromStdString(rec->status.sortKey);
557 case Date:
558 return QString::fromStdString(strprintf("%020s-%s", rec->time, rec->status.sortKey));
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);
567 } // no default case, so the compiler can warn about missing cases
568 assert(false);
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
576 {
578 }
579 // Non-confirmed (but not immature) as transactions are grey
581 {
582 return COLOR_UNCONFIRMED;
583 }
584 if(index.column() == Amount && (rec->credit+rec->debit) < 0)
585 {
586 return COLOR_NEGATIVE;
587 }
588 if(index.column() == ToAddress)
589 {
590 return addressColor(rec);
591 }
592 break;
593 case TypeRole:
594 return rec->type;
595 case DateRole:
596 return QDateTime::fromSecsSinceEpoch(rec->time);
597 case WatchonlyRole:
598 return rec->involvesWatchAddress;
600 return txWatchonlyDecoration(rec);
603 case AddressRole:
604 return QString::fromStdString(rec->address);
605 case LabelRole:
606 return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
607 case AmountRole:
608 return qint64(rec->credit + rec->debit);
609 case TxHashRole:
610 return rec->getTxHash();
611 case TxHexRole:
612 return priv->getTxHex(walletModel->wallet(), rec);
613 case TxPlainTextRole:
614 {
615 QString details;
616 QDateTime date = QDateTime::fromSecsSinceEpoch(rec->time);
617 QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
618
619 details.append(date.toString("M/d/yy HH:mm"));
620 details.append(" ");
621 details.append(formatTxStatus(rec));
622 details.append(". ");
623 if(!formatTxType(rec).isEmpty()) {
624 details.append(formatTxType(rec));
625 details.append(" ");
626 }
627 if(!rec->address.empty()) {
628 if(txLabel.isEmpty())
629 details.append(tr("(no label)") + " ");
630 else {
631 details.append("(");
632 details.append(txLabel);
633 details.append(") ");
634 }
635 details.append(QString::fromStdString(rec->address));
636 details.append(" ");
637 }
638 details.append(formatTxAmount(rec, false, BitcoinUnits::SeparatorStyle::NEVER));
639 return details;
640 }
641 case ConfirmedRole:
642 return rec->status.status == TransactionStatus::Status::Confirming || rec->status.status == TransactionStatus::Status::Confirmed;
644 // Used for copy/export, so don't include separators
646 case StatusRole:
647 return rec->status.status;
648 }
649 return QVariant();
650}
651
652QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
653{
654 if(orientation == Qt::Horizontal)
655 {
656 if(role == Qt::DisplayRole)
657 {
658 return columns[section];
659 }
660 else if (role == Qt::TextAlignmentRole)
661 {
662 return column_alignments[section];
663 } else if (role == Qt::ToolTipRole)
664 {
665 switch(section)
666 {
667 case Status:
668 return tr("Transaction status. Hover over this field to show number of confirmations.");
669 case Date:
670 return tr("Date and time that the transaction was received.");
671 case Type:
672 return tr("Type of transaction.");
673 case Watchonly:
674 return tr("Whether or not a watch-only address is involved in this transaction.");
675 case ToAddress:
676 return tr("User-defined intent/purpose of the transaction.");
677 case Amount:
678 return tr("Amount removed from or added to balance.");
679 }
680 }
681 }
682 return QVariant();
683}
684
685QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
686{
687 Q_UNUSED(parent);
689 if(data)
690 {
691 return createIndex(row, column, data);
692 }
693 return QModelIndex();
694}
695
697{
698 // emit dataChanged to update Amount column with the current unit
700 Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
701}
702
704{
705 // Find transaction in wallet
706 // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
707 bool showTransaction = TransactionRecord::showTransaction();
708
709 TransactionNotification notification(hash, status, showTransaction);
710
711 if (!m_loaded || m_loading)
712 {
713 vQueueNotifications.push_back(notification);
714 return;
715 }
716 notification.invoke(parent);
717}
718
720{
721 if (!m_loaded || m_loading) return;
722
723 if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
724 bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
725 assert(invoked);
726 }
727 for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
728 {
729 if (vQueueNotifications.size() - i <= 10) {
730 bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
731 assert(invoked);
732 }
733
734 vQueueNotifications[i].invoke(parent);
735 }
736 vQueueNotifications.clear();
737}
738
740{
741 // Connect signals to wallet
743 m_handler_show_progress = walletModel->wallet().handleShowProgress([this](const std::string&, int progress) {
744 priv->m_loading = progress < 100;
746 });
747}
748
750{
751 // Disconnect signals from wallet
752 m_handler_transaction_changed->disconnect();
753 m_handler_show_progress->disconnect();
754}
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
static QString format(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
static QString getAmountColumnTitle(Unit unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
Unit
Bitcoin units.
Definition: bitcoinunits.h:42
void displayUnitChanged(BitcoinUnit unit)
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
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, BitcoinUnit unit)
UI model for a transaction.
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
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.
QString getTxHash() const
Return the unique identifier for this transaction (part)
bool statusUpdateNeeded(const uint256 &block_hash) const
Return whether a status update is needed.
void updateStatus(const interfaces::WalletTxStatus &wtx, const uint256 &block_hash, int numBlocks, int64_t block_time)
Update status from core wallet tx.
bool involvesWatchAddress
Whether the transaction was sent/received with a watch-only address.
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.
@ 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)
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
QVariant txAddressDecoration(const TransactionRecord *wtx) const
QString formatTxDate(const TransactionRecord *wtx) const
QString getTxHex(interfaces::Wallet &wallet, TransactionRecord *rec)
TransactionTablePriv(TransactionTableModel *_parent)
TransactionTableModel * parent
QList< TransactionRecord > cachedWallet
Local cache of wallet sorted by transaction hash.
void refreshWallet(interfaces::Wallet &wallet)
bool m_loading
True when transactions are being notified, for instance when scanning.
void NotifyTransactionChanged(const uint256 &hash, ChangeType status)
void updateWallet(interfaces::Wallet &wallet, const uint256 &hash, int status, bool showTransaction)
TransactionRecord * index(interfaces::Wallet &wallet, const uint256 &cur_block_hash, const int idx)
std::vector< TransactionNotification > vQueueNotifications
QString describe(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, BitcoinUnit unit)
bool m_loaded
True when model finishes loading all wallet transactions on start.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:48
interfaces::Node & node() const
Definition: walletmodel.h:137
AddressTableModel * getAddressTableModel() const
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
OptionsModel * getOptionsModel() const
uint256 getLastBlockProcessed() const
constexpr bool IsNull() const
Definition: uint256.h:48
std::string ToString() const
Definition: uint256.cpp:47
void SetHexDeprecated(std::string_view str)
Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated!
Definition: uint256.cpp:21
std::string GetHex() const
Definition: uint256.cpp:11
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:71
Interface for accessing a wallet.
Definition: wallet.h:66
virtual std::unique_ptr< Handler > handleShowProgress(ShowProgressFn fn)=0
virtual std::unique_ptr< Handler > handleTransactionChanged(TransactionChangedFn fn)=0
256-bit opaque blob.
Definition: uint256.h:190
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:143
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:37
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:31
#define COLOR_NEGATIVE
Definition: guiconstants.h:33
#define COLOR_BLACK
Definition: guiconstants.h:39
#define COLOR_BAREADDRESS
Definition: guiconstants.h:35
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:90
Definition: messages.h:20
TransactionNotification()=default
TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction)
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.
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
bool operator()(const TransactionRecord &a, const uint256 &b) const
bool operator()(const uint256 &a, const TransactionRecord &b) const
CTransactionRef tx
Definition: wallet.h:401
Updated transaction status.
Definition: wallet.h:419
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1165
static int column_alignments[]
ChangeType
General change type (added, updated, removed).
Definition: ui_change_type.h:9
@ CT_UPDATED
@ CT_DELETED
@ CT_NEW
assert(!tx.IsCoinBase())