From 289f9ab1d2692144b50266bbcbcb8b9c561372fa Mon Sep 17 00:00:00 2001 From: dsc Date: Mon, 25 Apr 2022 21:35:16 +0200 Subject: [PATCH] The balance fiat display does not 'round to ceiling' anymore, instead introduced some more decimals: ![https://i.imgur.com/aZAonV4.png](https://i.imgur.com/aZAonV4.png) New fiat columns in the history table: - Historical price (`balance * historical fiat price`) - Historical rate (the historical fiat price at that date) - Current price (`balance * current fiat price`) ![https://i.imgur.com/QkWCLRf.png](https://i.imgur.com/QkWCLRf.png) When preferred fiat is changed (in the settings), the balance fiat display now follows accordingly. Requires https://git.wownero.com/wowlet/wowlet-backend/pulls/19 --- src/appcontext.cpp | 8 +++++ src/libwalletqt/TransactionHistory.cpp | 6 ++++ src/libwalletqt/TransactionHistory.h | 3 ++ src/libwalletqt/TransactionInfo.cpp | 50 ++++++++++++++++++++++++++ src/libwalletqt/TransactionInfo.h | 14 ++++++++ src/mainwindow.cpp | 10 +++++- src/model/TransactionHistoryModel.cpp | 37 ++++++++++--------- src/model/TransactionHistoryModel.h | 4 ++- src/utils/utils.cpp | 6 ++-- src/utils/utils.h | 2 +- 10 files changed, 117 insertions(+), 23 deletions(-) diff --git a/src/appcontext.cpp b/src/appcontext.cpp index c0df7c3..4153ed7 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -334,6 +334,7 @@ void AppContext::onPreferredFiatCurrencyChanged(const QString &symbol) { auto *model = this->currentWallet->transactionHistoryModel(); if(model != nullptr) { model->preferredFiatSymbol = symbol; + this->currentWallet->transactionHistoryModel()->transactionHistory()->calcFiatInfo(); } } } @@ -379,6 +380,13 @@ void AppContext::onWalletOpened(Wallet *wallet) { connect(this->currentWallet, &Wallet::heightRefreshed, this, &AppContext::onHeightRefreshed); connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated); + this->currentWallet->historyModel(); // load historyModel + auto *txHistory = this->currentWallet->history(); + txHistory->refresh(this->currentWallet->currentSubaddressAccount()); + + connect(AppContext::prices, &Prices::fiatPricesUpdated, txHistory, &TransactionHistory::calcFiatInfo); + connect(AppContext::prices, &Prices::cryptoPricesUpdated, txHistory, &TransactionHistory::calcFiatInfo); + emit walletOpened(wallet); connect(this->currentWallet, &Wallet::connectionStatusChanged, [this]{ diff --git a/src/libwalletqt/TransactionHistory.cpp b/src/libwalletqt/TransactionHistory.cpp index a4f4432..f3ad4f8 100644 --- a/src/libwalletqt/TransactionHistory.cpp +++ b/src/libwalletqt/TransactionHistory.cpp @@ -32,6 +32,12 @@ TransactionInfo* TransactionHistory::transaction(const QString &id) return itr != m_tinfo.end() ? *itr : nullptr; } +void TransactionHistory::calcFiatInfo() { + for(const auto &tx: m_tinfo) { + tx->calcFiatInfo(); + } +} + void TransactionHistory::refresh(quint32 accountIndex) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) diff --git a/src/libwalletqt/TransactionHistory.h b/src/libwalletqt/TransactionHistory.h index cd7fbbf..9107db0 100644 --- a/src/libwalletqt/TransactionHistory.h +++ b/src/libwalletqt/TransactionHistory.h @@ -39,6 +39,9 @@ public: quint64 minutesToUnlock() const; bool locked() const; +public slots: + void calcFiatInfo(); + signals: void refreshStarted() const; void refreshFinished() const; diff --git a/src/libwalletqt/TransactionInfo.cpp b/src/libwalletqt/TransactionInfo.cpp index 890c16f..e4beaea 100644 --- a/src/libwalletqt/TransactionInfo.cpp +++ b/src/libwalletqt/TransactionInfo.cpp @@ -5,6 +5,8 @@ #include "libwalletqt/WalletManager.h" #include "Transfer.h" #include "Ring.h" +#include "globals.h" +#include "appcontext.h" TransactionInfo::Direction TransactionInfo::direction() const { @@ -109,6 +111,21 @@ QDateTime TransactionInfo::timestamp() const return m_timestamp; } +QString TransactionInfo::currentPriceStr() const +{ + return m_currentPriceStr; +} + +QString TransactionInfo::historicalRateStr() const +{ + return m_historicalRateStr; +} + +QString TransactionInfo::historicalPriceStr() const +{ + return m_historicalPriceStr; +} + QString TransactionInfo::date() const { return timestamp().date().toString(Qt::ISODate); @@ -161,6 +178,37 @@ QString TransactionInfo::rings_formatted() const return rings; } +void TransactionInfo::calcFiatInfo() { + auto const hash = this->hash(); + auto timestamp = this->timestamp().toString("yyyyMMdd"); + + if(!AppContext::prices->markets.contains("WOW")) + return; + + double fiat_rate = AppContext::prices->markets["WOW"].price_usd; + double historical_fiat_rate = AppContext::txFiatHistory->get(timestamp); + if (historical_fiat_rate == 0.0) + return; + + auto const preferredFiat = config()->get(Config::preferredFiatCurrency).toString(); + + if(preferredFiat != "USD") { + historical_fiat_rate = AppContext::prices->convert( + "USD", preferredFiat, historical_fiat_rate); + fiat_rate = AppContext::prices->convert( + "USD", preferredFiat, fiat_rate); + } + + double balance = (this->balanceDelta() / globals::cdiv); + + m_historicalRate = historical_fiat_rate; + m_historicalPrice = historical_fiat_rate * balance; + m_currentPrice = fiat_rate * balance; + m_historicalPriceStr = Utils::amountToCurrencyString(m_historicalPrice, preferredFiat, 2); + m_historicalRateStr = Utils::amountToCurrencyString(m_historicalRate, preferredFiat, 5); + m_currentPriceStr = Utils::amountToCurrencyString(m_currentPrice, preferredFiat, 2); +} + TransactionInfo::TransactionInfo(const Monero::TransactionInfo *pimpl, QObject *parent) : QObject(parent) , m_amount(pimpl->amount()) @@ -193,4 +241,6 @@ TransactionInfo::TransactionInfo(const Monero::TransactionInfo *pimpl, QObject * { m_subaddrIndex.insert(i); } + + this->calcFiatInfo(); } diff --git a/src/libwalletqt/TransactionInfo.h b/src/libwalletqt/TransactionInfo.h index 11d767c..4cd1979 100644 --- a/src/libwalletqt/TransactionInfo.h +++ b/src/libwalletqt/TransactionInfo.h @@ -71,6 +71,9 @@ public: QDateTime timestamp() const; QString date() const; QString time() const; + QString currentPriceStr() const; + QString historicalRateStr() const; + QString historicalPriceStr() const; QString paymentId() const; //! only applicable for output transactions //! used in tx details popup @@ -79,6 +82,9 @@ public: QList transfers() const; QString rings_formatted() const; +public slots: + void calcFiatInfo(); + private: explicit TransactionInfo(const Monero::TransactionInfo *pimpl, QObject *parent = nullptr); private: @@ -102,6 +108,14 @@ private: QDateTime m_timestamp; quint64 m_unlockTime; bool m_coinbase; + + double m_historicalPrice = 0.0; + double m_historicalRate = 0.0; + double m_currentPrice = 0.0; + + QString m_currentPriceStr = "?"; + QString m_historicalRateStr = "?"; + QString m_historicalPriceStr = "?"; }; #endif // TRANSACTIONINFO_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c155976..e35a7d8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -282,6 +282,9 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : // settings connects connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, this, &MainWindow::onUpdateFiatBalanceWidget); + connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, this, &MainWindow::onUpdateWowWidget); + connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, this, &MainWindow::onUpdateBTCWidget); + connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, this, &MainWindow::onUpdateXMRWidget); connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_ctx, &AppContext::onPreferredFiatCurrencyChanged); connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, ui->suchWowWidget, &SuchWowWidget::onPreferredFiatCurrencyChanged); connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, ui->sendWidget, QOverload<>::of(&SendWidget::onPreferredFiatCurrencyChanged)); @@ -1411,7 +1414,12 @@ void MainWindow::onUpdateWowWidget() { } auto wowObj = AppContext::prices->markets["WOW"]; - auto currencyText = Utils::amountToCurrencyString(wowObj.price_usd, fiatCurrency); + + double amount = wowObj.price_usd; + if(fiatCurrency != "USD") + amount = AppContext::prices->convert("USD", fiatCurrency, amount); + + auto currencyText = Utils::amountToCurrencyString(amount, fiatCurrency, 5); m_tickerWOW->setFiatText(currencyText); auto pct24h = AppContext::prices->markets["WOW"].price_usd_change_pct_24h; diff --git a/src/model/TransactionHistoryModel.cpp b/src/model/TransactionHistoryModel.cpp index 7ac747d..6796770 100644 --- a/src/model/TransactionHistoryModel.cpp +++ b/src/model/TransactionHistoryModel.cpp @@ -53,10 +53,10 @@ int TransactionHistoryModel::columnCount(const QModelIndex &parent) const { // When wowlet is in QtWidgets mode, it will only use the first 5 columns, // the rest should be hidden, because it shows in the GUI. So by default we'll - // use 5 as column count. When in QtQuick (QML) mode, we want to expose more columns + // use 6 as column count. When in QtQuick (QML) mode, we want to expose more columns // so we can change the column count here. - return AppContext::isQML ? this->COUNT : 5; + return AppContext::isQML ? this->COUNT : 7; } QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const { @@ -76,7 +76,9 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const else if (role == Qt::TextAlignmentRole) { switch (index.column()) { case TransactionInfoRole::Amount: - case TransactionInfoRole::FiatAmount: + case TransactionInfoRole::HistoricalPrice: + case TransactionInfoRole::HistoricalRate: + case TransactionInfoRole::CurrentPrice: result = Qt::AlignRight; } } @@ -118,7 +120,6 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const } else if (role == Qt::ForegroundRole) { switch(index.column()) { - case TransactionInfoRole::FiatAmount: case TransactionInfoRole::Amount: { if (tInfo.direction() == TransactionInfo::Direction_Out) { @@ -170,18 +171,16 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tI } case TransactionInfoRole::TxID: return tInfo.hash(); - case TransactionInfoRole::FiatAmount: + case TransactionInfoRole::HistoricalRate: { + return tInfo.historicalRateStr(); + } + case TransactionInfoRole::HistoricalPrice: { - double usd_price = AppContext::txFiatHistory->get(tInfo.timestamp().toString("yyyyMMdd")); - if (usd_price == 0.0) - return QVariant("?"); - - double usd_amount = usd_price * (tInfo.balanceDelta() / globals::cdiv); - if(this->preferredFiatSymbol != "USD") - usd_amount = AppContext::prices->convert("USD", this->preferredFiatSymbol, usd_amount); - double fiat_rounded = ceil(Utils::roundSignificant(usd_amount, 3) * 100.0) / 100.0; - - return QString("%1").arg(Utils::amountToCurrencyString(fiat_rounded, this->preferredFiatSymbol)); + return tInfo.historicalPriceStr(); + } + case TransactionInfoRole::CurrentPrice: + { + return tInfo.currentPriceStr(); } default: { @@ -206,8 +205,12 @@ QVariant TransactionHistoryModel::headerData(int section, Qt::Orientation orient return QString("Amount"); case TransactionInfoRole::TxID: return QString("Txid"); - case TransactionInfoRole::FiatAmount: - return QString("Fiat"); + case TransactionInfoRole::HistoricalPrice: + return QString("Historical price"); + case TransactionInfoRole::HistoricalRate: + return QString("Historical rate"); + case TransactionInfoRole::CurrentPrice: + return QString("Current price"); default: return QVariant(); } diff --git a/src/model/TransactionHistoryModel.h b/src/model/TransactionHistoryModel.h index 93d0d25..e43bc6c 100644 --- a/src/model/TransactionHistoryModel.h +++ b/src/model/TransactionHistoryModel.h @@ -27,7 +27,9 @@ public: Description, Amount, TxID, - FiatAmount, + HistoricalPrice, + HistoricalRate, + CurrentPrice, TransactionIsOutRole, TransactionFailedRole, TransactionPendingRole, diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 2fdfce3..3071253 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -418,14 +418,14 @@ double Utils::roundUp(double value, int decimal_places) { return std::ceil(value * multiplier) / multiplier; } -QString Utils::amountToCurrencyString(double amount, const QString ¤cyCode) { +QString Utils::amountToCurrencyString(double amount, const QString ¤cyCode, int precision) { QLocale locale = getCurrencyLocale(currencyCode); // \xC2\xA0 = UTF-8 non-breaking space, it looks off. if (currencyCode == "USD") - return locale.toCurrencyString(amount, "$").remove("\xC2\xA0"); + return locale.toCurrencyString(amount, "$", precision).remove("\xC2\xA0"); - return locale.toCurrencyString(amount).remove("\xC2\xA0"); + return locale.toCurrencyString(amount, nullptr, precision).remove("\xC2\xA0"); } int Utils::maxLength(const QVector &array) { diff --git a/src/utils/utils.h b/src/utils/utils.h index d2a7422..4ccca15 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -75,7 +75,7 @@ public: static double roundSignificant(double N, double n); static QString formatBytes(quint64 bytes); static QLocale getCurrencyLocale(const QString ¤cyCode); - static QString amountToCurrencyString(double amount, const QString ¤cyCode); + static QString amountToCurrencyString(double amount, const QString ¤cyCode, int precision = 2); static int maxLength(const QVector &array); static double roundUp(double value, int decimal_places); static QMap localeCache;