Bitcoin Core 22.99.0
P2P Digital Currency
transactiontablemodel.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2020 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/clientmodel.h>
9#include <qt/guiconstants.h>
10#include <qt/guiutil.h>
11#include <qt/optionsmodel.h>
12#include <qt/platformstyle.h>
13#include <qt/transactiondesc.h>
15#include <qt/walletmodel.h>
16
17#include <core_io.h>
18#include <interfaces/handler.h>
19#include <uint256.h>
20
21#include <algorithm>
22#include <functional>
23
24#include <QColor>
25#include <QDateTime>
26#include <QDebug>
27#include <QIcon>
28#include <QLatin1Char>
29#include <QLatin1String>
30#include <QList>
31
32
33// Amount column is right-aligned it contains numbers
34static int column_alignments[] = {
35 Qt::AlignLeft|Qt::AlignVCenter, /* status */
36 Qt::AlignLeft|Qt::AlignVCenter, /* watchonly */
37 Qt::AlignLeft|Qt::AlignVCenter, /* date */
38 Qt::AlignLeft|Qt::AlignVCenter, /* type */
39 Qt::AlignLeft|Qt::AlignVCenter, /* address */
40 Qt::AlignRight|Qt::AlignVCenter /* amount */
41 };
42
43// Comparison operator for sort/binary search of model tx list
45{
46 bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
47 {
48 return a.hash < b.hash;
49 }
50 bool operator()(const TransactionRecord &a, const uint256 &b) const
51 {
52 return a.hash < b;
53 }
54 bool operator()(const uint256 &a, const TransactionRecord &b) const
55 {
56 return a < b.hash;
57 }
58};
59
60// queue notifications to show a non freezing progress dialog e.g. for rescan
62{
63public:
65 TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
66 hash(_hash), status(_status), showTransaction(_showTransaction) {}
67
68 void invoke(QObject *ttm)
69 {
70 QString strHash = QString::fromStdString(hash.GetHex());
71 qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
72 bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
73 Q_ARG(QString, strHash),
74 Q_ARG(int, status),
75 Q_ARG(bool, showTransaction));
76 assert(invoked);
77 }
78private:
82};
83
84// Private implementation
86{
87public:
89 parent(_parent)
90 {
91 }
92
94
95 /* Local cache of wallet.
96 * As it is in the same order as the CWallet, by definition
97 * this is sorted by sha256.
98 */
99 QList<TransactionRecord> cachedWallet;
100
102 bool m_loaded = false;
104 bool m_loading = false;
105 std::vector< TransactionNotification > vQueueNotifications;
106
107 void NotifyTransactionChanged(const uint256 &hash, ChangeType status);
109
110 /* Query entire wallet anew from core.
111 */
113 {
115 {
116 for (const auto& wtx : wallet.getWalletTxs()) {
119 }
120 }
121 }
122 m_loaded = true;
124 }
125
126 /* Update our model of the wallet incrementally, to synchronize our model of the wallet
127 with that of the core.
128
129 Call with transaction that was added, removed or changed.
130 */
131 void updateWallet(interfaces::Wallet& wallet, const uint256 &hash, int status, bool showTransaction)
132 {
133 qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
134
135 // Find bounds of this transaction in model
136 QList<TransactionRecord>::iterator lower = std::lower_bound(
137 cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
138 QList<TransactionRecord>::iterator upper = std::upper_bound(
139 cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
140 int lowerIndex = (lower - cachedWallet.begin());
141 int upperIndex = (upper - cachedWallet.begin());
142 bool inModel = (lower != upper);
143
144 if(status == CT_UPDATED)
145 {
146 if(showTransaction && !inModel)
147 status = CT_NEW; /* Not in model, but want to show, treat as new */
148 if(!showTransaction && inModel)
149 status = CT_DELETED; /* In model, but want to hide, treat as deleted */
150 }
151
152 qDebug() << " inModel=" + QString::number(inModel) +
153 " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
154 " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
155
156 switch(status)
157 {
158 case CT_NEW:
159 if(inModel)
160 {
161 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
162 break;
163 }
164 if(showTransaction)
165 {
166 // Find transaction in wallet
167 interfaces::WalletTx wtx = wallet.getWalletTx(hash);
168 if(!wtx.tx)
169 {
170 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
171 break;
172 }
173 // Added -- insert at the right position
174 QList<TransactionRecord> toInsert =
176 if(!toInsert.isEmpty()) /* only if something to insert */
177 {
178 parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
179 int insert_idx = lowerIndex;
180 for (const TransactionRecord &rec : toInsert)
181 {
182 cachedWallet.insert(insert_idx, rec);
183 insert_idx += 1;
184 }
185 parent->endInsertRows();
186 }
187 }
188 break;
189 case CT_DELETED:
190 if(!inModel)
191 {
192 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
193 break;
194 }
195 // Removed -- remove entire transaction from table
196 parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
197 cachedWallet.erase(lower, upper);
198 parent->endRemoveRows();
199 break;
200 case CT_UPDATED:
201 // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
202 // visible transactions.
203 for (int i = lowerIndex; i < upperIndex; i++) {
205 rec->status.needsUpdate = true;
206 }
207 break;
208 }
209 }
210
211 int size()
212 {
213 return cachedWallet.size();
214 }
215
216 TransactionRecord* index(interfaces::Wallet& wallet, const uint256& cur_block_hash, const int idx)
217 {
218 if (idx >= 0 && idx < cachedWallet.size()) {
219 TransactionRecord *rec = &cachedWallet[idx];
220
221 // If a status update is needed (blocks came in since last check),
222 // try to update the status of this transaction from the wallet.
223 // Otherwise, simply re-use the cached status.
225 int numBlocks;
226 int64_t block_time;
227 if (!cur_block_hash.IsNull() && rec->statusUpdateNeeded(cur_block_hash) && wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time)) {
228 rec->updateStatus(wtx, cur_block_hash, numBlocks, block_time);
229 }
230 return rec;
231 }
232 return nullptr;
233 }
234
236 {
237 return TransactionDesc::toHTML(node, wallet, rec, unit);
238 }
239
241 {
242 auto tx = wallet.getTx(rec->hash);
243 if (tx) {
244 std::string strHex = EncodeHexTx(*tx);
245 return QString::fromStdString(strHex);
246 }
247 return QString();
248 }
249};
250
252 QAbstractTableModel(parent),
253 walletModel(parent),
254 priv(new TransactionTablePriv(this)),
255 fProcessingQueuedTransactions(false),
256 platformStyle(_platformStyle)
257{
259
260 columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
262
264}
265
267{
269 delete priv;
270}
271
274{
276 Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
277}
278
279void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
280{
281 uint256 updated;
282 updated.SetHex(hash.toStdString());
283
284 priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
285}
286
288{
289 // Blocks came in since last poll.
290 // Invalidate status (number of confirmations) and (possibly) description
291 // for all rows. Qt is smart enough to only actually request the data for the
292 // visible rows.
293 Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
294 Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
295}
296
297int TransactionTableModel::rowCount(const QModelIndex &parent) const
298{
299 if (parent.isValid()) {
300 return 0;
301 }
302 return priv->size();
303}
304
305int TransactionTableModel::columnCount(const QModelIndex &parent) const
306{
307 if (parent.isValid()) {
308 return 0;
309 }
310 return columns.length();
311}
312
314{
315 QString status;
316
317 switch(wtx->status.status)
318 {
320 status = tr("Open for %n more block(s)","",wtx->status.open_for);
321 break;
323 status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
324 break;
326 status = tr("Unconfirmed");
327 break;
329 status = tr("Abandoned");
330 break;
332 status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
333 break;
335 status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
336 break;
338 status = tr("Conflicted");
339 break;
341 status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
342 break;
344 status = tr("Generated but not accepted");
345 break;
346 }
347
348 return status;
349}
350
352{
353 if(wtx->time)
354 {
355 return GUIUtil::dateTimeStr(wtx->time);
356 }
357 return QString();
358}
359
360/* Look up address in address book, if found return label (address)
361 otherwise just return (address)
362 */
363QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
364{
365 QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
366 QString description;
367 if(!label.isEmpty())
368 {
369 description += label;
370 }
371 if(label.isEmpty() || tooltip)
372 {
373 description += QString(" (") + QString::fromStdString(address) + QString(")");
374 }
375 return description;
376}
377
379{
380 switch(wtx->type)
381 {
383 return tr("Received with");
385 return tr("Received from");
388 return tr("Sent to");
390 return tr("Payment to yourself");
392 return tr("Mined");
393 default:
394 return QString();
395 }
396}
397
399{
400 switch(wtx->type)
401 {
403 return QIcon(":/icons/tx_mined");
406 return QIcon(":/icons/tx_input");
409 return QIcon(":/icons/tx_output");
410 default:
411 return QIcon(":/icons/tx_inout");
412 }
413}
414
415QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
416{
417 QString watchAddress;
418 if (tooltip && wtx->involvesWatchAddress) {
419 // Mark transactions involving watch-only addresses by adding " (watch-only)"
420 watchAddress = QLatin1String(" (") + tr("watch-only") + QLatin1Char(')');
421 }
422
423 switch(wtx->type)
424 {
426 return QString::fromStdString(wtx->address) + watchAddress;
430 return lookupAddress(wtx->address, tooltip) + watchAddress;
432 return QString::fromStdString(wtx->address) + watchAddress;
434 return lookupAddress(wtx->address, tooltip) + watchAddress;
435 default:
436 return tr("(n/a)") + watchAddress;
437 }
438}
439
441{
442 // Show addresses without label in a less visible color
443 switch(wtx->type)
444 {
448 {
449 QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
450 if(label.isEmpty())
451 return COLOR_BAREADDRESS;
452 } break;
454 return COLOR_BAREADDRESS;
455 default:
456 break;
457 }
458 return QVariant();
459}
460
461QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
462{
463 QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
464 if(showUnconfirmed)
465 {
466 if(!wtx->status.countsForBalance)
467 {
468 str = QString("[") + str + QString("]");
469 }
470 }
471 return QString(str);
472}
473
475{
476 switch(wtx->status.status)
477 {
482 return QIcon(":/icons/transaction_0");
484 return QIcon(":/icons/transaction_abandoned");
486 switch(wtx->status.depth)
487 {
488 case 1: return QIcon(":/icons/transaction_1");
489 case 2: return QIcon(":/icons/transaction_2");
490 case 3: return QIcon(":/icons/transaction_3");
491 case 4: return QIcon(":/icons/transaction_4");
492 default: return QIcon(":/icons/transaction_5");
493 };
495 return QIcon(":/icons/transaction_confirmed");
497 return QIcon(":/icons/transaction_conflicted");
499 int total = wtx->status.depth + wtx->status.matures_in;
500 int part = (wtx->status.depth * 4 / total) + 1;
501 return QIcon(QString(":/icons/transaction_%1").arg(part));
502 }
504 return QIcon(":/icons/transaction_0");
505 default:
506 return COLOR_BLACK;
507 }
508}
509
511{
512 if (wtx->involvesWatchAddress)
513 return QIcon(":/icons/eye");
514 else
515 return QVariant();
516}
517
519{
520 QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
523 {
524 tooltip += QString(" ") + formatTxToAddress(rec, true);
525 }
526 return tooltip;
527}
528
529QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
530{
531 if(!index.isValid())
532 return QVariant();
533 TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
534
535 const auto column = static_cast<ColumnIndex>(index.column());
536 switch (role) {
538 switch (column) {
539 case Status:
540 return txStatusDecoration(rec);
541 case Watchonly:
542 return txWatchonlyDecoration(rec);
543 case Date: return {};
544 case Type: return {};
545 case ToAddress:
546 return txAddressDecoration(rec);
547 case Amount: return {};
548 } // no default case, so the compiler can warn about missing cases
549 assert(false);
550 case Qt::DecorationRole:
551 {
552 QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
553 return platformStyle->TextColorIcon(icon);
554 }
555 case Qt::DisplayRole:
556 switch (column) {
557 case Status: return {};
558 case Watchonly: return {};
559 case Date:
560 return formatTxDate(rec);
561 case Type:
562 return formatTxType(rec);
563 case ToAddress:
564 return formatTxToAddress(rec, false);
565 case Amount:
567 } // no default case, so the compiler can warn about missing cases
568 assert(false);
569 case Qt::EditRole:
570 // Edit role is used for sorting, so return the unformatted values
571 switch (column) {
572 case Status:
573 return QString::fromStdString(rec->status.sortKey);
574 case Date:
575 return rec->time;
576 case Type:
577 return formatTxType(rec);
578 case Watchonly:
579 return (rec->involvesWatchAddress ? 1 : 0);
580 case ToAddress:
581 return formatTxToAddress(rec, true);
582 case Amount:
583 return qint64(rec->credit + rec->debit);
584 } // no default case, so the compiler can warn about missing cases
585 assert(false);
586 case Qt::ToolTipRole:
587 return formatTooltip(rec);
588 case Qt::TextAlignmentRole:
589 return column_alignments[index.column()];
590 case Qt::ForegroundRole:
591 // Use the "danger" color for abandoned transactions
593 {
595 }
596 // Non-confirmed (but not immature) as transactions are grey
598 {
599 return COLOR_UNCONFIRMED;
600 }
601 if(index.column() == Amount && (rec->credit+rec->debit) < 0)
602 {
603 return COLOR_NEGATIVE;
604 }
605 if(index.column() == ToAddress)
606 {
607 return addressColor(rec);
608 }
609 break;
610 case TypeRole:
611 return rec->type;
612 case DateRole:
613 return QDateTime::fromSecsSinceEpoch(rec->time);
614 case WatchonlyRole:
615 return rec->involvesWatchAddress;
617 return txWatchonlyDecoration(rec);
620 case AddressRole:
621 return QString::fromStdString(rec->address);
622 case LabelRole:
623 return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
624 case AmountRole:
625 return qint64(rec->credit + rec->debit);
626 case TxHashRole:
627 return rec->getTxHash();
628 case TxHexRole:
629 return priv->getTxHex(walletModel->wallet(), rec);
630 case TxPlainTextRole:
631 {
632 QString details;
633 QDateTime date = QDateTime::fromSecsSinceEpoch(rec->time);
634 QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
635
636 details.append(date.toString("M/d/yy HH:mm"));
637 details.append(" ");
638 details.append(formatTxStatus(rec));
639 details.append(". ");
640 if(!formatTxType(rec).isEmpty()) {
641 details.append(formatTxType(rec));
642 details.append(" ");
643 }
644 if(!rec->address.empty()) {
645 if(txLabel.isEmpty())
646 details.append(tr("(no label)") + " ");
647 else {
648 details.append("(");
649 details.append(txLabel);
650 details.append(") ");
651 }
652 details.append(QString::fromStdString(rec->address));
653 details.append(" ");
654 }
655 details.append(formatTxAmount(rec, false, BitcoinUnits::SeparatorStyle::NEVER));
656 return details;
657 }
658 case ConfirmedRole:
659 return rec->status.status == TransactionStatus::Status::Confirming || rec->status.status == TransactionStatus::Status::Confirmed;
661 // Used for copy/export, so don't include separators
663 case StatusRole:
664 return rec->status.status;
665 }
666 return QVariant();
667}
668
669QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
670{
671 if(orientation == Qt::Horizontal)
672 {
673 if(role == Qt::DisplayRole)
674 {
675 return columns[section];
676 }
677 else if (role == Qt::TextAlignmentRole)
678 {
679 return column_alignments[section];
680 } else if (role == Qt::ToolTipRole)
681 {
682 switch(section)
683 {
684 case Status:
685 return tr("Transaction status. Hover over this field to show number of confirmations.");
686 case Date:
687 return tr("Date and time that the transaction was received.");
688 case Type:
689 return tr("Type of transaction.");
690 case Watchonly:
691 return tr("Whether or not a watch-only address is involved in this transaction.");
692 case ToAddress:
693 return tr("User-defined intent/purpose of the transaction.");
694 case Amount:
695 return tr("Amount removed from or added to balance.");
696 }
697 }
698 }
699 return QVariant();
700}
701
702QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
703{
704 Q_UNUSED(parent);
706 if(data)
707 {
708 return createIndex(row, column, data);
709 }
710 return QModelIndex();
711}
712
714{
715 // emit dataChanged to update Amount column with the current unit
717 Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
718}
719
721{
722 // Find transaction in wallet
723 // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
724 bool showTransaction = TransactionRecord::showTransaction();
725
726 TransactionNotification notification(hash, status, showTransaction);
727
728 if (!m_loaded || m_loading)
729 {
730 vQueueNotifications.push_back(notification);
731 return;
732 }
733 notification.invoke(parent);
734}
735
737{
738 if (!m_loaded || m_loading) return;
739
740 if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
741 bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
742 assert(invoked);
743 }
744 for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
745 {
746 if (vQueueNotifications.size() - i <= 10) {
747 bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
748 assert(invoked);
749 }
750
751 vQueueNotifications[i].invoke(parent);
752 }
753 vQueueNotifications.clear();
754}
755
757{
758 // Connect signals to wallet
760 m_handler_show_progress = walletModel->wallet().handleShowProgress([this](const std::string&, int progress) {
761 priv->m_loading = progress < 100;
763 });
764}
765
767{
768 // Disconnect signals from wallet
769 m_handler_transaction_changed->disconnect();
770 m_handler_show_progress->disconnect();
771}
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
int getDisplayUnit() const
Definition: optionsmodel.h:88
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)
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.
bool countsForBalance
Transaction counts towards available balance.
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ OpenUntilDate
Normal (sent/received) transactions.
@ Unconfirmed
Not yet mined into a block.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ OpenUntilBlock
Transaction not yet final, waiting for block.
@ 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.
@ 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
void refreshWallet(interfaces::Wallet &wallet)
bool m_loading
True when transactions are being notified, for instance when scanning.
QString describe(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, int unit)
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
bool m_loaded
True when model finishes loading all wallet transactions on start.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:52
interfaces::Node & node() const
Definition: walletmodel.h:143
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:144
uint256 getLastBlockProcessed() const
void SetHex(const char *psz)
Definition: uint256.cpp:30
std::string ToString() const
Definition: uint256.cpp:64
bool IsNull() const
Definition: uint256.h:31
std::string GetHex() const
Definition: uint256.cpp:20
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:55
Interface for accessing a wallet.
Definition: wallet.h:53
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:124
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:138
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:33
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
#define COLOR_TX_STATUS_OPENUNTILDATE
Definition: guiconstants.h:31
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
#define COLOR_BLACK
Definition: guiconstants.h:35
#define COLOR_BAREADDRESS
Definition: guiconstants.h:29
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:78
TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction)
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:377
Updated transaction status.
Definition: wallet.h:392
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())