mirror of
https://github.com/feather-wallet/feather.git
synced 2024-11-17 09:47:36 +00:00
refactor: consolidate wallet_api into libwalletqt [1/?]
This commit is contained in:
parent
a13ca973cc
commit
769af188e2
46 changed files with 928 additions and 687 deletions
|
@ -299,7 +299,7 @@ void CoinsWidget::freezeCoins(QStringList &pubkeys) {
|
||||||
for (auto &pubkey : pubkeys) {
|
for (auto &pubkey : pubkeys) {
|
||||||
m_wallet->coins()->freeze(pubkey);
|
m_wallet->coins()->freeze(pubkey);
|
||||||
}
|
}
|
||||||
m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
|
m_wallet->coins()->refresh();
|
||||||
m_wallet->updateBalance();
|
m_wallet->updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ void CoinsWidget::thawCoins(QStringList &pubkeys) {
|
||||||
for (auto &pubkey : pubkeys) {
|
for (auto &pubkey : pubkeys) {
|
||||||
m_wallet->coins()->thaw(pubkey);
|
m_wallet->coins()->thaw(pubkey);
|
||||||
}
|
}
|
||||||
m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
|
m_wallet->coins()->refresh();
|
||||||
m_wallet->updateBalance();
|
m_wallet->updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,9 +135,9 @@ void ContactsWidget::newContact(QString address, QString name)
|
||||||
QString address_entry;
|
QString address_entry;
|
||||||
QString name_entry;
|
QString name_entry;
|
||||||
for (int i=0; i<num_addresses; i++) {
|
for (int i=0; i<num_addresses; i++) {
|
||||||
m_wallet->addressBook()->getRow(i, [&address_entry, &name_entry](const AddressBookInfo &entry){
|
m_wallet->addressBook()->getRow(i, [&address_entry, &name_entry](const ContactRow &entry){
|
||||||
address_entry = entry.address();
|
address_entry = entry.getAddress();
|
||||||
name_entry = entry.description();
|
name_entry = entry.getLabel();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (address == address_entry) {
|
if (address == address_entry) {
|
||||||
|
@ -152,7 +152,7 @@ void ContactsWidget::newContact(QString address, QString name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_wallet->addressBook()->addRow(address, "", name);
|
m_wallet->addressBook()->addRow(address, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsWidget::deleteContact()
|
void ContactsWidget::deleteContact()
|
||||||
|
|
|
@ -86,7 +86,7 @@ void HistoryWidget::showContextMenu(const QPoint &point) {
|
||||||
if (!tx) return;
|
if (!tx) return;
|
||||||
|
|
||||||
bool unconfirmed = tx->isFailed() || tx->isPending();
|
bool unconfirmed = tx->isFailed() || tx->isPending();
|
||||||
if (unconfirmed && tx->direction() != TransactionInfo::Direction_In) {
|
if (unconfirmed && tx->direction() != TransactionRow::Direction_In) {
|
||||||
menu.addAction("Resend transaction", this, &HistoryWidget::onResendTransaction);
|
menu.addAction("Resend transaction", this, &HistoryWidget::onResendTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "dialog/WalletInfoDialog.h"
|
#include "dialog/WalletInfoDialog.h"
|
||||||
#include "dialog/WalletCacheDebugDialog.h"
|
#include "dialog/WalletCacheDebugDialog.h"
|
||||||
#include "libwalletqt/AddressBook.h"
|
#include "libwalletqt/AddressBook.h"
|
||||||
#include "libwalletqt/CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
#include "libwalletqt/Transfer.h"
|
#include "libwalletqt/Transfer.h"
|
||||||
#include "utils/AppData.h"
|
#include "utils/AppData.h"
|
||||||
#include "utils/AsyncTask.h"
|
#include "utils/AsyncTask.h"
|
||||||
|
@ -502,20 +502,20 @@ void MainWindow::onWalletOpened() {
|
||||||
m_wallet->subaddressModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
|
m_wallet->subaddressModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
|
||||||
|
|
||||||
// history page
|
// history page
|
||||||
m_wallet->history()->refresh(m_wallet->currentSubaddressAccount());
|
m_wallet->history()->refresh();
|
||||||
|
|
||||||
// coins page
|
// coins page
|
||||||
m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
|
m_wallet->coins()->refresh();
|
||||||
m_coinsWidget->setModel(m_wallet->coinsModel(), m_wallet->coins());
|
m_coinsWidget->setModel(m_wallet->coinsModel(), m_wallet->coins());
|
||||||
m_wallet->coinsModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
|
m_wallet->coinsModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
|
||||||
|
|
||||||
// Coin labeling uses set_tx_note, so we need to refresh history too
|
// Coin labeling uses set_tx_note, so we need to refresh history too
|
||||||
connect(m_wallet->coins(), &Coins::descriptionChanged, [this] {
|
connect(m_wallet->coins(), &Coins::descriptionChanged, [this] {
|
||||||
m_wallet->history()->refresh(m_wallet->currentSubaddressAccount());
|
m_wallet->history()->refresh();
|
||||||
});
|
});
|
||||||
// Vice versa
|
// Vice versa
|
||||||
connect(m_wallet->history(), &TransactionHistory::txNoteChanged, [this] {
|
connect(m_wallet->history(), &TransactionHistory::txNoteChanged, [this] {
|
||||||
m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
|
m_wallet->coins()->refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
this->updatePasswordIcon();
|
this->updatePasswordIcon();
|
||||||
|
@ -898,7 +898,7 @@ void MainWindow::onTransactionCommitted(bool success, PendingTransaction *tx, co
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
if (msgBox.clickedButton() == showDetailsButton) {
|
if (msgBox.clickedButton() == showDetailsButton) {
|
||||||
this->showHistoryTab();
|
this->showHistoryTab();
|
||||||
TransactionInfo *txInfo = m_wallet->history()->transaction(txid.first());
|
TransactionRow *txInfo = m_wallet->history()->transaction(txid.first());
|
||||||
auto *dialog = new TxInfoDialog(m_wallet, txInfo, this);
|
auto *dialog = new TxInfoDialog(m_wallet, txInfo, this);
|
||||||
connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
|
connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
|
||||||
dialog->show();
|
dialog->show();
|
||||||
|
@ -1145,7 +1145,7 @@ void MainWindow::importContacts() {
|
||||||
i.next();
|
i.next();
|
||||||
bool addressValid = WalletManager::addressValid(i.value(), m_wallet->nettype());
|
bool addressValid = WalletManager::addressValid(i.value(), m_wallet->nettype());
|
||||||
if(addressValid) {
|
if(addressValid) {
|
||||||
m_wallet->addressBook()->addRow(i.value(), "", i.key());
|
m_wallet->addressBook()->addRow(i.value(), i.key());
|
||||||
inserts++;
|
inserts++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ void AccountSwitcherDialog::switchAccount() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_wallet->switchSubaddressAccount(row->getRowId());
|
m_wallet->switchSubaddressAccount(row->getRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountSwitcherDialog::copyLabel() {
|
void AccountSwitcherDialog::copyLabel() {
|
||||||
|
@ -73,7 +73,7 @@ void AccountSwitcherDialog::copyLabel() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::copyToClipboard(QString::fromStdString(row->getLabel()));
|
Utils::copyToClipboard(row->getLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountSwitcherDialog::copyBalance() {
|
void AccountSwitcherDialog::copyBalance() {
|
||||||
|
@ -82,7 +82,7 @@ void AccountSwitcherDialog::copyBalance() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::copyToClipboard(QString::fromStdString(row->getBalance()));
|
Utils::copyToClipboard(row->getBalance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountSwitcherDialog::editLabel() {
|
void AccountSwitcherDialog::editLabel() {
|
||||||
|
@ -93,6 +93,9 @@ void AccountSwitcherDialog::editLabel() {
|
||||||
|
|
||||||
void AccountSwitcherDialog::updateSelection() {
|
void AccountSwitcherDialog::updateSelection() {
|
||||||
QModelIndex index = m_model->index(m_wallet->currentSubaddressAccount(), 0);
|
QModelIndex index = m_model->index(m_wallet->currentSubaddressAccount(), 0);
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ui->accounts->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
ui->accounts->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +114,7 @@ void AccountSwitcherDialog::showContextMenu(const QPoint &point) {
|
||||||
menu->popup(ui->accounts->viewport()->mapToGlobal(point));
|
menu->popup(ui->accounts->viewport()->mapToGlobal(point));
|
||||||
}
|
}
|
||||||
|
|
||||||
Monero::SubaddressAccountRow* AccountSwitcherDialog::currentEntry() {
|
AccountRow* AccountSwitcherDialog::currentEntry() {
|
||||||
QModelIndex index = m_proxyModel->mapToSource(ui->accounts->currentIndex());
|
QModelIndex index = m_proxyModel->mapToSource(ui->accounts->currentIndex());
|
||||||
return m_wallet->subaddressAccountModel()->entryFromIndex(index);
|
return m_wallet->subaddressAccountModel()->entryFromIndex(index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ private:
|
||||||
void copyBalance();
|
void copyBalance();
|
||||||
void editLabel();
|
void editLabel();
|
||||||
|
|
||||||
Monero::SubaddressAccountRow* currentEntry();
|
AccountRow* currentEntry();
|
||||||
|
|
||||||
QScopedPointer<Ui::AccountSwitcherDialog> ui;
|
QScopedPointer<Ui::AccountSwitcherDialog> ui;
|
||||||
Wallet *m_wallet;
|
Wallet *m_wallet;
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeView" name="accounts">
|
<widget class="QTreeView" name="accounts">
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="rootIsDecorated">
|
<property name="rootIsDecorated">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "libwalletqt/Coins.h"
|
#include "libwalletqt/Coins.h"
|
||||||
#include "libwalletqt/CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class OutputInfoDialog;
|
class OutputInfoDialog;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "libwalletqt/CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class OutputSweepDialog;
|
class OutputSweepDialog;
|
||||||
|
|
|
@ -10,14 +10,14 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "libwalletqt/Coins.h"
|
#include "libwalletqt/Coins.h"
|
||||||
#include "libwalletqt/CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
#include "libwalletqt/TransactionHistory.h"
|
#include "libwalletqt/TransactionHistory.h"
|
||||||
#include "libwalletqt/Transfer.h"
|
#include "libwalletqt/Transfer.h"
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
||||||
TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent)
|
TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, ui(new Ui::TxInfoDialog)
|
, ui(new Ui::TxInfoDialog)
|
||||||
, m_wallet(wallet)
|
, m_wallet(wallet)
|
||||||
|
@ -41,7 +41,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *par
|
||||||
|
|
||||||
this->setData(txInfo);
|
this->setData(txInfo);
|
||||||
|
|
||||||
if ((txInfo->isFailed() || txInfo->isPending()) && txInfo->direction() != TransactionInfo::Direction_In) {
|
if ((txInfo->isFailed() || txInfo->isPending()) && txInfo->direction() != TransactionRow::Direction_In) {
|
||||||
connect(ui->btn_rebroadcastTx, &QPushButton::pressed, [this]{
|
connect(ui->btn_rebroadcastTx, &QPushButton::pressed, [this]{
|
||||||
emit resendTranscation(m_txid);
|
emit resendTranscation(m_txid);
|
||||||
});
|
});
|
||||||
|
@ -49,7 +49,7 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *par
|
||||||
ui->btn_rebroadcastTx->hide();
|
ui->btn_rebroadcastTx->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txInfo->direction() == TransactionInfo::Direction_In) {
|
if (txInfo->direction() == TransactionRow::Direction_In) {
|
||||||
ui->btn_CopyTxKey->setDisabled(true);
|
ui->btn_CopyTxKey->setDisabled(true);
|
||||||
ui->btn_CopyTxKey->setToolTip("No tx secret key available for incoming transactions.");
|
ui->btn_CopyTxKey->setToolTip("No tx secret key available for incoming transactions.");
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ void TxInfoDialog::adjustHeight(QTextEdit *textEdit, qreal docHeight) {
|
||||||
textEdit->verticalScrollBar()->hide();
|
textEdit->verticalScrollBar()->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxInfoDialog::setData(TransactionInfo *tx) {
|
void TxInfoDialog::setData(TransactionRow *tx) {
|
||||||
QString blockHeight = QString::number(tx->blockHeight());
|
QString blockHeight = QString::number(tx->blockHeight());
|
||||||
|
|
||||||
if (tx->isFailed()) {
|
if (tx->isFailed()) {
|
||||||
|
@ -131,13 +131,13 @@ void TxInfoDialog::setData(TransactionInfo *tx) {
|
||||||
ui->label_lock->setText("Lock: Outputs are spendable");
|
ui->label_lock->setText("Lock: Outputs are spendable");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString direction = tx->direction() == TransactionInfo::Direction_In ? "received" : "sent";
|
QString direction = tx->direction() == TransactionRow::Direction_In ? "received" : "sent";
|
||||||
ui->label_amount->setText(QString("Amount %1: %2 XMR").arg(direction, tx->displayAmount()));
|
ui->label_amount->setText(QString("Amount %1: %2 XMR").arg(direction, tx->displayAmount()));
|
||||||
|
|
||||||
QString fee;
|
QString fee;
|
||||||
if (tx->isCoinbase())
|
if (tx->isCoinbase())
|
||||||
fee = "Not applicable";
|
fee = "Not applicable";
|
||||||
else if (tx->direction() == TransactionInfo::Direction_In)
|
else if (tx->direction() == TransactionRow::Direction_In)
|
||||||
fee = "Paid by sender";
|
fee = "Paid by sender";
|
||||||
else if (tx->fee().isEmpty())
|
else if (tx->fee().isEmpty())
|
||||||
fee = "N/A";
|
fee = "N/A";
|
||||||
|
@ -149,7 +149,7 @@ void TxInfoDialog::setData(TransactionInfo *tx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxInfoDialog::updateData() {
|
void TxInfoDialog::updateData() {
|
||||||
TransactionInfo *tx = m_wallet->history()->transaction(m_txid);
|
TransactionRow *tx = m_wallet->history()->transaction(m_txid);
|
||||||
if (!tx) return;
|
if (!tx) return;
|
||||||
this->setData(tx);
|
this->setData(tx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QSvgWidget>
|
#include <QSvgWidget>
|
||||||
|
|
||||||
#include "dialog/TxProofDialog.h"
|
#include "dialog/TxProofDialog.h"
|
||||||
|
#include "libwalletqt/rows/TransactionRow.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class TxInfoDialog;
|
class TxInfoDialog;
|
||||||
|
@ -20,7 +21,7 @@ class TxInfoDialog : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent = nullptr);
|
explicit TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *parent = nullptr);
|
||||||
~TxInfoDialog() override;
|
~TxInfoDialog() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -30,14 +31,14 @@ private:
|
||||||
void copyTxID();
|
void copyTxID();
|
||||||
void copyTxKey();
|
void copyTxKey();
|
||||||
void createTxProof();
|
void createTxProof();
|
||||||
void setData(TransactionInfo *tx);
|
void setData(TransactionRow *tx);
|
||||||
void updateData();
|
void updateData();
|
||||||
void adjustHeight(QTextEdit *textEdit, qreal docHeight);
|
void adjustHeight(QTextEdit *textEdit, qreal docHeight);
|
||||||
void viewOnBlockExplorer();
|
void viewOnBlockExplorer();
|
||||||
|
|
||||||
QScopedPointer<Ui::TxInfoDialog> ui;
|
QScopedPointer<Ui::TxInfoDialog> ui;
|
||||||
Wallet *m_wallet;
|
Wallet *m_wallet;
|
||||||
TransactionInfo *m_txInfo;
|
TransactionRow *m_txInfo;
|
||||||
TxProofDialog *m_txProofDialog;
|
TxProofDialog *m_txProofDialog;
|
||||||
QString m_txid;
|
QString m_txid;
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
||||||
TxProofDialog::TxProofDialog(QWidget *parent, Wallet *wallet, TransactionInfo *txInfo)
|
TxProofDialog::TxProofDialog(QWidget *parent, Wallet *wallet, TransactionRow *txInfo)
|
||||||
: WindowModalDialog(parent)
|
: WindowModalDialog(parent)
|
||||||
, ui(new Ui::TxProofDialog)
|
, ui(new Ui::TxProofDialog)
|
||||||
, m_wallet(wallet)
|
, m_wallet(wallet)
|
||||||
|
@ -70,7 +70,7 @@ void TxProofDialog::selectSpendProof() {
|
||||||
m_mode = Mode::SpendProof;
|
m_mode = Mode::SpendProof;
|
||||||
this->resetFrames();
|
this->resetFrames();
|
||||||
|
|
||||||
if (m_direction == TransactionInfo::Direction_In) {
|
if (m_direction == TransactionRow::Direction_In) {
|
||||||
this->showWarning("Your wallet did not construct this transaction. Creating a SpendProof is not possible.");
|
this->showWarning("Your wallet did not construct this transaction. Creating a SpendProof is not possible.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ void TxProofDialog::selectInProof() {
|
||||||
m_mode = Mode::InProof;
|
m_mode = Mode::InProof;
|
||||||
this->resetFrames();
|
this->resetFrames();
|
||||||
|
|
||||||
if (m_direction == TransactionInfo::Direction_Out) {
|
if (m_direction == TransactionRow::Direction_Out) {
|
||||||
this->showWarning("Can't create InProofs for outgoing transactions.");
|
this->showWarning("Can't create InProofs for outgoing transactions.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "libwalletqt/TransactionInfo.h"
|
|
||||||
#include "libwalletqt/Wallet.h"
|
#include "libwalletqt/Wallet.h"
|
||||||
|
#include "rows/TransactionRow.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class TxProofDialog;
|
class TxProofDialog;
|
||||||
|
@ -19,7 +19,7 @@ class TxProofDialog : public WindowModalDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TxProofDialog(QWidget *parent, Wallet *wallet, TransactionInfo *txid);
|
explicit TxProofDialog(QWidget *parent, Wallet *wallet, TransactionRow *txid);
|
||||||
~TxProofDialog() override;
|
~TxProofDialog() override;
|
||||||
void setTxId(const QString &txid);
|
void setTxId(const QString &txid);
|
||||||
void getTxKey();
|
void getTxKey();
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
QString m_txid;
|
QString m_txid;
|
||||||
QString m_txKey;
|
QString m_txKey;
|
||||||
Mode m_mode;
|
Mode m_mode;
|
||||||
TransactionInfo::Direction m_direction;
|
TransactionRow::Direction m_direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEATHER_TXPROOFDIALOG_H
|
#endif //FEATHER_TXPROOFDIALOG_H
|
||||||
|
|
|
@ -4,48 +4,54 @@
|
||||||
#include "AddressBook.h"
|
#include "AddressBook.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
AddressBook::AddressBook(Monero::AddressBook *abImpl, QObject *parent)
|
AddressBook::AddressBook(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent)
|
||||||
: QObject(parent), m_addressBookImpl(abImpl)
|
: QObject(parent)
|
||||||
|
, m_wallet(wallet)
|
||||||
|
, m_wallet2(wallet2)
|
||||||
{
|
{
|
||||||
getAll();
|
this->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AddressBook::errorString() const
|
QString AddressBook::errorString() const
|
||||||
{
|
{
|
||||||
return QString::fromStdString(m_addressBookImpl->errorString());
|
return m_errorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AddressBook::errorCode() const
|
AddressBook::ErrorCode AddressBook::errorCode() const
|
||||||
{
|
{
|
||||||
return m_addressBookImpl->errorCode();
|
return m_errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressBook::getAll()
|
void AddressBook::refresh()
|
||||||
{
|
{
|
||||||
emit refreshStarted();
|
emit refreshStarted();
|
||||||
|
|
||||||
{
|
clearRows();
|
||||||
QWriteLocker locker(&m_lock);
|
|
||||||
|
|
||||||
qDeleteAll(m_rows);
|
// Fetch from Wallet2 and create vector of AddressBookRow objects
|
||||||
|
std::vector<tools::wallet2::address_book_row> rows = m_wallet2->get_address_book();
|
||||||
|
for (qsizetype i = 0; i < rows.size(); ++i) {
|
||||||
|
tools::wallet2::address_book_row *row = &rows.at(i);
|
||||||
|
|
||||||
m_addresses.clear();
|
std::string address;
|
||||||
m_rows.clear();
|
if (row->m_has_payment_id)
|
||||||
|
address = cryptonote::get_account_integrated_address_as_str(m_wallet2->nettype(), row->m_address, row->m_payment_id);
|
||||||
|
else
|
||||||
|
address = get_account_address_as_str(m_wallet2->nettype(), row->m_is_subaddress, row->m_address);
|
||||||
|
|
||||||
for (auto &abr: m_addressBookImpl->getAll()) {
|
auto* abr = new ContactRow{this,
|
||||||
m_addresses.insert(QString::fromStdString(abr->getAddress()), m_rows.size());
|
i,
|
||||||
|
QString::fromStdString(address),
|
||||||
m_rows.append(new AddressBookInfo(abr, this));
|
QString::fromStdString(row->m_description)};
|
||||||
}
|
m_rows.push_back(abr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emit refreshFinished();
|
emit refreshFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressBook::getRow(int index, std::function<void (AddressBookInfo &)> callback) const
|
bool AddressBook::getRow(int index, std::function<void (ContactRow &)> callback) const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
|
||||||
|
|
||||||
if (index < 0 || index >= m_rows.size())
|
if (index < 0 || index >= m_rows.size())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,88 +61,58 @@ bool AddressBook::getRow(int index, std::function<void (AddressBookInfo &)> call
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressBook::addRow(const QString &address, const QString &payment_id, const QString &description)
|
bool AddressBook::addRow(const QString &address, const QString &description)
|
||||||
{
|
{
|
||||||
// virtual bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) = 0;
|
m_errorString = "";
|
||||||
bool result;
|
|
||||||
|
|
||||||
{
|
cryptonote::address_parse_info info;
|
||||||
QWriteLocker locker(&m_lock);
|
if (!cryptonote::get_account_address_from_str(info, m_wallet2->nettype(), address.toStdString())) {
|
||||||
|
m_errorString = tr("Invalid destination address");
|
||||||
result = m_addressBookImpl->addRow(address.toStdString(), payment_id.toStdString(), description.toStdString());
|
m_errorCode = Invalid_Address;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
bool r = m_wallet2->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : nullptr, description.toStdString(), info.is_subaddress);
|
||||||
{
|
if (r)
|
||||||
getAll();
|
refresh();
|
||||||
}
|
else
|
||||||
|
m_errorCode = General_Error;
|
||||||
return result;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressBook::setDescription(int index, const QString &description) {
|
bool AddressBook::setDescription(int index, const QString &description) {
|
||||||
bool result;
|
m_errorString = "";
|
||||||
|
|
||||||
{
|
const auto ab = m_wallet2->get_address_book();
|
||||||
QWriteLocker locker(&m_lock);
|
if (index >= ab.size()){
|
||||||
|
return false;
|
||||||
result = m_addressBookImpl->setDescription(index, description.toStdString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
tools::wallet2::address_book_row entry = ab[index];
|
||||||
{
|
entry.m_description = description.toStdString();
|
||||||
getAll();
|
bool r = m_wallet2->set_address_book_row(index, entry.m_address, entry.m_has_payment_id ? &entry.m_payment_id : nullptr, entry.m_description, entry.m_is_subaddress);
|
||||||
emit descriptionChanged();
|
if (r)
|
||||||
}
|
refresh();
|
||||||
|
else
|
||||||
|
m_errorCode = General_Error;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressBook::deleteRow(int rowId)
|
bool AddressBook::deleteRow(int rowId)
|
||||||
{
|
{
|
||||||
bool result;
|
bool r = m_wallet2->delete_address_book_row(rowId);
|
||||||
|
if (r)
|
||||||
{
|
refresh();
|
||||||
QWriteLocker locker(&m_lock);
|
return r;
|
||||||
|
|
||||||
result = m_addressBookImpl->deleteRow(rowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch new data from wallet2.
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
getAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 AddressBook::count() const
|
qsizetype AddressBook::count() const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
return m_rows.length();
|
||||||
|
|
||||||
return m_rows.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AddressBook::getDescription(const QString &address) const
|
void AddressBook::clearRows()
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
qDeleteAll(m_rows);
|
||||||
|
m_rows.clear();
|
||||||
const QMap<QString, size_t>::const_iterator it = m_addresses.find(address);
|
|
||||||
if (it == m_addresses.end())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return m_rows.value(*it)->description();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AddressBook::getAddress(const QString &description) const
|
|
||||||
{
|
|
||||||
QReadLocker locker(&m_lock);
|
|
||||||
|
|
||||||
for (const auto &row : m_rows) {
|
|
||||||
if (row->description() == description) {
|
|
||||||
return row->address();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString();
|
|
||||||
}
|
}
|
|
@ -5,43 +5,44 @@
|
||||||
#define ADDRESSBOOK_H
|
#define ADDRESSBOOK_H
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
#include <wallet/api/wallet2_api.h>
|
||||||
#include "AddressBookInfo.h"
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "rows/ContactRow.h"
|
||||||
|
#include "Wallet.h"
|
||||||
|
#include "wallet/wallet2.h"
|
||||||
|
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
struct AddressBook;
|
struct AddressBook;
|
||||||
}
|
}
|
||||||
class AddressBookRow;
|
|
||||||
|
|
||||||
class AddressBook : public QObject
|
class AddressBook : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
|
||||||
Q_INVOKABLE bool getRow(int index, std::function<void (AddressBookInfo &)> callback) const;
|
|
||||||
Q_INVOKABLE bool addRow(const QString &address, const QString &payment_id, const QString &description);
|
|
||||||
Q_INVOKABLE bool deleteRow(int rowId);
|
|
||||||
Q_INVOKABLE void setDescription(int index, const QString &label);
|
|
||||||
quint64 count() const;
|
|
||||||
Q_INVOKABLE QString errorString() const;
|
|
||||||
Q_INVOKABLE int errorCode() const;
|
|
||||||
Q_INVOKABLE QString getDescription(const QString &address) const;
|
|
||||||
Q_INVOKABLE QString getAddress(const QString &description) const;
|
|
||||||
|
|
||||||
|
public:
|
||||||
enum ErrorCode {
|
enum ErrorCode {
|
||||||
Status_Ok,
|
Status_Ok,
|
||||||
General_Error,
|
General_Error,
|
||||||
Invalid_Address,
|
Invalid_Address,
|
||||||
Invalid_Payment_Id
|
Invalid_Payment_Id
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_ENUM(ErrorCode);
|
Q_ENUM(ErrorCode);
|
||||||
|
|
||||||
private:
|
bool getRow(int index, std::function<void (ContactRow &)> callback) const;
|
||||||
void getAll();
|
bool addRow(const QString &address, const QString &description);
|
||||||
|
bool deleteRow(int rowId);
|
||||||
|
bool setDescription(int index, const QString &label);
|
||||||
|
qsizetype count() const;
|
||||||
|
QString errorString() const;
|
||||||
|
ErrorCode errorCode() const;
|
||||||
|
|
||||||
|
void refresh();
|
||||||
|
void clearRows();
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshStarted() const;
|
void refreshStarted() const;
|
||||||
|
@ -49,12 +50,15 @@ signals:
|
||||||
void descriptionChanged() const;
|
void descriptionChanged() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AddressBook(Monero::AddressBook * abImpl, QObject *parent);
|
explicit AddressBook(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent);
|
||||||
friend class Wallet;
|
friend class Wallet;
|
||||||
Monero::AddressBook * m_addressBookImpl;
|
|
||||||
mutable QReadWriteLock m_lock;
|
Wallet *m_wallet;
|
||||||
QList<AddressBookInfo*> m_rows;
|
tools::wallet2 *m_wallet2;
|
||||||
QMap<QString, size_t> m_addresses;
|
QList<ContactRow*> m_rows;
|
||||||
|
|
||||||
|
QString m_errorString;
|
||||||
|
ErrorCode m_errorCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ADDRESSBOOK_H
|
#endif // ADDRESSBOOK_H
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
|
||||||
|
|
||||||
#include "AddressBookInfo.h"
|
|
||||||
|
|
||||||
QString AddressBookInfo::address() const {
|
|
||||||
return m_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AddressBookInfo::description() const {
|
|
||||||
return m_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressBookInfo::AddressBookInfo(const Monero::AddressBookRow *pimpl, QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_address(QString::fromStdString(pimpl->getAddress()))
|
|
||||||
, m_description(QString::fromStdString(pimpl->getDescription()))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
|
||||||
|
|
||||||
#ifndef FEATHER_ADDRESSBOOKINFO_H
|
|
||||||
#define FEATHER_ADDRESSBOOKINFO_H
|
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class AddressBookInfo : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString address READ address);
|
|
||||||
Q_PROPERTY(QString description READ description);
|
|
||||||
|
|
||||||
public:
|
|
||||||
QString address() const;
|
|
||||||
QString description() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit AddressBookInfo(const Monero::AddressBookRow *pimpl, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
friend class AddressBook;
|
|
||||||
QString m_address;
|
|
||||||
QString m_description;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //FEATHER_ADDRESSBOOKINFO_H
|
|
|
@ -2,50 +2,80 @@
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
#include "Coins.h"
|
#include "Coins.h"
|
||||||
|
#include "rows/CoinsInfo.h"
|
||||||
|
|
||||||
#include <QDebug>
|
Coins::Coins(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
#include "CoinsInfo.h"
|
, m_wallet(wallet)
|
||||||
|
, m_wallet2(wallet2)
|
||||||
#include <QFile>
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool Coins::coin(int index, std::function<void (CoinsInfo &)> callback)
|
bool Coins::coin(int index, std::function<void (CoinsInfo &)> callback)
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
if (index < 0 || index >= m_tinfo.size()) {
|
if (index < 0 || index >= m_rows.size()) {
|
||||||
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
|
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
|
||||||
qCritical("%s: there's %d transactions in backend", __FUNCTION__, m_pimpl->count());
|
qCritical("%s: there's %lld transactions in backend", __FUNCTION__, m_rows.count());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(*m_tinfo.value(index));
|
callback(*m_rows.value(index));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoinsInfo* Coins::coin(int index)
|
CoinsInfo* Coins::coin(int index)
|
||||||
{
|
{
|
||||||
return m_tinfo.value(index);
|
return m_rows.value(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Coins::refresh(quint32 accountIndex)
|
void Coins::refresh()
|
||||||
{
|
{
|
||||||
emit refreshStarted();
|
emit refreshStarted();
|
||||||
|
|
||||||
|
boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet2->m_transfers_mutex);
|
||||||
|
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&m_lock);
|
QWriteLocker locker(&m_lock);
|
||||||
|
|
||||||
qDeleteAll(m_tinfo);
|
clearRows();
|
||||||
m_tinfo.clear();
|
uint32_t account = m_wallet->currentSubaddressAccount();
|
||||||
|
|
||||||
m_pimpl->refresh();
|
for (size_t i = 0; i < m_wallet2->get_num_transfer_details(); ++i)
|
||||||
for (const auto i : m_pimpl->getAll()) {
|
{
|
||||||
if (i->subaddrAccount() != accountIndex) {
|
const tools::wallet2::transfer_details &td = m_wallet2->get_transfer_details(i);
|
||||||
|
|
||||||
|
if (td.m_subaddr_index.major != account) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tinfo.append(new CoinsInfo(i, this));
|
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_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);
|
||||||
|
|
||||||
|
m_rows.push_back(ci);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +86,9 @@ void Coins::refreshUnlocked()
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&m_lock);
|
QWriteLocker locker(&m_lock);
|
||||||
|
|
||||||
for (CoinsInfo* c : m_tinfo) {
|
for (CoinsInfo* c : m_rows) {
|
||||||
if (!c->unlocked()) {
|
if (!c->unlocked()) {
|
||||||
bool unlocked = m_pimpl->isTransferUnlocked(c->unlockTime(), c->blockHeight());
|
bool unlocked = m_wallet2->is_transfer_unlocked(c->unlockTime(), c->blockHeight());
|
||||||
c->setUnlocked(unlocked);
|
c->setUnlocked(unlocked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,18 +98,50 @@ quint64 Coins::count() const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
return m_tinfo.count();
|
return m_rows.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Coins::freeze(QString &publicKey) const
|
void Coins::freeze(QString &publicKey)
|
||||||
{
|
{
|
||||||
m_pimpl->setFrozen(publicKey.toStdString());
|
crypto::public_key pk;
|
||||||
|
if (!epee::string_tools::hex_to_pod(publicKey.toStdString(), pk))
|
||||||
|
{
|
||||||
|
qWarning() << "Invalid public key: " << publicKey;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet2->freeze(pk);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
qWarning() << "freeze: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
emit coinFrozen();
|
emit coinFrozen();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Coins::thaw(QString &publicKey) const
|
void Coins::thaw(QString &publicKey)
|
||||||
{
|
{
|
||||||
m_pimpl->thaw(publicKey.toStdString());
|
crypto::public_key pk;
|
||||||
|
if (!epee::string_tools::hex_to_pod(publicKey.toStdString(), pk))
|
||||||
|
{
|
||||||
|
qWarning() << "Invalid public key: " << publicKey;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet2->thaw(pk);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
qWarning() << "thaw: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
emit coinThawed();
|
emit coinThawed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,14 +173,12 @@ QVector<CoinsInfo*> Coins::coinsFromKeyImage(const QStringList &keyimages) {
|
||||||
|
|
||||||
void Coins::setDescription(const QString &publicKey, quint32 accountIndex, const QString &description)
|
void Coins::setDescription(const QString &publicKey, quint32 accountIndex, const QString &description)
|
||||||
{
|
{
|
||||||
m_pimpl->setDescription(publicKey.toStdString(), description.toStdString());
|
m_wallet->setCacheAttribute(QString("coin.description:%1").arg(publicKey), description);
|
||||||
this->refresh(accountIndex);
|
this->refresh();
|
||||||
emit descriptionChanged();
|
emit descriptionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
Coins::Coins(Monero::Coins *pimpl, QObject *parent)
|
void Coins::clearRows() {
|
||||||
: QObject(parent)
|
qDeleteAll(m_rows);
|
||||||
, m_pimpl(pimpl)
|
m_rows.clear();
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,6 +12,9 @@
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <wallet/api/wallet2_api.h>
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
|
#include "Wallet.h"
|
||||||
|
#include "wallet/wallet2.h"
|
||||||
|
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
struct TransactionHistory;
|
struct TransactionHistory;
|
||||||
}
|
}
|
||||||
|
@ -25,15 +28,16 @@ Q_OBJECT
|
||||||
public:
|
public:
|
||||||
bool coin(int index, std::function<void (CoinsInfo &)> callback);
|
bool coin(int index, std::function<void (CoinsInfo &)> callback);
|
||||||
CoinsInfo * coin(int index);
|
CoinsInfo * coin(int index);
|
||||||
void refresh(quint32 accountIndex);
|
void refresh();
|
||||||
void refreshUnlocked();
|
void refreshUnlocked();
|
||||||
void freeze(QString &publicKey) const;
|
void freeze(QString &publicKey);
|
||||||
void thaw(QString &publicKey) const;
|
void thaw(QString &publicKey);
|
||||||
QVector<CoinsInfo*> coins_from_txid(const QString &txid);
|
QVector<CoinsInfo*> coins_from_txid(const QString &txid);
|
||||||
QVector<CoinsInfo*> coinsFromKeyImage(const QStringList &keyimages);
|
QVector<CoinsInfo*> coinsFromKeyImage(const QStringList &keyimages);
|
||||||
void setDescription(const QString &publicKey, quint32 accountIndex, const QString &description);
|
void setDescription(const QString &publicKey, quint32 accountIndex, const QString &description);
|
||||||
|
|
||||||
quint64 count() const;
|
quint64 count() const;
|
||||||
|
void clearRows();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshStarted() const;
|
void refreshStarted() const;
|
||||||
|
@ -43,13 +47,16 @@ signals:
|
||||||
void descriptionChanged() const;
|
void descriptionChanged() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Coins(Monero::Coins * pimpl, QObject *parent = nullptr);
|
explicit Coins(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Wallet;
|
friend class Wallet;
|
||||||
|
|
||||||
|
Wallet *m_wallet;
|
||||||
|
tools::wallet2 *m_wallet2;
|
||||||
|
QList<CoinsInfo*> m_rows;
|
||||||
|
|
||||||
mutable QReadWriteLock m_lock;
|
mutable QReadWriteLock m_lock;
|
||||||
Monero::Coins * m_pimpl;
|
|
||||||
mutable QList<CoinsInfo*> m_tinfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEATHER_COINS_H
|
#endif //FEATHER_COINS_H
|
||||||
|
|
|
@ -12,14 +12,15 @@
|
||||||
class Ring : public QObject
|
class Ring : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString keyImage READ keyImage)
|
|
||||||
Q_PROPERTY(std::vector<uint64_t> ringMembers READ ringMembers)
|
public:
|
||||||
private:
|
|
||||||
explicit Ring(QString _keyImage, std::vector<uint64_t> _ringMembers, QObject *parent = nullptr): QObject(parent), m_keyImage(std::move(_keyImage)), m_ringMembers(std::move(_ringMembers)) {};
|
explicit Ring(QString _keyImage, std::vector<uint64_t> _ringMembers, QObject *parent = nullptr): QObject(parent), m_keyImage(std::move(_keyImage)), m_ringMembers(std::move(_ringMembers)) {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TransactionInfo;
|
friend class TransactionInfo;
|
||||||
QString m_keyImage;
|
QString m_keyImage;
|
||||||
std::vector<uint64_t> m_ringMembers;
|
std::vector<uint64_t> m_ringMembers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString keyImage() const { return m_keyImage; }
|
QString keyImage() const { return m_keyImage; }
|
||||||
std::vector<uint64_t> ringMembers() const { return m_ringMembers; }
|
std::vector<uint64_t> ringMembers() const { return m_ringMembers; }
|
||||||
|
|
|
@ -159,8 +159,8 @@ void Subaddress::clearRows() {
|
||||||
|
|
||||||
SubaddressRow* Subaddress::row(int index) const {
|
SubaddressRow* Subaddress::row(int index) const {
|
||||||
return m_rows.value(index);
|
return m_rows.value(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
QString Subaddress::getError() const {
|
QString Subaddress::getError() const {
|
||||||
return m_errorString;
|
return m_errorString;
|
||||||
};
|
}
|
|
@ -4,31 +4,15 @@
|
||||||
#include "SubaddressAccount.h"
|
#include "SubaddressAccount.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
SubaddressAccount::SubaddressAccount(Monero::SubaddressAccount *subaddressAccountImpl, QObject *parent)
|
SubaddressAccount::SubaddressAccount(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent)
|
||||||
: QObject(parent), m_subaddressAccountImpl(subaddressAccountImpl)
|
: QObject(parent)
|
||||||
|
, m_wallet(wallet)
|
||||||
|
, m_wallet2(wallet2)
|
||||||
{
|
{
|
||||||
getAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubaddressAccount::getAll() const
|
bool SubaddressAccount::getRow(int index, std::function<void (AccountRow &row)> callback) const
|
||||||
{
|
{
|
||||||
emit refreshStarted();
|
|
||||||
|
|
||||||
{
|
|
||||||
QWriteLocker locker(&m_lock);
|
|
||||||
m_rows.clear();
|
|
||||||
for (auto &row: m_subaddressAccountImpl->getAll()) {
|
|
||||||
m_rows.append(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit refreshFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SubaddressAccount::getRow(int index, std::function<void (Monero::SubaddressAccountRow &)> callback) const
|
|
||||||
{
|
|
||||||
QReadLocker locker(&m_lock);
|
|
||||||
|
|
||||||
if (index < 0 || index >= m_rows.size())
|
if (index < 0 || index >= m_rows.size())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -38,32 +22,50 @@ bool SubaddressAccount::getRow(int index, std::function<void (Monero::Subaddress
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubaddressAccount::addRow(const QString &label) const
|
void SubaddressAccount::addRow(const QString &label)
|
||||||
{
|
{
|
||||||
m_subaddressAccountImpl->addRow(label.toStdString());
|
m_wallet2->add_subaddress_account(label.toStdString());
|
||||||
getAll();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubaddressAccount::setLabel(quint32 accountIndex, const QString &label) const
|
void SubaddressAccount::setLabel(quint32 accountIndex, const QString &label)
|
||||||
{
|
{
|
||||||
m_subaddressAccountImpl->setLabel(accountIndex, label.toStdString());
|
m_wallet2->set_subaddress_label({accountIndex, 0}, label.toStdString());
|
||||||
getAll();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubaddressAccount::refresh() const
|
void SubaddressAccount::refresh()
|
||||||
{
|
{
|
||||||
m_subaddressAccountImpl->refresh();
|
emit refreshStarted();
|
||||||
getAll();
|
|
||||||
|
this->clearRows();
|
||||||
|
for (uint32_t i = 0; i < m_wallet2->get_num_subaddress_accounts(); ++i)
|
||||||
|
{
|
||||||
|
auto *row = new AccountRow{this,
|
||||||
|
i,
|
||||||
|
QString::fromStdString(m_wallet2->get_subaddress_as_str({i,0})),
|
||||||
|
QString::fromStdString(m_wallet2->get_subaddress_label({i,0})),
|
||||||
|
m_wallet2->balance(i, false),
|
||||||
|
m_wallet2->unlocked_balance(i, false)};
|
||||||
|
|
||||||
|
m_rows.append(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit refreshFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 SubaddressAccount::count() const
|
qsizetype SubaddressAccount::count() const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
return m_rows.length();
|
||||||
|
|
||||||
return m_rows.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Monero::SubaddressAccountRow* SubaddressAccount::row(int index) const
|
void SubaddressAccount::clearRows()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_rows);
|
||||||
|
m_rows.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountRow* SubaddressAccount::row(int index) const
|
||||||
{
|
{
|
||||||
return m_rows.value(index);
|
return m_rows.value(index);
|
||||||
}
|
}
|
|
@ -12,30 +12,40 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include <wallet/wallet2.h>
|
||||||
|
|
||||||
|
#include "Wallet.h"
|
||||||
|
#include "rows/AccountRow.h"
|
||||||
|
|
||||||
class SubaddressAccount : public QObject
|
class SubaddressAccount : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE void getAll() const;
|
void getAll() const;
|
||||||
Q_INVOKABLE bool getRow(int index, std::function<void (Monero::SubaddressAccountRow &)> callback) const;
|
bool getRow(int index, std::function<void (AccountRow &row)> callback) const;
|
||||||
Q_INVOKABLE void addRow(const QString &label) const;
|
void addRow(const QString &label);
|
||||||
Q_INVOKABLE void setLabel(quint32 accountIndex, const QString &label) const;
|
|
||||||
Q_INVOKABLE void refresh() const;
|
void setLabel(quint32 accountIndex, const QString &label);
|
||||||
quint64 count() const;
|
|
||||||
Monero::SubaddressAccountRow* row(int index) const;
|
void refresh();
|
||||||
|
|
||||||
|
qsizetype count() const;
|
||||||
|
void clearRows();
|
||||||
|
|
||||||
|
AccountRow* row(int index) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshStarted() const;
|
void refreshStarted() const;
|
||||||
void refreshFinished() const;
|
void refreshFinished() const;
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit SubaddressAccount(Monero::SubaddressAccount * subaddressAccountImpl, QObject *parent);
|
explicit SubaddressAccount(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent);
|
||||||
friend class Wallet;
|
friend class Wallet;
|
||||||
mutable QReadWriteLock m_lock;
|
|
||||||
Monero::SubaddressAccount * m_subaddressAccountImpl;
|
Wallet *m_wallet;
|
||||||
mutable QList<Monero::SubaddressAccountRow*> m_rows;
|
tools::wallet2 *m_wallet2;
|
||||||
|
QList<AccountRow*> m_rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SUBADDRESSACCOUNT_H
|
#endif // SUBADDRESSACCOUNT_H
|
||||||
|
|
|
@ -2,48 +2,49 @@
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
#include "TransactionHistory.h"
|
#include "TransactionHistory.h"
|
||||||
#include "TransactionInfo.h"
|
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
#include "utils/AppData.h"
|
#include "utils/AppData.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "WalletManager.h"
|
#include "WalletManager.h"
|
||||||
|
#include "Transfer.h"
|
||||||
|
#include "Ring.h"
|
||||||
|
|
||||||
bool TransactionHistory::transaction(int index, std::function<void (TransactionInfo &)> callback)
|
bool TransactionHistory::transaction(int index, std::function<void (TransactionRow &)> callback)
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
if (index < 0 || index >= m_tinfo.size()) {
|
if (index < 0 || index >= m_rows.size()) {
|
||||||
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
|
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
|
||||||
qCritical("%s: there's %d transactions in backend", __FUNCTION__, m_pimpl->count());
|
qCritical("%s: there's %d transactions in backend", __FUNCTION__, this->count());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(*m_tinfo.value(index));
|
callback(*m_rows.value(index));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo* TransactionHistory::transaction(const QString &id)
|
TransactionRow* TransactionHistory::transaction(const QString &id)
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
auto itr = std::find_if(m_tinfo.begin(), m_tinfo.end(),
|
auto itr = std::find_if(m_rows.begin(), m_rows.end(),
|
||||||
[&](const TransactionInfo * ti) {
|
[&](const TransactionRow * ti) {
|
||||||
return ti->hash() == id;
|
return ti->hash() == id;
|
||||||
});
|
});
|
||||||
return itr != m_tinfo.end() ? *itr : nullptr;
|
return itr != m_rows.end() ? *itr : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo* TransactionHistory::transaction(int index)
|
TransactionRow* TransactionHistory::transaction(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= m_tinfo.size()) {
|
if (index < 0 || index >= m_rows.size()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_tinfo[index];
|
return m_rows[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransactionHistory::refresh(quint32 accountIndex)
|
void TransactionHistory::refresh()
|
||||||
{
|
{
|
||||||
QDateTime firstDateTime = QDate(2014, 4, 18).startOfDay();
|
QDateTime firstDateTime = QDate(2014, 4, 18).startOfDay();
|
||||||
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
||||||
|
@ -53,55 +54,214 @@ void TransactionHistory::refresh(quint32 accountIndex)
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&m_lock);
|
QWriteLocker locker(&m_lock);
|
||||||
|
|
||||||
qDeleteAll(m_tinfo);
|
clearRows();
|
||||||
m_tinfo.clear();
|
|
||||||
|
|
||||||
quint64 lastTxHeight = 0;
|
quint64 lastTxHeight = 0;
|
||||||
m_locked = false;
|
m_locked = false;
|
||||||
m_minutesToUnlock = 0;
|
m_minutesToUnlock = 0;
|
||||||
|
|
||||||
m_pimpl->refresh();
|
|
||||||
for (const auto i : m_pimpl->getAll()) {
|
uint64_t min_height = 0;
|
||||||
if (i->subaddrAccount() != accountIndex) {
|
uint64_t max_height = (uint64_t)-1;
|
||||||
|
uint64_t wallet_height = m_wallet->blockChainHeight();
|
||||||
|
uint32_t account = m_wallet->currentSubaddressAccount();
|
||||||
|
|
||||||
|
// transactions are stored in wallet2:
|
||||||
|
// - confirmed_transfer_details - out transfers
|
||||||
|
// - unconfirmed_transfer_details - pending out transfers
|
||||||
|
// - payment_details - input transfers
|
||||||
|
|
||||||
|
// payments are "input transactions";
|
||||||
|
// one input transaction contains only one transfer. e.g. <transaction_id> - <100XMR>
|
||||||
|
|
||||||
|
std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> in_payments;
|
||||||
|
m_wallet2->get_payments(in_payments, min_height, max_height);
|
||||||
|
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = in_payments.begin(); i != in_payments.end(); ++i)
|
||||||
|
{
|
||||||
|
const tools::wallet2::payment_details &pd = i->second;
|
||||||
|
if (pd.m_subaddr_index.major != account) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tinfo.append(new TransactionInfo(i, this));
|
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);
|
||||||
|
|
||||||
const TransactionInfo *ti = m_tinfo.back();
|
auto* t = new TransactionRow();
|
||||||
// looking for transactions timestamp scope
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
if (ti->timestamp() >= lastDateTime) {
|
t->m_coinbase = pd.m_coinbase;
|
||||||
lastDateTime = ti->timestamp();
|
t->m_amount = 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_description = QString::fromStdString(m_wallet2->get_tx_note(pd.m_tx_hash));
|
||||||
|
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;
|
||||||
|
|
||||||
|
m_rows.append(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// confirmed output transactions
|
||||||
|
// one output transaction may contain more than one money transfer, e.g.
|
||||||
|
// <transaction_id>:
|
||||||
|
// transfer1: 100XMR to <address_1>
|
||||||
|
// transfer2: 50XMR to <address_2>
|
||||||
|
// fee: fee charged per transaction
|
||||||
|
//
|
||||||
|
|
||||||
|
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments;
|
||||||
|
m_wallet2->get_payments_out(out_payments, min_height, max_height);
|
||||||
|
|
||||||
|
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = out_payments.begin();
|
||||||
|
i != out_payments.end(); ++i) {
|
||||||
|
|
||||||
|
const crypto::hash &hash = i->first;
|
||||||
|
const tools::wallet2::confirmed_transfer_details &pd = i->second;
|
||||||
|
if (pd.m_subaddr_account != account) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (ti->timestamp() <= firstDateTime) {
|
|
||||||
firstDateTime = ti->timestamp();
|
uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
|
||||||
|
uint64_t fee = pd.m_amount_in - pd.m_amount_out;
|
||||||
|
|
||||||
|
|
||||||
|
std::string payment_id = epee::string_tools::pod_to_hex(i->second.m_payment_id);
|
||||||
|
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||||
|
payment_id = payment_id.substr(0,16);
|
||||||
|
|
||||||
|
|
||||||
|
auto* t = new TransactionRow();
|
||||||
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
|
t->m_amount = pd.m_amount_in - change - fee;
|
||||||
|
t->m_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;
|
||||||
|
|
||||||
|
for (uint32_t idx : t->subaddrIndex())
|
||||||
|
{
|
||||||
|
t->m_subaddrIndex.insert(idx);
|
||||||
}
|
}
|
||||||
quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 10;
|
|
||||||
// store last tx height
|
// single output transaction might contain multiple transfers
|
||||||
if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
|
for (auto const &d: pd.m_dests)
|
||||||
lastTxHeight = ti->blockHeight();
|
{
|
||||||
// TODO: Fetch block time and confirmations needed from wallet2?
|
Transfer *transfer = new Transfer(d.amount, QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id)), this);
|
||||||
m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
|
t->m_transfers.append(transfer);
|
||||||
m_locked = true;
|
|
||||||
}
|
}
|
||||||
|
for (auto const &r: pd.m_rings)
|
||||||
|
{
|
||||||
|
Ring *ring = new Ring(QString::fromStdString(epee::string_tools::pod_to_hex(r.first)), cryptonote::relative_output_offsets_to_absolute(r.second), this);
|
||||||
|
t->m_rings.append(ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rows.append(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unconfirmed output transactions
|
||||||
|
std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments_out;
|
||||||
|
m_wallet2->get_unconfirmed_payments_out(upayments_out);
|
||||||
|
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments_out.begin(); i != upayments_out.end(); ++i) {
|
||||||
|
const tools::wallet2::unconfirmed_transfer_details &pd = i->second;
|
||||||
|
if (pd.m_subaddr_account != account) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::hash &hash = i->first;
|
||||||
|
uint64_t amount = pd.m_amount_in;
|
||||||
|
uint64_t fee = amount - pd.m_amount_out;
|
||||||
|
std::string payment_id = epee::string_tools::pod_to_hex(i->second.m_payment_id);
|
||||||
|
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||||
|
payment_id = payment_id.substr(0,16);
|
||||||
|
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
|
||||||
|
|
||||||
|
auto *t = new TransactionRow();
|
||||||
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
|
t->m_amount = amount - pd.m_change - fee;
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
t->m_subaddrIndex.insert(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const &d: pd.m_dests)
|
||||||
|
{
|
||||||
|
Transfer *transfer = new Transfer(d.amount, QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id)), this);
|
||||||
|
t->m_transfers.append(transfer);
|
||||||
|
}
|
||||||
|
for (auto const &r: pd.m_rings)
|
||||||
|
{
|
||||||
|
Ring *ring = new Ring(QString::fromStdString(epee::string_tools::pod_to_hex(r.first)), cryptonote::relative_output_offsets_to_absolute(r.second), this);
|
||||||
|
t->m_rings.append(ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rows.append(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unconfirmed payments (tx pool)
|
||||||
|
std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> upayments;
|
||||||
|
m_wallet2->get_unconfirmed_payments(upayments);
|
||||||
|
for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
|
||||||
|
const tools::wallet2::payment_details &pd = i->second.m_pd;
|
||||||
|
if (pd.m_subaddr_index.major != account) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
|
t->m_amount = 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_description = QString::fromStdString(m_wallet2->get_tx_note(pd.m_tx_hash));
|
||||||
|
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;
|
||||||
|
|
||||||
|
m_rows.append(t);
|
||||||
|
|
||||||
|
LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit refreshFinished();
|
emit refreshFinished();
|
||||||
|
|
||||||
if (m_firstDateTime != firstDateTime) {
|
|
||||||
m_firstDateTime = firstDateTime;
|
|
||||||
emit firstDateTimeChanged();
|
|
||||||
}
|
|
||||||
if (m_lastDateTime != lastDateTime) {
|
|
||||||
m_lastDateTime = lastDateTime;
|
|
||||||
emit lastDateTimeChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransactionHistory::setTxNote(const QString &txid, const QString ¬e)
|
void TransactionHistory::setTxNote(const QString &txid, const QString ¬e)
|
||||||
{
|
{
|
||||||
m_pimpl->setTxNote(txid.toStdString(), note.toStdString());
|
cryptonote::blobdata txid_data;
|
||||||
|
if(!epee::string_tools::parse_hexstr_to_binbuff(txid.toStdString(), txid_data) || txid_data.size() != sizeof(crypto::hash))
|
||||||
|
return;
|
||||||
|
const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
|
||||||
|
|
||||||
|
m_wallet2->set_tx_note(htxid, note.toStdString());
|
||||||
|
refresh();
|
||||||
emit txNoteChanged();
|
emit txNoteChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +269,7 @@ quint64 TransactionHistory::count() const
|
||||||
{
|
{
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
return m_tinfo.count();
|
return m_rows.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime TransactionHistory::firstDateTime() const
|
QDateTime TransactionHistory::firstDateTime() const
|
||||||
|
@ -133,8 +293,12 @@ bool TransactionHistory::TransactionHistory::locked() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObject *parent)
|
TransactionHistory::TransactionHistory(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent)
|
||||||
: QObject(parent), m_pimpl(pimpl), m_minutesToUnlock(0), m_locked(false)
|
: QObject(parent)
|
||||||
|
, m_wallet(wallet)
|
||||||
|
, m_wallet2(wallet2)
|
||||||
|
, m_minutesToUnlock(0)
|
||||||
|
, m_locked(false)
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||||
m_firstDateTime = QDate(2014, 4, 18).startOfDay();
|
m_firstDateTime = QDate(2014, 4, 18).startOfDay();
|
||||||
|
@ -144,22 +308,25 @@ TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObjec
|
||||||
m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TransactionHistory::clearRows() {
|
||||||
|
qDeleteAll(m_rows);
|
||||||
|
m_rows.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool TransactionHistory::writeCSV(const QString &path) {
|
bool TransactionHistory::writeCSV(const QString &path) {
|
||||||
QString data;
|
QString data;
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
auto transactions = m_pimpl->getAll();
|
auto transactions = m_rows;
|
||||||
|
|
||||||
std::sort(transactions.begin(), transactions.end(), [](const Monero::TransactionInfo *info1, const Monero::TransactionInfo *info2){
|
std::sort(m_rows.begin(), m_rows.end(), [](const TransactionRow *info1, const TransactionRow *info2){
|
||||||
return info1->blockHeight() < info2->blockHeight();
|
return info1->blockHeight() < info2->blockHeight();
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const auto &tx : transactions) {
|
for (const auto &info : transactions) {
|
||||||
TransactionInfo info(tx, this);
|
|
||||||
|
|
||||||
// collect column data
|
// collect column data
|
||||||
QDateTime timeStamp = info.timestamp();
|
QDateTime timeStamp = info->timestamp();
|
||||||
double amount = info.amount();
|
double amount = info->amount();
|
||||||
|
|
||||||
// calc historical fiat price
|
// calc historical fiat price
|
||||||
QString fiatAmount;
|
QString fiatAmount;
|
||||||
|
@ -176,31 +343,31 @@ bool TransactionHistory::writeCSV(const QString &path) {
|
||||||
fiatAmount = "\"?\"";
|
fiatAmount = "\"?\"";
|
||||||
|
|
||||||
QString direction = QString("");
|
QString direction = QString("");
|
||||||
if (info.direction() == TransactionInfo::Direction_In)
|
if (info->direction() == TransactionRow::Direction_In)
|
||||||
direction = QString("in");
|
direction = QString("in");
|
||||||
else if (info.direction() == TransactionInfo::Direction_Out)
|
else if (info->direction() == TransactionRow::Direction_Out)
|
||||||
direction = QString("out");
|
direction = QString("out");
|
||||||
else
|
else
|
||||||
continue; // skip TransactionInfo::Direction_Both
|
continue; // skip TransactionInfo::Direction_Both
|
||||||
|
|
||||||
QString displayAmount = info.displayAmount();
|
QString displayAmount = info->displayAmount();
|
||||||
QString paymentId = info.paymentId();
|
QString paymentId = info->paymentId();
|
||||||
if (paymentId == "0000000000000000") {
|
if (paymentId == "0000000000000000") {
|
||||||
paymentId = "";
|
paymentId = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QString date = QString("%1T%2Z").arg(info.date(), info.time()); // ISO 8601
|
QString date = QString("%1T%2Z").arg(info->date(), info->time()); // ISO 8601
|
||||||
|
|
||||||
QString balanceDelta = WalletManager::displayAmount(info.balanceDelta());
|
QString balanceDelta = WalletManager::displayAmount(info->balanceDelta());
|
||||||
if (info.direction() == TransactionInfo::Direction_Out) {
|
if (info->direction() == TransactionRow::Direction_Out) {
|
||||||
balanceDelta = "-" + balanceDelta;
|
balanceDelta = "-" + balanceDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
// format and write
|
// format and write
|
||||||
QString line = QString("\n%1,%2,\"%3\",%4,\"%5\",%6,%7,%8,\"%9\",\"%10\",\"%11\",%12,\"%13\"")
|
QString line = QString("\n%1,%2,\"%3\",%4,\"%5\",%6,%7,%8,\"%9\",\"%10\",\"%11\",%12,\"%13\"")
|
||||||
.arg(QString::number(info.blockHeight()), QString::number(timeStamp.toSecsSinceEpoch()), date,
|
.arg(QString::number(info->blockHeight()), QString::number(timeStamp.toSecsSinceEpoch()), date,
|
||||||
QString::number(info.subaddrAccount()), direction, balanceDelta, info.displayAmount(),
|
QString::number(info->subaddrAccount()), direction, balanceDelta, info->displayAmount(),
|
||||||
info.fee(), info.hash(), info.description(), paymentId, fiatAmount, preferredFiatSymbol);
|
info->fee(), info->hash(), info->description(), paymentId, fiatAmount, preferredFiatSymbol);
|
||||||
data += line;
|
data += line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "rows/TransactionRow.h"
|
||||||
|
#include "Wallet.h"
|
||||||
|
#include "wallet/wallet2.h"
|
||||||
|
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
struct TransactionHistory;
|
struct TransactionHistory;
|
||||||
}
|
}
|
||||||
|
@ -20,24 +24,20 @@ class TransactionInfo;
|
||||||
class TransactionHistory : public QObject
|
class TransactionHistory : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int count READ count)
|
|
||||||
Q_PROPERTY(QDateTime firstDateTime READ firstDateTime NOTIFY firstDateTimeChanged)
|
|
||||||
Q_PROPERTY(QDateTime lastDateTime READ lastDateTime NOTIFY lastDateTimeChanged)
|
|
||||||
Q_PROPERTY(int minutesToUnlock READ minutesToUnlock)
|
|
||||||
Q_PROPERTY(bool locked READ locked)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE bool transaction(int index, std::function<void (TransactionInfo &)> callback);
|
bool transaction(int index, std::function<void (TransactionRow &)> callback);
|
||||||
Q_INVOKABLE TransactionInfo * transaction(const QString &id);
|
TransactionRow * transaction(const QString &id);
|
||||||
TransactionInfo* transaction(int index);
|
TransactionRow* transaction(int index);
|
||||||
Q_INVOKABLE void refresh(quint32 accountIndex);
|
void refresh();
|
||||||
Q_INVOKABLE void setTxNote(const QString &txid, const QString ¬e);
|
void setTxNote(const QString &txid, const QString ¬e);
|
||||||
Q_INVOKABLE bool writeCSV(const QString &path);
|
bool writeCSV(const QString &path);
|
||||||
quint64 count() const;
|
quint64 count() const;
|
||||||
QDateTime firstDateTime() const;
|
QDateTime firstDateTime() const;
|
||||||
QDateTime lastDateTime() const;
|
QDateTime lastDateTime() const;
|
||||||
quint64 minutesToUnlock() const;
|
quint64 minutesToUnlock() const;
|
||||||
bool locked() const;
|
bool locked() const;
|
||||||
|
void clearRows();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshStarted() const;
|
void refreshStarted() const;
|
||||||
|
@ -47,13 +47,16 @@ signals:
|
||||||
void txNoteChanged() const;
|
void txNoteChanged() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit TransactionHistory(Monero::TransactionHistory * pimpl, QObject *parent = nullptr);
|
explicit TransactionHistory(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Wallet;
|
friend class Wallet;
|
||||||
mutable QReadWriteLock m_lock;
|
mutable QReadWriteLock m_lock;
|
||||||
Monero::TransactionHistory * m_pimpl;
|
|
||||||
mutable QList<TransactionInfo*> m_tinfo;
|
Wallet *m_wallet;
|
||||||
|
tools::wallet2 *m_wallet2;
|
||||||
|
QList<TransactionRow*> m_rows;
|
||||||
|
|
||||||
mutable QDateTime m_firstDateTime;
|
mutable QDateTime m_firstDateTime;
|
||||||
mutable QDateTime m_lastDateTime;
|
mutable QDateTime m_lastDateTime;
|
||||||
mutable int m_minutesToUnlock;
|
mutable int m_minutesToUnlock;
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
|
||||||
|
|
||||||
#include "TransactionInfo.h"
|
|
||||||
#include "libwalletqt/WalletManager.h"
|
|
||||||
#include "Transfer.h"
|
|
||||||
#include "Ring.h"
|
|
||||||
|
|
||||||
TransactionInfo::Direction TransactionInfo::direction() const
|
|
||||||
{
|
|
||||||
return m_direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransactionInfo::isPending() const
|
|
||||||
{
|
|
||||||
return m_pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransactionInfo::isFailed() const
|
|
||||||
{
|
|
||||||
return m_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransactionInfo::isCoinbase() const
|
|
||||||
{
|
|
||||||
return m_coinbase;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::balanceDelta() const
|
|
||||||
{
|
|
||||||
if (m_direction == Direction_In) {
|
|
||||||
return m_amount;
|
|
||||||
}
|
|
||||||
else if (m_direction == Direction_Out) {
|
|
||||||
return m_amount + m_fee;
|
|
||||||
}
|
|
||||||
return m_amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransactionInfo::amount() const
|
|
||||||
{
|
|
||||||
// there's no unsigned uint64 for JS, so better use double
|
|
||||||
return displayAmount().toDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::atomicAmount() const
|
|
||||||
{
|
|
||||||
return m_amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::displayAmount() const
|
|
||||||
{
|
|
||||||
return WalletManager::displayAmount(m_amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::atomicFee() const
|
|
||||||
{
|
|
||||||
return m_fee;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::fee() const
|
|
||||||
{
|
|
||||||
if(m_fee == 0)
|
|
||||||
return "";
|
|
||||||
return WalletManager::displayAmount(m_fee);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::blockHeight() const
|
|
||||||
{
|
|
||||||
return m_blockHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::description() const
|
|
||||||
{
|
|
||||||
return m_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<quint32> TransactionInfo::subaddrIndex() const
|
|
||||||
{
|
|
||||||
return m_subaddrIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 TransactionInfo::subaddrAccount() const
|
|
||||||
{
|
|
||||||
return m_subaddrAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::label() const
|
|
||||||
{
|
|
||||||
return m_label;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::confirmations() const
|
|
||||||
{
|
|
||||||
return m_confirmations;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::confirmationsRequired() const
|
|
||||||
{
|
|
||||||
return (m_blockHeight < m_unlockTime) ? m_unlockTime - m_blockHeight : 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 TransactionInfo::unlockTime() const
|
|
||||||
{
|
|
||||||
return m_unlockTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::hash() const
|
|
||||||
{
|
|
||||||
return m_hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime TransactionInfo::timestamp() const
|
|
||||||
{
|
|
||||||
return m_timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::date() const
|
|
||||||
{
|
|
||||||
return timestamp().date().toString(Qt::ISODate);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::time() const
|
|
||||||
{
|
|
||||||
return timestamp().time().toString(Qt::ISODate);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::paymentId() const
|
|
||||||
{
|
|
||||||
return m_paymentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::destinations_formatted() const
|
|
||||||
{
|
|
||||||
QString destinations;
|
|
||||||
for (auto const& t: m_transfers) {
|
|
||||||
if (!destinations.isEmpty())
|
|
||||||
destinations += "<br> ";
|
|
||||||
destinations += WalletManager::displayAmount(t->amount()) + ": " + t->address();
|
|
||||||
}
|
|
||||||
return destinations;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QString> TransactionInfo::destinations() const
|
|
||||||
{
|
|
||||||
QList<QString> dests;
|
|
||||||
for (auto const& t: m_transfers) {
|
|
||||||
dests.append(t->address());
|
|
||||||
}
|
|
||||||
return dests;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Transfer*> TransactionInfo::transfers() const {
|
|
||||||
return m_transfers;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TransactionInfo::rings_formatted() const
|
|
||||||
{
|
|
||||||
QString rings;
|
|
||||||
for (auto const& r: m_rings) {
|
|
||||||
rings += r->keyImage() + ": \n";
|
|
||||||
for (uint64_t m : r->ringMembers()){
|
|
||||||
rings += QString::number(m) + " ";
|
|
||||||
}
|
|
||||||
rings += "\n\n";
|
|
||||||
}
|
|
||||||
return rings;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionInfo::TransactionInfo(const Monero::TransactionInfo *pimpl, QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_amount(pimpl->amount())
|
|
||||||
, m_blockHeight(pimpl->blockHeight())
|
|
||||||
, m_description(QString::fromStdString(pimpl->description()))
|
|
||||||
, m_confirmations(pimpl->confirmations())
|
|
||||||
, m_direction(static_cast<Direction>(pimpl->direction()))
|
|
||||||
, m_failed(pimpl->isFailed())
|
|
||||||
, m_fee(pimpl->fee())
|
|
||||||
, m_hash(QString::fromStdString(pimpl->hash()))
|
|
||||||
, m_label(QString::fromStdString(pimpl->label()))
|
|
||||||
, m_paymentId(QString::fromStdString(pimpl->paymentId()))
|
|
||||||
, m_pending(pimpl->isPending())
|
|
||||||
, m_subaddrAccount(pimpl->subaddrAccount())
|
|
||||||
, m_timestamp(QDateTime::fromSecsSinceEpoch(pimpl->timestamp()))
|
|
||||||
, m_unlockTime(pimpl->unlockTime())
|
|
||||||
, m_coinbase(pimpl->isCoinbase())
|
|
||||||
{
|
|
||||||
for (auto const &t: pimpl->transfers())
|
|
||||||
{
|
|
||||||
Transfer *transfer = new Transfer(t.amount, QString::fromStdString(t.address), this);
|
|
||||||
m_transfers.append(transfer);
|
|
||||||
}
|
|
||||||
for (auto const &r: pimpl->rings())
|
|
||||||
{
|
|
||||||
Ring *ring = new Ring(QString::fromStdString(r.first), r.second, this);
|
|
||||||
m_rings.append(ring);
|
|
||||||
}
|
|
||||||
for (uint32_t i : pimpl->subaddrIndex())
|
|
||||||
{
|
|
||||||
m_subaddrIndex.insert(i);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@ class Transfer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
public:
|
||||||
explicit Transfer(uint64_t _amount, QString _address, QObject *parent = 0)
|
explicit Transfer(uint64_t _amount, QString _address, QObject *parent = 0)
|
||||||
: QObject(parent), m_amount(_amount), m_address(std::move(_address)) {};
|
: QObject(parent), m_amount(_amount), m_address(std::move(_address)) {};
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -32,21 +32,21 @@ namespace {
|
||||||
Wallet::Wallet(Monero::Wallet *wallet, QObject *parent)
|
Wallet::Wallet(Monero::Wallet *wallet, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_walletImpl(wallet)
|
, m_walletImpl(wallet)
|
||||||
, m_history(new TransactionHistory(m_walletImpl->history(), this))
|
, m_history(new TransactionHistory(this, wallet->getWallet(), this))
|
||||||
, m_historyModel(nullptr)
|
, m_historyModel(nullptr)
|
||||||
, m_addressBook(new AddressBook(m_walletImpl->addressBook(), this))
|
, m_addressBook(new AddressBook(this, wallet->getWallet(), this))
|
||||||
, m_addressBookModel(nullptr)
|
, m_addressBookModel(nullptr)
|
||||||
, m_daemonBlockChainHeight(0)
|
, m_daemonBlockChainHeight(0)
|
||||||
, m_daemonBlockChainTargetHeight(0)
|
, m_daemonBlockChainTargetHeight(0)
|
||||||
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
||||||
, m_currentSubaddressAccount(0)
|
, m_currentSubaddressAccount(0)
|
||||||
, m_subaddress(new Subaddress(this, wallet->getWallet(), this))
|
, m_subaddress(new Subaddress(this, wallet->getWallet(), this))
|
||||||
, m_subaddressAccount(new SubaddressAccount(m_walletImpl->subaddressAccount(), this))
|
, m_subaddressAccount(new SubaddressAccount(this, wallet->getWallet(), this))
|
||||||
, m_refreshNow(false)
|
, m_refreshNow(false)
|
||||||
, m_refreshEnabled(false)
|
, m_refreshEnabled(false)
|
||||||
, m_scheduler(this)
|
, m_scheduler(this)
|
||||||
, m_useSSL(true)
|
, m_useSSL(true)
|
||||||
, m_coins(new Coins(m_walletImpl->coins(), this))
|
, m_coins(new Coins(this, wallet->getWallet(), this))
|
||||||
, m_storeTimer(new QTimer(this))
|
, m_storeTimer(new QTimer(this))
|
||||||
{
|
{
|
||||||
m_walletListener = new WalletListenerImpl(this);
|
m_walletListener = new WalletListenerImpl(this);
|
||||||
|
@ -71,7 +71,7 @@ Wallet::Wallet(Monero::Wallet *wallet, QObject *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(this->history(), &TransactionHistory::txNoteChanged, [this]{
|
connect(this->history(), &TransactionHistory::txNoteChanged, [this]{
|
||||||
this->history()->refresh(this->currentSubaddressAccount());
|
this->history()->refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &Wallet::refreshed, this, &Wallet::onRefreshed);
|
connect(this, &Wallet::refreshed, this, &Wallet::onRefreshed);
|
||||||
|
@ -185,8 +185,8 @@ void Wallet::switchSubaddressAccount(quint32 accountIndex) {
|
||||||
qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute";
|
qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute";
|
||||||
}
|
}
|
||||||
m_subaddress->refresh(m_currentSubaddressAccount);
|
m_subaddress->refresh(m_currentSubaddressAccount);
|
||||||
m_history->refresh(m_currentSubaddressAccount);
|
m_history->refresh();
|
||||||
m_coins->refresh(m_currentSubaddressAccount);
|
m_coins->refresh();
|
||||||
this->subaddressModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
|
this->subaddressModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
|
||||||
this->coinsModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
|
this->coinsModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
|
||||||
this->updateBalance();
|
this->updateBalance();
|
||||||
|
@ -453,8 +453,8 @@ void Wallet::onRefreshed(bool success, const QString &message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::refreshModels() {
|
void Wallet::refreshModels() {
|
||||||
m_history->refresh(this->currentSubaddressAccount());
|
m_history->refresh();
|
||||||
m_coins->refresh(this->currentSubaddressAccount());
|
m_coins->refresh();
|
||||||
bool r = this->subaddress()->refresh(this->currentSubaddressAccount());
|
bool r = this->subaddress()->refresh(this->currentSubaddressAccount());
|
||||||
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
|
@ -776,8 +776,8 @@ void Wallet::onTransactionCommitted(bool success, PendingTransaction *tx, const
|
||||||
// Store wallet immediately, so we don't risk losing tx key if wallet crashes
|
// Store wallet immediately, so we don't risk losing tx key if wallet crashes
|
||||||
this->storeSafer();
|
this->storeSafer();
|
||||||
|
|
||||||
this->history()->refresh(this->currentSubaddressAccount());
|
this->history()->refresh();
|
||||||
this->coins()->refresh(this->currentSubaddressAccount());
|
this->coins()->refresh();
|
||||||
this->updateBalance();
|
this->updateBalance();
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|
25
src/libwalletqt/rows/AccountRow.cpp
Normal file
25
src/libwalletqt/rows/AccountRow.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
|
#include "AccountRow.h"
|
||||||
|
#include "WalletManager.h"
|
||||||
|
|
||||||
|
qsizetype AccountRow::getRow() const {
|
||||||
|
return m_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& AccountRow::getAddress() const {
|
||||||
|
return m_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& AccountRow::getLabel() const {
|
||||||
|
return m_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AccountRow::getBalance() const {
|
||||||
|
return WalletManager::displayAmount(m_balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AccountRow::getUnlockedBalance() const {
|
||||||
|
return WalletManager::displayAmount(m_unlockedBalance);
|
||||||
|
}
|
36
src/libwalletqt/rows/AccountRow.h
Normal file
36
src/libwalletqt/rows/AccountRow.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
|
#ifndef FEATHER_ACCOUNTROW_H
|
||||||
|
#define FEATHER_ACCOUNTROW_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class AccountRow : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
AccountRow(QObject *parent, qsizetype row, const QString& address, const QString &label, uint64_t balance, uint64_t unlockedBalance)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_row(row)
|
||||||
|
, m_address(address)
|
||||||
|
, m_label(label)
|
||||||
|
, m_balance(balance)
|
||||||
|
, m_unlockedBalance(unlockedBalance) {}
|
||||||
|
|
||||||
|
qsizetype getRow() const;
|
||||||
|
const QString& getAddress() const;
|
||||||
|
const QString& getLabel() const;
|
||||||
|
QString getBalance() const;
|
||||||
|
QString getUnlockedBalance() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
qsizetype m_row;
|
||||||
|
QString m_address;
|
||||||
|
QString m_label;
|
||||||
|
uint64_t m_balance;
|
||||||
|
uint64_t m_unlockedBalance;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FEATHER_ACCOUNTROW_H
|
|
@ -74,7 +74,15 @@ QString CoinsInfo::address() const {
|
||||||
|
|
||||||
QString CoinsInfo::addressLabel() const {
|
QString CoinsInfo::addressLabel() const {
|
||||||
if (m_subaddrIndex == 0) {
|
if (m_subaddrIndex == 0) {
|
||||||
return m_coinbase ? "Coinbase" : "Change";
|
if (m_coinbase) {
|
||||||
|
return "Coinbase";
|
||||||
|
}
|
||||||
|
if (m_change) {
|
||||||
|
return "Change";
|
||||||
|
}
|
||||||
|
if (m_addressLabel == "Primary account") {
|
||||||
|
return "Primary address";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_addressLabel;
|
return m_addressLabel;
|
||||||
|
@ -108,29 +116,28 @@ QString CoinsInfo::description() const {
|
||||||
return m_description;
|
return m_description;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoinsInfo::CoinsInfo(const Monero::CoinsInfo *pimpl, QObject *parent)
|
bool CoinsInfo::change() const {
|
||||||
|
return m_change;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinsInfo::CoinsInfo(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_blockHeight(pimpl->blockHeight())
|
, m_blockHeight(0)
|
||||||
, m_hash(QString::fromStdString(pimpl->hash()))
|
, m_internalOutputIndex(0)
|
||||||
, m_internalOutputIndex(pimpl->internalOutputIndex())
|
, m_globalOutputIndex(0)
|
||||||
, m_globalOutputIndex(pimpl->globalOutputIndex())
|
, m_spent(false)
|
||||||
, m_spent(pimpl->spent())
|
, m_frozen(false)
|
||||||
, m_frozen(pimpl->frozen())
|
, m_spentHeight(0)
|
||||||
, m_spentHeight(pimpl->spentHeight())
|
, m_amount(0)
|
||||||
, m_amount(pimpl->amount())
|
, m_rct(false)
|
||||||
, m_rct(pimpl->rct())
|
, m_keyImageKnown(false)
|
||||||
, m_keyImageKnown(pimpl->keyImageKnown())
|
, m_pkIndex(0)
|
||||||
, m_pkIndex(pimpl->pkIndex())
|
, m_subaddrIndex(0)
|
||||||
, m_subaddrIndex(pimpl->subaddrIndex())
|
, m_subaddrAccount(0)
|
||||||
, m_subaddrAccount(pimpl->subaddrAccount())
|
, m_unlockTime(0)
|
||||||
, m_address(QString::fromStdString(pimpl->address()))
|
, m_unlocked(false)
|
||||||
, m_addressLabel(QString::fromStdString(pimpl->addressLabel()))
|
, m_coinbase(false)
|
||||||
, m_keyImage(QString::fromStdString(pimpl->keyImage()))
|
, m_change(false)
|
||||||
, m_unlockTime(pimpl->unlockTime())
|
|
||||||
, m_unlocked(pimpl->unlocked())
|
|
||||||
, m_pubKey(QString::fromStdString(pimpl->pubKey()))
|
|
||||||
, m_coinbase(pimpl->coinbase())
|
|
||||||
, m_description(QString::fromStdString(pimpl->description()))
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,28 +14,6 @@ class Coins;
|
||||||
class CoinsInfo : public QObject
|
class CoinsInfo : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
|
||||||
Q_PROPERTY(QString hash READ hash)
|
|
||||||
Q_PROPERTY(quint64 internalOutputIndex READ internalOutputIndex)
|
|
||||||
Q_PROPERTY(quint64 globalOutputIndex READ globalOutputIndex)
|
|
||||||
Q_PROPERTY(bool spent READ spent)
|
|
||||||
Q_PROPERTY(bool frozen READ frozen)
|
|
||||||
Q_PROPERTY(quint64 spentHeight READ spentHeight)
|
|
||||||
Q_PROPERTY(quint64 amount READ amount)
|
|
||||||
Q_PROPERTY(QString displayAmount READ displayAmount)
|
|
||||||
Q_PROPERTY(bool rct READ rct)
|
|
||||||
Q_PROPERTY(bool keyImageKnown READ keyImageKnown)
|
|
||||||
Q_PROPERTY(quint64 pkIndex READ pkIndex)
|
|
||||||
Q_PROPERTY(quint32 subaddrIndex READ subaddrIndex)
|
|
||||||
Q_PROPERTY(quint32 subaddrAccount READ subaddrAccount)
|
|
||||||
Q_PROPERTY(QString address READ address)
|
|
||||||
Q_PROPERTY(QString addressLabel READ addressLabel)
|
|
||||||
Q_PROPERTY(QString keyImage READ keyImage)
|
|
||||||
Q_PROPERTY(quint64 unlockTime READ unlockTime)
|
|
||||||
Q_PROPERTY(bool unlocked READ unlocked)
|
|
||||||
Q_PROPERTY(QString pubKey READ pubKey)
|
|
||||||
Q_PROPERTY(bool coinbase READ coinbase)
|
|
||||||
Q_PROPERTY(QString description READ description)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
quint64 blockHeight() const;
|
quint64 blockHeight() const;
|
||||||
|
@ -60,11 +38,13 @@ public:
|
||||||
QString pubKey() const;
|
QString pubKey() const;
|
||||||
bool coinbase() const;
|
bool coinbase() const;
|
||||||
QString description() const;
|
QString description() const;
|
||||||
|
bool change() const;
|
||||||
|
|
||||||
void setUnlocked(bool unlocked);
|
void setUnlocked(bool unlocked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit CoinsInfo(const Monero::CoinsInfo *pimpl, QObject *parent = nullptr);
|
explicit CoinsInfo(QObject *parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Coins;
|
friend class Coins;
|
||||||
|
|
||||||
|
@ -89,6 +69,7 @@ private:
|
||||||
QString m_pubKey;
|
QString m_pubKey;
|
||||||
bool m_coinbase;
|
bool m_coinbase;
|
||||||
QString m_description;
|
QString m_description;
|
||||||
|
bool m_change;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEATHER_COINSINFO_H
|
#endif //FEATHER_COINSINFO_H
|
16
src/libwalletqt/rows/ContactRow.cpp
Normal file
16
src/libwalletqt/rows/ContactRow.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
|
#include "ContactRow.h"
|
||||||
|
|
||||||
|
qsizetype ContactRow::getRow() const {
|
||||||
|
return m_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& ContactRow::getAddress() const {
|
||||||
|
return m_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& ContactRow::getLabel() const {
|
||||||
|
return m_label;
|
||||||
|
}
|
31
src/libwalletqt/rows/ContactRow.h
Normal file
31
src/libwalletqt/rows/ContactRow.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
|
#ifndef FEATHER_CONTACTROW_H
|
||||||
|
#define FEATHER_CONTACTROW_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ContactRow : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ContactRow(QObject *parent, qsizetype row, const QString& address, const QString &label)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_row(row)
|
||||||
|
, m_address(address)
|
||||||
|
, m_label(label) {}
|
||||||
|
|
||||||
|
qsizetype getRow() const;
|
||||||
|
const QString& getAddress() const;
|
||||||
|
const QString& getLabel() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
qsizetype m_row;
|
||||||
|
QString m_address;
|
||||||
|
QString m_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //FEATHER_CONTACTROW_H
|
183
src/libwalletqt/rows/TransactionRow.cpp
Normal file
183
src/libwalletqt/rows/TransactionRow.cpp
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
|
#include "TransactionRow.h"
|
||||||
|
#include "WalletManager.h"
|
||||||
|
#include "Transfer.h"
|
||||||
|
#include "Ring.h"
|
||||||
|
|
||||||
|
TransactionRow::TransactionRow()
|
||||||
|
: m_direction(TransactionRow::Direction_Out)
|
||||||
|
, m_pending(false)
|
||||||
|
, m_failed(false)
|
||||||
|
, m_coinbase(false)
|
||||||
|
, m_amount(0)
|
||||||
|
, m_fee(0)
|
||||||
|
, m_blockHeight(0)
|
||||||
|
, m_subaddrAccount(0)
|
||||||
|
, m_confirmations(0)
|
||||||
|
, m_unlockTime(0)
|
||||||
|
, m_confirmationsRequired(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionRow::Direction TransactionRow::direction() 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 TransactionRow::balanceDelta() const
|
||||||
|
{
|
||||||
|
if (m_direction == Direction_In) {
|
||||||
|
return m_amount;
|
||||||
|
}
|
||||||
|
else if (m_direction == Direction_Out) {
|
||||||
|
return m_amount + m_fee;
|
||||||
|
}
|
||||||
|
return m_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
double TransactionRow::amount() const
|
||||||
|
{
|
||||||
|
// there's no unsigned uint64 for JS, so better use double
|
||||||
|
return displayAmount().toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 TransactionRow::atomicAmount() const
|
||||||
|
{
|
||||||
|
return m_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionRow::displayAmount() const
|
||||||
|
{
|
||||||
|
return WalletManager::displayAmount(m_amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 TransactionRow::atomicFee() const
|
||||||
|
{
|
||||||
|
return m_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionRow::fee() const
|
||||||
|
{
|
||||||
|
if(m_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionRow::date() const
|
||||||
|
{
|
||||||
|
return timestamp().date().toString(Qt::ISODate);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionRow::time() const
|
||||||
|
{
|
||||||
|
return timestamp().time().toString(Qt::ISODate);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionRow::paymentId() const
|
||||||
|
{
|
||||||
|
return m_paymentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionRow::destinations_formatted() const
|
||||||
|
{
|
||||||
|
QString destinations;
|
||||||
|
for (auto const& t: m_transfers) {
|
||||||
|
if (!destinations.isEmpty())
|
||||||
|
destinations += "<br> ";
|
||||||
|
destinations += WalletManager::displayAmount(t->amount()) + ": " + t->address();
|
||||||
|
}
|
||||||
|
return destinations;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> TransactionRow::destinations() const
|
||||||
|
{
|
||||||
|
QList<QString> dests;
|
||||||
|
for (auto const& t: m_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";
|
||||||
|
for (uint64_t m : r->ringMembers()){
|
||||||
|
rings += QString::number(m) + " ";
|
||||||
|
}
|
||||||
|
rings += "\n\n";
|
||||||
|
}
|
||||||
|
return rings;
|
||||||
|
}
|
|
@ -1,48 +1,24 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
#ifndef TRANSACTIONINFO_H
|
#ifndef FEATHER_TRANSACTIONROW_H
|
||||||
#define TRANSACTIONINFO_H
|
#define FEATHER_TRANSACTIONROW_H
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QSet>
|
|
||||||
|
|
||||||
class Transfer;
|
class Transfer;
|
||||||
class Ring;
|
class Ring;
|
||||||
|
|
||||||
class TransactionInfo : public QObject
|
#include <QObject>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class TransactionRow : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(Direction direction READ direction)
|
|
||||||
Q_PROPERTY(bool isPending READ isPending)
|
|
||||||
Q_PROPERTY(bool isFailed READ isFailed)
|
|
||||||
Q_PROPERTY(bool isCoinbase READ isCoinbase)
|
|
||||||
Q_PROPERTY(double amount READ amount)
|
|
||||||
Q_PROPERTY(quint64 atomicAmount READ atomicAmount)
|
|
||||||
Q_PROPERTY(QString displayAmount READ displayAmount)
|
|
||||||
Q_PROPERTY(QString fee READ fee)
|
|
||||||
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
|
||||||
Q_PROPERTY(QString description READ description)
|
|
||||||
Q_PROPERTY(QSet<quint32> subaddrIndex READ subaddrIndex)
|
|
||||||
Q_PROPERTY(quint32 subaddrAccount READ subaddrAccount)
|
|
||||||
Q_PROPERTY(QString label READ label)
|
|
||||||
Q_PROPERTY(quint64 confirmations READ confirmations)
|
|
||||||
Q_PROPERTY(quint64 confirmationsRequired READ confirmationsRequired)
|
|
||||||
Q_PROPERTY(quint64 unlockTime READ unlockTime)
|
|
||||||
Q_PROPERTY(QString hash READ hash)
|
|
||||||
Q_PROPERTY(QDateTime timestamp READ timestamp)
|
|
||||||
Q_PROPERTY(QString date READ date)
|
|
||||||
Q_PROPERTY(QString time READ time)
|
|
||||||
Q_PROPERTY(QString paymentId READ paymentId)
|
|
||||||
Q_PROPERTY(QString destinations_formatted READ destinations_formatted)
|
|
||||||
Q_PROPERTY(QString rings_formatted READ rings_formatted)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Direction {
|
enum Direction {
|
||||||
Direction_In = Monero::TransactionInfo::Direction_In,
|
Direction_In = 0,
|
||||||
Direction_Out = Monero::TransactionInfo::Direction_Out,
|
Direction_Out = 1,
|
||||||
Direction_Both // invalid direction value, used for filtering
|
Direction_Both // invalid direction value, used for filtering
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,7 +56,10 @@ public:
|
||||||
QString rings_formatted() const;
|
QString rings_formatted() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit TransactionInfo(const Monero::TransactionInfo *pimpl, QObject *parent = nullptr);
|
explicit TransactionRow();
|
||||||
|
|
||||||
|
// TransactionRow(const Monero::TransactionInfo *pimpl, QObject *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TransactionHistory;
|
friend class TransactionHistory;
|
||||||
mutable QList<Transfer*> m_transfers;
|
mutable QList<Transfer*> m_transfers;
|
||||||
|
@ -104,4 +83,5 @@ private:
|
||||||
bool m_coinbase;
|
bool m_coinbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRANSACTIONINFO_H
|
|
||||||
|
#endif //FEATHER_TRANSACTIONROW_H
|
|
@ -70,12 +70,12 @@ QVariant AddressBookModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
QVariant result;
|
QVariant result;
|
||||||
|
|
||||||
bool found = m_addressBook->getRow(index.row(), [this, &result, &role, &index](const AddressBookInfo &row) {
|
bool found = m_addressBook->getRow(index.row(), [this, &result, &role, &index](const ContactRow &row) {
|
||||||
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case Address:
|
case Address:
|
||||||
{
|
{
|
||||||
QString address = row.address();
|
QString address = row.getAddress();
|
||||||
if (!m_showFullAddresses && role != Qt::UserRole) {
|
if (!m_showFullAddresses && role != Qt::UserRole) {
|
||||||
address = Utils::displayAddress(address);
|
address = Utils::displayAddress(address);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ QVariant AddressBookModel::data(const QModelIndex &index, int role) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Description:
|
case Description:
|
||||||
result = row.description();
|
result = row.getLabel();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qCritical() << "Invalid column" << index.column();
|
qCritical() << "Invalid column" << index.column();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
|
||||||
|
|
||||||
#include "CoinsModel.h"
|
#include "CoinsModel.h"
|
||||||
#include "CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
#include "Coins.h"
|
#include "Coins.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "utils/ColorScheme.h"
|
#include "utils/ColorScheme.h"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "CoinsProxyModel.h"
|
#include "CoinsProxyModel.h"
|
||||||
#include "CoinsModel.h"
|
#include "CoinsModel.h"
|
||||||
#include "libwalletqt/CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
|
|
||||||
CoinsProxyModel::CoinsProxyModel(QObject *parent, Coins *coins)
|
CoinsProxyModel::CoinsProxyModel(QObject *parent, Coins *coins)
|
||||||
: QSortFilterProxyModel(parent)
|
: QSortFilterProxyModel(parent)
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "HistoryView.h"
|
#include "HistoryView.h"
|
||||||
|
|
||||||
#include "TransactionHistoryProxyModel.h"
|
#include "TransactionHistoryProxyModel.h"
|
||||||
#include "libwalletqt/TransactionInfo.h"
|
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
@ -71,7 +70,7 @@ TransactionHistoryModel* HistoryView::sourceModel()
|
||||||
return dynamic_cast<TransactionHistoryModel *>(m_model->sourceModel());
|
return dynamic_cast<TransactionHistoryModel *>(m_model->sourceModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo* HistoryView::currentEntry()
|
TransactionRow* HistoryView::currentEntry()
|
||||||
{
|
{
|
||||||
QModelIndexList list = selectionModel()->selectedRows();
|
QModelIndexList list = selectionModel()->selectedRows();
|
||||||
if (list.size() == 1) {
|
if (list.size() == 1) {
|
||||||
|
@ -199,7 +198,7 @@ void HistoryView::resetViewToDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryView::keyPressEvent(QKeyEvent *event) {
|
void HistoryView::keyPressEvent(QKeyEvent *event) {
|
||||||
TransactionInfo* tx = this->currentEntry();
|
TransactionRow* tx = this->currentEntry();
|
||||||
|
|
||||||
if (event->matches(QKeySequence::Copy) && tx) {
|
if (event->matches(QKeySequence::Copy) && tx) {
|
||||||
Utils::copyToClipboard(tx->hash());
|
Utils::copyToClipboard(tx->hash());
|
||||||
|
|
|
@ -18,7 +18,7 @@ class HistoryView : public QTreeView
|
||||||
public:
|
public:
|
||||||
explicit HistoryView(QWidget* parent = nullptr);
|
explicit HistoryView(QWidget* parent = nullptr);
|
||||||
void setHistoryModel(TransactionHistoryProxyModel *model);
|
void setHistoryModel(TransactionHistoryProxyModel *model);
|
||||||
TransactionInfo* currentEntry();
|
TransactionRow* currentEntry();
|
||||||
|
|
||||||
void setSearchMode(bool mode);
|
void setSearchMode(bool mode);
|
||||||
QByteArray viewState() const;
|
QByteArray viewState() const;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
#include "rows/AccountRow.h"
|
||||||
|
|
||||||
SubaddressAccountModel::SubaddressAccountModel(QObject *parent, SubaddressAccount *subaddressAccount)
|
SubaddressAccountModel::SubaddressAccountModel(QObject *parent, SubaddressAccount *subaddressAccount)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
|
@ -49,7 +50,7 @@ QVariant SubaddressAccountModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
QVariant result;
|
QVariant result;
|
||||||
|
|
||||||
bool found = m_subaddressAccount->getRow(index.row(), [this, &index, &result, &role](const Monero::SubaddressAccountRow &row) {
|
bool found = m_subaddressAccount->getRow(index.row(), [this, &index, &result, &role](const AccountRow &row) {
|
||||||
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
||||||
result = parseSubaddressAccountRow(row, index, role);
|
result = parseSubaddressAccountRow(row, index, role);
|
||||||
}
|
}
|
||||||
|
@ -72,7 +73,7 @@ QVariant SubaddressAccountModel::data(const QModelIndex &index, int role) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant SubaddressAccountModel::parseSubaddressAccountRow(const Monero::SubaddressAccountRow &row,
|
QVariant SubaddressAccountModel::parseSubaddressAccountRow(const AccountRow &row,
|
||||||
const QModelIndex &index, int role) const
|
const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
|
@ -82,19 +83,19 @@ QVariant SubaddressAccountModel::parseSubaddressAccountRow(const Monero::Subaddr
|
||||||
}
|
}
|
||||||
return QString("#%1").arg(QString::number(index.row()));
|
return QString("#%1").arg(QString::number(index.row()));
|
||||||
case Address:
|
case Address:
|
||||||
return QString::fromStdString(row.getAddress());
|
return row.getAddress();
|
||||||
case Label:
|
case Label:
|
||||||
return QString::fromStdString(row.getLabel());
|
return row.getLabel();
|
||||||
case Balance:
|
case Balance:
|
||||||
if (role == Qt::UserRole) {
|
if (role == Qt::UserRole) {
|
||||||
return WalletManager::amountFromString(QString::fromStdString(row.getBalance()));
|
return WalletManager::amountFromString(row.getBalance());
|
||||||
}
|
}
|
||||||
return QString::fromStdString(row.getBalance());
|
return row.getBalance();
|
||||||
case UnlockedBalance:
|
case UnlockedBalance:
|
||||||
if (role == Qt::UserRole) {
|
if (role == Qt::UserRole) {
|
||||||
return WalletManager::amountFromString(QString::fromStdString(row.getUnlockedBalance()));
|
return WalletManager::amountFromString(row.getUnlockedBalance());
|
||||||
}
|
}
|
||||||
return QString::fromStdString(row.getUnlockedBalance());
|
return row.getUnlockedBalance();
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -154,8 +155,7 @@ Qt::ItemFlags SubaddressAccountModel::flags(const QModelIndex &index) const
|
||||||
return QAbstractTableModel::flags(index);
|
return QAbstractTableModel::flags(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Monero::SubaddressAccountRow* SubaddressAccountModel::entryFromIndex(const QModelIndex &index) const {
|
AccountRow* SubaddressAccountModel::entryFromIndex(const QModelIndex &index) const {
|
||||||
Q_ASSERT(index.isValid() && index.row() < m_subaddressAccount->count());
|
|
||||||
return m_subaddressAccount->row(index.row());
|
return m_subaddressAccount->row(index.row());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include "rows/AccountRow.h"
|
||||||
|
|
||||||
class SubaddressAccount;
|
class SubaddressAccount;
|
||||||
|
|
||||||
class SubaddressAccountModel : public QAbstractTableModel
|
class SubaddressAccountModel : public QAbstractTableModel
|
||||||
|
@ -34,14 +36,14 @@ public:
|
||||||
|
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||||
|
|
||||||
Monero::SubaddressAccountRow* entryFromIndex(const QModelIndex &index) const;
|
AccountRow* entryFromIndex(const QModelIndex &index) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startReset();
|
void startReset();
|
||||||
void endReset();
|
void endReset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant parseSubaddressAccountRow(const Monero::SubaddressAccountRow &row, const QModelIndex &index, int role) const;
|
QVariant parseSubaddressAccountRow(const AccountRow &row, const QModelIndex &index, int role) const;
|
||||||
|
|
||||||
SubaddressAccount *m_subaddressAccount;
|
SubaddressAccount *m_subaddressAccount;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
#include "TransactionHistoryModel.h"
|
#include "TransactionHistoryModel.h"
|
||||||
#include "TransactionHistory.h"
|
#include "TransactionHistory.h"
|
||||||
#include "TransactionInfo.h"
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "utils/ColorScheme.h"
|
#include "utils/ColorScheme.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/AppData.h"
|
#include "utils/AppData.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
#include "libwalletqt/rows/TransactionRow.h"
|
||||||
|
|
||||||
TransactionHistoryModel::TransactionHistoryModel(QObject *parent)
|
TransactionHistoryModel::TransactionHistoryModel(QObject *parent)
|
||||||
: QAbstractTableModel(parent),
|
: QAbstractTableModel(parent),
|
||||||
|
@ -34,7 +34,7 @@ TransactionHistory *TransactionHistoryModel::transactionHistory() const {
|
||||||
return m_transactionHistory;
|
return m_transactionHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo* TransactionHistoryModel::entryFromIndex(const QModelIndex &index) const {
|
TransactionRow* TransactionHistoryModel::entryFromIndex(const QModelIndex &index) const {
|
||||||
Q_ASSERT(index.isValid() && index.row() < m_transactionHistory->count());
|
Q_ASSERT(index.isValid() && index.row() < m_transactionHistory->count());
|
||||||
return m_transactionHistory->transaction(index.row());
|
return m_transactionHistory->transaction(index.row());
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
QVariant result;
|
QVariant result;
|
||||||
|
|
||||||
bool found = m_transactionHistory->transaction(index.row(), [this, &index, &result, &role](const TransactionInfo &tInfo) {
|
bool found = m_transactionHistory->transaction(index.row(), [this, &index, &result, &role](const TransactionRow &tInfo) {
|
||||||
if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
|
||||||
result = parseTransactionInfo(tInfo, index.column(), role);
|
result = parseTransactionInfo(tInfo, index.column(), role);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
|
||||||
case Column::FiatAmount:
|
case Column::FiatAmount:
|
||||||
case Column::Amount:
|
case Column::Amount:
|
||||||
{
|
{
|
||||||
if (tInfo.direction() == TransactionInfo::Direction_Out) {
|
if (tInfo.direction() == TransactionRow::Direction_Out) {
|
||||||
result = QVariant(QColor("#BC1E1E"));
|
result = QVariant(QColor("#BC1E1E"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tInfo, int column, int role) const
|
QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionRow &tInfo, int column, int role) const
|
||||||
{
|
{
|
||||||
switch (column)
|
switch (column)
|
||||||
{
|
{
|
||||||
|
@ -159,7 +159,7 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tI
|
||||||
return tInfo.balanceDelta();
|
return tInfo.balanceDelta();
|
||||||
}
|
}
|
||||||
QString amount = QString::number(tInfo.balanceDelta() / constants::cdiv, 'f', conf()->get(Config::amountPrecision).toInt());
|
QString amount = QString::number(tInfo.balanceDelta() / constants::cdiv, 'f', conf()->get(Config::amountPrecision).toInt());
|
||||||
amount = (tInfo.direction() == TransactionInfo::Direction_Out) ? "-" + amount : "+" + amount;
|
amount = (tInfo.direction() == TransactionRow::Direction_Out) ? "-" + amount : "+" + amount;
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
case Column::TxID: {
|
case Column::TxID: {
|
||||||
|
@ -227,7 +227,7 @@ bool TransactionHistoryModel::setData(const QModelIndex &index, const QVariant &
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case Column::Description:
|
case Column::Description:
|
||||||
{
|
{
|
||||||
m_transactionHistory->transaction(index.row(), [this, &hash, &value](const TransactionInfo &tInfo){
|
m_transactionHistory->transaction(index.row(), [this, &hash, &value](const TransactionRow &tInfo){
|
||||||
hash = tInfo.hash();
|
hash = tInfo.hash();
|
||||||
});
|
});
|
||||||
m_transactionHistory->setTxNote(hash, value.toString());
|
m_transactionHistory->setTxNote(hash, value.toString());
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
class TransactionHistory;
|
class TransactionHistory;
|
||||||
class TransactionInfo;
|
class TransactionRow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The TransactionHistoryModel class - read-only table model for Transaction History
|
* @brief The TransactionHistoryModel class - read-only table model for Transaction History
|
||||||
|
@ -33,7 +33,7 @@ public:
|
||||||
explicit TransactionHistoryModel(QObject * parent = nullptr);
|
explicit TransactionHistoryModel(QObject * parent = nullptr);
|
||||||
void setTransactionHistory(TransactionHistory * th);
|
void setTransactionHistory(TransactionHistory * th);
|
||||||
TransactionHistory * transactionHistory() const;
|
TransactionHistory * transactionHistory() const;
|
||||||
TransactionInfo* entryFromIndex(const QModelIndex& index) const;
|
TransactionRow* entryFromIndex(const QModelIndex& index) const;
|
||||||
|
|
||||||
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
@ -47,7 +47,7 @@ signals:
|
||||||
void transactionHistoryChanged();
|
void transactionHistoryChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant parseTransactionInfo(const TransactionInfo &tInfo, int column, int role) const;
|
QVariant parseTransactionInfo(const TransactionRow &tInfo, int column, int role) const;
|
||||||
|
|
||||||
TransactionHistory * m_transactionHistory;
|
TransactionHistory * m_transactionHistory;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "TransactionHistoryProxyModel.h"
|
#include "TransactionHistoryProxyModel.h"
|
||||||
#include "TransactionHistoryModel.h"
|
#include "TransactionHistoryModel.h"
|
||||||
|
|
||||||
#include "libwalletqt/TransactionInfo.h"
|
#include "libwalletqt/rows/TransactionRow.h"
|
||||||
|
|
||||||
TransactionHistoryProxyModel::TransactionHistoryProxyModel(Wallet *wallet, QObject *parent)
|
TransactionHistoryProxyModel::TransactionHistoryProxyModel(Wallet *wallet, QObject *parent)
|
||||||
: QSortFilterProxyModel(parent)
|
: QSortFilterProxyModel(parent)
|
||||||
|
@ -25,7 +25,7 @@ bool TransactionHistoryProxyModel::filterAcceptsRow(int sourceRow, const QModelI
|
||||||
quint32 subaddrAccount;
|
quint32 subaddrAccount;
|
||||||
QSet<quint32> subaddrIndex;
|
QSet<quint32> subaddrIndex;
|
||||||
|
|
||||||
m_history->transaction(sourceRow, [&description, &txid, &subaddrlabel, &subaddrAccount, &subaddrIndex](TransactionInfo &tInfo){
|
m_history->transaction(sourceRow, [&description, &txid, &subaddrlabel, &subaddrAccount, &subaddrIndex](TransactionRow &tInfo){
|
||||||
description = tInfo.description();
|
description = tInfo.description();
|
||||||
txid = tInfo.hash();
|
txid = tInfo.hash();
|
||||||
subaddrlabel = tInfo.label();
|
subaddrlabel = tInfo.label();
|
||||||
|
|
Loading…
Reference in a new issue