Changeset View
Changeset View
Standalone View
Standalone View
src/qt/transactiontablemodel.cpp
Show All 36 Lines | |||||
}; | }; | ||||
// Comparison operator for sort/binary search of model tx list | // Comparison operator for sort/binary search of model tx list | ||||
struct TxLessThan { | struct TxLessThan { | ||||
bool operator()(const TransactionRecord &a, | bool operator()(const TransactionRecord &a, | ||||
const TransactionRecord &b) const { | const TransactionRecord &b) const { | ||||
return a.hash < b.hash; | return a.hash < b.hash; | ||||
} | } | ||||
bool operator()(const TransactionRecord &a, const uint256 &b) const { | bool operator()(const TransactionRecord &a, const TxHash &b) const { | ||||
return a.hash < b; | return a.hash < b; | ||||
} | } | ||||
bool operator()(const uint256 &a, const TransactionRecord &b) const { | bool operator()(const TxHash &a, const TransactionRecord &b) const { | ||||
return a < b.hash; | return a < b.hash; | ||||
} | } | ||||
}; | }; | ||||
// Private implementation | // Private implementation | ||||
class TransactionTablePriv { | class TransactionTablePriv { | ||||
public: | public: | ||||
TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent) | TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent) | ||||
Show All 10 Lines | public: | ||||
/* Query entire wallet anew from core. | /* Query entire wallet anew from core. | ||||
*/ | */ | ||||
void refreshWallet() { | void refreshWallet() { | ||||
qDebug() << "TransactionTablePriv::refreshWallet"; | qDebug() << "TransactionTablePriv::refreshWallet"; | ||||
cachedWallet.clear(); | cachedWallet.clear(); | ||||
{ | { | ||||
LOCK2(cs_main, wallet->cs_wallet); | LOCK2(cs_main, wallet->cs_wallet); | ||||
for (std::map<uint256, CWalletTx>::iterator it = | for (std::map<TxHash, CWalletTx>::iterator it = | ||||
wallet->mapWallet.begin(); | wallet->mapWallet.begin(); | ||||
it != wallet->mapWallet.end(); ++it) { | it != wallet->mapWallet.end(); ++it) { | ||||
if (TransactionRecord::showTransaction(it->second)) | if (TransactionRecord::showTransaction(it->second)) | ||||
cachedWallet.append(TransactionRecord::decomposeTransaction( | cachedWallet.append(TransactionRecord::decomposeTransaction( | ||||
wallet, it->second)); | wallet, it->second)); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Update our model of the wallet incrementally, to synchronize our model of | * Update our model of the wallet incrementally, to synchronize our model of | ||||
* the wallet with that of the core. | * the wallet with that of the core. | ||||
* Call with transaction that was added, removed or changed. | * Call with transaction that was added, removed or changed. | ||||
*/ | */ | ||||
void updateWallet(const uint256 &hash, int status, bool showTransaction) { | void updateWallet(const TxHash &hash, int status, bool showTransaction) { | ||||
qDebug() << "TransactionTablePriv::updateWallet: " + | qDebug() << "TransactionTablePriv::updateWallet: " + | ||||
QString::fromStdString(hash.ToString()) + " " + | QString::fromStdString(hash.ToString()) + " " + | ||||
QString::number(status); | QString::number(status); | ||||
// Find bounds of this transaction in model | // Find bounds of this transaction in model | ||||
QList<TransactionRecord>::iterator lower = qLowerBound( | QList<TransactionRecord>::iterator lower = qLowerBound( | ||||
cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); | cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); | ||||
QList<TransactionRecord>::iterator upper = qUpperBound( | QList<TransactionRecord>::iterator upper = qUpperBound( | ||||
Show All 21 Lines | void updateWallet(const TxHash &hash, int status, bool showTransaction) { | ||||
qWarning() << "TransactionTablePriv::updateWallet: " | qWarning() << "TransactionTablePriv::updateWallet: " | ||||
"Warning: Got CT_NEW, but transaction is " | "Warning: Got CT_NEW, but transaction is " | ||||
"already in model"; | "already in model"; | ||||
break; | break; | ||||
} | } | ||||
if (showTransaction) { | if (showTransaction) { | ||||
LOCK2(cs_main, wallet->cs_wallet); | LOCK2(cs_main, wallet->cs_wallet); | ||||
// Find transaction in wallet | // Find transaction in wallet | ||||
std::map<uint256, CWalletTx>::iterator mi = | std::map<TxHash, CWalletTx>::iterator mi = | ||||
wallet->mapWallet.find(hash); | wallet->mapWallet.find(hash); | ||||
if (mi == wallet->mapWallet.end()) { | if (mi == wallet->mapWallet.end()) { | ||||
qWarning() << "TransactionTablePriv::updateWallet: " | qWarning() << "TransactionTablePriv::updateWallet: " | ||||
"Warning: Got CT_NEW, but transaction is " | "Warning: Got CT_NEW, but transaction is " | ||||
"not in wallet"; | "not in wallet"; | ||||
break; | break; | ||||
} | } | ||||
// Added -- insert at the right position | // Added -- insert at the right position | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | TransactionRecord *index(int idx) { | ||||
// | // | ||||
// If a status update is needed (blocks came in since last check), | // If a status update is needed (blocks came in since last check), | ||||
// update the status of this transaction from the wallet. Otherwise, | // update the status of this transaction from the wallet. Otherwise, | ||||
// simply re-use the cached status. | // simply re-use the cached status. | ||||
TRY_LOCK(cs_main, lockMain); | TRY_LOCK(cs_main, lockMain); | ||||
if (lockMain) { | if (lockMain) { | ||||
TRY_LOCK(wallet->cs_wallet, lockWallet); | TRY_LOCK(wallet->cs_wallet, lockWallet); | ||||
if (lockWallet && rec->statusUpdateNeeded()) { | if (lockWallet && rec->statusUpdateNeeded()) { | ||||
std::map<uint256, CWalletTx>::iterator mi = | std::map<TxHash, CWalletTx>::iterator mi = | ||||
wallet->mapWallet.find(rec->hash); | wallet->mapWallet.find(rec->hash); | ||||
if (mi != wallet->mapWallet.end()) { | if (mi != wallet->mapWallet.end()) { | ||||
rec->updateStatus(mi->second); | rec->updateStatus(mi->second); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return rec; | return rec; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
QString describe(TransactionRecord *rec, int unit) { | QString describe(TransactionRecord *rec, int unit) { | ||||
{ | { | ||||
LOCK2(cs_main, wallet->cs_wallet); | LOCK2(cs_main, wallet->cs_wallet); | ||||
std::map<uint256, CWalletTx>::iterator mi = | std::map<TxHash, CWalletTx>::iterator mi = | ||||
wallet->mapWallet.find(rec->hash); | wallet->mapWallet.find(rec->hash); | ||||
if (mi != wallet->mapWallet.end()) { | if (mi != wallet->mapWallet.end()) { | ||||
return TransactionDesc::toHTML(wallet, mi->second, rec, unit); | return TransactionDesc::toHTML(wallet, mi->second, rec, unit); | ||||
} | } | ||||
} | } | ||||
return QString(); | return QString(); | ||||
} | } | ||||
QString getTxHex(TransactionRecord *rec) { | QString getTxHex(TransactionRecord *rec) { | ||||
LOCK2(cs_main, wallet->cs_wallet); | LOCK2(cs_main, wallet->cs_wallet); | ||||
std::map<uint256, CWalletTx>::iterator mi = | std::map<TxHash, CWalletTx>::iterator mi = | ||||
wallet->mapWallet.find(rec->hash); | wallet->mapWallet.find(rec->hash); | ||||
if (mi != wallet->mapWallet.end()) { | if (mi != wallet->mapWallet.end()) { | ||||
std::string strHex = | std::string strHex = | ||||
EncodeHexTx(static_cast<CTransaction>(mi->second)); | EncodeHexTx(static_cast<CTransaction>(mi->second)); | ||||
return QString::fromStdString(strHex); | return QString::fromStdString(strHex); | ||||
} | } | ||||
return QString(); | return QString(); | ||||
} | } | ||||
Show All 25 Lines | |||||
void TransactionTableModel::updateAmountColumnTitle() { | void TransactionTableModel::updateAmountColumnTitle() { | ||||
columns[Amount] = BitcoinUnits::getAmountColumnTitle( | columns[Amount] = BitcoinUnits::getAmountColumnTitle( | ||||
walletModel->getOptionsModel()->getDisplayUnit()); | walletModel->getOptionsModel()->getDisplayUnit()); | ||||
Q_EMIT headerDataChanged(Qt::Horizontal, Amount, Amount); | Q_EMIT headerDataChanged(Qt::Horizontal, Amount, Amount); | ||||
} | } | ||||
void TransactionTableModel::updateTransaction(const QString &hash, int status, | void TransactionTableModel::updateTransaction(const QString &hash, int status, | ||||
bool showTransaction) { | bool showTransaction) { | ||||
uint256 updated; | TxHash updated; | ||||
updated.SetHex(hash.toStdString()); | updated.SetHex(hash.toStdString()); | ||||
priv->updateWallet(updated, status, showTransaction); | priv->updateWallet(updated, status, showTransaction); | ||||
} | } | ||||
void TransactionTableModel::updateConfirmations() { | void TransactionTableModel::updateConfirmations() { | ||||
// Blocks came in since last poll. | // Blocks came in since last poll. | ||||
// Invalidate status (number of confirmations) and (possibly) description | // Invalidate status (number of confirmations) and (possibly) description | ||||
▲ Show 20 Lines • Show All 431 Lines • ▼ Show 20 Lines | void TransactionTableModel::updateDisplayUnit() { | ||||
updateAmountColumnTitle(); | updateAmountColumnTitle(); | ||||
Q_EMIT dataChanged(index(0, Amount), index(priv->size() - 1, Amount)); | Q_EMIT dataChanged(index(0, Amount), index(priv->size() - 1, Amount)); | ||||
} | } | ||||
// queue notifications to show a non freezing progress dialog e.g. for rescan | // queue notifications to show a non freezing progress dialog e.g. for rescan | ||||
struct TransactionNotification { | struct TransactionNotification { | ||||
public: | public: | ||||
TransactionNotification() {} | TransactionNotification() {} | ||||
TransactionNotification(uint256 _hash, ChangeType _status, | TransactionNotification(TxHash _hash, ChangeType _status, | ||||
bool _showTransaction) | bool _showTransaction) | ||||
: hash(_hash), status(_status), showTransaction(_showTransaction) {} | : hash(_hash), status(_status), showTransaction(_showTransaction) {} | ||||
void invoke(QObject *ttm) { | void invoke(QObject *ttm) { | ||||
QString strHash = QString::fromStdString(hash.GetHex()); | QString strHash = QString::fromStdString(hash.GetHex()); | ||||
qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + | qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + | ||||
QString::number(status); | QString::number(status); | ||||
QMetaObject::invokeMethod(ttm, "updateTransaction", | QMetaObject::invokeMethod(ttm, "updateTransaction", | ||||
Qt::QueuedConnection, Q_ARG(QString, strHash), | Qt::QueuedConnection, Q_ARG(QString, strHash), | ||||
Q_ARG(int, status), | Q_ARG(int, status), | ||||
Q_ARG(bool, showTransaction)); | Q_ARG(bool, showTransaction)); | ||||
} | } | ||||
private: | private: | ||||
uint256 hash; | TxHash hash; | ||||
ChangeType status; | ChangeType status; | ||||
bool showTransaction; | bool showTransaction; | ||||
}; | }; | ||||
static bool fQueueNotifications = false; | static bool fQueueNotifications = false; | ||||
static std::vector<TransactionNotification> vQueueNotifications; | static std::vector<TransactionNotification> vQueueNotifications; | ||||
static void NotifyTransactionChanged(TransactionTableModel *ttm, | static void NotifyTransactionChanged(TransactionTableModel *ttm, | ||||
CWallet *wallet, const uint256 &hash, | CWallet *wallet, const TxHash &hash, | ||||
ChangeType status) { | ChangeType status) { | ||||
// Find transaction in wallet | // Find transaction in wallet | ||||
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash); | std::map<TxHash, CWalletTx>::iterator mi = wallet->mapWallet.find(hash); | ||||
// Determine whether to show transaction or not (determine this here so that | // Determine whether to show transaction or not (determine this here so that | ||||
// no relocking is needed in GUI thread) | // no relocking is needed in GUI thread) | ||||
bool inWallet = mi != wallet->mapWallet.end(); | bool inWallet = mi != wallet->mapWallet.end(); | ||||
bool showTransaction = | bool showTransaction = | ||||
(inWallet && TransactionRecord::showTransaction(mi->second)); | (inWallet && TransactionRecord::showTransaction(mi->second)); | ||||
TransactionNotification notification(hash, status, showTransaction); | TransactionNotification notification(hash, status, showTransaction); | ||||
▲ Show 20 Lines • Show All 43 Lines • Show Last 20 Lines |