26 #include <QtConcurrent/QtConcurrent>
29 #define SINGLE_THREAD_MAX_TXES_SIZE 4000
34 #define MAX_AMOUNT_LOADED_RECORDS 20000
37 static int column_alignments[] = {
38 Qt::AlignLeft | Qt::AlignVCenter,
39 Qt::AlignLeft | Qt::AlignVCenter,
40 Qt::AlignLeft | Qt::AlignVCenter,
41 Qt::AlignLeft | Qt::AlignVCenter,
42 Qt::AlignLeft | Qt::AlignVCenter,
43 Qt::AlignRight | Qt::AlignVCenter
96 qDebug() <<
"TransactionTablePriv::refreshWallet";
102 std::size_t txesSize = walletTxes.size();
108 sort(walletTxes.begin(), walletTxes.end(),
110 return a.GetTxTime() > b.GetTxTime();
115 txesSize = walletTxes.size();
119 std::size_t threadsCount = (QThreadPool::globalInstance()->maxThreadCount() / 2 ) + 1;
122 std::size_t
const subsetSize = txesSize / (threadsCount + 1);
123 std::size_t totalSumSize = 0;
124 QList<QFuture<ConvertTxToVectorResult>> tasks;
127 for (std::size_t i = 0; i < threadsCount; ++i) {
133 std::vector<CWalletTx>(walletTxes.begin() + totalSumSize, walletTxes.begin() + totalSumSize + subsetSize)
136 totalSumSize += subsetSize;
140 std::size_t
const remainingSize = txesSize - totalSumSize;
142 std::vector<CWalletTx>(walletTxes.end() - remainingSize, walletTxes.end())
147 for (
auto &future : tasks) {
148 future.waitForFinished();
175 const std::vector<CWalletTx>& walletTxes)
178 for (
const auto& tx : walletTxes) {
180 if (records.isEmpty())
continue;
181 qint64 time = records.first().time;
185 for (
const auto& rec : records) {
200 qDebug() <<
"TransactionTablePriv::updateWallet : " + QString::fromStdString(hash.
ToString()) +
" " + QString::number(status);
203 QList<TransactionRecord>::iterator lower = std::lower_bound(
205 QList<TransactionRecord>::iterator upper = std::upper_bound(
209 bool inModel = (lower != upper);
212 if (showTransaction && !inModel)
214 if (!showTransaction && inModel)
218 qDebug() <<
" inModel=" + QString::number(inModel) +
219 " Index=" + QString::number(lowerIndex) +
"-" + QString::number(upperIndex) +
220 " showTransaction=" + QString::number(showTransaction) +
" derivedStatus=" + QString::number(status);
225 qWarning() <<
"TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is already in model";
228 if (showTransaction) {
232 qWarning() <<
"TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is not in wallet";
243 QList<TransactionRecord> toInsert =
245 if (!toInsert.isEmpty()) {
246 parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex + toInsert.size() - 1);
247 int insert_idx = lowerIndex;
259 qWarning() <<
"TransactionTablePriv::updateWallet : Warning: Got CT_DELETED, but transaction is not in model";
263 parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex - 1);
270 for (
int i = lowerIndex; i < upperIndex; i++) {
309 fProcessingQueuedTransactions(
false)
332 Q_EMIT headerDataChanged(Qt::Horizontal,
Amount,
Amount);
338 updated.
SetHex(hash.toStdString());
379 status = tr(
"Open for %n more block(s)",
"", wtx->
status.
open_for);
385 status = tr(
"Unconfirmed");
391 status = tr(
"Confirmed (%1 confirmations)").arg(wtx->
status.
depth);
394 status = tr(
"Conflicted");
400 status = tr(
"Orphan Block - Generated but not accepted. This does not impact your holdings.");
422 if (!label.isEmpty()) {
423 description += label + QString(
" ");
425 if (label.isEmpty() || tooltip) {
426 description += QString::fromStdString(address);
435 return tr(
"Received with");
437 return tr(
"Masternode Reward");
439 return tr(
"Budget Payment");
441 return tr(
"Received from");
444 return tr(
"Sent to");
446 return tr(
"Payment to yourself");
448 return tr(
"Shielding coins to yourself");
450 return tr(
"Unshielding coins to yourself");
452 return tr(
"Shielded change, transfer between own shielded addresses");
460 return tr(
"%1 Stake on behalf of").arg(
CURRENCY_UNIT.c_str());
464 return tr(
"Stake delegation");
467 return tr(
"Stake delegation spent by");
475 return tr(
"Received %1 from z%1").arg(
CURRENCY_UNIT.c_str());
477 return tr(
"Minted Change as z%1 from z%1 Spend").arg(
CURRENCY_UNIT.c_str());
481 return tr(
"Received with shielded");
483 return tr(
"Received shielded memo");
485 return tr(
"Shielded send to");
487 return tr(
"Burned PIVs");
501 return QIcon(
":/icons/tx_mined");
505 return QIcon(
":/icons/tx_input");
509 return QIcon(
"://ic-transaction-sent");
511 return QIcon(
":/icons/tx_inout");
517 QString watchAddress;
520 watchAddress = wtx->
involvesWatchAddress ? QString(
" (") + tr(
"watch-only") + QString(
")") :
"";
525 return QString::fromStdString(wtx->
address) + watchAddress;
540 return QString::fromStdString(wtx->
address);
542 return QString::fromStdString(wtx->
address) + watchAddress;
544 return QString::fromStdString(wtx->
address);
548 return tr(
"Anonymous");
558 return label.isEmpty() ?
"" : label;
566 if (watchAddress.isEmpty()) {
567 return tr(
"No information");
569 return tr(
"(n/a)") + watchAddress;
598 if (showUnconfirmed) {
600 str = QString(
"[") + str + QString(
"]");
613 return QIcon(
":/icons/transaction_0");
617 return QIcon(
":/icons/transaction_1");
619 return QIcon(
":/icons/transaction_2");
621 return QIcon(
":/icons/transaction_3");
623 return QIcon(
":/icons/transaction_4");
625 return QIcon(
":/icons/transaction_5");
628 return QIcon(
":/icons/transaction_confirmed");
630 return QIcon(
":/icons/transaction_conflicted");
634 return QIcon(QString(
":/icons/transaction_%1").arg(part));
637 return QIcon(
":/icons/transaction_0");
646 return QIcon(
":/icons/eye");
658 if (!
index.isValid())
663 case Qt::DecorationRole:
664 switch (
index.column()) {
673 case Qt::DisplayRole:
674 switch (
index.column()) {
687 switch (
index.column()) {
702 case Qt::ToolTipRole:
704 case Qt::TextAlignmentRole:
705 return column_alignments[
index.column()];
706 case Qt::ForegroundRole:
739 return QDateTime::fromTime_t(
static_cast<uint
>(rec->
time));
745 return QString::fromStdString(rec->
address);
767 if (orientation == Qt::Horizontal) {
768 if (role == Qt::DisplayRole) {
770 }
else if (role == Qt::TextAlignmentRole) {
771 return column_alignments[section];
772 }
else if (role == Qt::ToolTipRole) {
775 return tr(
"Transaction status. Hover over this field to show number of confirmations.");
777 return tr(
"Date and time that the transaction was received.");
779 return tr(
"Type of transaction.");
781 return tr(
"Whether or not a watch-only address is involved in this transaction.");
783 return tr(
"Destination address of transaction.");
785 return tr(
"Amount removed from or added to balance.");
799 return createIndex(row, column,
data);
801 return QModelIndex();
819 QString strHash = QString::fromStdString(
hash.
GetHex());
820 qDebug() <<
"NotifyTransactionChanged : " + strHash +
" status= " + QString::number(
status);
821 QMetaObject::invokeMethod(ttm,
"updateTransaction", Qt::QueuedConnection,
822 Q_ARG(QString, strHash),
832 static bool fQueueNotifications =
false;
833 static std::vector<TransactionNotification> vQueueNotifications;
840 if (fQueueNotifications)
842 vQueueNotifications.push_back(notification);
851 fQueueNotifications =
true;
853 if (nProgress == 100) {
854 fQueueNotifications =
false;
855 if (vQueueNotifications.size() > 10)
856 QMetaObject::invokeMethod(ttm,
"setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(
bool,
true));
857 for (
unsigned int i = 0; i < vQueueNotifications.size(); ++i) {
858 if (vQueueNotifications.size() - i <= 10)
859 QMetaObject::invokeMethod(ttm,
"setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(
bool,
false));
861 vQueueNotifications[i].invoke(ttm);
863 std::vector<TransactionNotification>().swap(vQueueNotifications);
QString labelForAddress(const QString &address) const
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard, bool cleanRemainderZeros=true)
Format as string.
static QString getAmountColumnTitle(int unit)
Gets title for amount column including current display unit if optionsModel reference available */.
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
std::map< uint256, CWalletTx > mapWallet
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
A transaction with a bunch of additional info that only the owner cares about.
void displayUnitChanged(int unit)
UI model for a transaction.
bool isMNReward() const
Return true if the tx is a MN reward.
@ RecvWithShieldedAddress
@ SendToSelfShieldToTransparent
@ ZerocoinSpend_Change_zPiv
@ P2CSDelegationSentOwner
@ SendToSelfShieldedAddress
@ RecvWithShieldedAddressMemo
@ SendToSelfShieldToShieldChangeAddress
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
Optional< CAmount > shieldedCredit
bool isCoinStake() const
Return true if the tx is a coinstake.
TransactionStatus status
Status: can change with block chain update.
void updateStatus(const CWalletTx &wtx, int chainHeight)
Update status from core wallet tx.
bool isAnyColdStakingType() const
Return true if the tx is a any cold staking type tx.
bool isNull() const
Return true if the tx hash is null and/or if the size is 0.
static QList< TransactionRecord > decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
Decompose CWallet transaction to model transaction records.
bool statusUpdateNeeded(int blockHeight) const
Return whether a status update is needed.
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)
@ 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.
qint64 open_for
Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined befor...
std::string sortKey
Sorting key based on status.
UI model for the transaction table of a wallet.
QVariant txStatusDecoration(const TransactionRecord *wtx) const
void subscribeToCoreSignals()
TransactionTablePriv * priv
void unsubscribeFromCoreSignals()
QVariant addressColor(const TransactionRecord *wtx) const
@ SizeRole
Transaction size in bytes.
@ LabelRole
Label of address related to transaction.
@ TypeRole
Type of transaction.
@ StatusRole
Transaction status (TransactionRecord::Status)
@ DateRole
Date and time this transaction was created.
@ TxHashRole
Transaction hash.
@ ShieldedCreditAmountRole
Credit amount of transaction.
@ 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 formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::separatorStandard) const
QString formatTooltip(const TransactionRecord *rec) const
void updateConfirmations()
QVariant data(const QModelIndex &index, int role) const override
void txArrived(const QString &hash, const bool isCoinStake, const bool isMNReward, const bool isCSAnyType)
QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const
void updateTransaction(const QString &hash, int status, bool showTransaction)
QString formatTxStatus(const TransactionRecord *wtx) const
WalletModel * walletModel
std::unique_ptr< interfaces::Handler > m_handler_transaction_changed
int columnCount(const QModelIndex &parent) const override
void txLoaded(const QString &hash, const int txType, const int txStatus)
TransactionTableModel(CWallet *wallet, WalletModel *parent=nullptr)
~TransactionTableModel() override
std::unique_ptr< interfaces::Handler > m_handler_show_progress
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
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
qint64 nFirstLoadedTxTime
Time of the oldest transaction loaded into the model.
TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent)
TransactionTableModel * parent
TransactionRecord * index(int cur_block_num, const uint256 &cur_block_hash, int idx)
static ConvertTxToVectorResult convertTxToRecords(TransactionTablePriv *tablePriv, const CWallet *wallet, const std::vector< CWalletTx > &walletTxes)
QList< TransactionRecord > cachedWallet
void updateWallet(const uint256 &hash, int status, bool showTransaction, TransactionRecord &ret)
void emitTxLoaded(const TransactionRecord &rec)
Interface to PIVX wallet from Qt view code.
int getLastBlockProcessedNum() const
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
uint256 getLastBlockProcessed() const
void SetHex(const char *psz)
std::string ToString() const
std::string GetHex() const
const std::string CURRENCY_UNIT
std::vector< CWalletTx > getWalletTxs()
int64_t GetTxTime() const
const CWalletTx * GetWalletTx(const uint256 &hash) const
#define COLOR_UNCONFIRMED
#define COLOR_TX_STATUS_OPENUNTILDATE
#define COLOR_BAREADDRESS
ChangeType
General change type (added, updated, removed).
QString dateTimeStr(const QDateTime &date)
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
qint64 nFirstLoadedTxTime
QList< TransactionRecord > records
TransactionNotification(uint256 hash, ChangeType status)
void invoke(QObject *ttm)
TransactionNotification()=delete
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
#define TRY_LOCK(cs, name)
#define SINGLE_THREAD_MAX_TXES_SIZE
#define MAX_AMOUNT_LOADED_RECORDS