From: tobtoht Date: Tue, 11 Mar 2025 20:45:38 +0000 (+0100) Subject: Coins: cleanup X-Git-Url: https://git.nutra.tk/v1?a=commitdiff_plain;h=c5f010bd3c9061d4981c9640b9e5b11c7ca688c2;p=gamesguru%2Ffeather.git Coins: cleanup --- diff --git a/src/CoinsWidget.cpp b/src/CoinsWidget.cpp index 1df73103..c955575e 100644 --- a/src/CoinsWidget.cpp +++ b/src/CoinsWidget.cpp @@ -121,12 +121,15 @@ void CoinsWidget::showContextMenu(const QPoint &point) { menu->addAction(m_sweepOutputsAction); } else { - CoinsInfo* c = this->currentEntry(); - if (!c) return; + auto index = this->getCurrentIndex(); + if (!index.isValid()) { + return; + } + const CoinsInfo& c = m_model->entryFromIndex(index); - bool isSpent = c->spent(); - bool isFrozen = c->frozen(); - bool isUnlocked = c->unlocked(); + bool isSpent = c.spent; + bool isFrozen = c.frozen; + bool isUnlocked = c.unlocked; menu->addAction(m_spendAction); menu->addMenu(m_copyMenu); @@ -170,7 +173,7 @@ QStringList CoinsWidget::selectedPubkeys() { QStringList pubkeys; for (QModelIndex index: list) { - pubkeys << m_model->entryFromIndex(m_proxyModel->mapToSource(index))->pubKey(); + pubkeys << m_model->entryFromIndex(m_proxyModel->mapToSource(index)).pubKey; } return pubkeys; } @@ -186,16 +189,19 @@ void CoinsWidget::thawAllSelected() { } void CoinsWidget::spendSelected() { - QVector selectedCoins = this->currentEntries(); - QStringList keyimages; + QModelIndexList selectedRows = ui->coins->selectionModel()->selectedRows(); - for (const auto coin : selectedCoins) { - if (!coin) return; + QStringList keyimages; + for (const auto index : selectedRows) { + if (!index.isValid()) { + return; + } + const CoinsInfo& coin = m_model->entryFromIndex(m_proxyModel->mapToSource(index)); bool spendable = this->isCoinSpendable(coin); if (!spendable) return; - QString keyImage = coin->keyImage(); + QString keyImage = coin.keyImage; keyimages << keyImage; } @@ -204,8 +210,11 @@ void CoinsWidget::spendSelected() { } void CoinsWidget::viewOutput() { - CoinsInfo* c = this->currentEntry(); - if (!c) return; + auto index = this->getCurrentIndex(); + if (!index.isValid()) { + return; + } + const CoinsInfo& c = m_model->entryFromIndex(index); auto * dialog = new OutputInfoDialog(c, this); dialog->show(); @@ -224,19 +233,23 @@ void CoinsWidget::onSweepOutputs() { return; } - QVector selectedCoins = this->currentEntries(); + QModelIndexList selectedRows = ui->coins->selectionModel()->selectedRows(); + QVector keyImages; quint64 totalAmount = 0; - for (const auto coin : selectedCoins) { - if (!coin) return; + for (const auto index : selectedRows) { + if (!index.isValid()) { + return; + } + const CoinsInfo& coin = m_model->entryFromIndex(m_proxyModel->mapToSource(index)); bool spendable = this->isCoinSpendable(coin); if (!spendable) return; - QString keyImage = coin->keyImage(); + QString keyImage = coin.keyImage; keyImages.push_back(keyImage); - totalAmount += coin->amount(); + totalAmount += coin.amount; } OutputSweepDialog dialog{this, totalAmount}; @@ -270,59 +283,44 @@ void CoinsWidget::onSweepOutputs() { } void CoinsWidget::copy(copyField field) { - CoinsInfo* c = this->currentEntry(); - if (!c) return; + auto index = this->getCurrentIndex(); + if (!index.isValid()) { + return; + } + const CoinsInfo& c = m_model->entryFromIndex(index); QString data; switch (field) { case PubKey: - data = c->pubKey(); + data = c.pubKey; break; case KeyImage: - data = c->keyImage(); + data = c.keyImage; break; case TxID: - data = c->hash(); + data = c.hash; break; case Address: - data = c->address(); + data = c.address; break; case Label: { - if (!c->description().isEmpty()) - data = c->description(); + if (!c.description.isEmpty()) + data = c.description; else - data = c->addressLabel(); + data = c.getAddressLabel(); break; } case Height: - data = QString::number(c->blockHeight()); + data = QString::number(c.blockHeight); break; case Amount: - data = c->displayAmount(); + data = c.displayAmount(); break; } Utils::copyToClipboard(data); } -CoinsInfo* CoinsWidget::currentEntry() { - QModelIndexList list = ui->coins->selectionModel()->selectedRows(); - if (list.size() == 1) { - return m_model->entryFromIndex(m_proxyModel->mapToSource(list.first())); - } else { - return nullptr; - } -} - -QVector CoinsWidget::currentEntries() { - QModelIndexList list = ui->coins->selectionModel()->selectedRows(); - QVector selectedCoins; - for (const auto index : list) { - selectedCoins.push_back(m_model->entryFromIndex(m_proxyModel->mapToSource(index))); - } - return selectedCoins; -} - void CoinsWidget::freezeCoins(QStringList &pubkeys) { m_wallet->coins()->freeze(pubkeys); m_wallet->updateBalance(); @@ -344,23 +342,23 @@ void CoinsWidget::editLabel() { ui->coins->edit(index); } -bool CoinsWidget::isCoinSpendable(CoinsInfo *coin) { - if (!coin->keyImageKnown()) { +bool CoinsWidget::isCoinSpendable(const CoinsInfo &coin) { + if (!coin.keyImageKnown) { Utils::showError(this, "Unable to spend outputs", "Selected output has unknown key image"); return false; } - if (coin->spent()) { + if (coin.spent) { Utils::showError(this, "Unable to spend outputs", "Selected output was already spent"); return false; } - if (coin->frozen()) { + if (coin.frozen) { Utils::showError(this, "Unable to spend outputs", "Selected output is frozen", {"Thaw the selected output(s) before spending"}, "freeze_thaw_outputs"); return false; } - if (!coin->unlocked()) { + if (!coin.unlocked) { Utils::showError(this, "Unable to spend outputs", "Selected output is locked", {"Wait until the output has reached the required number of confirmation before spending."}); return false; } @@ -368,4 +366,14 @@ bool CoinsWidget::isCoinSpendable(CoinsInfo *coin) { return true; } +QModelIndex CoinsWidget::getCurrentIndex() +{ + QModelIndexList list = ui->coins->selectionModel()->selectedRows(); + if (list.length() < 1) { + return {}; + } + + return m_proxyModel->mapToSource(list.first()); +} + CoinsWidget::~CoinsWidget() = default; \ No newline at end of file diff --git a/src/CoinsWidget.h b/src/CoinsWidget.h index f3ddcb5f..5ca8bc5c 100644 --- a/src/CoinsWidget.h +++ b/src/CoinsWidget.h @@ -83,10 +83,9 @@ private: void showContextMenu(const QPoint & point); void copy(copyField field); - CoinsInfo* currentEntry(); - QVector currentEntries(); QStringList selectedPubkeys(); - bool isCoinSpendable(CoinsInfo* coin); + bool isCoinSpendable(const CoinsInfo& coin); + QModelIndex getCurrentIndex(); }; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index bac74d46..8ac436bc 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -1673,11 +1673,7 @@ void MainWindow::onSelectedInputsChanged(const QStringList &selectedInputs) { ui->frame_coinControl->setVisible(numInputs > 0); if (numInputs > 0) { - quint64 totalAmount = 0; - auto coins = m_wallet->coins()->coinsFromKeyImage(selectedInputs); - for (const auto coin : coins) { - totalAmount += coin->amount(); - } + quint64 totalAmount = m_wallet->coins()->sumAmounts(selectedInputs); QString text = QString("Coin control active: %1 selected outputs, %2 XMR").arg(QString::number(numInputs), WalletManager::displayAmount(totalAmount)); ui->label_coinControl->setText(text); diff --git a/src/dialog/OutputInfoDialog.cpp b/src/dialog/OutputInfoDialog.cpp index e78ef2c8..8f7ceb63 100644 --- a/src/dialog/OutputInfoDialog.cpp +++ b/src/dialog/OutputInfoDialog.cpp @@ -6,7 +6,7 @@ #include "utils/Utils.h" -OutputInfoDialog::OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent) +OutputInfoDialog::OutputInfoDialog(const CoinsInfo &cInfo, QWidget *parent) : WindowModalDialog(parent) , ui(new Ui::OutputInfoDialog) { @@ -18,19 +18,19 @@ OutputInfoDialog::OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent) ui->label_txid->setFont(font); ui->label_address->setFont(font); - ui->label_pubKey->setText(cInfo->pubKey()); - ui->label_keyImage->setText(cInfo->keyImage()); - ui->label_txid->setText(cInfo->hash()); - ui->label_address->setText(cInfo->address()); + ui->label_pubKey->setText(cInfo.pubKey); + ui->label_keyImage->setText(cInfo.keyImage); + ui->label_txid->setText(cInfo.hash); + ui->label_address->setText(cInfo.address); - QString status = cInfo->spent() ? "spent" : (cInfo->frozen() ? "frozen" : "unspent"); + QString status = cInfo.spent ? "spent" : (cInfo.frozen ? "frozen" : "unspent"); ui->label_status->setText(status); - ui->label_amount->setText(QString("%1 XMR").arg(cInfo->displayAmount())); - ui->label_creationHeight->setText(QString::number(cInfo->blockHeight())); - ui->label_globalIndex->setText(QString::number(cInfo->globalOutputIndex())); - ui->label_internalIndex->setText(QString::number(cInfo->internalOutputIndex())); + ui->label_amount->setText(QString("%1 XMR").arg(cInfo.displayAmount())); + ui->label_creationHeight->setText(QString::number(cInfo.blockHeight)); + ui->label_globalIndex->setText(QString::number(cInfo.globalOutputIndex)); + ui->label_internalIndex->setText(QString::number(cInfo.internalOutputIndex)); - QString spentHeight = QVariant(cInfo->spentHeight()).toString(); + QString spentHeight = QVariant(cInfo.spentHeight).toString(); if (spentHeight == "0") spentHeight = "n/a"; ui->label_spentHeight->setText(spentHeight); diff --git a/src/dialog/OutputInfoDialog.h b/src/dialog/OutputInfoDialog.h index 0a6cdf5c..1bc31068 100644 --- a/src/dialog/OutputInfoDialog.h +++ b/src/dialog/OutputInfoDialog.h @@ -19,12 +19,11 @@ class OutputInfoDialog : public WindowModalDialog Q_OBJECT public: - explicit OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent = nullptr); + explicit OutputInfoDialog(const CoinsInfo &cInfo, QWidget *parent = nullptr); ~OutputInfoDialog() override; private: QScopedPointer ui; }; - #endif //FEATHER_OUTPUTINFODIALOG_H diff --git a/src/libwalletqt/Coins.cpp b/src/libwalletqt/Coins.cpp index ef0b7c84..5ffbaab5 100644 --- a/src/libwalletqt/Coins.cpp +++ b/src/libwalletqt/Coins.cpp @@ -13,23 +13,17 @@ Coins::Coins(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent) } -bool Coins::coin(int index, std::function callback) +const QList& Coins::getRows() { - 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 %lld transactions in backend", __FUNCTION__, m_rows.count()); - return false; - } - - callback(*m_rows.value(index)); - return true; + return m_rows; } -CoinsInfo* Coins::coin(int index) +const CoinsInfo& Coins::getRow(const qsizetype i) { - return m_rows.value(index); + if (i < 0 || i >= m_rows.size()) { + throw std::out_of_range("Index out of range"); + } + return m_rows[i]; } void Coins::refresh() @@ -54,30 +48,30 @@ void Coins::refresh() continue; } - auto ci = new CoinsInfo(this); - ci->m_blockHeight = td.m_block_height; - ci->m_hash = QString::fromStdString(epee::string_tools::pod_to_hex(td.m_txid)); - ci->m_internalOutputIndex = td.m_internal_output_index; - ci->m_globalOutputIndex = td.m_global_output_index; - ci->m_spent = td.m_spent; - ci->m_frozen = td.m_frozen; - ci->m_spentHeight = td.m_spent_height; - ci->m_amount = td.m_amount; - ci->m_rct = td.m_rct; - ci->m_keyImageKnown = td.m_key_image_known; - ci->m_pkIndex = td.m_pk_index; - ci->m_subaddrIndex = td.m_subaddr_index.minor; - ci->m_subaddrAccount = td.m_subaddr_index.major; - ci->m_address = QString::fromStdString(m_wallet2->get_subaddress_as_str(td.m_subaddr_index)); // todo: this is expensive, cache maybe? - ci->m_addressLabel = QString::fromStdString(m_wallet2->get_subaddress_label(td.m_subaddr_index)); - ci->m_txNote = QString::fromStdString(m_wallet2->get_tx_note(td.m_txid)); - ci->m_keyImage = QString::fromStdString(epee::string_tools::pod_to_hex(td.m_key_image)); - ci->m_unlockTime = td.m_tx.unlock_time; - ci->m_unlocked = m_wallet2->is_transfer_unlocked(td); - ci->m_pubKey = QString::fromStdString(epee::string_tools::pod_to_hex(td.get_public_key())); - ci->m_coinbase = td.m_tx.vin.size() == 1 && td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen); - ci->m_description = m_wallet->getCacheAttribute(QString("coin.description:%1").arg(ci->m_pubKey)); - ci->m_change = m_wallet2->is_change(td); + CoinsInfo ci; + ci.blockHeight = td.m_block_height; + ci.hash = QString::fromStdString(epee::string_tools::pod_to_hex(td.m_txid)); + ci.internalOutputIndex = td.m_internal_output_index; + ci.globalOutputIndex = td.m_global_output_index; + ci.spent = td.m_spent; + ci.frozen = td.m_frozen; + ci.spentHeight = td.m_spent_height; + ci.amount = td.m_amount; + ci.rct = td.m_rct; + ci.keyImageKnown = td.m_key_image_known; + ci.pkIndex = td.m_pk_index; + ci.subaddrIndex = td.m_subaddr_index.minor; + ci.subaddrAccount = td.m_subaddr_index.major; + ci.address = QString::fromStdString(m_wallet2->get_subaddress_as_str(td.m_subaddr_index)); // todo: this is expensive, cache maybe? + ci.addressLabel = QString::fromStdString(m_wallet2->get_subaddress_label(td.m_subaddr_index)); + ci.txNote = QString::fromStdString(m_wallet2->get_tx_note(td.m_txid)); + ci.keyImage = QString::fromStdString(epee::string_tools::pod_to_hex(td.m_key_image)); + ci.unlockTime = td.m_tx.unlock_time; + ci.unlocked = m_wallet2->is_transfer_unlocked(td); + ci.pubKey = QString::fromStdString(epee::string_tools::pod_to_hex(td.get_public_key())); + ci.coinbase = td.m_tx.vin.size() == 1 && td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen); + ci.description = m_wallet->getCacheAttribute(QString("coin.description:%1").arg(ci.pubKey)); + ci.change = m_wallet2->is_change(td); m_rows.push_back(ci); } @@ -90,10 +84,10 @@ void Coins::refreshUnlocked() { QWriteLocker locker(&m_lock); - for (CoinsInfo* c : m_rows) { - if (!c->unlocked()) { - bool unlocked = m_wallet2->is_transfer_unlocked(c->unlockTime(), c->blockHeight()); - c->setUnlocked(unlocked); + for (CoinsInfo& c : m_rows) { + if (!c.unlocked) { + bool unlocked = m_wallet2->is_transfer_unlocked(c.unlockTime, c.blockHeight); + c.setUnlocked(unlocked); } } } @@ -153,30 +147,21 @@ void Coins::thaw(QStringList &publicKeys) refresh(); } -QVector Coins::coins_from_txid(const QString &txid) -{ - QVector coins; - - for (int i = 0; i < this->count(); i++) { - CoinsInfo* coin = this->coin(i); - if (coin->hash() == txid) { - coins.append(coin); +quint64 Coins::sumAmounts(const QStringList &keyImages) { + quint64 amount = 0; + for (const CoinsInfo& coin : m_rows) { + if (!coin.keyImageKnown) { + continue; } - } - return coins; -} - -QVector Coins::coinsFromKeyImage(const QStringList &keyimages) { - QVector coins; - for (int i = 0; i < this->count(); i++) { - CoinsInfo* coin = this->coin(i); - if (coin->keyImageKnown() && keyimages.contains(coin->keyImage())) { - coins.append(coin); + if (!keyImages.contains(coin.keyImage)) { + continue; } + + amount += coin.amount; } - return coins; + return amount; } void Coins::setDescription(const QString &publicKey, quint32 accountIndex, const QString &description) @@ -187,6 +172,5 @@ void Coins::setDescription(const QString &publicKey, quint32 accountIndex, const } void Coins::clearRows() { - qDeleteAll(m_rows); m_rows.clear(); -} \ No newline at end of file +} diff --git a/src/libwalletqt/Coins.h b/src/libwalletqt/Coins.h index eadf92c6..a967c47b 100644 --- a/src/libwalletqt/Coins.h +++ b/src/libwalletqt/Coins.h @@ -4,8 +4,6 @@ #ifndef FEATHER_COINS_H #define FEATHER_COINS_H -#include - #include #include #include @@ -27,16 +25,17 @@ class Coins : public QObject Q_OBJECT public: - bool coin(int index, std::function callback); - CoinsInfo * coin(int index); + const QList& getRows(); + const CoinsInfo& getRow(qsizetype i); + void refresh(); void refreshUnlocked(); void freeze(QStringList &publicKeys); void thaw(QStringList &publicKeys); - QVector coins_from_txid(const QString &txid); - QVector coinsFromKeyImage(const QStringList &keyimages); + quint64 sumAmounts(const QStringList &keyImages); + void setDescription(const QString &publicKey, quint32 accountIndex, const QString &description); quint64 count() const; @@ -55,7 +54,7 @@ private: Wallet *m_wallet; tools::wallet2 *m_wallet2; - QList m_rows; + QList m_rows; mutable QReadWriteLock m_lock; }; diff --git a/src/libwalletqt/rows/CoinsInfo.cpp b/src/libwalletqt/rows/CoinsInfo.cpp index 2c12b5c6..2f7dba92 100644 --- a/src/libwalletqt/rows/CoinsInfo.cpp +++ b/src/libwalletqt/rows/CoinsInfo.cpp @@ -4,144 +4,49 @@ #include "CoinsInfo.h" #include "libwalletqt/WalletManager.h" -quint64 CoinsInfo::blockHeight() const -{ - return m_blockHeight; -} - -QString CoinsInfo::hash() const -{ - return m_hash; -} - -quint64 CoinsInfo::internalOutputIndex() const -{ - return m_internalOutputIndex; -} - -quint64 CoinsInfo::globalOutputIndex() const -{ - return m_globalOutputIndex; -} - -bool CoinsInfo::spent() const -{ - return m_spent; -} - -bool CoinsInfo::frozen() const -{ - return m_frozen; -} - -quint64 CoinsInfo::spentHeight() const -{ - return m_spentHeight; -} - -quint64 CoinsInfo::amount() const { - return m_amount; -} - QString CoinsInfo::displayAmount() const { - return WalletManager::displayAmount(m_amount); -} - -bool CoinsInfo::rct() const { - return m_rct; + return WalletManager::displayAmount(amount); } -bool CoinsInfo::keyImageKnown() const { - return m_keyImageKnown; -} - -quint64 CoinsInfo::pkIndex() const { - return m_pkIndex; -} - -quint32 CoinsInfo::subaddrIndex() const { - return m_subaddrIndex; -} - -quint32 CoinsInfo::subaddrAccount() const { - return m_subaddrAccount; -} - -QString CoinsInfo::address() const { - return m_address; -} - -QString CoinsInfo::addressLabel() const { - if (m_subaddrIndex == 0) { - if (m_coinbase) { +QString CoinsInfo::getAddressLabel() const { + if (subaddrIndex == 0) { + if (coinbase) { return "Coinbase"; } - if (m_change) { + if (change) { return "Change"; } - if (m_addressLabel == "Primary account") { + if (addressLabel == "Primary account") { return "Primary address"; } } - return m_addressLabel; + return addressLabel; } -QString CoinsInfo::keyImage() const { - return m_keyImage; -} - -quint64 CoinsInfo::unlockTime() const { - return m_unlockTime; -} - -bool CoinsInfo::unlocked() const { - return m_unlocked; -} - -void CoinsInfo::setUnlocked(bool unlocked) { - m_unlocked = unlocked; -} - -QString CoinsInfo::pubKey() const { - return m_pubKey; -} - -bool CoinsInfo::coinbase() const { - return m_coinbase; -} - -QString CoinsInfo::description() const { - return m_description; -} - -bool CoinsInfo::change() const { - return m_change; -} -QString CoinsInfo::txNote() const { - return m_txNote; +void CoinsInfo::setUnlocked(bool unlocked_) { + unlocked = unlocked_; } -CoinsInfo::CoinsInfo(QObject *parent) - : QObject(parent) - , m_blockHeight(0) - , m_internalOutputIndex(0) - , m_globalOutputIndex(0) - , m_spent(false) - , m_frozen(false) - , m_spentHeight(0) - , m_amount(0) - , m_rct(false) - , m_keyImageKnown(false) - , m_pkIndex(0) - , m_subaddrIndex(0) - , m_subaddrAccount(0) - , m_unlockTime(0) - , m_unlocked(false) - , m_coinbase(false) - , m_change(false) +CoinsInfo::CoinsInfo() + : blockHeight(0) + , internalOutputIndex(0) + , globalOutputIndex(0) + , spent(false) + , frozen(false) + , spentHeight(0) + , amount(0) + , rct(false) + , keyImageKnown(false) + , pkIndex(0) + , subaddrIndex(0) + , subaddrAccount(0) + , unlockTime(0) + , unlocked(false) + , coinbase(false) + , change(false) { } diff --git a/src/libwalletqt/rows/CoinsInfo.h b/src/libwalletqt/rows/CoinsInfo.h index 65f7f883..2eeb3fbb 100644 --- a/src/libwalletqt/rows/CoinsInfo.h +++ b/src/libwalletqt/rows/CoinsInfo.h @@ -4,73 +4,39 @@ #ifndef FEATHER_COINSINFO_H #define FEATHER_COINSINFO_H -#include -#include -#include +#include -class Coins; - -class CoinsInfo : public QObject +struct CoinsInfo { -Q_OBJECT - -public: - quint64 blockHeight() const; - QString hash() const; - quint64 internalOutputIndex() const; - quint64 globalOutputIndex() const; - bool spent() const; - bool frozen() const; - quint64 spentHeight() const; - quint64 amount() const; + quint64 blockHeight; + QString hash; + quint64 internalOutputIndex; + quint64 globalOutputIndex; + bool spent; + bool frozen; + quint64 spentHeight; + quint64 amount; + bool rct; + bool keyImageKnown; + quint64 pkIndex; + quint32 subaddrIndex; + quint32 subaddrAccount; + QString address; + QString addressLabel; + QString keyImage; + quint64 unlockTime; + bool unlocked; + QString pubKey; + bool coinbase; + QString description; + bool change; + QString txNote; + + QString getAddressLabel() const; QString displayAmount() const; - bool rct() const; - bool keyImageKnown() const; - quint64 pkIndex() const; - quint32 subaddrIndex() const; - quint32 subaddrAccount() const; - QString address() const; - QString addressLabel() const; - QString keyImage() const; - quint64 unlockTime() const; - bool unlocked() const; - QString pubKey() const; - bool coinbase() const; - QString description() const; - bool change() const; - QString txNote() const; - void setUnlocked(bool unlocked); -private: - explicit CoinsInfo(QObject *parent); - -private: - friend class Coins; - - quint64 m_blockHeight; - QString m_hash; - quint64 m_internalOutputIndex; - quint64 m_globalOutputIndex; - bool m_spent; - bool m_frozen; - quint64 m_spentHeight; - quint64 m_amount; - bool m_rct; - bool m_keyImageKnown; - quint64 m_pkIndex; - quint32 m_subaddrIndex; - quint32 m_subaddrAccount; - QString m_address; - QString m_addressLabel; - QString m_keyImage; - quint64 m_unlockTime; - bool m_unlocked; - QString m_pubKey; - bool m_coinbase; - QString m_description; - bool m_change; - QString m_txNote; + explicit CoinsInfo(); }; #endif //FEATHER_COINSINFO_H diff --git a/src/model/CoinsModel.cpp b/src/model/CoinsModel.cpp index b7970400..938316da 100644 --- a/src/model/CoinsModel.cpp +++ b/src/model/CoinsModel.cpp @@ -28,10 +28,6 @@ void CoinsModel::endReset(){ endResetModel(); } -Coins * CoinsModel::coins() const { - return m_coins; -} - int CoinsModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { @@ -51,91 +47,81 @@ int CoinsModel::columnCount(const QModelIndex &parent) const QVariant CoinsModel::data(const QModelIndex &index, int role) const { - if (!m_coins) { - return QVariant(); + const QList& rows = m_coins->getRows(); + if (index.row() < 0 || index.row() >= rows.size()) { + return {}; } + const CoinsInfo& row = rows[index.row()]; - if (!index.isValid() || index.row() < 0 || static_cast(index.row()) >= m_coins->count()) - return QVariant(); - - QVariant result; + bool selected = row.keyImageKnown && m_selected.contains(row.keyImage); - bool found = m_coins->coin(index.row(), [this, &index, &result, &role](const CoinsInfo &cInfo) { - bool selected = cInfo.keyImageKnown() && m_selected.contains(cInfo.keyImage()); - - if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) { - result = parseTransactionInfo(cInfo, index.column(), role); + if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) { + return parseTransactionInfo(row, index.column(), role); + } + else if (role == Qt::BackgroundRole) { + if (row.spent) { + return QBrush(ColorScheme::RED.asColor(true)); } - else if (role == Qt::BackgroundRole) { - if (cInfo.spent()) { - result = QBrush(ColorScheme::RED.asColor(true)); - } - else if (cInfo.frozen()) { - result = QBrush(ColorScheme::BLUE.asColor(true)); - } - else if (!cInfo.unlocked()) { - result = QBrush(ColorScheme::YELLOW.asColor(true)); - } - else if (selected) { - result = QBrush(ColorScheme::GREEN.asColor(true)); - } + if (row.frozen) { + return QBrush(ColorScheme::BLUE.asColor(true)); } - else if (role == Qt::TextAlignmentRole) { - switch (index.column()) { - case Amount: - result = Qt::AlignRight; - } + if (!row.unlocked) { + return QBrush(ColorScheme::YELLOW.asColor(true)); } - else if (role == Qt::DecorationRole) { - switch (index.column()) { - case KeyImageKnown: - { - if (cInfo.keyImageKnown()) { - result = QVariant(icons()->icon("eye1.png")); - } - else { - result = QVariant(icons()->icon("eye_blind.png")); - } + if (selected) { + return QBrush(ColorScheme::GREEN.asColor(true)); + } + } + else if (role == Qt::TextAlignmentRole) { + switch (index.column()) { + case Amount: + return Qt::AlignRight; + } + } + else if (role == Qt::DecorationRole) { + switch (index.column()) { + case KeyImageKnown: + { + if (row.keyImageKnown) { + return QVariant(icons()->icon("eye1.png")); } + return QVariant(icons()->icon("eye_blind.png")); } } - else if (role == Qt::FontRole) { - switch(index.column()) { - case PubKey: - case TxID: - case Address: - result = Utils::getMonospaceFont(); - } + } + else if (role == Qt::FontRole) { + switch(index.column()) { + case PubKey: + case TxID: + case Address: + return Utils::getMonospaceFont(); } - else if (role == Qt::ToolTipRole) { - switch(index.column()) { - case KeyImageKnown: - { - if (cInfo.keyImageKnown()) { - result = "Key image known"; - } else { - result = "Key image unknown. Outgoing transactions that include this output will not be detected."; - } + } + else if (role == Qt::ToolTipRole) { + switch(index.column()) { + case KeyImageKnown: + { + if (row.keyImageKnown) { + return "Key image known"; } + return "Key image unknown. Outgoing transactions that include this output will not be detected."; } - if (cInfo.frozen()) { - result = "Output is frozen."; - } - else if (!cInfo.unlocked()) { - result = "Output is locked (needs more confirmations)"; - } - else if (cInfo.spent()) { - result = "Output is spent"; - } - else if (selected) { - result = "Coin selected to be spent"; - } } - }); - if (!found) { - qCritical("%s: internal error: no transaction info for index %d", __FUNCTION__, index.row()); + if (row.frozen) { + return "Output is frozen."; + } + if (!row.unlocked) { + return "Output is locked (needs more confirmations)"; + } + if (row.spent) { + return "Output is spent"; + } + if (selected) { + return "Coin selected to be spent"; + } } - return result; + + return {}; } QVariant CoinsModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -185,15 +171,9 @@ Qt::ItemFlags CoinsModel::flags(const QModelIndex &index) const bool CoinsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::EditRole) { - const int row = index.row(); + const CoinsInfo& row = m_coins->getRow(index.row()); - QString pubkey; - bool found = m_coins->coin(index.row(), [this, &pubkey](const CoinsInfo &cInfo) { - pubkey = cInfo.pubKey(); - }); - if (!found) { - return false; - } + QString pubkey = row.pubKey; switch (index.column()) { case Label: @@ -218,33 +198,33 @@ QVariant CoinsModel::parseTransactionInfo(const CoinsInfo &cInfo, int column, in case KeyImageKnown: return ""; case PubKey: - return cInfo.pubKey().mid(0,8); + return cInfo.pubKey.mid(0,8); case TxID: - return cInfo.hash().mid(0, 8) + " "; + return cInfo.hash.mid(0, 8) + " "; case BlockHeight: - return cInfo.blockHeight(); + return cInfo.blockHeight; case Address: - return Utils::displayAddress(cInfo.address(), 1, ""); + return Utils::displayAddress(cInfo.address, 1, ""); case Label: { - if (!cInfo.description().isEmpty()) - return cInfo.description(); - if (!cInfo.txNote().isEmpty()) - return cInfo.txNote(); - return cInfo.addressLabel(); + if (!cInfo.description.isEmpty()) + return cInfo.description; + if (!cInfo.txNote.isEmpty()) + return cInfo.txNote; + return cInfo.getAddressLabel(); } case Spent: - return cInfo.spent(); + return cInfo.spent; case SpentHeight: - return cInfo.spentHeight(); + return cInfo.spentHeight; case Amount: { if (role == Qt::UserRole) { - return cInfo.amount(); + return cInfo.amount; } return cInfo.displayAmount(); } case Frozen: - return cInfo.frozen(); + return cInfo.frozen; default: { qCritical() << "Unimplemented role"; @@ -265,7 +245,7 @@ void CoinsModel::setSelected(const QStringList &keyimages) { emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); } -CoinsInfo* CoinsModel::entryFromIndex(const QModelIndex &index) const { +const CoinsInfo& CoinsModel::entryFromIndex(const QModelIndex &index) const { Q_ASSERT(index.isValid() && index.row() < m_coins->count()); - return m_coins->coin(index.row()); -} \ No newline at end of file + return m_coins->getRow(index.row()); +} diff --git a/src/model/CoinsModel.h b/src/model/CoinsModel.h index 792debe3..47afb7e9 100644 --- a/src/model/CoinsModel.h +++ b/src/model/CoinsModel.h @@ -31,8 +31,6 @@ public: explicit CoinsModel(QObject *parent, Coins *coins); - Coins * coins() const; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; @@ -40,7 +38,7 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; - CoinsInfo* entryFromIndex(const QModelIndex &index) const; + const CoinsInfo& entryFromIndex(const QModelIndex &index) const; void setCurrentSubaddressAccount(quint32 accountIndex); void setSelected(const QStringList &selected); diff --git a/src/model/CoinsProxyModel.cpp b/src/model/CoinsProxyModel.cpp index d4ef2336..193f4280 100644 --- a/src/model/CoinsProxyModel.cpp +++ b/src/model/CoinsProxyModel.cpp @@ -26,16 +26,16 @@ void CoinsProxyModel::setSearchFilter(const QString &searchString) { bool CoinsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - CoinsInfo* coin = m_coins->coin(sourceRow); + const CoinsInfo& coin = m_coins->getRow(sourceRow); - if (!m_showSpent && coin->spent()) { + if (!m_showSpent && coin.spent) { return false; } if (!m_searchRegExp.pattern().isEmpty()) { - return coin->pubKey().contains(m_searchRegExp) || coin->address().contains(m_searchRegExp) - || coin->hash().contains(m_searchRegExp) || coin->addressLabel().contains(m_searchRegExp) - || coin->description().contains(m_searchRegExp); + return coin.pubKey.contains(m_searchRegExp) || coin.address.contains(m_searchRegExp) + || coin.hash.contains(m_searchRegExp) || coin.addressLabel.contains(m_searchRegExp) + || coin.description.contains(m_searchRegExp); } return true;