diff --git a/src/calcwidget.cpp b/src/calcwidget.cpp index 2190c408..11616a29 100644 --- a/src/calcwidget.cpp +++ b/src/calcwidget.cpp @@ -8,6 +8,7 @@ #include "utils/ColorScheme.h" #include "utils/AppData.h" #include "utils/config.h" +#include "dialog/CalcConfigDialog.h" CalcWidget::CalcWidget(QWidget *parent) : QWidget(parent) @@ -29,14 +30,20 @@ CalcWidget::CalcWidget(QWidget *parent) ui->lineFrom->setValidator(dv); ui->lineTo->setValidator(dv); - connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &CalcWidget::initComboBox); - connect(&appData()->prices, &Prices::cryptoPricesUpdated, this, &CalcWidget::initComboBox); + connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &CalcWidget::onPricesReceived); + connect(&appData()->prices, &Prices::cryptoPricesUpdated, this, &CalcWidget::onPricesReceived); connect(ui->lineFrom, &QLineEdit::textEdited, this, [this]{this->convert(false);}); connect(ui->lineTo, &QLineEdit::textEdited, this, [this]{this->convert(true);}); connect(ui->comboCalcFrom, QOverload::of(&QComboBox::currentIndexChanged), [this]{this->convert(false);}); - connect(ui->comboCalcTo, QOverload::of(&QComboBox::currentIndexChanged), [this]{this->convert(true);}); + connect(ui->comboCalcTo, QOverload::of(&QComboBox::currentIndexChanged), [this]{this->convert(false);}); + + connect(ui->btn_configure, &QPushButton::clicked, this, &CalcWidget::showCalcConfigureDialog); + + QTimer::singleShot(1, [this]{ + this->skinChanged(); + }); } void CalcWidget::convert(bool reverse) { @@ -67,33 +74,76 @@ void CalcWidget::convert(bool reverse) { lineTo->setText(QString::number(result, 'f', precision)); } -void CalcWidget::initComboBox() { +void CalcWidget::onPricesReceived() { if (m_comboBoxInit) return; - QList marketsKeys = appData()->prices.markets.keys(); - QList ratesKeys = appData()->prices.rates.keys(); - if(marketsKeys.count() <= 0 || ratesKeys.count() <= 0) return; + QList cryptoKeys = appData()->prices.markets.keys(); + QList fiatKeys = appData()->prices.rates.keys(); + if (cryptoKeys.empty() || fiatKeys.empty()) + return; - ui->comboCalcFrom->addItems(marketsKeys); - ui->comboCalcFrom->insertSeparator(marketsKeys.count()); - ui->comboCalcFrom->addItems(ratesKeys); - ui->comboCalcFrom->setCurrentIndex(marketsKeys.indexOf("XMR")); + ui->btn_configure->setEnabled(true); + this->initComboBox(); + m_comboBoxInit = true; +} - ui->comboCalcTo->addItems(marketsKeys); - ui->comboCalcTo->insertSeparator(marketsKeys.count()); - ui->comboCalcTo->addItems(ratesKeys); +void CalcWidget::initComboBox() { + QList cryptoKeys = appData()->prices.markets.keys(); + QList fiatKeys = appData()->prices.rates.keys(); + QStringList enabledCrypto = config()->get(Config::cryptoSymbols).toStringList(); + QStringList filteredCryptoKeys; + for (const auto& symbol : cryptoKeys) { + if (enabledCrypto.contains(symbol)) { + filteredCryptoKeys.append(symbol); + } + } + + QStringList enabledFiat = config()->get(Config::fiatSymbols).toStringList(); auto preferredFiat = config()->get(Config::preferredFiatCurrency).toString(); - ui->comboCalcTo->setCurrentText(preferredFiat); + if (!enabledFiat.contains(preferredFiat) && fiatKeys.contains(preferredFiat)) { + enabledFiat.append(preferredFiat); + config()->set(Config::fiatSymbols, enabledFiat); + } + QStringList filteredFiatKeys; + for (const auto &symbol : fiatKeys) { + if (enabledFiat.contains(symbol)) { + filteredFiatKeys.append(symbol); + } + } - this->m_comboBoxInit = true; + this->setupComboBox(ui->comboCalcFrom, filteredCryptoKeys, filteredFiatKeys); + this->setupComboBox(ui->comboCalcTo, filteredCryptoKeys, filteredFiatKeys); + + ui->comboCalcFrom->setCurrentIndex(ui->comboCalcFrom->findText("XMR")); + + if (!preferredFiat.isEmpty()) { + ui->comboCalcTo->setCurrentIndex(ui->comboCalcTo->findText(preferredFiat)); + } else { + ui->comboCalcTo->setCurrentIndex(ui->comboCalcTo->findText("USD")); + } } void CalcWidget::skinChanged() { ui->imageExchange->setMode(ColorScheme::hasDarkBackground(this)); } +void CalcWidget::showCalcConfigureDialog() { + CalcConfigDialog dialog{this}; + + if (dialog.exec() == QDialog::Accepted) { + this->initComboBox(); + } +} + +void CalcWidget::setupComboBox(QComboBox *comboBox, const QStringList &crypto, const QStringList &fiat) { + comboBox->clear(); + comboBox->addItems(crypto); + comboBox->insertSeparator(comboBox->count()); + comboBox->addItems(fiat); +} + CalcWidget::~CalcWidget() { delete ui; } diff --git a/src/calcwidget.h b/src/calcwidget.h index de95604a..f5c4af12 100644 --- a/src/calcwidget.h +++ b/src/calcwidget.h @@ -5,6 +5,7 @@ #define FEATHER_CALCWIDGET_H #include +#include namespace Ui { class CalcWidget; @@ -23,9 +24,12 @@ public slots: private slots: void initComboBox(); + void showCalcConfigureDialog(); + void onPricesReceived(); private: void convert(bool reverse); + void setupComboBox(QComboBox *comboBox, const QStringList &crypto, const QStringList &fiat); Ui::CalcWidget *ui; bool m_comboBoxInit = false; diff --git a/src/calcwidget.ui b/src/calcwidget.ui index 66360aed..3fa1db2b 100644 --- a/src/calcwidget.ui +++ b/src/calcwidget.ui @@ -6,141 +6,22 @@ 0 0 - 737 - 153 + 800 + 132 MainWindow - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + - - - 9 + + + Crypto/fiat and fiat/fiat calculator. - - - - Crypto/fiat and fiat/fiat calculator. - - - - - - - Qt::Horizontal - - - - - - - - - 18 - - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - true - - - From... - - - - - - - - - - - - exchange image - - - - - - - 0 - - - - - - 0 - 0 - - - - false - - - To... - - - - - - - - - - - - - - - - Exchange rates are updated every 2 minutes. - - - - - - - Qt::Vertical - - - - 20 - 170 - - - - - + @@ -155,8 +36,98 @@ + + + + Configure + + + + + + + Qt::Horizontal + + + + + + + 18 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + true + + + From... + + + + + + + + + + + + exchange image + + + + + + + 0 + + + + + + 0 + 0 + + + + false + + + To... + + + + + + + + + + + + + + Exchange rates are updated every 2 minutes. + + + diff --git a/src/dialog/CalcConfigDialog.cpp b/src/dialog/CalcConfigDialog.cpp new file mode 100644 index 00000000..319d376b --- /dev/null +++ b/src/dialog/CalcConfigDialog.cpp @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#include "CalcConfigDialog.h" +#include "ui_CalcConfigDialog.h" +#include "AppData.h" +#include "utils/config.h" + +CalcConfigDialog::CalcConfigDialog(QWidget *parent) + : QDialog(parent) + , ui(new Ui::CalcConfigDialog) +{ + ui->setupUi(this); + + this->fillListWidgets(); + + connect(ui->btn_selectAll, &QPushButton::clicked, this, &CalcConfigDialog::selectAll); + connect(ui->btn_deselectAll, &QPushButton::clicked, this, &CalcConfigDialog::deselectAll); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, [this]{ + config()->set(Config::fiatSymbols, this->checkedFiat()); + config()->set(Config::cryptoSymbols, this->checkedCrypto()); + this->accept(); + }); + + this->adjustSize(); +} + +QStringList CalcConfigDialog::checkedFiat() { + return this->getChecked(ui->list_fiat); +} + +QStringList CalcConfigDialog::checkedCrypto() { + return this->getChecked(ui->list_crypto); +} + +void CalcConfigDialog::selectAll() { + this->setCheckState(this->getVisibleListWidget(), Qt::Checked); +} + +void CalcConfigDialog::deselectAll() { + this->setCheckState(this->getVisibleListWidget(), Qt::Unchecked); +} + +void CalcConfigDialog::setCheckState(QListWidget *widget, Qt::CheckState checkState) { + QListWidgetItem *item; + for (int i=0; i < widget->count(); i++) { + item = widget->item(i); + item->setCheckState(checkState); + } +} + +QStringList CalcConfigDialog::getChecked(QListWidget *widget) { + QStringList checked; + QListWidgetItem *item; + for (int i=0; i < widget->count(); i++) { + item = widget->item(i); + if (item->checkState() == Qt::Checked) { + checked.append(item->text()); + } + } + return checked; +} + +QListWidget* CalcConfigDialog::getVisibleListWidget() { + if (ui->tabWidget->currentIndex() == 0) { + return ui->list_fiat; + } else { + return ui->list_crypto; + } +} + +void CalcConfigDialog::fillListWidgets() { + QStringList cryptoCurrencies = appData()->prices.markets.keys(); + QStringList fiatCurrencies = appData()->prices.rates.keys(); + + QStringList checkedCryptoCurrencies = config()->get(Config::cryptoSymbols).toStringList(); + QStringList checkedFiatCurrencies = config()->get(Config::fiatSymbols).toStringList(); + + ui->list_crypto->addItems(cryptoCurrencies); + ui->list_fiat->addItems(fiatCurrencies); + + auto setChecked = [](QListWidget *widget, const QStringList &checked){ + QListWidgetItem *item; + for (int i=0; i < widget->count(); i++) { + item = widget->item(i); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + if (checked.contains(item->text())) { + item->setCheckState(Qt::Checked); + } else { + item->setCheckState(Qt::Unchecked); + } + } + }; + + setChecked(ui->list_crypto, checkedCryptoCurrencies); + setChecked(ui->list_fiat, checkedFiatCurrencies); +} + +CalcConfigDialog::~CalcConfigDialog() { + delete ui; +} diff --git a/src/dialog/CalcConfigDialog.h b/src/dialog/CalcConfigDialog.h new file mode 100644 index 00000000..aceed432 --- /dev/null +++ b/src/dialog/CalcConfigDialog.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2020-2021, The Monero Project. + +#ifndef FEATHER_CALCCONFIGDIALOG_H +#define FEATHER_CALCCONFIGDIALOG_H + +#include +#include + +namespace Ui { + class CalcConfigDialog; +} + +class CalcConfigDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CalcConfigDialog(QWidget *parent = nullptr); + ~CalcConfigDialog() override; + + QStringList checkedFiat(); + QStringList checkedCrypto(); + +private slots: + void selectAll(); + void deselectAll(); + +private: + void setCheckState(QListWidget *widget, Qt::CheckState checkState); + QStringList getChecked(QListWidget *widget); + void fillListWidgets(); + QListWidget* getVisibleListWidget(); + + Ui::CalcConfigDialog *ui; +}; + + +#endif //FEATHER_CALCCONFIGDIALOG_H diff --git a/src/dialog/CalcConfigDialog.ui b/src/dialog/CalcConfigDialog.ui new file mode 100644 index 00000000..d88daeeb --- /dev/null +++ b/src/dialog/CalcConfigDialog.ui @@ -0,0 +1,153 @@ + + + CalcConfigDialog + + + + 0 + 0 + 509 + 574 + + + + Calc config + + + + + + 0 + + + + Fiat + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + Crypto + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + Qt::Vertical + + + + + + + + + Select all + + + + + + + Deselect all + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + CalcConfigDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CalcConfigDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 3358f0f3..577576a8 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -249,8 +249,41 @@ Calc + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 0 + 20 + + + + - + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + diff --git a/src/utils/config.cpp b/src/utils/config.cpp index 9af405c7..2e4baf96 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -68,6 +68,9 @@ static const QHash configStrings = { {Config::redditFrontend, {QS("redditFrontend"), "old.reddit.com"}}, {Config::localMoneroFrontend, {QS("localMoneroFrontend"), "https://localmonero.co"}}, + {Config::fiatSymbols, {QS("fiatSymbols"), QStringList{"USD", "EUR", "GBP", "CAD", "AUD", "RUB"}}}, + {Config::cryptoSymbols, {QS("cryptoSymbols"), QStringList{"BTC", "ETH", "LTC", "XMR", "ZEC"}}}, + // Tor {Config::torPrivacyLevel, {QS("torPrivacyLevel"), 1}}, {Config::socks5Host, {QS("socks5Host"), "127.0.0.1"}}, diff --git a/src/utils/config.h b/src/utils/config.h index 5a0fb4b0..96fdb345 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -20,6 +20,7 @@ public: enum ConfigKey { + // General firstRun, warnOnStagenet, warnOnTestnet, @@ -33,14 +34,17 @@ public: windowState, GUI_HistoryViewState, + // Wallets walletDirectory, // Directory where wallet files are stored autoOpenWalletPath, recentlyOpenedWallets, + // Nodes nodes, nodeSource, useOnionNodes, + // Tabs showTabHome, showTabCoins, showTabExchange, @@ -48,9 +52,11 @@ public: showTabXMRig, showSearchbar, + // Mining xmrigPath, xmrigPool, + // Settings preferredFiatCurrency, skin, amountPrecision, @@ -66,6 +72,10 @@ public: redditFrontend, localMoneroFrontend, + fiatSymbols, + cryptoSymbols, + + // Tor torPrivacyLevel, socks5Host, socks5Port, diff --git a/src/utils/prices.cpp b/src/utils/prices.cpp index ca9bd817..ea1d03c5 100644 --- a/src/utils/prices.cpp +++ b/src/utils/prices.cpp @@ -3,9 +3,9 @@ #include "utils/prices.h" -Prices::Prices(QObject *parent) : QObject(parent) { - this->rates = QMap(); - this->markets = QMap(); +Prices::Prices(QObject *parent) + : QObject(parent) +{ } void Prices::cryptoPricesReceived(const QJsonArray &data) { @@ -30,9 +30,8 @@ void Prices::cryptoPricesReceived(const QJsonArray &data) { void Prices::fiatPricesReceived(const QJsonObject &data) { QJsonObject ratesData = data.value("rates").toObject(); - for (const auto ¤cy : ratesData) { - QString currencyStr = currency.toString(); - this->rates.insert(currencyStr, ratesData.value(currencyStr).toDouble()); + for (const auto ¤cy : ratesData.keys()) { + this->rates.insert(currency, ratesData.value(currency).toDouble()); } emit fiatPricesUpdated(); }