return m_proxyModel->mapToSource(list.first());
}
-CoinsWidget::~CoinsWidget() = default;
\ No newline at end of file
+CoinsWidget::~CoinsWidget() = default;
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);
}
}
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);
}
}
}
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){
}
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) {
}
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();
}
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("");
}
"To update the history page during synchronization press Ctrl+R.");
}
-HistoryWidget::~HistoryWidget() = default;
\ No newline at end of file
+HistoryWidget::~HistoryWidget() = default;
// 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;
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);
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){
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();
}
this->setAmounts(utx->amount(0), utx->fee(0));
- ConstructionInfo *ci = m_utx->constructionInfo(0);
+ const ConstructionInfo& ci = m_utx->constructionInfo(0);
this->setupConstructionData(ci);
}
}
}
-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));
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();
}
return;
}
- Utils::copyToClipboard(m_tx->transaction(0)->txKey());
+ Utils::copyToClipboard(m_tx->transaction(0).txKey);
}
void TxConfAdvDialog::broadcastTransaction() {
void setUnsignedTransaction(UnsignedTransaction *utx);
private:
- void setupConstructionData(ConstructionInfo *ci);
+ void setupConstructionData(const ConstructionInfo& ci);
void signTransaction();
void broadcastTransaction();
void closeDialog();
#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);
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);
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);
});
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.");
}
QTextCursor cursor = ui->outputs->textCursor();
- auto transfers = txInfo->transfers();
+ auto transfers = txInfo.transfers;
if (!transfers.isEmpty()) {
bool hasIntegrated = false;
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.");
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") {
}
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() {
Utils::externalLinkWarning(this, link);
}
-TxInfoDialog::~TxInfoDialog() = default;
\ No newline at end of file
+TxInfoDialog::~TxInfoDialog() = default;
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:
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;
};
#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
return proof;
}
-TxProofDialog::~TxProofDialog() = default;
\ No newline at end of file
+TxProofDialog::~TxProofDialog() = default;
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();
#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);
}
-}
\ No newline at end of file
+}
#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
-
-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;
+ quint64 unlockTime;
+ QSet<quint32> subaddressIndices;
+ QVector<QString> subaddresses;
+ quint64 minMixinCount;
+ QList<Input> inputs;
+ QList<Transfer> outputs;
+
+ explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl);
};
#endif //FEATHER_CONSTRUCTIONINFO_H
#ifndef FEATHER_INPUT_H
#define FEATHER_INPUT_H
-#include <QObject>
-
-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
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);
}
}
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);
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
#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()))
{
-}
\ No newline at end of file
+}
#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
-
-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
return description;
}
-bool TransactionHistory::transaction(int index, std::function<void (TransactionRow &)> 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<TransactionRow>& TransactionHistory::getRows()
{
- if (index < 0 || index >= m_rows.size()) {
- return nullptr;
- }
-
- return m_rows[index];
+ return m_rows;
}
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
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
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));
}
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);
}
}
void TransactionHistory::clearRows() {
- qDeleteAll(m_rows);
m_rows.clear();
}
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;
Wallet *m_wallet;
tools::wallet2 *m_wallet2;
- QList<TransactionRow*> m_rows;
+ QList<TransactionRow> m_rows;
mutable QDateTime m_firstDateTime;
mutable QDateTime m_lastDateTime;
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);
}
}
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);
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
#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<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";
}
#ifndef FEATHER_TRANSACTIONROW_H
#define FEATHER_TRANSACTIONROW_H
-#include <QObject>
#include <QSet>
#include <QDateTime>
};
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<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;
+
+ 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
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);
}
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());
+}
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);
void keyPressEvent(QKeyEvent *event);
private:
- TransactionHistoryModel* sourceModel();
-
TransactionHistoryProxyModel* m_model;
bool m_inSearchMode = false;
bool m_columnsNeedRelayout = true;
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());
}
}
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 (!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;
- }
+ 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
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") {
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;
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;
bool TransactionHistoryProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
- QString description, txid, subaddrlabel;
- quint32 subaddrAccount;
- QSet<quint32> 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<quint32> subaddrIndex = row.subaddrIndex;
bool addressFound;
for (quint32 i : subaddrIndex) {
}
return (description.contains(m_searchRegExp) || txid.contains(m_searchRegExp) || subaddrlabel.contains(m_searchRegExp)) || addressFound;
-}
\ No newline at end of file
+}