From 4f28d83ac32f54efcc63a2e08cea6b27ae48d1f3 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Wed, 12 Mar 2025 10:04:33 +0100 Subject: [PATCH] History: cleanup --- src/CoinsWidget.cpp | 2 +- src/HistoryWidget.cpp | 72 +++++---- src/MainWindow.cpp | 15 +- src/dialog/HistoryExportDialog.cpp | 48 +++--- src/dialog/TxConfAdvDialog.cpp | 22 +-- src/dialog/TxConfAdvDialog.h | 2 +- src/dialog/TxInfoDialog.cpp | 55 ++++--- src/dialog/TxInfoDialog.h | 5 +- src/dialog/TxProofDialog.cpp | 14 +- src/dialog/TxProofDialog.h | 2 +- src/libwalletqt/ConstructionInfo.cpp | 40 +---- src/libwalletqt/ConstructionInfo.h | 36 ++--- src/libwalletqt/Input.h | 20 +-- src/libwalletqt/PendingTransaction.cpp | 5 +- src/libwalletqt/PendingTransaction.h | 4 +- src/libwalletqt/PendingTransactionInfo.cpp | 30 +--- src/libwalletqt/PendingTransactionInfo.h | 27 +--- src/libwalletqt/TransactionHistory.cpp | 180 +++++++++------------ src/libwalletqt/TransactionHistory.h | 8 +- src/libwalletqt/UnsignedTransaction.cpp | 5 +- src/libwalletqt/UnsignedTransaction.h | 4 +- src/libwalletqt/rows/TransactionRow.cpp | 152 ++++------------- src/libwalletqt/rows/TransactionRow.h | 79 +++------ src/model/HistoryView.cpp | 32 ++-- src/model/HistoryView.h | 5 +- src/model/TransactionHistoryModel.cpp | 162 +++++++++---------- src/model/TransactionHistoryModel.h | 2 +- src/model/TransactionHistoryProxyModel.cpp | 24 +-- 28 files changed, 424 insertions(+), 628 deletions(-) diff --git a/src/CoinsWidget.cpp b/src/CoinsWidget.cpp index a357be7b..edee303b 100644 --- a/src/CoinsWidget.cpp +++ b/src/CoinsWidget.cpp @@ -377,4 +377,4 @@ QModelIndex CoinsWidget::getCurrentIndex() return m_proxyModel->mapToSource(list.first()); } -CoinsWidget::~CoinsWidget() = default; \ No newline at end of file +CoinsWidget::~CoinsWidget() = default; diff --git a/src/HistoryWidget.cpp b/src/HistoryWidget.cpp index 69926fd7..49912293 100644 --- a/src/HistoryWidget.cpp +++ b/src/HistoryWidget.cpp @@ -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; \ No newline at end of file +HistoryWidget::~HistoryWidget() = default; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index cf9ca6d9..d1bc2901 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -942,7 +942,7 @@ void MainWindow::onTransactionCreated(PendingTransaction *tx, const QVectorrefresh(); QSet 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 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); diff --git a/src/dialog/HistoryExportDialog.cpp b/src/dialog/HistoryExportDialog.cpp index 0849ced5..766f4fc3 100644 --- a/src/dialog/HistoryExportDialog.cpp +++ b/src/dialog/HistoryExportDialog.cpp @@ -95,77 +95,77 @@ void HistoryExportDialog::exportHistory() QList> 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 &tx1, const QPair &tx2){ diff --git a/src/dialog/TxConfAdvDialog.cpp b/src/dialog/TxConfAdvDialog.cpp index b20309fa..b9d72600 100644 --- a/src/dialog/TxConfAdvDialog.cpp +++ b/src/dialog/TxConfAdvDialog.cpp @@ -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() { diff --git a/src/dialog/TxConfAdvDialog.h b/src/dialog/TxConfAdvDialog.h index 86d5e421..63a0ee3b 100644 --- a/src/dialog/TxConfAdvDialog.h +++ b/src/dialog/TxConfAdvDialog.h @@ -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(); diff --git a/src/dialog/TxInfoDialog.cpp b/src/dialog/TxInfoDialog.cpp index cd13f141..f3b53e6e 100644 --- a/src/dialog/TxInfoDialog.cpp +++ b/src/dialog/TxInfoDialog.cpp @@ -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; \ No newline at end of file +TxInfoDialog::~TxInfoDialog() = default; diff --git a/src/dialog/TxInfoDialog.h b/src/dialog/TxInfoDialog.h index 5d53805b..e2e1d4ff 100644 --- a/src/dialog/TxInfoDialog.h +++ b/src/dialog/TxInfoDialog.h @@ -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; Wallet *m_wallet; - TransactionRow *m_txInfo; TxProofDialog *m_txProofDialog; QString m_txid; }; diff --git a/src/dialog/TxProofDialog.cpp b/src/dialog/TxProofDialog.cpp index b0364076..d56bf352 100644 --- a/src/dialog/TxProofDialog.cpp +++ b/src/dialog/TxProofDialog.cpp @@ -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; \ No newline at end of file +TxProofDialog::~TxProofDialog() = default; diff --git a/src/dialog/TxProofDialog.h b/src/dialog/TxProofDialog.h index 636cfb40..b1c98f92 100644 --- a/src/dialog/TxProofDialog.h +++ b/src/dialog/TxProofDialog.h @@ -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(); diff --git a/src/libwalletqt/ConstructionInfo.cpp b/src/libwalletqt/ConstructionInfo.cpp index 32f767bd..0aa33cfa 100644 --- a/src/libwalletqt/ConstructionInfo.cpp +++ b/src/libwalletqt/ConstructionInfo.cpp @@ -7,47 +7,21 @@ #include "Transfer.h" #include -quint64 ConstructionInfo::unlockTime() const { - return m_unlockTime; -} - -QSet ConstructionInfo::subaddressIndices() const { - return m_subaddressIndices; -} - -QVector ConstructionInfo::subaddresses() const { - return m_subaddresses; -} - -quint64 ConstructionInfo::minMixinCount() const { - return m_minMixinCount; -} - -QList ConstructionInfo::inputs() const { - return m_inputs; -} - -QList 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); } -} \ No newline at end of file +} diff --git a/src/libwalletqt/ConstructionInfo.h b/src/libwalletqt/ConstructionInfo.h index ff18be30..28e21b2e 100644 --- a/src/libwalletqt/ConstructionInfo.h +++ b/src/libwalletqt/ConstructionInfo.h @@ -4,39 +4,25 @@ #ifndef FEATHER_CONSTRUCTIONINFO_H #define FEATHER_CONSTRUCTIONINFO_H -#include #include -#include "Transfer.h" -class Input; +#include "Transfer.h" +#include "Input.h" namespace Monero { class TransactionConstructionInfo; } -class ConstructionInfo : public QObject +struct ConstructionInfo { - Q_OBJECT - -public: - quint64 unlockTime() const; - QSet subaddressIndices() const; - QVector subaddresses() const; - quint64 minMixinCount() const; - QList inputs() const; - QList outputs() const; - -private: - explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent = nullptr); - - friend class PendingTransactionInfo; - friend class UnsignedTransaction; - quint64 m_unlockTime; - QSet m_subaddressIndices; - QVector m_subaddresses; - quint64 m_minMixinCount; - mutable QList m_inputs; - mutable QList m_outputs; + quint64 unlockTime; + QSet subaddressIndices; + QVector subaddresses; + quint64 minMixinCount; + QList inputs; + QList outputs; + + explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl); }; #endif //FEATHER_CONSTRUCTIONINFO_H diff --git a/src/libwalletqt/Input.h b/src/libwalletqt/Input.h index 4c56fb25..b98cf70e 100644 --- a/src/libwalletqt/Input.h +++ b/src/libwalletqt/Input.h @@ -4,22 +4,14 @@ #ifndef FEATHER_INPUT_H #define FEATHER_INPUT_H -#include - -class Input : public QObject +struct Input { - Q_OBJECT - -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; + QString pubKey; + quint64 amount; -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 diff --git a/src/libwalletqt/PendingTransaction.cpp b/src/libwalletqt/PendingTransaction.cpp index cc6696ea..5bb66595 100644 --- a/src/libwalletqt/PendingTransaction.cpp +++ b/src/libwalletqt/PendingTransaction.cpp @@ -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); } } diff --git a/src/libwalletqt/PendingTransaction.h b/src/libwalletqt/PendingTransaction.h index dfbb2e48..e62fc68a 100644 --- a/src/libwalletqt/PendingTransaction.h +++ b/src/libwalletqt/PendingTransaction.h @@ -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 m_pending_tx_info; + mutable QList m_pending_tx_info; }; #endif // PENDINGTRANSACTION_H diff --git a/src/libwalletqt/PendingTransactionInfo.cpp b/src/libwalletqt/PendingTransactionInfo.cpp index e8220da1..9a71f8b9 100644 --- a/src/libwalletqt/PendingTransactionInfo.cpp +++ b/src/libwalletqt/PendingTransactionInfo.cpp @@ -4,28 +4,12 @@ #include "PendingTransactionInfo.h" #include -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())) { -} \ No newline at end of file +} diff --git a/src/libwalletqt/PendingTransactionInfo.h b/src/libwalletqt/PendingTransactionInfo.h index 54cf9904..540a4e58 100644 --- a/src/libwalletqt/PendingTransactionInfo.h +++ b/src/libwalletqt/PendingTransactionInfo.h @@ -5,34 +5,21 @@ #define FEATHER_PENDINGTRANSACTIONINFO_H #include "ConstructionInfo.h" -#include -#include -class Input; -class Transfer; +#include namespace Monero { class PendingTransactionInfo; } -class PendingTransactionInfo : public ConstructionInfo +struct PendingTransactionInfo : ConstructionInfo { - Q_OBJECT - -public: - quint64 fee() const; - quint64 dust() const; - bool dustAddedToFee() const; - QString txKey() const; - -private: - explicit PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent = nullptr); + quint64 fee; + quint64 dust; + bool dustAddedToFee; + QString txKey; - 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 diff --git a/src/libwalletqt/TransactionHistory.cpp b/src/libwalletqt/TransactionHistory.cpp index 13fd1cf7..9b2a8efa 100644 --- a/src/libwalletqt/TransactionHistory.cpp +++ b/src/libwalletqt/TransactionHistory.cpp @@ -27,38 +27,17 @@ QString description(tools::wallet2 *wallet2, const tools::wallet2::payment_detai return description; } -bool TransactionHistory::transaction(int index, std::function callback) +const TransactionRow& TransactionHistory::transaction(int index) { - 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; + throw std::out_of_range("Index out of range"); } - - 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; + return m_rows[index]; } -TransactionRow* TransactionHistory::transaction(int index) +const QList& TransactionHistory::getRows() { - if (index < 0 || index >= m_rows.size()) { - return nullptr; - } - - return m_rows[index]; + return m_rows; } void TransactionHistory::refresh() @@ -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); - - m_rows.append(t); + 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(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); - - t->m_amount = pd.m_amount_out - change; - t->m_balanceDelta = change - pd.m_amount_in; - t->m_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()) + TransactionRow t; + t.paymentId = QString::fromStdString(payment_id); + + t.amount = pd.m_amount_out - change; + t.balanceDelta = change - pd.m_amount_in; + t.fee = fee; + + 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(); } diff --git a/src/libwalletqt/TransactionHistory.h b/src/libwalletqt/TransactionHistory.h index cd665315..c07a4af5 100644 --- a/src/libwalletqt/TransactionHistory.h +++ b/src/libwalletqt/TransactionHistory.h @@ -29,9 +29,9 @@ class TransactionHistory : public QObject Q_OBJECT public: - bool transaction(int index, std::function callback); - TransactionRow * transaction(const QString &id); - TransactionRow* transaction(int index); + const TransactionRow& transaction(int index); + const QList& 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 m_rows; + QList m_rows; mutable QDateTime m_firstDateTime; mutable QDateTime m_lastDateTime; diff --git a/src/libwalletqt/UnsignedTransaction.cpp b/src/libwalletqt/UnsignedTransaction.cpp index 2fc76613..543d6b56 100644 --- a/src/libwalletqt/UnsignedTransaction.cpp +++ b/src/libwalletqt/UnsignedTransaction.cpp @@ -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); } } diff --git a/src/libwalletqt/UnsignedTransaction.h b/src/libwalletqt/UnsignedTransaction.h index 3ceb410b..a81970c4 100644 --- a/src/libwalletqt/UnsignedTransaction.h +++ b/src/libwalletqt/UnsignedTransaction.h @@ -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 m_construction_info; + mutable QList m_construction_info; }; #endif // UNSIGNEDTRANSACTION_H diff --git a/src/libwalletqt/rows/TransactionRow.cpp b/src/libwalletqt/rows/TransactionRow.cpp index 65b3c74a..523bccf7 100644 --- a/src/libwalletqt/rows/TransactionRow.cpp +++ b/src/libwalletqt/rows/TransactionRow.cpp @@ -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); -} - -quint64 TransactionRow::atomicFee() const -{ - return m_fee; + return WalletManager::displayAmount(amount); } -QString TransactionRow::fee() const +QString TransactionRow::displayFee() 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 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 TransactionRow::destinations() const { QList dests; - for (auto const& t: m_transfers) { + for (auto const& t: transfers) { dests.append(t.address); } return dests; } -QList 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"; } diff --git a/src/libwalletqt/rows/TransactionRow.h b/src/libwalletqt/rows/TransactionRow.h index 9ae6f357..1501e00a 100644 --- a/src/libwalletqt/rows/TransactionRow.h +++ b/src/libwalletqt/rows/TransactionRow.h @@ -4,7 +4,6 @@ #ifndef FEATHER_TRANSACTIONROW_H #define FEATHER_TRANSACTIONROW_H -#include #include #include @@ -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) - - Direction direction() const; - bool isPending() const; - bool isFailed() const; - bool isCoinbase() const; - qint64 balanceDelta() const; - double amount() const; - qint64 atomicAmount() const; + QList transfers; + QList 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 subaddrIndex; + QDateTime timestamp; + quint64 unlockTime; + bool failed; + bool pending; + bool coinbase; + quint64 fee; + + QString displayFee() const; QString displayAmount() const; - QString fee() const; - quint64 atomicFee() const; - quint64 blockHeight() const; - QString description() const; - QSet 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 destinations() const; - QList transfers() const; QString rings_formatted() const; bool hasPaymentId() const; -private: - explicit TransactionRow(QObject *parent); - -private: - friend class TransactionHistory; - QList m_transfers; - QList 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 m_subaddrIndex; - QDateTime m_timestamp; - quint64 m_unlockTime; - bool m_coinbase; + explicit TransactionRow(); }; - #endif //FEATHER_TRANSACTIONROW_H diff --git a/src/model/HistoryView.cpp b/src/model/HistoryView.cpp index 1c462205..53bf21b6 100644 --- a/src/model/HistoryView.cpp +++ b/src/model/HistoryView.cpp @@ -75,16 +75,6 @@ TransactionHistoryModel* HistoryView::sourceModel() return dynamic_cast(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); } -} \ No newline at end of file +} + +QModelIndex HistoryView::getCurrentIndex() +{ + QModelIndexList list = this->selectionModel()->selectedRows(); + if (list.length() < 1) { + return {}; + } + + return m_model->mapToSource(list.first()); +} diff --git a/src/model/HistoryView.h b/src/model/HistoryView.h index 372ce357..7775d34d 100644 --- a/src/model/HistoryView.h +++ b/src/model/HistoryView.h @@ -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; diff --git a/src/model/TransactionHistoryModel.cpp b/src/model/TransactionHistoryModel.cpp index 704b03f8..b2362e7e 100644 --- a/src/model/TransactionHistoryModel.cpp +++ b/src/model/TransactionHistoryModel.cpp @@ -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& rows = m_transactionHistory->getRows(); + if (index.row() < 0 || index.row() >= rows.size()) { + return {}; } + const TransactionRow& tInfo = rows[index.row()]; - if (!index.isValid() || index.row() < 0 || static_cast(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; - } + 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.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::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.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::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) { - result = QVariant(QColor("#BC1E1E")); - } + } + 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: - { - result = Utils::getMonospaceFont(); - } + } + else if (role == Qt::FontRole) { + switch(index.column()) { + case Column::TxID: + { + return 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; diff --git a/src/model/TransactionHistoryModel.h b/src/model/TransactionHistoryModel.h index feca8d31..d5978bb0 100644 --- a/src/model/TransactionHistoryModel.h +++ b/src/model/TransactionHistoryModel.h @@ -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; diff --git a/src/model/TransactionHistoryProxyModel.cpp b/src/model/TransactionHistoryProxyModel.cpp index 7a542b2d..b12b822e 100644 --- a/src/model/TransactionHistoryProxyModel.cpp +++ b/src/model/TransactionHistoryProxyModel.cpp @@ -21,17 +21,17 @@ TransactionHistory* TransactionHistoryProxyModel::history() { bool TransactionHistoryProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - QString description, txid, subaddrlabel; - quint32 subaddrAccount; - QSet subaddrIndex; - - 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(); - }); + if (sourceRow < 0 || sourceRow >= m_history->count()) { + return false; + } + + const TransactionRow& row = m_history->transaction(sourceRow); + + QString description = row.description; + QString txid = row.hash; + QString subaddrlabel = row.label; + quint32 subaddrAccount = row.subaddrAccount; + QSet 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; -} \ No newline at end of file +} -- 2.52.0