mirror of
https://github.com/feather-wallet/feather.git
synced 2025-04-23 20:58:13 +00:00
History: cleanup
This commit is contained in:
parent
1219bfc3a7
commit
4f28d83ac3
28 changed files with 430 additions and 634 deletions
src
CoinsWidget.cppHistoryWidget.cppMainWindow.cpp
dialog
HistoryExportDialog.cppTxConfAdvDialog.cppTxConfAdvDialog.hTxInfoDialog.cppTxInfoDialog.hTxProofDialog.cppTxProofDialog.h
libwalletqt
ConstructionInfo.cppConstructionInfo.hInput.hPendingTransaction.cppPendingTransaction.hPendingTransactionInfo.cppPendingTransactionInfo.hTransactionHistory.cppTransactionHistory.hUnsignedTransaction.cppUnsignedTransaction.h
rows
model
|
@ -377,4 +377,4 @@ QModelIndex CoinsWidget::getCurrentIndex()
|
|||
return m_proxyModel->mapToSource(list.first());
|
||||
}
|
||||
|
||||
CoinsWidget::~CoinsWidget() = default;
|
||||
CoinsWidget::~CoinsWidget() = default;
|
||||
|
|
|
@ -84,15 +84,18 @@ void HistoryWidget::showContextMenu(const QPoint &point) {
|
|||
|
||||
QMenu menu(this);
|
||||
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (!tx) return;
|
||||
auto txIdx = ui->history->getCurrentIndex();
|
||||
if (!txIdx.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(txIdx);
|
||||
|
||||
bool unconfirmed = tx->isFailed() || tx->isPending();
|
||||
if (unconfirmed && tx->direction() != TransactionRow::Direction_In) {
|
||||
bool unconfirmed = tx.failed || tx.pending;
|
||||
if (unconfirmed && tx.direction != TransactionRow::Direction_In) {
|
||||
menu.addAction("Resend transaction", this, &HistoryWidget::onResendTransaction);
|
||||
}
|
||||
|
||||
if (tx->isFailed()) {
|
||||
if (tx.failed) {
|
||||
menu.addAction("Remove from history", this, &HistoryWidget::onRemoveFromHistory);
|
||||
}
|
||||
|
||||
|
@ -105,20 +108,24 @@ void HistoryWidget::showContextMenu(const QPoint &point) {
|
|||
}
|
||||
|
||||
void HistoryWidget::onResendTransaction() {
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (tx) {
|
||||
QString txid = tx->hash();
|
||||
emit resendTransaction(txid);
|
||||
auto index = ui->history->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(index);
|
||||
emit resendTransaction(tx.hash);
|
||||
}
|
||||
|
||||
void HistoryWidget::onRemoveFromHistory() {
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (!tx) return;
|
||||
auto index = ui->history->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(index);
|
||||
|
||||
auto result = QMessageBox::question(this, "Remove transaction from history", "Are you sure you want to remove this transaction from the history?");
|
||||
if (result == QMessageBox::Yes) {
|
||||
m_wallet->removeFailedTx(tx->hash());
|
||||
m_wallet->removeFailedTx(tx.hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,8 +139,11 @@ void HistoryWidget::resetModel()
|
|||
}
|
||||
|
||||
void HistoryWidget::showTxDetails() {
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (!tx) return;
|
||||
auto index = ui->history->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(index);
|
||||
|
||||
auto *dialog = new TxInfoDialog(m_wallet, tx, this);
|
||||
connect(dialog, &TxInfoDialog::resendTranscation, [this](const QString &txid){
|
||||
|
@ -144,11 +154,13 @@ void HistoryWidget::showTxDetails() {
|
|||
}
|
||||
|
||||
void HistoryWidget::onViewOnBlockExplorer() {
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (!tx) return;
|
||||
auto index = ui->history->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(index);
|
||||
|
||||
QString txid = tx->hash();
|
||||
emit viewOnBlockExplorer(txid);
|
||||
emit viewOnBlockExplorer(tx.hash);
|
||||
}
|
||||
|
||||
void HistoryWidget::setSearchText(const QString &text) {
|
||||
|
@ -161,8 +173,11 @@ void HistoryWidget::setSearchFilter(const QString &filter) {
|
|||
}
|
||||
|
||||
void HistoryWidget::createTxProof() {
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (!tx) return;
|
||||
auto index = ui->history->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(index);
|
||||
|
||||
TxProofDialog dialog{this, m_wallet, tx};
|
||||
dialog.getTxKey();
|
||||
|
@ -170,20 +185,23 @@ void HistoryWidget::createTxProof() {
|
|||
}
|
||||
|
||||
void HistoryWidget::copy(copyField field) {
|
||||
auto *tx = ui->history->currentEntry();
|
||||
if (!tx) return;
|
||||
auto index = ui->history->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = ui->history->sourceModel()->entryFromIndex(index);
|
||||
|
||||
QString data = [field, tx]{
|
||||
switch(field) {
|
||||
case copyField::TxID:
|
||||
return tx->hash();
|
||||
return tx.hash;
|
||||
case copyField::Description:
|
||||
return tx->description();
|
||||
return tx.description;
|
||||
case copyField::Date:
|
||||
return tx->timestamp().toString(QString("%1 %2").arg(conf()->get(Config::dateFormat).toString(),
|
||||
return tx.timestamp.toString(QString("%1 %2").arg(conf()->get(Config::dateFormat).toString(),
|
||||
conf()->get(Config::timeFormat).toString()));
|
||||
case copyField::Amount:
|
||||
return WalletManager::displayAmount(abs(tx->balanceDelta()));
|
||||
return WalletManager::displayAmount(abs(tx.balanceDelta));
|
||||
default:
|
||||
return QString("");
|
||||
}
|
||||
|
@ -205,4 +223,4 @@ void HistoryWidget::showSyncNoticeMsg() {
|
|||
"To update the history page during synchronization press Ctrl+R.");
|
||||
}
|
||||
|
||||
HistoryWidget::~HistoryWidget() = default;
|
||||
HistoryWidget::~HistoryWidget() = default;
|
||||
|
|
|
@ -942,7 +942,7 @@ void MainWindow::onTransactionCreated(PendingTransaction *tx, const QVector<QStr
|
|||
// TODO: also check that amounts match
|
||||
tx->refresh();
|
||||
QSet<QString> outputAddresses;
|
||||
for (const auto &output : tx->transaction(0)->outputs()) {
|
||||
for (const auto &output : tx->transaction(0).outputs) {
|
||||
outputAddresses.insert(WalletManager::baseAddressFromIntegratedAddress(output.address, constants::networkType));
|
||||
}
|
||||
QSet<QString> destAddresses;
|
||||
|
@ -1053,8 +1053,17 @@ void MainWindow::onTransactionCommitted(bool success, PendingTransaction *tx, co
|
|||
msgBox.exec();
|
||||
if (msgBox.clickedButton() == showDetailsButton) {
|
||||
this->showHistoryTab();
|
||||
TransactionRow *txInfo = m_wallet->history()->transaction(txid.first());
|
||||
auto *dialog = new TxInfoDialog(m_wallet, txInfo, this);
|
||||
|
||||
const auto& rows = m_wallet->history()->getRows();
|
||||
auto itr = std::find_if(rows.begin(), rows.end(),
|
||||
[&](const TransactionRow& ti) {
|
||||
return ti.hash == txid.first();
|
||||
});
|
||||
if (itr == rows.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *dialog = new TxInfoDialog(m_wallet, *itr, this);
|
||||
connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
|
||||
dialog->show();
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
|
|
@ -95,77 +95,77 @@ void HistoryExportDialog::exportHistory()
|
|||
QList<QPair<uint64_t, QString>> csvData;
|
||||
|
||||
for (int i = 0; i < num_transactions; i++) {
|
||||
TransactionRow* tx = m_wallet->history()->transaction(i);
|
||||
const TransactionRow& tx = m_wallet->history()->transaction(i);
|
||||
|
||||
QDate minimumDate = ui->date_min->date();
|
||||
if (tx->timestamp().date() < minimumDate) {
|
||||
if (tx.timestamp.date() < minimumDate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QDate maximumDate = ui->date_max->date();
|
||||
if (tx->timestamp().date() > maximumDate) {
|
||||
if (tx.timestamp.date() > maximumDate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ui->check_excludePending->isChecked() && tx->isPending()) {
|
||||
if (ui->check_excludePending->isChecked() && tx.pending) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ui->check_excludeFailed->isChecked() && tx->isFailed()) {
|
||||
if (ui->check_excludeFailed->isChecked() && tx.failed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ui->radio_incomingTransactions->isChecked() && tx->direction() != TransactionRow::Direction_In) {
|
||||
if (ui->radio_incomingTransactions->isChecked() && tx.direction != TransactionRow::Direction_In) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ui->radio_outgoingTransactions->isChecked() && tx->direction() != TransactionRow::Direction_Out) {
|
||||
if (ui->radio_outgoingTransactions->isChecked() && tx.direction != TransactionRow::Direction_Out) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ui->radio_coinbaseTransactions->isChecked() && !tx->isCoinbase()) {
|
||||
if (ui->radio_coinbaseTransactions->isChecked() && !tx.coinbase) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString date = QString("%1T%2Z").arg(tx->date(), tx->time());
|
||||
QString date = QString("%1T%2Z").arg(tx.date(), tx.time());
|
||||
|
||||
QString direction = QString("");
|
||||
if (tx->direction() == TransactionRow::Direction_In)
|
||||
if (tx.direction == TransactionRow::Direction_In)
|
||||
direction = QString("in");
|
||||
else if (tx->direction() == TransactionRow::Direction_Out)
|
||||
else if (tx.direction == TransactionRow::Direction_Out)
|
||||
direction = QString("out");
|
||||
else
|
||||
continue; // skip TransactionInfo::Direction_Both
|
||||
|
||||
QString balanceDelta = WalletManager::displayAmount(abs(tx->balanceDelta()));
|
||||
if (tx->direction() == TransactionRow::Direction_Out) {
|
||||
QString balanceDelta = WalletManager::displayAmount(abs(tx.balanceDelta));
|
||||
if (tx.direction == TransactionRow::Direction_Out) {
|
||||
balanceDelta = "-" + balanceDelta;
|
||||
}
|
||||
|
||||
QString paymentId = tx->paymentId();
|
||||
QString paymentId = tx.paymentId;
|
||||
if (paymentId == "0000000000000000") {
|
||||
paymentId = "";
|
||||
}
|
||||
|
||||
const double usd_price = appData()->txFiatHistory->get(tx->timestamp().toString("yyyyMMdd"));
|
||||
double fiat_price = usd_price * tx->amount();
|
||||
const double usd_price = appData()->txFiatHistory->get(tx.timestamp.toString("yyyyMMdd"));
|
||||
double fiat_price = usd_price * tx.amountDouble();
|
||||
QString fiatAmount = (usd_price > 0) ? QString::number(fiat_price, 'f', 2) : "?";
|
||||
|
||||
QString line = QString(R"(%1,%2,"%3",%4,"%5",%6,%7,%8,"%9","%10","%11","%12","%13")")
|
||||
.arg(QString::number(tx->blockHeight()),
|
||||
QString::number(tx->timestamp().toSecsSinceEpoch()),
|
||||
.arg(QString::number(tx.blockHeight),
|
||||
QString::number(tx.timestamp.toSecsSinceEpoch()),
|
||||
date,
|
||||
QString::number(tx->subaddrAccount()),
|
||||
QString::number(tx.subaddrAccount),
|
||||
direction,
|
||||
balanceDelta,
|
||||
tx->displayAmount(),
|
||||
tx->fee(),
|
||||
tx->hash(),
|
||||
tx->description(),
|
||||
tx.displayAmount(),
|
||||
tx.displayFee(),
|
||||
tx.hash,
|
||||
tx.description,
|
||||
paymentId,
|
||||
fiatAmount,
|
||||
"USD");
|
||||
csvData.append({tx->blockHeight(), line});
|
||||
csvData.append({tx.blockHeight, line});
|
||||
}
|
||||
|
||||
std::sort(csvData.begin(), csvData.end(), [](const QPair<uint64_t, QString> &tx1, const QPair<uint64_t, QString> &tx2){
|
||||
|
|
|
@ -72,10 +72,10 @@ void TxConfAdvDialog::setTransaction(PendingTransaction *tx, bool isSigned) {
|
|||
|
||||
m_tx = tx;
|
||||
m_tx->refresh();
|
||||
PendingTransactionInfo *ptx = m_tx->transaction(0); //Todo: support split transactions
|
||||
const PendingTransactionInfo& ptx = m_tx->transaction(0); //Todo: support split transactions
|
||||
|
||||
// TODO: implement hasTxKey()
|
||||
if (!m_wallet->isHwBacked() && m_tx->transaction(0)->txKey() == "0100000000000000000000000000000000000000000000000000000000000000") {
|
||||
if (!m_wallet->isHwBacked() && m_tx->transaction(0).txKey == "0100000000000000000000000000000000000000000000000000000000000000") {
|
||||
ui->btn_exportTxKey->hide();
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ void TxConfAdvDialog::setUnsignedTransaction(UnsignedTransaction *utx) {
|
|||
|
||||
this->setAmounts(utx->amount(0), utx->fee(0));
|
||||
|
||||
ConstructionInfo *ci = m_utx->constructionInfo(0);
|
||||
const ConstructionInfo& ci = m_utx->constructionInfo(0);
|
||||
this->setupConstructionData(ci);
|
||||
}
|
||||
|
||||
|
@ -136,20 +136,20 @@ void TxConfAdvDialog::setAmounts(quint64 amount, quint64 fee) {
|
|||
}
|
||||
}
|
||||
|
||||
void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
|
||||
for (const auto &in: ci->inputs()) {
|
||||
void TxConfAdvDialog::setupConstructionData(const ConstructionInfo& ci) {
|
||||
for (const auto &in: ci.inputs) {
|
||||
auto *item = new QTreeWidgetItem(ui->treeInputs);
|
||||
item->setText(0, in->pubKey());
|
||||
item->setText(0, in.pubKey);
|
||||
item->setFont(0, Utils::getMonospaceFont());
|
||||
item->setText(1, WalletManager::displayAmount(in->amount()));
|
||||
item->setText(1, WalletManager::displayAmount(in.amount));
|
||||
}
|
||||
ui->treeInputs->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
ui->treeInputs->resizeColumnToContents(1);
|
||||
ui->treeInputs->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
ui->label_inputs->setText(QString("Inputs (%1)").arg(QString::number(ci->inputs().size())));
|
||||
ui->label_inputs->setText(QString("Inputs (%1)").arg(QString::number(ci.inputs.size())));
|
||||
|
||||
for (const auto &out: ci->outputs()) {
|
||||
for (const auto &out: ci.outputs) {
|
||||
auto *item = new QTreeWidgetItem(ui->treeOutputs);
|
||||
item->setText(0, out.address);
|
||||
item->setText(1, WalletManager::displayAmount(out.amount));
|
||||
|
@ -175,7 +175,7 @@ void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
|
|||
ui->treeOutputs->resizeColumnToContents(1);
|
||||
ui->treeOutputs->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
ui->label_outputs->setText(QString("Outputs (%1)").arg(QString::number(ci->outputs().size())));
|
||||
ui->label_outputs->setText(QString("Outputs (%1)").arg(QString::number(ci.outputs.size())));
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ void TxConfAdvDialog::txKeyCopy() {
|
|||
return;
|
||||
}
|
||||
|
||||
Utils::copyToClipboard(m_tx->transaction(0)->txKey());
|
||||
Utils::copyToClipboard(m_tx->transaction(0).txKey);
|
||||
}
|
||||
|
||||
void TxConfAdvDialog::broadcastTransaction() {
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
void setUnsignedTransaction(UnsignedTransaction *utx);
|
||||
|
||||
private:
|
||||
void setupConstructionData(ConstructionInfo *ci);
|
||||
void setupConstructionData(const ConstructionInfo& ci);
|
||||
void signTransaction();
|
||||
void broadcastTransaction();
|
||||
void closeDialog();
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
#include "utils/Icons.h"
|
||||
#include "utils/Utils.h"
|
||||
|
||||
TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *parent)
|
||||
TxInfoDialog::TxInfoDialog(Wallet *wallet, const TransactionRow &txInfo, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::TxInfoDialog)
|
||||
, m_wallet(wallet)
|
||||
, m_txInfo(txInfo)
|
||||
, m_txProofDialog(new TxProofDialog(this, wallet, txInfo))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -30,7 +29,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
|||
ui->btn_viewOnBlockExplorer->setToolTip("View on block explorer");
|
||||
connect(ui->btn_viewOnBlockExplorer, &QPushButton::clicked, this, &TxInfoDialog::viewOnBlockExplorer);
|
||||
|
||||
m_txid = txInfo->hash();
|
||||
m_txid = txInfo.hash;
|
||||
ui->label_txid->setText(m_txid);
|
||||
|
||||
connect(ui->btn_copyTxID, &QPushButton::clicked, this, &TxInfoDialog::copyTxID);
|
||||
|
@ -41,7 +40,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
|||
|
||||
this->setData(txInfo);
|
||||
|
||||
if ((txInfo->isFailed() || txInfo->isPending()) && txInfo->direction() != TransactionRow::Direction_In) {
|
||||
if ((txInfo.failed || txInfo.pending) && txInfo.direction != TransactionRow::Direction_In) {
|
||||
connect(ui->btn_rebroadcastTx, &QPushButton::pressed, [this]{
|
||||
emit resendTranscation(m_txid);
|
||||
});
|
||||
|
@ -49,7 +48,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
|||
ui->btn_rebroadcastTx->hide();
|
||||
}
|
||||
|
||||
if (txInfo->direction() == TransactionRow::Direction_In) {
|
||||
if (txInfo.direction == TransactionRow::Direction_In) {
|
||||
ui->btn_CopyTxKey->setDisabled(true);
|
||||
ui->btn_CopyTxKey->setToolTip("No tx secret key available for incoming transactions.");
|
||||
}
|
||||
|
@ -74,7 +73,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
|||
|
||||
QTextCursor cursor = ui->outputs->textCursor();
|
||||
|
||||
auto transfers = txInfo->transfers();
|
||||
auto transfers = txInfo.transfers;
|
||||
if (!transfers.isEmpty()) {
|
||||
bool hasIntegrated = false;
|
||||
|
||||
|
@ -94,7 +93,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
|||
this->adjustHeight(ui->outputs, transfers.size());
|
||||
|
||||
// Trezor saves a mangled payment ID.
|
||||
if (m_wallet->isTrezor() && !hasIntegrated && txInfo->hasPaymentId()) {
|
||||
if (m_wallet->isTrezor() && !hasIntegrated && txInfo.hasPaymentId()) {
|
||||
ui->frame_destinationsWarning->setInfo(icons()->icon("warning"), "The address displayed here does not contain a payment ID. "
|
||||
"If you are making a repeat payment to a service, "
|
||||
"do not copy the address from here to prevent a loss of funds.");
|
||||
|
@ -122,10 +121,10 @@ void TxInfoDialog::adjustHeight(QTextEdit *textEdit, qreal docHeight) {
|
|||
textEdit->verticalScrollBar()->hide();
|
||||
}
|
||||
|
||||
void TxInfoDialog::setData(TransactionRow *tx) {
|
||||
QString blockHeight = QString::number(tx->blockHeight());
|
||||
void TxInfoDialog::setData(const TransactionRow &tx) {
|
||||
QString blockHeight = QString::number(tx.blockHeight);
|
||||
|
||||
if (tx->isFailed()) {
|
||||
if (tx.failed) {
|
||||
ui->label_status->setText("Status: Failed (node was unable to relay transaction)");
|
||||
}
|
||||
if (blockHeight == "0") {
|
||||
|
@ -133,41 +132,47 @@ void TxInfoDialog::setData(TransactionRow *tx) {
|
|||
}
|
||||
else {
|
||||
QString dateTimeFormat = QString("%1 %2").arg(conf()->get(Config::dateFormat).toString(), conf()->get(Config::timeFormat).toString());
|
||||
QString date = tx->timestamp().toString(dateTimeFormat);
|
||||
QString statusText = QString("Status: Included in block %1 (%2 confirmations) on %3").arg(blockHeight, QString::number(tx->confirmations()), date);
|
||||
QString date = tx.timestamp.toString(dateTimeFormat);
|
||||
QString statusText = QString("Status: Included in block %1 (%2 confirmations) on %3").arg(blockHeight, QString::number(tx.confirmations), date);
|
||||
ui->label_status->setText(statusText);
|
||||
}
|
||||
|
||||
|
||||
if (tx->confirmationsRequired() > tx->confirmations()) {
|
||||
bool mandatoryLock = tx->confirmationsRequired() == 10;
|
||||
QString confsRequired = QString::number(tx->confirmationsRequired() - tx->confirmations());
|
||||
if (tx.confirmationsRequired() > tx.confirmations) {
|
||||
bool mandatoryLock = tx.confirmationsRequired() == 10;
|
||||
QString confsRequired = QString::number(tx.confirmationsRequired() - tx.confirmations);
|
||||
ui->label_lock->setText(QString("Lock: Outputs become spendable in %1 blocks (%2)").arg(confsRequired, mandatoryLock ? "consensus rule" : "specified by sender"));
|
||||
} else {
|
||||
ui->label_lock->setText("Lock: Outputs are spendable");
|
||||
}
|
||||
|
||||
QString direction = tx->direction() == TransactionRow::Direction_In ? "received" : "sent";
|
||||
ui->label_amount->setText(QString("Amount %1: %2 XMR").arg(direction, tx->displayAmount()));
|
||||
QString direction = tx.direction == TransactionRow::Direction_In ? "received" : "sent";
|
||||
ui->label_amount->setText(QString("Amount %1: %2 XMR").arg(direction, tx.displayAmount()));
|
||||
|
||||
QString fee;
|
||||
if (tx->isCoinbase())
|
||||
if (tx.coinbase)
|
||||
fee = "Not applicable";
|
||||
else if (tx->direction() == TransactionRow::Direction_In)
|
||||
else if (tx.direction == TransactionRow::Direction_In)
|
||||
fee = "Paid by sender";
|
||||
else if (tx->fee().isEmpty())
|
||||
else if (tx.displayFee().isEmpty())
|
||||
fee = "N/A";
|
||||
else
|
||||
fee = QString("%1 XMR").arg(tx->fee());
|
||||
fee = QString("%1 XMR").arg(tx.displayFee());
|
||||
|
||||
ui->label_fee->setText(QString("Fee: %1").arg(fee));
|
||||
|
||||
}
|
||||
|
||||
void TxInfoDialog::updateData() {
|
||||
TransactionRow *tx = m_wallet->history()->transaction(m_txid);
|
||||
if (!tx) return;
|
||||
this->setData(tx);
|
||||
const auto& rows = m_wallet->history()->getRows();
|
||||
auto itr = std::find_if(rows.begin(), rows.end(),
|
||||
[&](const TransactionRow& ti) {
|
||||
return ti.hash == m_txid;
|
||||
});
|
||||
if (itr == rows.end()) {
|
||||
return;
|
||||
}
|
||||
this->setData(*itr);
|
||||
}
|
||||
|
||||
void TxInfoDialog::copyTxID() {
|
||||
|
@ -207,4 +212,4 @@ void TxInfoDialog::viewOnBlockExplorer() {
|
|||
Utils::externalLinkWarning(this, link);
|
||||
}
|
||||
|
||||
TxInfoDialog::~TxInfoDialog() = default;
|
||||
TxInfoDialog::~TxInfoDialog() = default;
|
||||
|
|
|
@ -21,7 +21,7 @@ class TxInfoDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *parent = nullptr);
|
||||
explicit TxInfoDialog(Wallet *wallet, const TransactionRow &txInfo, QWidget *parent = nullptr);
|
||||
~TxInfoDialog() override;
|
||||
|
||||
signals:
|
||||
|
@ -31,14 +31,13 @@ private:
|
|||
void copyTxID();
|
||||
void copyTxKey();
|
||||
void createTxProof();
|
||||
void setData(TransactionRow *tx);
|
||||
void setData(const TransactionRow& tx);
|
||||
void updateData();
|
||||
void adjustHeight(QTextEdit *textEdit, qreal docHeight);
|
||||
void viewOnBlockExplorer();
|
||||
|
||||
QScopedPointer<Ui::TxInfoDialog> ui;
|
||||
Wallet *m_wallet;
|
||||
TransactionRow *m_txInfo;
|
||||
TxProofDialog *m_txProofDialog;
|
||||
QString m_txid;
|
||||
};
|
||||
|
|
|
@ -10,23 +10,23 @@
|
|||
#include "utils/Icons.h"
|
||||
#include "utils/Utils.h"
|
||||
|
||||
TxProofDialog::TxProofDialog(QWidget *parent, Wallet *wallet, TransactionRow *txInfo)
|
||||
TxProofDialog::TxProofDialog(QWidget *parent, Wallet *wallet, const TransactionRow& txInfo)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::TxProofDialog)
|
||||
, m_wallet(wallet)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_txid = txInfo->hash();
|
||||
m_txid = txInfo.hash;
|
||||
|
||||
m_direction = txInfo->direction();
|
||||
m_direction = txInfo.direction;
|
||||
|
||||
for (auto const &t: txInfo->transfers()) {
|
||||
for (auto const &t: txInfo.transfers) {
|
||||
m_OutDestinations.push_back(t.address);
|
||||
}
|
||||
|
||||
for (auto const &s: txInfo->subaddrIndex()) {
|
||||
m_InDestinations.push_back(m_wallet->address(txInfo->subaddrAccount(), s));
|
||||
for (auto const &s: txInfo.subaddrIndex) {
|
||||
m_InDestinations.push_back(m_wallet->address(txInfo.subaddrAccount, s));
|
||||
}
|
||||
|
||||
// Due to some logic in core we can't create OutProofs
|
||||
|
@ -244,4 +244,4 @@ TxProof TxProofDialog::getProof() {
|
|||
return proof;
|
||||
}
|
||||
|
||||
TxProofDialog::~TxProofDialog() = default;
|
||||
TxProofDialog::~TxProofDialog() = default;
|
||||
|
|
|
@ -19,7 +19,7 @@ class TxProofDialog : public WindowModalDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TxProofDialog(QWidget *parent, Wallet *wallet, TransactionRow *txid);
|
||||
explicit TxProofDialog(QWidget *parent, Wallet *wallet, const TransactionRow &txid);
|
||||
~TxProofDialog() override;
|
||||
void setTxId(const QString &txid);
|
||||
void getTxKey();
|
||||
|
|
|
@ -7,47 +7,21 @@
|
|||
#include "Transfer.h"
|
||||
#include <wallet/api/wallet2_api.h>
|
||||
|
||||
quint64 ConstructionInfo::unlockTime() const {
|
||||
return m_unlockTime;
|
||||
}
|
||||
|
||||
QSet<quint32> ConstructionInfo::subaddressIndices() const {
|
||||
return m_subaddressIndices;
|
||||
}
|
||||
|
||||
QVector<QString> ConstructionInfo::subaddresses() const {
|
||||
return m_subaddresses;
|
||||
}
|
||||
|
||||
quint64 ConstructionInfo::minMixinCount() const {
|
||||
return m_minMixinCount;
|
||||
}
|
||||
|
||||
QList<Input *> ConstructionInfo::inputs() const {
|
||||
return m_inputs;
|
||||
}
|
||||
|
||||
QList<Transfer> ConstructionInfo::outputs() const {
|
||||
return m_outputs;
|
||||
}
|
||||
|
||||
ConstructionInfo::ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_unlockTime(pimpl->unlockTime())
|
||||
, m_minMixinCount(pimpl->minMixinCount())
|
||||
ConstructionInfo::ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl)
|
||||
: unlockTime(pimpl->unlockTime())
|
||||
, minMixinCount(pimpl->minMixinCount())
|
||||
{
|
||||
for (auto const &i : pimpl->inputs())
|
||||
{
|
||||
Input *input = new Input(i.amount, QString::fromStdString(i.pubkey), this);
|
||||
m_inputs.append(input);
|
||||
inputs.emplace_back(i.amount, QString::fromStdString(i.pubkey));
|
||||
}
|
||||
|
||||
for (auto const &o : pimpl->outputs())
|
||||
{
|
||||
m_outputs.emplace_back(o.amount, QString::fromStdString(o.address));
|
||||
outputs.emplace_back(o.amount, QString::fromStdString(o.address));
|
||||
}
|
||||
for (uint32_t i : pimpl->subaddressIndices())
|
||||
{
|
||||
m_subaddressIndices.insert(i);
|
||||
subaddressIndices.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,39 +4,25 @@
|
|||
#ifndef FEATHER_CONSTRUCTIONINFO_H
|
||||
#define FEATHER_CONSTRUCTIONINFO_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include "Transfer.h"
|
||||
|
||||
class Input;
|
||||
#include "Transfer.h"
|
||||
#include "Input.h"
|
||||
|
||||
namespace Monero {
|
||||
class TransactionConstructionInfo;
|
||||
}
|
||||
|
||||
class ConstructionInfo : public QObject
|
||||
struct ConstructionInfo
|
||||
{
|
||||
Q_OBJECT
|
||||
quint64 unlockTime;
|
||||
QSet<quint32> subaddressIndices;
|
||||
QVector<QString> subaddresses;
|
||||
quint64 minMixinCount;
|
||||
QList<Input> inputs;
|
||||
QList<Transfer> outputs;
|
||||
|
||||
public:
|
||||
quint64 unlockTime() const;
|
||||
QSet<quint32> subaddressIndices() const;
|
||||
QVector<QString> subaddresses() const;
|
||||
quint64 minMixinCount() const;
|
||||
QList<Input*> inputs() const;
|
||||
QList<Transfer> outputs() const;
|
||||
|
||||
private:
|
||||
explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent = nullptr);
|
||||
|
||||
friend class PendingTransactionInfo;
|
||||
friend class UnsignedTransaction;
|
||||
quint64 m_unlockTime;
|
||||
QSet<quint32> m_subaddressIndices;
|
||||
QVector<QString> m_subaddresses;
|
||||
quint64 m_minMixinCount;
|
||||
mutable QList<Input*> m_inputs;
|
||||
mutable QList<Transfer> m_outputs;
|
||||
explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl);
|
||||
};
|
||||
|
||||
#endif //FEATHER_CONSTRUCTIONINFO_H
|
||||
|
|
|
@ -4,22 +4,14 @@
|
|||
#ifndef FEATHER_INPUT_H
|
||||
#define FEATHER_INPUT_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Input : public QObject
|
||||
struct Input
|
||||
{
|
||||
Q_OBJECT
|
||||
QString pubKey;
|
||||
quint64 amount;
|
||||
|
||||
private:
|
||||
explicit Input(uint64_t _amount, QString _address, QObject *parent = nullptr): QObject(parent), m_amount(_amount), m_pubkey(std::move(_address)) {};
|
||||
|
||||
friend class ConstructionInfo;
|
||||
quint64 m_amount;
|
||||
QString m_pubkey;
|
||||
|
||||
public:
|
||||
quint64 amount() const { return m_amount; }
|
||||
QString pubKey() const { return m_pubkey; }
|
||||
explicit Input(uint64_t _amount, QString _pubkey)
|
||||
: pubKey(std::move(_pubkey))
|
||||
, amount(_amount) {}
|
||||
};
|
||||
|
||||
#endif //FEATHER_INPUT_H
|
||||
|
|
|
@ -90,18 +90,17 @@ quint64 PendingTransaction::weight(int index) const
|
|||
return m_pimpl->weight(index);
|
||||
}
|
||||
|
||||
PendingTransactionInfo * PendingTransaction::transaction(int index) const {
|
||||
const PendingTransactionInfo& PendingTransaction::transaction(int index) const {
|
||||
return m_pending_tx_info[index];
|
||||
}
|
||||
|
||||
void PendingTransaction::refresh()
|
||||
{
|
||||
qDeleteAll(m_pending_tx_info);
|
||||
m_pending_tx_info.clear();
|
||||
|
||||
m_pimpl->refresh();
|
||||
for (const auto i : m_pimpl->getAll()) {
|
||||
m_pending_tx_info.append(new PendingTransactionInfo(i, this));
|
||||
m_pending_tx_info.emplace_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
quint64 weight(int index) const;
|
||||
void refresh();
|
||||
|
||||
PendingTransactionInfo * transaction(int index) const;
|
||||
const PendingTransactionInfo& transaction(int index) const;
|
||||
|
||||
private:
|
||||
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = nullptr);
|
||||
|
@ -50,7 +50,7 @@ private:
|
|||
private:
|
||||
friend class Wallet;
|
||||
Monero::PendingTransaction * m_pimpl;
|
||||
mutable QList<PendingTransactionInfo*> m_pending_tx_info;
|
||||
mutable QList<PendingTransactionInfo> m_pending_tx_info;
|
||||
};
|
||||
|
||||
#endif // PENDINGTRANSACTION_H
|
||||
|
|
|
@ -4,28 +4,12 @@
|
|||
#include "PendingTransactionInfo.h"
|
||||
#include <wallet/api/wallet2_api.h>
|
||||
|
||||
quint64 PendingTransactionInfo::fee() const {
|
||||
return m_fee;
|
||||
}
|
||||
|
||||
quint64 PendingTransactionInfo::dust() const {
|
||||
return m_dust;
|
||||
}
|
||||
|
||||
bool PendingTransactionInfo::dustAddedToFee() const {
|
||||
return m_dustAddedToFee;
|
||||
}
|
||||
|
||||
QString PendingTransactionInfo::txKey() const {
|
||||
return m_txKey;
|
||||
}
|
||||
|
||||
PendingTransactionInfo::PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent)
|
||||
: ConstructionInfo(pimpl->constructionData(), parent)
|
||||
, m_fee(pimpl->fee())
|
||||
, m_dust(pimpl->dust())
|
||||
, m_dustAddedToFee(pimpl->dustAddedToFee())
|
||||
, m_txKey(QString::fromStdString(pimpl->txKey()))
|
||||
PendingTransactionInfo::PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl)
|
||||
: ConstructionInfo(pimpl->constructionData())
|
||||
, fee(pimpl->fee())
|
||||
, dust(pimpl->dust())
|
||||
, dustAddedToFee(pimpl->dustAddedToFee())
|
||||
, txKey(QString::fromStdString(pimpl->txKey()))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,34 +5,21 @@
|
|||
#define FEATHER_PENDINGTRANSACTIONINFO_H
|
||||
|
||||
#include "ConstructionInfo.h"
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
|
||||
class Input;
|
||||
class Transfer;
|
||||
#include <QObject>
|
||||
|
||||
namespace Monero {
|
||||
class PendingTransactionInfo;
|
||||
}
|
||||
|
||||
class PendingTransactionInfo : public ConstructionInfo
|
||||
struct PendingTransactionInfo : ConstructionInfo
|
||||
{
|
||||
Q_OBJECT
|
||||
quint64 fee;
|
||||
quint64 dust;
|
||||
bool dustAddedToFee;
|
||||
QString txKey;
|
||||
|
||||
public:
|
||||
quint64 fee() const;
|
||||
quint64 dust() const;
|
||||
bool dustAddedToFee() const;
|
||||
QString txKey() const;
|
||||
|
||||
private:
|
||||
explicit PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent = nullptr);
|
||||
|
||||
friend class PendingTransaction;
|
||||
quint64 m_fee;
|
||||
quint64 m_dust;
|
||||
bool m_dustAddedToFee;
|
||||
QString m_txKey;
|
||||
explicit PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl);
|
||||
};
|
||||
|
||||
#endif //FEATHER_PENDINGTRANSACTIONINFO_H
|
||||
|
|
|
@ -27,40 +27,19 @@ QString description(tools::wallet2 *wallet2, const tools::wallet2::payment_detai
|
|||
return description;
|
||||
}
|
||||
|
||||
bool TransactionHistory::transaction(int index, std::function<void (TransactionRow &)> callback)
|
||||
{
|
||||
QReadLocker locker(&m_lock);
|
||||
|
||||
if (index < 0 || index >= m_rows.size()) {
|
||||
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
|
||||
qCritical("%s: there's %d transactions in backend", __FUNCTION__, this->count());
|
||||
return false;
|
||||
}
|
||||
|
||||
callback(*m_rows.value(index));
|
||||
return true;
|
||||
}
|
||||
|
||||
TransactionRow* TransactionHistory::transaction(const QString &id)
|
||||
{
|
||||
QReadLocker locker(&m_lock);
|
||||
|
||||
auto itr = std::find_if(m_rows.begin(), m_rows.end(),
|
||||
[&](const TransactionRow * ti) {
|
||||
return ti->hash() == id;
|
||||
});
|
||||
return itr != m_rows.end() ? *itr : nullptr;
|
||||
}
|
||||
|
||||
TransactionRow* TransactionHistory::transaction(int index)
|
||||
const TransactionRow& TransactionHistory::transaction(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_rows.size()) {
|
||||
return nullptr;
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
|
||||
return m_rows[index];
|
||||
}
|
||||
|
||||
const QList<TransactionRow>& TransactionHistory::getRows()
|
||||
{
|
||||
return m_rows;
|
||||
}
|
||||
|
||||
void TransactionHistory::refresh()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
@ -106,24 +85,24 @@ void TransactionHistory::refresh()
|
|||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||
payment_id = payment_id.substr(0,16);
|
||||
|
||||
auto* t = new TransactionRow(this);
|
||||
t->m_paymentId = QString::fromStdString(payment_id);
|
||||
t->m_coinbase = pd.m_coinbase;
|
||||
t->m_amount = pd.m_amount;
|
||||
t->m_balanceDelta = pd.m_amount;
|
||||
t->m_fee = pd.m_fee;
|
||||
t->m_direction = TransactionRow::Direction_In;
|
||||
t->m_hash = QString::fromStdString(epee::string_tools::pod_to_hex(pd.m_tx_hash));
|
||||
t->m_blockHeight = pd.m_block_height;
|
||||
t->m_subaddrIndex = { pd.m_subaddr_index.minor };
|
||||
t->m_subaddrAccount = pd.m_subaddr_index.major;
|
||||
t->m_label = QString::fromStdString(m_wallet2->get_subaddress_label(pd.m_subaddr_index));
|
||||
t->m_timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
|
||||
t->m_unlockTime = pd.m_unlock_time;
|
||||
t->m_description = description(m_wallet2, pd);
|
||||
TransactionRow t;
|
||||
t.paymentId = QString::fromStdString(payment_id);
|
||||
t.coinbase = pd.m_coinbase;
|
||||
t.amount = pd.m_amount;
|
||||
t.balanceDelta = pd.m_amount;
|
||||
t.fee = pd.m_fee;
|
||||
t.direction = TransactionRow::Direction_In;
|
||||
t.hash = QString::fromStdString(epee::string_tools::pod_to_hex(pd.m_tx_hash));
|
||||
t.blockHeight = pd.m_block_height;
|
||||
t.subaddrIndex = { pd.m_subaddr_index.minor };
|
||||
t.subaddrAccount = pd.m_subaddr_index.major;
|
||||
t.label = QString::fromStdString(m_wallet2->get_subaddress_label(pd.m_subaddr_index));
|
||||
t.timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t.confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
|
||||
t.unlockTime = pd.m_unlock_time;
|
||||
t.description = description(m_wallet2, pd);
|
||||
|
||||
m_rows.append(t);
|
||||
m_rows.append(std::move(t));
|
||||
}
|
||||
|
||||
// confirmed output transactions
|
||||
|
@ -153,42 +132,42 @@ void TransactionHistory::refresh()
|
|||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||
payment_id = payment_id.substr(0,16);
|
||||
|
||||
auto* t = new TransactionRow(this);
|
||||
t->m_paymentId = QString::fromStdString(payment_id);
|
||||
TransactionRow t;
|
||||
t.paymentId = QString::fromStdString(payment_id);
|
||||
|
||||
t->m_amount = pd.m_amount_out - change;
|
||||
t->m_balanceDelta = change - pd.m_amount_in;
|
||||
t->m_fee = fee;
|
||||
t.amount = pd.m_amount_out - change;
|
||||
t.balanceDelta = change - pd.m_amount_in;
|
||||
t.fee = fee;
|
||||
|
||||
t->m_direction = TransactionRow::Direction_Out;
|
||||
t->m_hash = QString::fromStdString(epee::string_tools::pod_to_hex(hash));
|
||||
t->m_blockHeight = pd.m_block_height;
|
||||
t->m_description = QString::fromStdString(m_wallet2->get_tx_note(hash));
|
||||
t->m_subaddrAccount = pd.m_subaddr_account;
|
||||
t->m_label = QString::fromStdString(pd.m_subaddr_indices.size() == 1 ? m_wallet2->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "");
|
||||
t->m_timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
|
||||
t.direction = TransactionRow::Direction_Out;
|
||||
t.hash = QString::fromStdString(epee::string_tools::pod_to_hex(hash));
|
||||
t.blockHeight = pd.m_block_height;
|
||||
t.description = QString::fromStdString(m_wallet2->get_tx_note(hash));
|
||||
t.subaddrAccount = pd.m_subaddr_account;
|
||||
t.label = QString::fromStdString(pd.m_subaddr_indices.size() == 1 ? m_wallet2->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "");
|
||||
t.timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t.confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
|
||||
|
||||
for (uint32_t idx : t->subaddrIndex())
|
||||
for (uint32_t idx : t.subaddrIndex)
|
||||
{
|
||||
t->m_subaddrIndex.insert(idx);
|
||||
t.subaddrIndex.insert(idx);
|
||||
}
|
||||
|
||||
// single output transaction might contain multiple transfers
|
||||
for (auto const &d: pd.m_dests)
|
||||
{
|
||||
t->m_transfers.emplace_back(
|
||||
t.transfers.emplace_back(
|
||||
d.amount,
|
||||
QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id, !hasFakePaymentId)));
|
||||
}
|
||||
for (auto const &r: pd.m_rings)
|
||||
{
|
||||
t->m_rings.emplace_back(
|
||||
t.rings.emplace_back(
|
||||
QString::fromStdString(epee::string_tools::pod_to_hex(r.first)),
|
||||
cryptonote::relative_output_offsets_to_absolute(r.second));
|
||||
}
|
||||
|
||||
m_rows.append(t);
|
||||
m_rows.append(std::move(t));
|
||||
}
|
||||
|
||||
// unconfirmed output transactions
|
||||
|
@ -209,41 +188,41 @@ void TransactionHistory::refresh()
|
|||
payment_id = payment_id.substr(0,16);
|
||||
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
|
||||
|
||||
auto *t = new TransactionRow(this);
|
||||
t->m_paymentId = QString::fromStdString(payment_id);
|
||||
TransactionRow t;
|
||||
t.paymentId = QString::fromStdString(payment_id);
|
||||
|
||||
t->m_amount = pd.m_amount_out - change;
|
||||
t->m_balanceDelta = change - pd.m_amount_in;
|
||||
t->m_fee = fee;
|
||||
t.amount = pd.m_amount_out - change;
|
||||
t.balanceDelta = change - pd.m_amount_in;
|
||||
t.fee = fee;
|
||||
|
||||
t->m_direction = TransactionRow::Direction_Out;
|
||||
t->m_failed = is_failed;
|
||||
t->m_pending = true;
|
||||
t->m_hash = QString::fromStdString(epee::string_tools::pod_to_hex(hash));
|
||||
t->m_description = QString::fromStdString(m_wallet2->get_tx_note(hash));
|
||||
t->m_subaddrAccount = pd.m_subaddr_account;
|
||||
t->m_label = QString::fromStdString(pd.m_subaddr_indices.size() == 1 ? m_wallet2->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "");
|
||||
t->m_timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t->m_confirmations = 0;
|
||||
for (uint32_t idx : t->subaddrIndex())
|
||||
t.direction = TransactionRow::Direction_Out;
|
||||
t.failed = is_failed;
|
||||
t.pending = true;
|
||||
t.hash = QString::fromStdString(epee::string_tools::pod_to_hex(hash));
|
||||
t.description = QString::fromStdString(m_wallet2->get_tx_note(hash));
|
||||
t.subaddrAccount = pd.m_subaddr_account;
|
||||
t.label = QString::fromStdString(pd.m_subaddr_indices.size() == 1 ? m_wallet2->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "");
|
||||
t.timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t.confirmations = 0;
|
||||
for (uint32_t idx : t.subaddrIndex)
|
||||
{
|
||||
t->m_subaddrIndex.insert(idx);
|
||||
t.subaddrIndex.insert(idx);
|
||||
}
|
||||
|
||||
for (auto const &d: pd.m_dests)
|
||||
{
|
||||
t->m_transfers.emplace_back(
|
||||
t.transfers.emplace_back(
|
||||
d.amount,
|
||||
QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id, !hasFakePaymentId)));
|
||||
}
|
||||
for (auto const &r: pd.m_rings)
|
||||
{
|
||||
t->m_rings.emplace_back(
|
||||
t.rings.emplace_back(
|
||||
QString::fromStdString(epee::string_tools::pod_to_hex(r.first)),
|
||||
cryptonote::relative_output_offsets_to_absolute(r.second));
|
||||
}
|
||||
|
||||
m_rows.append(t);
|
||||
m_rows.append(std::move(t));
|
||||
}
|
||||
|
||||
|
||||
|
@ -259,22 +238,24 @@ void TransactionHistory::refresh()
|
|||
std::string payment_id = epee::string_tools::pod_to_hex(i->first);
|
||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||
payment_id = payment_id.substr(0,16);
|
||||
auto *t = new TransactionRow(this);
|
||||
t->m_paymentId = QString::fromStdString(payment_id);
|
||||
t->m_amount = pd.m_amount;
|
||||
t->m_balanceDelta = pd.m_amount;
|
||||
t->m_direction = TransactionRow::Direction_In;
|
||||
t->m_hash = QString::fromStdString(epee::string_tools::pod_to_hex(pd.m_tx_hash));
|
||||
t->m_blockHeight = pd.m_block_height;
|
||||
t->m_pending = true;
|
||||
t->m_subaddrIndex = { pd.m_subaddr_index.minor };
|
||||
t->m_subaddrAccount = pd.m_subaddr_index.major;
|
||||
t->m_label = QString::fromStdString(m_wallet2->get_subaddress_label(pd.m_subaddr_index));
|
||||
t->m_timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t->m_confirmations = 0;
|
||||
t->m_description = description(m_wallet2, pd);
|
||||
|
||||
m_rows.append(t);
|
||||
TransactionRow t;
|
||||
|
||||
t.paymentId = QString::fromStdString(payment_id);
|
||||
t.amount = pd.m_amount;
|
||||
t.balanceDelta = pd.m_amount;
|
||||
t.direction = TransactionRow::Direction_In;
|
||||
t.hash = QString::fromStdString(epee::string_tools::pod_to_hex(pd.m_tx_hash));
|
||||
t.blockHeight = pd.m_block_height;
|
||||
t.pending = true;
|
||||
t.subaddrIndex = { pd.m_subaddr_index.minor };
|
||||
t.subaddrAccount = pd.m_subaddr_index.major;
|
||||
t.label = QString::fromStdString(m_wallet2->get_subaddress_label(pd.m_subaddr_index));
|
||||
t.timestamp = QDateTime::fromSecsSinceEpoch(pd.m_timestamp);
|
||||
t.confirmations = 0;
|
||||
t.description = description(m_wallet2, pd);
|
||||
|
||||
m_rows.append(std::move(t));
|
||||
|
||||
LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
|
||||
}
|
||||
|
@ -341,7 +322,6 @@ TransactionHistory::TransactionHistory(Wallet *wallet, tools::wallet2 *wallet2,
|
|||
}
|
||||
|
||||
void TransactionHistory::clearRows() {
|
||||
qDeleteAll(m_rows);
|
||||
m_rows.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ class TransactionHistory : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
bool transaction(int index, std::function<void (TransactionRow &)> callback);
|
||||
TransactionRow * transaction(const QString &id);
|
||||
TransactionRow* transaction(int index);
|
||||
const TransactionRow& transaction(int index);
|
||||
const QList<TransactionRow>& getRows();
|
||||
|
||||
void refresh();
|
||||
void setTxNote(const QString &txid, const QString ¬e);
|
||||
quint64 count() const;
|
||||
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
Wallet *m_wallet;
|
||||
tools::wallet2 *m_wallet2;
|
||||
QList<TransactionRow*> m_rows;
|
||||
QList<TransactionRow> m_rows;
|
||||
|
||||
mutable QDateTime m_firstDateTime;
|
||||
mutable QDateTime m_lastDateTime;
|
||||
|
|
|
@ -87,18 +87,17 @@ void UnsignedTransaction::setFilename(const QString &fileName)
|
|||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
ConstructionInfo * UnsignedTransaction::constructionInfo(int index) const {
|
||||
const ConstructionInfo& UnsignedTransaction::constructionInfo(int index) const {
|
||||
return m_construction_info[index];
|
||||
}
|
||||
|
||||
void UnsignedTransaction::refresh()
|
||||
{
|
||||
qDeleteAll(m_construction_info);
|
||||
m_construction_info.clear();
|
||||
|
||||
m_pimpl->refresh();
|
||||
for (const auto i : m_pimpl->getAll()) {
|
||||
m_construction_info.append(new ConstructionInfo(i, this));
|
||||
m_construction_info.emplace_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
void setFilename(const QString &fileName);
|
||||
void refresh();
|
||||
|
||||
ConstructionInfo * constructionInfo(int index) const;
|
||||
const ConstructionInfo& constructionInfo(int index) const;
|
||||
|
||||
private:
|
||||
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = nullptr);
|
||||
|
@ -51,7 +51,7 @@ private:
|
|||
Monero::UnsignedTransaction * m_pimpl;
|
||||
QString m_fileName;
|
||||
Monero::Wallet * m_walletImpl;
|
||||
mutable QList<ConstructionInfo*> m_construction_info;
|
||||
mutable QList<ConstructionInfo> m_construction_info;
|
||||
};
|
||||
|
||||
#endif // UNSIGNEDTRANSACTION_H
|
||||
|
|
|
@ -5,171 +5,75 @@
|
|||
#include "WalletManager.h"
|
||||
#include "Transfer.h"
|
||||
|
||||
TransactionRow::TransactionRow(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_direction(TransactionRow::Direction_Out)
|
||||
, m_pending(false)
|
||||
, m_failed(false)
|
||||
, m_coinbase(false)
|
||||
, m_amount(0)
|
||||
, m_balanceDelta(0)
|
||||
, m_fee(0)
|
||||
, m_blockHeight(0)
|
||||
, m_subaddrAccount(0)
|
||||
, m_confirmations(0)
|
||||
, m_unlockTime(0)
|
||||
, m_confirmationsRequired(0)
|
||||
TransactionRow::TransactionRow()
|
||||
: amount(0)
|
||||
, balanceDelta(0)
|
||||
, blockHeight(0)
|
||||
, confirmations(0)
|
||||
, direction(TransactionRow::Direction_Out)
|
||||
, subaddrAccount(0)
|
||||
, unlockTime(0)
|
||||
, failed(false)
|
||||
, pending(false)
|
||||
, coinbase(false)
|
||||
, fee(0)
|
||||
{
|
||||
}
|
||||
|
||||
TransactionRow::Direction TransactionRow::direction() const
|
||||
double TransactionRow::amountDouble() const
|
||||
{
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
bool TransactionRow::isPending() const
|
||||
{
|
||||
return m_pending;
|
||||
}
|
||||
|
||||
bool TransactionRow::isFailed() const
|
||||
{
|
||||
return m_failed;
|
||||
}
|
||||
|
||||
bool TransactionRow::isCoinbase() const
|
||||
{
|
||||
return m_coinbase;
|
||||
}
|
||||
|
||||
qint64 TransactionRow::balanceDelta() const
|
||||
{
|
||||
return m_balanceDelta;
|
||||
}
|
||||
|
||||
double TransactionRow::amount() const
|
||||
{
|
||||
// there's no unsigned uint64 for JS, so better use double
|
||||
return displayAmount().toDouble();
|
||||
}
|
||||
|
||||
qint64 TransactionRow::atomicAmount() const
|
||||
{
|
||||
return m_amount;
|
||||
}
|
||||
|
||||
QString TransactionRow::displayAmount() const
|
||||
{
|
||||
return WalletManager::displayAmount(m_amount);
|
||||
return WalletManager::displayAmount(amount);
|
||||
}
|
||||
|
||||
quint64 TransactionRow::atomicFee() const
|
||||
QString TransactionRow::displayFee() const
|
||||
{
|
||||
return m_fee;
|
||||
}
|
||||
|
||||
QString TransactionRow::fee() const
|
||||
{
|
||||
if(m_fee == 0)
|
||||
if (fee == 0)
|
||||
return "";
|
||||
return WalletManager::displayAmount(m_fee);
|
||||
}
|
||||
|
||||
quint64 TransactionRow::blockHeight() const
|
||||
{
|
||||
return m_blockHeight;
|
||||
}
|
||||
|
||||
QString TransactionRow::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
QSet<quint32> TransactionRow::subaddrIndex() const
|
||||
{
|
||||
return m_subaddrIndex;
|
||||
}
|
||||
|
||||
quint32 TransactionRow::subaddrAccount() const
|
||||
{
|
||||
return m_subaddrAccount;
|
||||
}
|
||||
|
||||
QString TransactionRow::label() const
|
||||
{
|
||||
return m_label;
|
||||
}
|
||||
|
||||
quint64 TransactionRow::confirmations() const
|
||||
{
|
||||
return m_confirmations;
|
||||
return WalletManager::displayAmount(fee);
|
||||
}
|
||||
|
||||
quint64 TransactionRow::confirmationsRequired() const
|
||||
{
|
||||
return (m_blockHeight < m_unlockTime) ? m_unlockTime - m_blockHeight : 10;
|
||||
}
|
||||
|
||||
quint64 TransactionRow::unlockTime() const
|
||||
{
|
||||
return m_unlockTime;
|
||||
}
|
||||
|
||||
QString TransactionRow::hash() const
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
QDateTime TransactionRow::timestamp() const
|
||||
{
|
||||
return m_timestamp;
|
||||
return (blockHeight < unlockTime) ? unlockTime - blockHeight : 10;
|
||||
}
|
||||
|
||||
QString TransactionRow::date() const
|
||||
{
|
||||
return timestamp().date().toString(Qt::ISODate);
|
||||
return timestamp.date().toString(Qt::ISODate);
|
||||
}
|
||||
|
||||
QString TransactionRow::time() const
|
||||
{
|
||||
return timestamp().time().toString(Qt::ISODate);
|
||||
}
|
||||
|
||||
QString TransactionRow::paymentId() const
|
||||
{
|
||||
return m_paymentId;
|
||||
return timestamp.time().toString(Qt::ISODate);
|
||||
}
|
||||
|
||||
QList<QString> TransactionRow::destinations() const
|
||||
{
|
||||
QList<QString> dests;
|
||||
for (auto const& t: m_transfers) {
|
||||
for (auto const& t: transfers) {
|
||||
dests.append(t.address);
|
||||
}
|
||||
return dests;
|
||||
}
|
||||
|
||||
QList<Transfer> TransactionRow::transfers() const {
|
||||
return m_transfers;
|
||||
}
|
||||
|
||||
QString TransactionRow::rings_formatted() const
|
||||
{
|
||||
QString rings;
|
||||
for (auto const& r: m_rings) {
|
||||
rings += r.keyImage + ": \n";
|
||||
QString ringsStr;
|
||||
for (auto const& r: rings) {
|
||||
ringsStr += r.keyImage + ": \n";
|
||||
for (uint64_t m : r.ringMembers){
|
||||
rings += QString::number(m) + " ";
|
||||
ringsStr += QString::number(m) + " ";
|
||||
}
|
||||
rings += "\n\n";
|
||||
ringsStr += "\n\n";
|
||||
}
|
||||
return rings;
|
||||
return ringsStr;
|
||||
}
|
||||
|
||||
bool TransactionRow::hasPaymentId() const {
|
||||
return m_paymentId != "0000000000000000";
|
||||
}
|
||||
|
||||
TransactionRow::~TransactionRow()
|
||||
{
|
||||
return paymentId != "0000000000000000";
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#ifndef FEATHER_TRANSACTIONROW_H
|
||||
#define FEATHER_TRANSACTIONROW_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QDateTime>
|
||||
|
||||
|
@ -19,75 +18,45 @@ struct Ring
|
|||
};
|
||||
struct Transfer;
|
||||
|
||||
class TransactionRow : public QObject
|
||||
struct TransactionRow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~TransactionRow() override;
|
||||
|
||||
enum Direction {
|
||||
Direction_In = 0,
|
||||
Direction_Out = 1,
|
||||
Direction_Both // invalid direction value, used for filtering
|
||||
};
|
||||
|
||||
Q_ENUM(Direction)
|
||||
QList<Transfer> transfers;
|
||||
QList<Ring> rings;
|
||||
qint64 amount; // Amount that was sent (to destinations) or received, excludes tx fee
|
||||
qint64 balanceDelta; // How much the total balance was mutated as a result of this tx (includes tx fee)
|
||||
quint64 blockHeight;
|
||||
QString description;
|
||||
quint64 confirmations;
|
||||
Direction direction;
|
||||
QString hash;
|
||||
QString label;
|
||||
QString paymentId;
|
||||
quint32 subaddrAccount;
|
||||
QSet<quint32> subaddrIndex;
|
||||
QDateTime timestamp;
|
||||
quint64 unlockTime;
|
||||
bool failed;
|
||||
bool pending;
|
||||
bool coinbase;
|
||||
quint64 fee;
|
||||
|
||||
Direction direction() const;
|
||||
bool isPending() const;
|
||||
bool isFailed() const;
|
||||
bool isCoinbase() const;
|
||||
qint64 balanceDelta() const;
|
||||
double amount() const;
|
||||
qint64 atomicAmount() const;
|
||||
QString displayFee() const;
|
||||
QString displayAmount() const;
|
||||
QString fee() const;
|
||||
quint64 atomicFee() const;
|
||||
quint64 blockHeight() const;
|
||||
QString description() const;
|
||||
QSet<quint32> subaddrIndex() const;
|
||||
quint32 subaddrAccount() const;
|
||||
QString label() const;
|
||||
quint64 confirmations() const;
|
||||
double amountDouble() const;
|
||||
quint64 confirmationsRequired() const;
|
||||
quint64 unlockTime() const;
|
||||
QString hash() const;
|
||||
QDateTime timestamp() const;
|
||||
QString date() const;
|
||||
QString time() const;
|
||||
QString paymentId() const;
|
||||
QList<QString> destinations() const;
|
||||
QList<Transfer> transfers() const;
|
||||
QString rings_formatted() const;
|
||||
bool hasPaymentId() const;
|
||||
|
||||
private:
|
||||
explicit TransactionRow(QObject *parent);
|
||||
|
||||
private:
|
||||
friend class TransactionHistory;
|
||||
QList<Transfer> m_transfers;
|
||||
QList<Ring> m_rings;
|
||||
qint64 m_amount; // Amount that was sent (to destinations) or received, excludes tx fee
|
||||
qint64 m_balanceDelta; // How much the total balance was mutated as a result of this tx (includes tx fee)
|
||||
quint64 m_blockHeight;
|
||||
QString m_description;
|
||||
quint64 m_confirmations;
|
||||
quint64 m_confirmationsRequired;
|
||||
Direction m_direction;
|
||||
bool m_failed;
|
||||
quint64 m_fee;
|
||||
QString m_hash;
|
||||
QString m_label;
|
||||
QString m_paymentId;
|
||||
bool m_pending;
|
||||
quint32 m_subaddrAccount;
|
||||
QSet<quint32> m_subaddrIndex;
|
||||
QDateTime m_timestamp;
|
||||
quint64 m_unlockTime;
|
||||
bool m_coinbase;
|
||||
explicit TransactionRow();
|
||||
};
|
||||
|
||||
|
||||
#endif //FEATHER_TRANSACTIONROW_H
|
||||
|
|
|
@ -75,16 +75,6 @@ TransactionHistoryModel* HistoryView::sourceModel()
|
|||
return dynamic_cast<TransactionHistoryModel *>(m_model->sourceModel());
|
||||
}
|
||||
|
||||
TransactionRow* HistoryView::currentEntry()
|
||||
{
|
||||
QModelIndexList list = selectionModel()->selectedRows();
|
||||
if (list.size() == 1) {
|
||||
return this->sourceModel()->entryFromIndex(m_model->mapToSource(list.first()));
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryView::setSearchMode(bool mode) {
|
||||
if (!m_inSearchMode) {
|
||||
m_showTxidColumn = !header()->isSectionHidden(TransactionHistoryModel::TxID);
|
||||
|
@ -213,12 +203,26 @@ void HistoryView::resetViewToDefaults()
|
|||
}
|
||||
|
||||
void HistoryView::keyPressEvent(QKeyEvent *event) {
|
||||
TransactionRow* tx = this->currentEntry();
|
||||
auto index = this->getCurrentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
const TransactionRow& tx = sourceModel()->entryFromIndex(index);
|
||||
|
||||
if (event->matches(QKeySequence::Copy) && tx) {
|
||||
Utils::copyToClipboard(tx->hash());
|
||||
if (event->matches(QKeySequence::Copy)) {
|
||||
Utils::copyToClipboard(tx.hash);
|
||||
}
|
||||
else {
|
||||
QTreeView::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex HistoryView::getCurrentIndex()
|
||||
{
|
||||
QModelIndexList list = this->selectionModel()->selectedRows();
|
||||
if (list.length() < 1) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return m_model->mapToSource(list.first());
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@ class HistoryView : public QTreeView
|
|||
public:
|
||||
explicit HistoryView(QWidget* parent = nullptr);
|
||||
void setHistoryModel(TransactionHistoryProxyModel *model);
|
||||
TransactionRow* currentEntry();
|
||||
|
||||
void setSearchMode(bool mode);
|
||||
QByteArray viewState() const;
|
||||
bool setViewState(const QByteArray& state);
|
||||
QModelIndex getCurrentIndex();
|
||||
TransactionHistoryModel* sourceModel();
|
||||
|
||||
private slots:
|
||||
void showHeaderMenu(const QPoint& position);
|
||||
|
@ -36,8 +37,6 @@ protected:
|
|||
void keyPressEvent(QKeyEvent *event);
|
||||
|
||||
private:
|
||||
TransactionHistoryModel* sourceModel();
|
||||
|
||||
TransactionHistoryProxyModel* m_model;
|
||||
bool m_inSearchMode = false;
|
||||
bool m_columnsNeedRelayout = true;
|
||||
|
|
|
@ -33,7 +33,7 @@ TransactionHistory *TransactionHistoryModel::transactionHistory() const {
|
|||
return m_transactionHistory;
|
||||
}
|
||||
|
||||
TransactionRow* TransactionHistoryModel::entryFromIndex(const QModelIndex &index) const {
|
||||
const TransactionRow& TransactionHistoryModel::entryFromIndex(const QModelIndex &index) const {
|
||||
Q_ASSERT(index.isValid() && index.row() < m_transactionHistory->count());
|
||||
return m_transactionHistory->transaction(index.row());
|
||||
}
|
||||
|
@ -55,87 +55,79 @@ int TransactionHistoryModel::columnCount(const QModelIndex &parent) const {
|
|||
}
|
||||
|
||||
QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const {
|
||||
if (!m_transactionHistory) {
|
||||
return QVariant();
|
||||
const QList<TransactionRow>& rows = m_transactionHistory->getRows();
|
||||
if (index.row() < 0 || index.row() >= rows.size()) {
|
||||
return {};
|
||||
}
|
||||
const TransactionRow& tInfo = rows[index.row()];
|
||||
|
||||
if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
||||
return parseTransactionInfo(tInfo, index.column(), role);
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole) {
|
||||
switch (index.column()) {
|
||||
case Column::Amount:
|
||||
case Column::FiatAmount:
|
||||
return Qt::AlignRight;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole) {
|
||||
switch (index.column()) {
|
||||
case Column::Date:
|
||||
{
|
||||
if (tInfo.failed)
|
||||
return QVariant(icons()->icon("warning.png"));
|
||||
else if (tInfo.pending)
|
||||
return QVariant(icons()->icon("unconfirmed.png"));
|
||||
else if (tInfo.confirmations <= (1.0/5.0 * tInfo.confirmationsRequired()))
|
||||
return QVariant(icons()->icon("clock1.png"));
|
||||
else if (tInfo.confirmations <= (2.0/5.0 * tInfo.confirmationsRequired()))
|
||||
return QVariant(icons()->icon("clock2.png"));
|
||||
else if (tInfo.confirmations <= (3.0/5.0 * tInfo.confirmationsRequired()))
|
||||
return QVariant(icons()->icon("clock3.png"));
|
||||
else if (tInfo.confirmations <= (4.0/5.0 * tInfo.confirmationsRequired()))
|
||||
return QVariant(icons()->icon("clock4.png"));
|
||||
else if (tInfo.confirmations < tInfo.confirmationsRequired())
|
||||
return QVariant(icons()->icon("clock5.png"));
|
||||
else if (tInfo.confirmations)
|
||||
return QVariant(icons()->icon("confirmed.svg"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole) {
|
||||
switch(index.column()) {
|
||||
case Column::Date:
|
||||
{
|
||||
if (tInfo.failed)
|
||||
return "Transaction failed";
|
||||
else if (tInfo.confirmations < tInfo.confirmationsRequired())
|
||||
return QString("%1/%2 confirmations").arg(QString::number(tInfo.confirmations), QString::number(tInfo.confirmationsRequired()));
|
||||
else
|
||||
return QString("%1 confirmations").arg(QString::number(tInfo.confirmations));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ForegroundRole) {
|
||||
switch(index.column()) {
|
||||
case Column::FiatAmount:
|
||||
case Column::Amount:
|
||||
{
|
||||
if (tInfo.balanceDelta < 0) {
|
||||
return QVariant(QColor("#BC1E1E"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::FontRole) {
|
||||
switch(index.column()) {
|
||||
case Column::TxID:
|
||||
{
|
||||
return Utils::getMonospaceFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!index.isValid() || index.row() < 0 || static_cast<quint64>(index.row()) >= m_transactionHistory->count())
|
||||
return QVariant();
|
||||
|
||||
QVariant result;
|
||||
|
||||
bool found = m_transactionHistory->transaction(index.row(), [this, &index, &result, &role](const TransactionRow &tInfo) {
|
||||
if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
||||
result = parseTransactionInfo(tInfo, index.column(), role);
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole) {
|
||||
switch (index.column()) {
|
||||
case Column::Amount:
|
||||
case Column::FiatAmount:
|
||||
result = Qt::AlignRight;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole) {
|
||||
switch (index.column()) {
|
||||
case Column::Date:
|
||||
{
|
||||
if (tInfo.isFailed())
|
||||
result = QVariant(icons()->icon("warning.png"));
|
||||
else if (tInfo.isPending())
|
||||
result = QVariant(icons()->icon("unconfirmed.png"));
|
||||
else if (tInfo.confirmations() <= (1.0/5.0 * tInfo.confirmationsRequired()))
|
||||
result = QVariant(icons()->icon("clock1.png"));
|
||||
else if (tInfo.confirmations() <= (2.0/5.0 * tInfo.confirmationsRequired()))
|
||||
result = QVariant(icons()->icon("clock2.png"));
|
||||
else if (tInfo.confirmations() <= (3.0/5.0 * tInfo.confirmationsRequired()))
|
||||
result = QVariant(icons()->icon("clock3.png"));
|
||||
else if (tInfo.confirmations() <= (4.0/5.0 * tInfo.confirmationsRequired()))
|
||||
result = QVariant(icons()->icon("clock4.png"));
|
||||
else if (tInfo.confirmations() < tInfo.confirmationsRequired())
|
||||
result = QVariant(icons()->icon("clock5.png"));
|
||||
else if (tInfo.confirmations())
|
||||
result = QVariant(icons()->icon("confirmed.svg"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole) {
|
||||
switch(index.column()) {
|
||||
case Column::Date:
|
||||
{
|
||||
if (tInfo.isFailed())
|
||||
result = "Transaction failed";
|
||||
else if (tInfo.confirmations() < tInfo.confirmationsRequired())
|
||||
result = QString("%1/%2 confirmations").arg(QString::number(tInfo.confirmations()), QString::number(tInfo.confirmationsRequired()));
|
||||
else
|
||||
result = QString("%1 confirmations").arg(QString::number(tInfo.confirmations()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ForegroundRole) {
|
||||
switch(index.column()) {
|
||||
case Column::FiatAmount:
|
||||
case Column::Amount:
|
||||
{
|
||||
if (tInfo.balanceDelta() < 0) {
|
||||
result = QVariant(QColor("#BC1E1E"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::FontRole) {
|
||||
switch(index.column()) {
|
||||
case Column::TxID:
|
||||
{
|
||||
result = Utils::getMonospaceFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
qCritical("%s: internal error: no transaction info for index %d", __FUNCTION__, index.row());
|
||||
}
|
||||
return result;
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionRow &tInfo, int column, int role) const
|
||||
|
@ -145,39 +137,39 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionRow &tIn
|
|||
case Column::Date:
|
||||
{
|
||||
if (role == Qt::UserRole) {
|
||||
if (tInfo.blockHeight() > 0) {
|
||||
return tInfo.blockHeight();
|
||||
if (tInfo.blockHeight > 0) {
|
||||
return tInfo.blockHeight;
|
||||
}
|
||||
return tInfo.timestamp().toMSecsSinceEpoch();
|
||||
return tInfo.timestamp.toMSecsSinceEpoch();
|
||||
}
|
||||
return tInfo.timestamp().toString(QString("%1 %2 ").arg(conf()->get(Config::dateFormat).toString(),
|
||||
return tInfo.timestamp.toString(QString("%1 %2 ").arg(conf()->get(Config::dateFormat).toString(),
|
||||
conf()->get(Config::timeFormat).toString()));
|
||||
}
|
||||
case Column::Description:
|
||||
return tInfo.description();
|
||||
return tInfo.description;
|
||||
case Column::Amount:
|
||||
{
|
||||
if (role == Qt::UserRole) {
|
||||
return tInfo.balanceDelta();
|
||||
return tInfo.balanceDelta;
|
||||
}
|
||||
QString amount = QString::number(tInfo.balanceDelta() / constants::cdiv, 'f', conf()->get(Config::amountPrecision).toInt());
|
||||
amount = (tInfo.balanceDelta() < 0) ? amount : "+" + amount;
|
||||
QString amount = QString::number(tInfo.balanceDelta / constants::cdiv, 'f', conf()->get(Config::amountPrecision).toInt());
|
||||
amount = (tInfo.balanceDelta < 0) ? amount : "+" + amount;
|
||||
return amount;
|
||||
}
|
||||
case Column::TxID: {
|
||||
if (conf()->get(Config::historyShowFullTxid).toBool()) {
|
||||
return tInfo.hash();
|
||||
return tInfo.hash;
|
||||
}
|
||||
return Utils::displayAddress(tInfo.hash(), 1);
|
||||
return Utils::displayAddress(tInfo.hash, 1);
|
||||
}
|
||||
case Column::FiatAmount:
|
||||
{
|
||||
double usd_price = appData()->txFiatHistory->get(tInfo.timestamp().toString("yyyyMMdd"));
|
||||
double usd_price = appData()->txFiatHistory->get(tInfo.timestamp.toString("yyyyMMdd"));
|
||||
if (usd_price == 0.0) {
|
||||
return QString("?");
|
||||
}
|
||||
|
||||
double usd_amount = usd_price * (abs(tInfo.balanceDelta()) / constants::cdiv);
|
||||
double usd_amount = usd_price * (abs(tInfo.balanceDelta) / constants::cdiv);
|
||||
|
||||
QString preferredFiatCurrency = conf()->get(Config::preferredFiatCurrency).toString();
|
||||
if (preferredFiatCurrency != "USD") {
|
||||
|
@ -227,15 +219,11 @@ QVariant TransactionHistoryModel::headerData(int section, Qt::Orientation orient
|
|||
|
||||
bool TransactionHistoryModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (index.isValid() && role == Qt::EditRole) {
|
||||
QString hash;
|
||||
|
||||
switch (index.column()) {
|
||||
case Column::Description:
|
||||
{
|
||||
m_transactionHistory->transaction(index.row(), [this, &hash, &value](const TransactionRow &tInfo){
|
||||
hash = tInfo.hash();
|
||||
});
|
||||
m_transactionHistory->setTxNote(hash, value.toString());
|
||||
const TransactionRow& row = m_transactionHistory->transaction(index.row());
|
||||
m_transactionHistory->setTxNote(row.hash, value.toString());
|
||||
m_transactionHistory->refresh();
|
||||
emit transactionDescriptionChanged();
|
||||
break;
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
explicit TransactionHistoryModel(QObject * parent = nullptr);
|
||||
void setTransactionHistory(TransactionHistory * th);
|
||||
TransactionHistory * transactionHistory() const;
|
||||
TransactionRow* entryFromIndex(const QModelIndex& index) const;
|
||||
const TransactionRow& entryFromIndex(const QModelIndex& index) const;
|
||||
|
||||
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
|
|
@ -21,17 +21,17 @@ TransactionHistory* TransactionHistoryProxyModel::history() {
|
|||
|
||||
bool TransactionHistoryProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
QString description, txid, subaddrlabel;
|
||||
quint32 subaddrAccount;
|
||||
QSet<quint32> subaddrIndex;
|
||||
if (sourceRow < 0 || sourceRow >= m_history->count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_history->transaction(sourceRow, [&description, &txid, &subaddrlabel, &subaddrAccount, &subaddrIndex](TransactionRow &tInfo){
|
||||
description = tInfo.description();
|
||||
txid = tInfo.hash();
|
||||
subaddrlabel = tInfo.label();
|
||||
subaddrAccount = tInfo.subaddrAccount();
|
||||
subaddrIndex = tInfo.subaddrIndex();
|
||||
});
|
||||
const TransactionRow& row = m_history->transaction(sourceRow);
|
||||
|
||||
QString description = row.description;
|
||||
QString txid = row.hash;
|
||||
QString subaddrlabel = row.label;
|
||||
quint32 subaddrAccount = row.subaddrAccount;
|
||||
QSet<quint32> subaddrIndex = row.subaddrIndex;
|
||||
|
||||
bool addressFound;
|
||||
for (quint32 i : subaddrIndex) {
|
||||
|
@ -41,4 +41,4 @@ bool TransactionHistoryProxyModel::filterAcceptsRow(int sourceRow, const QModelI
|
|||
}
|
||||
|
||||
return (description.contains(m_searchRegExp) || txid.contains(m_searchRegExp) || subaddrlabel.contains(m_searchRegExp)) || addressFound;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue