From 2bbab2b67528dd715ab36a3c1f63eb743ab5c33b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 26 Nov 2021 21:06:52 -0500 Subject: [PATCH 01/22] Plumbing for selecting language at run-time --- src/mainwindow.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++++ src/mainwindow.h | 19 ++++++++ src/settings.ui | 24 ++++++++++ 3 files changed, 158 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2348241..d6ef5ae 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -185,6 +185,70 @@ void MainWindow::doClose() { closeEvent(nullptr); } +// Called every time, when a menu entry of the language menu is called +void MainWindow::slotLanguageChanged(QAction* action) +{ + qDebug() << __func__ << ": action=" << action->data().toString(); + if(0 != action) { + // load the language dependant on the action content + loadLanguage(action->data().toString()); + setWindowIcon(action->icon()); + } +} + +void switchTranslator(QTranslator& translator, const QString& filename) { + qDebug() << __func__ << ": filename=" << filename; + // remove the old translator + qApp->removeTranslator(&translator); + + // load the new translator + QString path = QApplication::applicationDirPath(); + path.append("/res/"); + qDebug() << __func__ << ": attempting to load " << path + filename; + if(translator.load(path + filename)) { + qApp->installTranslator(&translator); + } +} + +void MainWindow::loadLanguage(const QString& rLanguage) { + qDebug() << "loadLanguage " << rLanguage; + if(m_currLang != rLanguage) { + m_currLang = rLanguage; + QLocale locale = QLocale(m_currLang); + QLocale::setDefault(locale); + QString languageName = QLocale::languageToString(locale.language()); + switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(rLanguage)); + switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(rLanguage)); + ui->statusBar->showMessage(tr("Current Language changed to %1").arg(languageName)); + } +} + +void MainWindow::changeEvent(QEvent* event) { + if(0 != event) { + switch(event->type()) { + // this event is sent if a translator is loaded + case QEvent::LanguageChange: + qDebug() << "QEvent::LanguageChange changeEvent"; + ui->retranslateUi(this); + break; + + // this event is sent, if the system, language changes + case QEvent::LocaleChange: + { + QString locale = QLocale::system().name(); + locale.truncate(locale.lastIndexOf('_')); + qDebug() << "QEvent::LocaleChange changeEvent locale=" << locale; + loadLanguage(locale); + } + break; + default: + qDebug() << __func__ << ": " << event->type(); + } + } + QMainWindow::changeEvent(event); +} + + void MainWindow::closeEvent(QCloseEvent* event) { QSettings s; @@ -346,6 +410,8 @@ void MainWindow::setupSettingsModal() { bool isUsingConsolidation = false; int size = 0; + qDebug() << __func__ << ": hushDir=" << rpc->getConnection()->config->hushDir; + QDir hushdir(rpc->getConnection()->config->hushDir); QFile WalletSize(hushdir.filePath("wallet.dat")); if (WalletSize.open(QIODevice::ReadOnly)){ @@ -418,6 +484,55 @@ void MainWindow::setupSettingsModal() { settings.testnetTxExplorerUrl->setText(explorer.testnetTxExplorerUrl); settings.testnetAddressExplorerUrl->setText(explorer.testnetAddressExplorerUrl); + /// create language drop down dynamically + QActionGroup* langGroup = new QActionGroup(settings.menuLanguage); + langGroup->setExclusive(true); + + qDebug() << __func__ << ": connecting langGroup to slotLanguageChanged"; + connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *))); + + // format systems language + QString defaultLocale = QLocale::system().name(); // e.g. "de_DE" + defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de" + + m_langPath = QApplication::applicationDirPath(); + m_langPath.append("/res"); + + qDebug() << __func__ <<": defaultLocale=" << defaultLocale << " m_langPath=" << m_langPath;; + + QDir dir(m_langPath); + QStringList fileNames = dir.entryList(QStringList("silentdragon_*.qm")); + + qDebug() << __func__ <<": found " << fileNames.size() << " translations"; + + for (int i = 0; i < fileNames.size(); ++i) { + // get locale extracted by filename + QString locale; + locale = fileNames[i]; // "silentdragon_de.qm" + locale.truncate(locale.lastIndexOf('.')); // "silentdragon_de" + locale.remove(0, locale.lastIndexOf('_') + 1); // "de" + + QString lang = QLocale::languageToString(QLocale(locale).language()); + //QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale)); + QIcon ico; + + QAction *action = new QAction(ico, lang, this); // ico, lang, this); + action->setCheckable(true); + action->setData(locale); + + settings.menuLanguage->addAction(action); + langGroup->addAction(action); + qDebug() << __func__ << ": added language=" << locale; + + // set default translators and language checked + if (defaultLocale == locale) { + action->setChecked(true); + } + } + + + /// + // Connection tab by default settings.tabWidget->setCurrentIndex(0); diff --git a/src/mainwindow.h b/src/mainwindow.h index ecf9edd..c5ef26d 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -72,10 +72,21 @@ public: Logger* logger; void doClose(); +protected: + // this event is called, when a new translator is loaded or the system language is changed + void changeEvent(QEvent* event); + + //void slotLanguageChanged(QAction* action); +protected slots: + // this slot is called by the language menu actions + void slotLanguageChanged(QAction *action); private: void closeEvent(QCloseEvent* event); + // loads a language by the given language shortcode (e.g. de, en) + void loadLanguage(const QString& rLanguage); + void setupSendTab(); void setupPeersTab(); void setupTransactionsTab(); @@ -87,6 +98,7 @@ private: void slot_change_theme(const QString& themeName); void slot_change_currency(const QString& currencyName); + void setupTurnstileDialog(); void setupSettingsModal(); void setupStatusBar(); @@ -144,6 +156,13 @@ private: QRegExpValidator* feesValidator = nullptr; QMovie* loadingMovie; + // creates the language menu dynamically from the content of m_langPath + void createLanguageMenu(void); + + QTranslator m_translator; // contains the translations for this application + QTranslator m_translatorQt; // contains the translations for qt + QString m_currLang; // contains the currently loaded language + QString m_langPath; // Path of language files }; #endif // MAINWINDOW_H diff --git a/src/settings.ui b/src/settings.ui index 0850bce..ce4887f 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -177,6 +177,29 @@ + + + + + Language + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + @@ -402,6 +425,7 @@ + From 391f3300448c6c04e949514ef8a1c5a384c29745 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 26 Nov 2021 21:38:33 -0500 Subject: [PATCH 02/22] Render language list as a QComboBox --- src/mainwindow.cpp | 41 ++++++++++++++++++++++++++--------------- src/mainwindow.h | 4 ++-- src/settings.ui | 8 +++++++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d6ef5ae..a17fc7a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -186,13 +186,13 @@ void MainWindow::doClose() { } // Called every time, when a menu entry of the language menu is called -void MainWindow::slotLanguageChanged(QAction* action) +void MainWindow::slotLanguageChanged(QString lang) { - qDebug() << __func__ << ": action=" << action->data().toString(); - if(0 != action) { - // load the language dependant on the action content - loadLanguage(action->data().toString()); - setWindowIcon(action->icon()); + qDebug() << __func__ << ": lang=" << lang; + if(lang != "") { + // load the language + loadLanguage(lang); + //setWindowIcon(action->icon()); } } @@ -210,9 +210,13 @@ void switchTranslator(QTranslator& translator, const QString& filename) { } } -void MainWindow::loadLanguage(const QString& rLanguage) { - qDebug() << "loadLanguage " << rLanguage; +void MainWindow::loadLanguage(QString& rLanguage) { + qDebug() << __func__ << ": currLang=" << m_currLang << " rLanguage=" << rLanguage; if(m_currLang != rLanguage) { + qDebug() << __func__ << ": changing language"; + if(rLanguage == "Russian") { + rLanguage = "ru"; + } m_currLang = rLanguage; QLocale locale = QLocale(m_currLang); QLocale::setDefault(locale); @@ -367,6 +371,11 @@ void MainWindow::setupSettingsModal() { QMessageBox::information(this, tr("Theme Change"), tr("This change can take a few seconds."), QMessageBox::Ok); }); + QObject::connect(settings.comboBoxLanguage, &QComboBox::currentTextChanged, [=] (QString lang) { + this->slotLanguageChanged(lang); + //QMessageBox::information(this, tr("Language Changed"), tr("This change can take a few seconds."), QMessageBox::Ok); + }); + // Set local currency QString ticker = Settings::getInstance()->get_currency_name(); int currency_index = settings.comboBoxCurrency->findText(ticker, Qt::MatchExactly); @@ -485,16 +494,19 @@ void MainWindow::setupSettingsModal() { settings.testnetAddressExplorerUrl->setText(explorer.testnetAddressExplorerUrl); /// create language drop down dynamically - QActionGroup* langGroup = new QActionGroup(settings.menuLanguage); + QActionGroup* langGroup = new QActionGroup(settings.comboBoxLanguage); langGroup->setExclusive(true); - qDebug() << __func__ << ": connecting langGroup to slotLanguageChanged"; - connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *))); + //qDebug() << __func__ << ": connecting langGroup to slotLanguageChanged"; + //connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *))); // format systems language QString defaultLocale = QLocale::system().name(); // e.g. "de_DE" defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de" + //QString defaultLang = QLocale::languageToString(QLocale("en").language()); + settings.comboBoxLanguage->addItem("English"); + m_langPath = QApplication::applicationDirPath(); m_langPath.append("/res"); @@ -520,19 +532,18 @@ void MainWindow::setupSettingsModal() { action->setCheckable(true); action->setData(locale); - settings.menuLanguage->addAction(action); + //settings.comboBoxLanguage->addItem(action); + settings.comboBoxLanguage->addItem(lang); langGroup->addAction(action); qDebug() << __func__ << ": added language=" << locale; // set default translators and language checked if (defaultLocale == locale) { action->setChecked(true); + qDebug() << " set defaultLocale=" << locale << " to checked"; } } - - /// - // Connection tab by default settings.tabWidget->setCurrentIndex(0); diff --git a/src/mainwindow.h b/src/mainwindow.h index c5ef26d..a6a6c13 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -79,13 +79,13 @@ protected: //void slotLanguageChanged(QAction* action); protected slots: // this slot is called by the language menu actions - void slotLanguageChanged(QAction *action); + void slotLanguageChanged(QString lang); private: void closeEvent(QCloseEvent* event); // loads a language by the given language shortcode (e.g. de, en) - void loadLanguage(const QString& rLanguage); + void loadLanguage(QString& rLanguage); void setupSendTab(); void setupPeersTab(); diff --git a/src/settings.ui b/src/settings.ui index ce4887f..8ed308f 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -196,7 +196,13 @@ - + + + + 0 + 0 + + From 1712fc1d5c3019309861d9487c18bc44ee1fb7ee Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 26 Nov 2021 22:00:16 -0500 Subject: [PATCH 03/22] Allow changing language at run-time to any supported language --- src/mainwindow.cpp | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a17fc7a..8807b45 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -212,17 +212,23 @@ void switchTranslator(QTranslator& translator, const QString& filename) { void MainWindow::loadLanguage(QString& rLanguage) { qDebug() << __func__ << ": currLang=" << m_currLang << " rLanguage=" << rLanguage; - if(m_currLang != rLanguage) { - qDebug() << __func__ << ": changing language"; - if(rLanguage == "Russian") { - rLanguage = "ru"; - } - m_currLang = rLanguage; + + QString lang = rLanguage; + lang.chop(1); // remove trailing ) + lang = lang.right(2); // last 2 chars are the language code + + if(m_currLang != lang) { + qDebug() << __func__ << ": changing language to " << lang; + m_currLang = lang; QLocale locale = QLocale(m_currLang); + qDebug() << __func__ << ": locale=" << locale; QLocale::setDefault(locale); QString languageName = QLocale::languageToString(locale.language()); - switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(rLanguage)); - switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(rLanguage)); + qDebug() << __func__ << ": languageName=" << languageName; + + switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(lang)); + switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(lang)); + ui->statusBar->showMessage(tr("Current Language changed to %1").arg(languageName)); } } @@ -232,7 +238,7 @@ void MainWindow::changeEvent(QEvent* event) { switch(event->type()) { // this event is sent if a translator is loaded case QEvent::LanguageChange: - qDebug() << "QEvent::LanguageChange changeEvent"; + qDebug() << __func__ << ": QEvent::LanguageChange changeEvent"; ui->retranslateUi(this); break; @@ -241,7 +247,7 @@ void MainWindow::changeEvent(QEvent* event) { { QString locale = QLocale::system().name(); locale.truncate(locale.lastIndexOf('_')); - qDebug() << "QEvent::LocaleChange changeEvent locale=" << locale; + qDebug() << __func__ << ": QEvent::LocaleChange changeEvent locale=" << locale; loadLanguage(locale); } break; @@ -505,7 +511,7 @@ void MainWindow::setupSettingsModal() { defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de" //QString defaultLang = QLocale::languageToString(QLocale("en").language()); - settings.comboBoxLanguage->addItem("English"); + settings.comboBoxLanguage->addItem("English (en)"); m_langPath = QApplication::applicationDirPath(); m_langPath.append("/res"); @@ -533,9 +539,9 @@ void MainWindow::setupSettingsModal() { action->setData(locale); //settings.comboBoxLanguage->addItem(action); - settings.comboBoxLanguage->addItem(lang); + settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); langGroup->addAction(action); - qDebug() << __func__ << ": added language=" << locale; + qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale; // set default translators and language checked if (defaultLocale == locale) { From d16b35d7c14cd2700d1f89e512f4703d636ca3f3 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 26 Nov 2021 23:20:30 -0500 Subject: [PATCH 04/22] cleanup --- src/mainwindow.cpp | 80 ++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8807b45..f980a81 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -192,7 +192,6 @@ void MainWindow::slotLanguageChanged(QString lang) if(lang != "") { // load the language loadLanguage(lang); - //setWindowIcon(action->icon()); } } @@ -229,7 +228,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(lang)); switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(lang)); - ui->statusBar->showMessage(tr("Current Language changed to %1").arg(languageName)); + ui->statusBar->showMessage(tr("Language changed to") + " " + languageName + " (" + lang + ")"); } } @@ -499,59 +498,56 @@ void MainWindow::setupSettingsModal() { settings.testnetTxExplorerUrl->setText(explorer.testnetTxExplorerUrl); settings.testnetAddressExplorerUrl->setText(explorer.testnetAddressExplorerUrl); - /// create language drop down dynamically - QActionGroup* langGroup = new QActionGroup(settings.comboBoxLanguage); - langGroup->setExclusive(true); + // format systems language + QString defaultLocale = QLocale::system().name(); // e.g. "de_DE" + defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de" - //qDebug() << __func__ << ": connecting langGroup to slotLanguageChanged"; - //connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *))); + // Set the current language to the default system language + // TODO: this will need to change when we read/write selected language to config on disk + m_currLang = defaultLocale; - // format systems language - QString defaultLocale = QLocale::system().name(); // e.g. "de_DE" - defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de" + //QString defaultLang = QLocale::languageToString(QLocale("en").language()); + settings.comboBoxLanguage->addItem("English (en)"); - //QString defaultLang = QLocale::languageToString(QLocale("en").language()); - settings.comboBoxLanguage->addItem("English (en)"); + m_langPath = QApplication::applicationDirPath(); + m_langPath.append("/res"); - m_langPath = QApplication::applicationDirPath(); - m_langPath.append("/res"); + qDebug() << __func__ <<": defaultLocale=" << defaultLocale << " m_langPath=" << m_langPath;; - qDebug() << __func__ <<": defaultLocale=" << defaultLocale << " m_langPath=" << m_langPath;; + QDir dir(m_langPath); + QStringList fileNames = dir.entryList(QStringList("silentdragon_*.qm")); - QDir dir(m_langPath); - QStringList fileNames = dir.entryList(QStringList("silentdragon_*.qm")); + qDebug() << __func__ <<": found " << fileNames.size() << " translations"; - qDebug() << __func__ <<": found " << fileNames.size() << " translations"; + // create language drop down dynamically + for (int i = 0; i < fileNames.size(); ++i) { + // get locale extracted by filename + QString locale; + locale = fileNames[i]; // "silentdragon_de.qm" + locale.truncate(locale.lastIndexOf('.')); // "silentdragon_de" + locale.remove(0, locale.lastIndexOf('_') + 1); // "de" - for (int i = 0; i < fileNames.size(); ++i) { - // get locale extracted by filename - QString locale; - locale = fileNames[i]; // "silentdragon_de.qm" - locale.truncate(locale.lastIndexOf('.')); // "silentdragon_de" - locale.remove(0, locale.lastIndexOf('_') + 1); // "de" + QString lang = QLocale::languageToString(QLocale(locale).language()); + //QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale)); + QIcon ico; - QString lang = QLocale::languageToString(QLocale(locale).language()); - //QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale)); - QIcon ico; + QAction *action = new QAction(ico, lang, this); // ico, lang, this); + action->setCheckable(true); + action->setData(locale); - QAction *action = new QAction(ico, lang, this); // ico, lang, this); - action->setCheckable(true); - action->setData(locale); + //settings.comboBoxLanguage->addItem(action); + settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); + qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale; - //settings.comboBoxLanguage->addItem(action); - settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); - langGroup->addAction(action); - qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale; - - // set default translators and language checked - if (defaultLocale == locale) { - action->setChecked(true); - qDebug() << " set defaultLocale=" << locale << " to checked"; + // set default translators and language checked + if (defaultLocale == locale) { + action->setChecked(true); + qDebug() << " set defaultLocale=" << locale << " to checked"; + } } - } - // Connection tab by default - settings.tabWidget->setCurrentIndex(0); + // Options tab by default + settings.tabWidget->setCurrentIndex(1); // Enable the troubleshooting options only if using embedded hushd if (!rpc->isEmbedded()) { From 1a9569cf50ba01bb2cd9dd1c24374846fb5a9cef Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 26 Nov 2021 23:51:47 -0500 Subject: [PATCH 05/22] Make Filipino and all 3 letter language codes work --- src/mainwindow.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f980a81..6fd6713 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -214,7 +214,11 @@ void MainWindow::loadLanguage(QString& rLanguage) { QString lang = rLanguage; lang.chop(1); // remove trailing ) - lang = lang.right(2); // last 2 chars are the language code + + // remove everything up to the first ( + lang = lang.remove(0, lang.indexOf("(") + 1); + + // NOTE: language codes can be 2 or 3 letters if(m_currLang != lang) { qDebug() << __func__ << ": changing language to " << lang; @@ -528,20 +532,15 @@ void MainWindow::setupSettingsModal() { locale.remove(0, locale.lastIndexOf('_') + 1); // "de" QString lang = QLocale::languageToString(QLocale(locale).language()); - //QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale)); QIcon ico; - QAction *action = new QAction(ico, lang, this); // ico, lang, this); - action->setCheckable(true); - action->setData(locale); - //settings.comboBoxLanguage->addItem(action); settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale; // set default translators and language checked if (defaultLocale == locale) { - action->setChecked(true); + settings.comboBoxLanguage->setCurrentIndex(i+1); qDebug() << " set defaultLocale=" << locale << " to checked"; } } From 1bdb948a3c7a4cc780a494cd93847cd288ed523b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 00:46:53 -0500 Subject: [PATCH 06/22] Show currently selected language in combobox --- src/mainwindow.cpp | 30 +++++++++++++++++++++--------- src/settings.h | 4 ++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6fd6713..7d35486 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -219,6 +219,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { lang = lang.remove(0, lang.indexOf("(") + 1); // NOTE: language codes can be 2 or 3 letters + // https://www.loc.gov/standards/iso639-2/php/code_list.php if(m_currLang != lang) { qDebug() << __func__ << ": changing language to " << lang; @@ -380,10 +381,6 @@ void MainWindow::setupSettingsModal() { QMessageBox::information(this, tr("Theme Change"), tr("This change can take a few seconds."), QMessageBox::Ok); }); - QObject::connect(settings.comboBoxLanguage, &QComboBox::currentTextChanged, [=] (QString lang) { - this->slotLanguageChanged(lang); - //QMessageBox::information(this, tr("Language Changed"), tr("This change can take a few seconds."), QMessageBox::Ok); - }); // Set local currency QString ticker = Settings::getInstance()->get_currency_name(); @@ -508,7 +505,8 @@ void MainWindow::setupSettingsModal() { // Set the current language to the default system language // TODO: this will need to change when we read/write selected language to config on disk - m_currLang = defaultLocale; + //m_currLang = defaultLocale; + //qDebug() << __func__ << ": changed m_currLang to " << defaultLocale; //QString defaultLang = QLocale::languageToString(QLocale("en").language()); settings.comboBoxLanguage->addItem("English (en)"); @@ -536,15 +534,29 @@ void MainWindow::setupSettingsModal() { //settings.comboBoxLanguage->addItem(action); settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); - qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale; + qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale << " defaultLocale=" << defaultLocale << " m_currLang=" << m_currLang; + qDebug() << __func__ << ": " << m_currLang << " ?= " << locale; - // set default translators and language checked - if (defaultLocale == locale) { + //if (defaultLocale == locale) { + if (m_currLang == locale) { settings.comboBoxLanguage->setCurrentIndex(i+1); - qDebug() << " set defaultLocale=" << locale << " to checked"; + qDebug() << " set defaultLocale=" << locale << " to checked!!!"; } } + QString lang = QLocale::languageToString(QLocale(m_currLang).language()); + qDebug() << __func__ << ": looking for " << lang + " (" + m_currLang + ")"; + int lang_index = settings.comboBoxLanguage->findText(lang + " (" + m_currLang + ")", Qt::MatchExactly); + + qDebug() << __func__ << ": setting comboBoxLanguage index to " << lang_index; + settings.comboBoxLanguage->setCurrentIndex(lang_index); + + QObject::connect(settings.comboBoxLanguage, &QComboBox::currentTextChanged, [=] (QString lang) { + qDebug() << "comboBoxLanguage.currentTextChanged lang=" << lang; + this->slotLanguageChanged(lang); + //QMessageBox::information(this, tr("Language Changed"), tr("This change can take a few seconds."), QMessageBox::Ok); + }); + // Options tab by default settings.tabWidget->setCurrentIndex(1); diff --git a/src/settings.h b/src/settings.h index d71d26f..6b930ed 100644 --- a/src/settings.h +++ b/src/settings.h @@ -146,6 +146,10 @@ public: static const int quickUpdateSpeed = 3 * 1000; // 3 sec static const int priceRefreshSpeed = 15 * 60 * 1000; // 15 mins +protected: + // this event is called, when a new translator is loaded or the system language is changed + // void changeEvent(QEvent* event); + private: // This class can only be accessed through Settings::getInstance() Settings() = default; From 3a17596931879653d93cf74bb1425e000dc009f2 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 02:11:40 -0500 Subject: [PATCH 07/22] Attempt to modify changeEvent for our dialogs, but not quite --- src/mainwindow.cpp | 19 +++++++++++++++++++ src/mainwindow.h | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7d35486..f63d038 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -22,6 +22,9 @@ #include "requestdialog.h" #include "websockets.h" +SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent) { +} + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) @@ -339,9 +342,25 @@ void MainWindow::setupStatusBar() { ui->statusBar->addPermanentWidget(statusIcon); } +// something like this is needed for QDialogs to listen to changeEvent +// so the Settings modal gets retranslated +// https://stackoverflow.com/questions/68665394/how-to-use-retranslateui-recursively-on-all-ui-in-qmainwindow +void SettingsDialog::changeEvent(QEvent* event) { + Ui_Settings settings; + qDebug() << __func__ << ":changeEvent type=" << event->type(); + if (event->type() == QEvent::LanguageChange) { + SettingsDialog settingsDialog(this); + settings.retranslateUi(&settingsDialog); + } + + QWidget::changeEvent(event); +} + void MainWindow::setupSettingsModal() { // Set up File -> Settings action QObject::connect(ui->actionSettings, &QAction::triggered, [=]() { + // this coredumps at run-time + //SettingsDialog settingsDialog(this); QDialog settingsDialog(this); Ui_Settings settings; settings.setupUi(&settingsDialog); diff --git a/src/mainwindow.h b/src/mainwindow.h index a6a6c13..a811665 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -32,6 +32,15 @@ namespace Ui { class MainWindow; } +class SettingsDialog : public QDialog +{ + Q_OBJECT +public: + explicit SettingsDialog(QWidget *parent = nullptr); + // this event is called, when a new translator is loaded or the system language is changed + void changeEvent(QEvent* event); +}; + class MainWindow : public QMainWindow { Q_OBJECT From ff522eff274adb15595bb95eb50fd5048d364b53 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 12:19:04 -0500 Subject: [PATCH 08/22] Retranslate the settings modal when language changes --- src/mainwindow.cpp | 30 +++++++----------------------- src/mainwindow.h | 13 +++---------- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f63d038..c771c92 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -22,9 +22,6 @@ #include "requestdialog.h" #include "websockets.h" -SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent) { -} - MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) @@ -195,6 +192,10 @@ void MainWindow::slotLanguageChanged(QString lang) if(lang != "") { // load the language loadLanguage(lang); + + QDialog settingsDialog(this); + qDebug() << __func__ << ": retranslating settingsDialog"; + settings.retranslateUi(&settingsDialog); } } @@ -342,27 +343,11 @@ void MainWindow::setupStatusBar() { ui->statusBar->addPermanentWidget(statusIcon); } -// something like this is needed for QDialogs to listen to changeEvent -// so the Settings modal gets retranslated -// https://stackoverflow.com/questions/68665394/how-to-use-retranslateui-recursively-on-all-ui-in-qmainwindow -void SettingsDialog::changeEvent(QEvent* event) { - Ui_Settings settings; - qDebug() << __func__ << ":changeEvent type=" << event->type(); - if (event->type() == QEvent::LanguageChange) { - SettingsDialog settingsDialog(this); - settings.retranslateUi(&settingsDialog); - } - - QWidget::changeEvent(event); -} - void MainWindow::setupSettingsModal() { // Set up File -> Settings action QObject::connect(ui->actionSettings, &QAction::triggered, [=]() { - // this coredumps at run-time - //SettingsDialog settingsDialog(this); QDialog settingsDialog(this); - Ui_Settings settings; + //Ui_Settings settings; settings.setupUi(&settingsDialog); Settings::saveRestore(&settingsDialog); @@ -397,7 +382,7 @@ void MainWindow::setupSettingsModal() { QObject::connect(settings.comboBoxTheme, &QComboBox::currentTextChanged, [=] (QString theme_name) { this->slot_change_theme(theme_name); - QMessageBox::information(this, tr("Theme Change"), tr("This change can take a few seconds."), QMessageBox::Ok); + // QMessageBox::information(this, tr("Theme Change"), tr("This change can take a few seconds."), QMessageBox::Ok); }); @@ -408,7 +393,7 @@ void MainWindow::setupSettingsModal() { QObject::connect(settings.comboBoxCurrency, &QComboBox::currentTextChanged, [=] (QString ticker) { this->slot_change_currency(ticker); rpc->refresh(true); - QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok); + // QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok); }); // Save sent transactions @@ -441,7 +426,6 @@ void MainWindow::setupSettingsModal() { } //Use Consolidation - bool isUsingConsolidation = false; int size = 0; qDebug() << __func__ << ": hushDir=" << rpc->getConnection()->config->hushDir; diff --git a/src/mainwindow.h b/src/mainwindow.h index a811665..0b75c6c 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -6,6 +6,7 @@ #include "precompiled.h" #include "logger.h" #include +#include "ui_settings.h" // Forward declare to break circular dependency. class RPC; @@ -32,15 +33,6 @@ namespace Ui { class MainWindow; } -class SettingsDialog : public QDialog -{ - Q_OBJECT -public: - explicit SettingsDialog(QWidget *parent = nullptr); - // this event is called, when a new translator is loaded or the system language is changed - void changeEvent(QEvent* event); -}; - class MainWindow : public QMainWindow { Q_OBJECT @@ -73,6 +65,7 @@ public: void updateFromCombo(); Ui::MainWindow* ui; + Ui_Settings settings; QLabel* statusLabel; QLabel* statusIcon; @@ -81,11 +74,11 @@ public: Logger* logger; void doClose(); + protected: // this event is called, when a new translator is loaded or the system language is changed void changeEvent(QEvent* event); - //void slotLanguageChanged(QAction* action); protected slots: // this slot is called by the language menu actions void slotLanguageChanged(QString lang); From 17337585a3e716861bd00a05b8e02f102f115a19 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 12:41:42 -0500 Subject: [PATCH 09/22] Sort languages in alphabetical order --- src/mainwindow.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c771c92..b1aa742 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -206,10 +206,12 @@ void switchTranslator(QTranslator& translator, const QString& filename) { // load the new translator QString path = QApplication::applicationDirPath(); - path.append("/res/"); + path.append("/res/"); qDebug() << __func__ << ": attempting to load " << path + filename; if(translator.load(path + filename)) { qApp->installTranslator(&translator); + } else { + qDebug() << __func__ << ": translation path does not exist! " << path + filename; } } @@ -219,7 +221,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { QString lang = rLanguage; lang.chop(1); // remove trailing ) - // remove everything up to the first ( + // remove everything up to and including the first ( lang = lang.remove(0, lang.indexOf("(") + 1); // NOTE: language codes can be 2 or 3 letters @@ -231,6 +233,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { QLocale locale = QLocale(m_currLang); qDebug() << __func__ << ": locale=" << locale; QLocale::setDefault(locale); + qDebug() << __func__ << ": setDefault locale=" << locale; QString languageName = QLocale::languageToString(locale.language()); qDebug() << __func__ << ": languageName=" << languageName; @@ -524,6 +527,7 @@ void MainWindow::setupSettingsModal() { qDebug() << __func__ <<": found " << fileNames.size() << " translations"; + // create language drop down dynamically for (int i = 0; i < fileNames.size(); ++i) { // get locale extracted by filename @@ -538,7 +542,7 @@ void MainWindow::setupSettingsModal() { //settings.comboBoxLanguage->addItem(action); settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale << " defaultLocale=" << defaultLocale << " m_currLang=" << m_currLang; - qDebug() << __func__ << ": " << m_currLang << " ?= " << locale; + //qDebug() << __func__ << ": " << m_currLang << " ?= " << locale; //if (defaultLocale == locale) { if (m_currLang == locale) { @@ -547,6 +551,9 @@ void MainWindow::setupSettingsModal() { } } + settings.comboBoxLanguage->model()->sort(0,Qt::AscendingOrder); + qDebug() << __func__ <<": sorted translations"; + QString lang = QLocale::languageToString(QLocale(m_currLang).language()); qDebug() << __func__ << ": looking for " << lang + " (" + m_currLang + ")"; int lang_index = settings.comboBoxLanguage->findText(lang + " (" + m_currLang + ")", Qt::MatchExactly); From 1267988ab4a4f874e52c5f3872216fc4d9025118 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 14:17:34 -0500 Subject: [PATCH 10/22] Theme change debugging and set to dark in exceptions --- src/mainwindow.cpp | 12 ++++++++---- src/settings.cpp | 5 ++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b1aa742..f000ef7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -33,7 +33,8 @@ MainWindow::MainWindow(QWidget *parent) : theme_name = Settings::getInstance()->get_theme_name(); } catch (...) { - theme_name = "default"; + qDebug() << __func__ << ": exception!"; + theme_name = "dark"; } this->slot_change_theme(theme_name); @@ -1896,7 +1897,7 @@ void MainWindow::updateLabels() { void MainWindow::slot_change_currency(const QString& currency_name) { - qDebug() << "slot_change_currency"; //<< ": " << currency_name; + qDebug() << __func__ << ": " << currency_name; Settings::getInstance()->set_currency_name(currency_name); qDebug() << "Refreshing price stats after currency change"; rpc->refreshPrice(); @@ -1913,6 +1914,7 @@ void MainWindow::slot_change_currency(const QString& currency_name) void MainWindow::slot_change_theme(const QString& theme_name) { + qDebug() << __func__ << ": theme_name=" << theme_name; Settings::getInstance()->set_theme_name(theme_name); // Include css @@ -1921,10 +1923,12 @@ void MainWindow::slot_change_theme(const QString& theme_name) saved_theme_name = Settings::getInstance()->get_theme_name(); } catch (const std::exception& e) { qDebug() << QString("Ignoring theme change Exception! : "); - saved_theme_name = "default"; + saved_theme_name = "dark"; } - QFile qFile(":/css/res/css/" + saved_theme_name +".css"); + QString filename = ":/css/res/css/" + saved_theme_name +".css"; + QFile qFile(filename); + qDebug() << __func__ << ": attempting to open filename=" << filename; if (qFile.open(QFile::ReadOnly)) { QString styleSheet = QLatin1String(qFile.readAll()); diff --git a/src/settings.cpp b/src/settings.cpp index 07eb0b1..0cedc43 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -246,10 +246,13 @@ void Settings::setAllowCustomFees(bool allow) { QString Settings::get_theme_name() { // Load from the QT Settings. - return QSettings().value("options/theme_name", false).toString(); + QString theme_name = QSettings().value("options/theme_name", false).toString(); + qDebug() << __func__ << ": theme_name=" << theme_name; + return theme_name; } void Settings::set_theme_name(QString theme_name) { + qDebug() << __func__ << ": settings theme_name=" << theme_name; QSettings().setValue("options/theme_name", theme_name); } From 82ef15ea75b4d893a2b473e7e147ff4d485af6a7 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 14:56:19 -0500 Subject: [PATCH 11/22] Show language list in native language --- src/mainwindow.cpp | 9 +++++---- src/mainwindow.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f000ef7..f38c359 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -235,7 +235,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { qDebug() << __func__ << ": locale=" << locale; QLocale::setDefault(locale); qDebug() << __func__ << ": setDefault locale=" << locale; - QString languageName = QLocale::languageToString(locale.language()); + QString languageName = locale.nativeLanguageName(); //locale.language()); qDebug() << __func__ << ": languageName=" << languageName; switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(lang)); @@ -537,8 +537,8 @@ void MainWindow::setupSettingsModal() { locale.truncate(locale.lastIndexOf('.')); // "silentdragon_de" locale.remove(0, locale.lastIndexOf('_') + 1); // "de" - QString lang = QLocale::languageToString(QLocale(locale).language()); - QIcon ico; + //QString lang = QLocale::languageToString(QLocale(locale).language()); + QString lang = QLocale(locale).nativeLanguageName(); //locale.language()); //settings.comboBoxLanguage->addItem(action); settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); @@ -1912,9 +1912,10 @@ void MainWindow::slot_change_currency(const QString& currency_name) } } -void MainWindow::slot_change_theme(const QString& theme_name) +void MainWindow::slot_change_theme(QString& theme_name) { qDebug() << __func__ << ": theme_name=" << theme_name; + Settings::getInstance()->set_theme_name(theme_name); // Include css diff --git a/src/mainwindow.h b/src/mainwindow.h index 0b75c6c..c48dd62 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -98,7 +98,7 @@ private: void setupChatTab(); void setupMarketTab(); - void slot_change_theme(const QString& themeName); + void slot_change_theme(QString& themeName); void slot_change_currency(const QString& currencyName); void setupTurnstileDialog(); From 4b35ff58dc1cab7b3b7e4aa37d82bacba2210cf7 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 16:54:21 -0500 Subject: [PATCH 12/22] Prevent invalid theme names and use dark theme if one is found --- src/mainwindow.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f38c359..49df62f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1916,7 +1916,13 @@ void MainWindow::slot_change_theme(QString& theme_name) { qDebug() << __func__ << ": theme_name=" << theme_name; - Settings::getInstance()->set_theme_name(theme_name); + if (theme_name == "dark" || theme_name == "default" || theme_name == "light" || + theme_name == "midnight" || theme_name == "blue") { + Settings::getInstance()->set_theme_name(theme_name); + } else { + qDebug() << __func__ << ": ignoring invalid theme_name=" << theme_name; + Settings::getInstance()->set_theme_name("dark"); + } // Include css QString saved_theme_name; From e9195e78d4188226575ee4141e23a6dd0a97d065 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 17:03:42 -0500 Subject: [PATCH 13/22] Uppercase the first letter of all languages --- src/mainwindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 49df62f..7923787 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -537,9 +537,12 @@ void MainWindow::setupSettingsModal() { locale.truncate(locale.lastIndexOf('.')); // "silentdragon_de" locale.remove(0, locale.lastIndexOf('_') + 1); // "de" - //QString lang = QLocale::languageToString(QLocale(locale).language()); QString lang = QLocale(locale).nativeLanguageName(); //locale.language()); + // uppercase the first letter of all languages + auto first = QString(lang.at(0)).toUpper(); + lang = first + lang.right(lang.size()-1); + //settings.comboBoxLanguage->addItem(action); settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale << " defaultLocale=" << defaultLocale << " m_currLang=" << m_currLang; From f4043ec4392bef38f9f26175cb1b662928f2d6ec Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 27 Nov 2021 17:13:00 -0500 Subject: [PATCH 14/22] Show properly uppercased language name in statusBar --- src/mainwindow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7923787..43a55aa 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -229,7 +229,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { // https://www.loc.gov/standards/iso639-2/php/code_list.php if(m_currLang != lang) { - qDebug() << __func__ << ": changing language to " << lang; + qDebug() << __func__ << ": changing language to lang=" << lang; m_currLang = lang; QLocale locale = QLocale(m_currLang); qDebug() << __func__ << ": locale=" << locale; @@ -241,6 +241,9 @@ void MainWindow::loadLanguage(QString& rLanguage) { switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(lang)); switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(lang)); + // TODO: this likely wont work for RTL languages like Arabic + auto first = QString(languageName.at(0)).toUpper(); + languageName = first + languageName.right(languageName.size()-1); ui->statusBar->showMessage(tr("Language changed to") + " " + languageName + " (" + lang + ")"); } } @@ -539,6 +542,7 @@ void MainWindow::setupSettingsModal() { QString lang = QLocale(locale).nativeLanguageName(); //locale.language()); + // TODO: this likely wont work for RTL languages like Arabic // uppercase the first letter of all languages auto first = QString(lang.at(0)).toUpper(); lang = first + lang.right(lang.size()-1); From c3ea342c7c6547c8882269e1f23c63e4d068dab2 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 28 Nov 2021 12:26:56 -0500 Subject: [PATCH 15/22] Replace old malicious explorer URLs if they are found in a config file --- src/settings.cpp | 11 +++++++++++ src/settings.h | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 0cedc43..eb57ff3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -40,9 +40,20 @@ Explorer Settings::getExplorer() { auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").toString(); auto addressExplorerUrl = s.value("explorer/addressExplorerUrl", explorer + "/address/").toString(); + auto testnetTxExplorerUrl = s.value("explorer/testnetTxExplorerUrl").toString(); auto testnetAddressExplorerUrl = s.value("explorer/testnetAddressExplorerUrl").toString(); + // Some users have the old malicious explorer URL saved in their config file, help them out + if (txExplorerUrl == "https://explorer.myhush.org/tx/") { + txExplorerUrl = explorer + "/tx/"; + saveExplorer(txExplorerUrl, addressExplorerUrl, testnetTxExplorerUrl, testnetAddressExplorerUrl); + } + if (addressExplorerUrl == "https://explorer.myhush.org/address/") { + addressExplorerUrl = explorer + "/address/"; + saveExplorer(txExplorerUrl, addressExplorerUrl, testnetTxExplorerUrl, testnetAddressExplorerUrl); + } + return Explorer{txExplorerUrl, addressExplorerUrl, testnetTxExplorerUrl, testnetAddressExplorerUrl}; } diff --git a/src/settings.h b/src/settings.h index 6b930ed..d788c7d 100644 --- a/src/settings.h +++ b/src/settings.h @@ -132,6 +132,7 @@ public: static double getZboardAmount(); static QString getZboardAddr(); + //TODO: this could be an advanced setting too static int getMaxMobileAppTxns() { return 30; } static bool isValidAddress(QString addr); @@ -162,12 +163,11 @@ private: bool _isTestnet = false; bool _isSyncing = false; int _blockNumber = 0; - int _hushdVersion = 0; + int _hushdVersion = 0; bool _useEmbedded = false; bool _headless = false; int _peerConnections = 0; - - double hushPrice = 0.0; + double hushPrice = 0.0; double fiat_price = 0.0; unsigned int btcPrice = 0; std::map prices; From e889668d4e75b22c89c742899c0ef1615bead5b9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 28 Nov 2021 13:49:33 -0500 Subject: [PATCH 16/22] Write the selected language to our config file and read it in and use it when SD starts --- src/mainwindow.cpp | 21 ++++++++++++++++++--- src/mainwindow.h | 4 ++-- src/rpc.cpp | 6 ++++++ src/settings.cpp | 12 ++++++++++++ src/settings.h | 3 +++ 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 43a55aa..625762b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -220,11 +220,18 @@ void MainWindow::loadLanguage(QString& rLanguage) { qDebug() << __func__ << ": currLang=" << m_currLang << " rLanguage=" << rLanguage; QString lang = rLanguage; - lang.chop(1); // remove trailing ) + + // this allows us to call this function with just a locale such as "zh" + if(lang.size() > 3) { + lang.chop(1); // remove trailing ) + } // remove everything up to and including the first ( lang = lang.remove(0, lang.indexOf("(") + 1); + // write this language (the locale shortcode) out to config file + Settings::getInstance()->set_language(lang); + // NOTE: language codes can be 2 or 3 letters // https://www.loc.gov/standards/iso639-2/php/code_list.php @@ -518,6 +525,9 @@ void MainWindow::setupSettingsModal() { //m_currLang = defaultLocale; //qDebug() << __func__ << ": changed m_currLang to " << defaultLocale; + m_currLang = Settings::getInstance()->get_language(); + qDebug() << __func__ << ": got a currLang=" << m_currLang << " from config file"; + //QString defaultLang = QLocale::languageToString(QLocale("en").language()); settings.comboBoxLanguage->addItem("English (en)"); @@ -550,7 +560,7 @@ void MainWindow::setupSettingsModal() { //settings.comboBoxLanguage->addItem(action); settings.comboBoxLanguage->addItem(lang + " (" + locale + ")"); qDebug() << __func__ << ": added lang=" << lang << " locale=" << locale << " defaultLocale=" << defaultLocale << " m_currLang=" << m_currLang; - //qDebug() << __func__ << ": " << m_currLang << " ?= " << locale; + qDebug() << __func__ << ": m_currLang=" << m_currLang << " ?= locale=" << locale; //if (defaultLocale == locale) { if (m_currLang == locale) { @@ -562,8 +572,13 @@ void MainWindow::setupSettingsModal() { settings.comboBoxLanguage->model()->sort(0,Qt::AscendingOrder); qDebug() << __func__ <<": sorted translations"; - QString lang = QLocale::languageToString(QLocale(m_currLang).language()); + //QString lang = QLocale::languageToString(QLocale(m_currLang).language()); + QString lang = QLocale(m_currLang).nativeLanguageName(); //locale.language()); + + auto first = QString(lang.at(0)).toUpper(); + lang = first + lang.right(lang.size()-1); qDebug() << __func__ << ": looking for " << lang + " (" + m_currLang + ")"; + //qDebug() << __func__ << ": looking for " << m_currLang; int lang_index = settings.comboBoxLanguage->findText(lang + " (" + m_currLang + ")", Qt::MatchExactly); qDebug() << __func__ << ": setting comboBoxLanguage index to " << lang_index; diff --git a/src/mainwindow.h b/src/mainwindow.h index c48dd62..135233f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -74,6 +74,8 @@ public: Logger* logger; void doClose(); + // loads a language by the given language shortcode (e.g. de, en) + void loadLanguage(QString& rLanguage); protected: // this event is called, when a new translator is loaded or the system language is changed @@ -86,8 +88,6 @@ protected slots: private: void closeEvent(QCloseEvent* event); - // loads a language by the given language shortcode (e.g. de, en) - void loadLanguage(QString& rLanguage); void setupSendTab(); void setupPeersTab(); diff --git a/src/rpc.cpp b/src/rpc.cpp index 378c755..cbd7216 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -63,6 +63,12 @@ RPC::RPC(MainWindow* main) { qDebug() << __func__ << "Done settings up all timers"; usedAddresses = new QMap(); + + auto lang = Settings::getInstance()->get_language(); + qDebug() << __func__ << ": found lang="<< lang << " in config file"; + + main->loadLanguage(lang); + qDebug() << __func__ << ": setting UI to lang="<< lang << " found in config file"; } RPC::~RPC() { diff --git a/src/settings.cpp b/src/settings.cpp index eb57ff3..c408a5e 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -365,6 +365,18 @@ void Settings::set_currency_name(QString currency_name) { QSettings().setValue("options/currency_name", currency_name); } +QString Settings::get_language() { + // TODO: use the default system language if none is set + auto lang = QSettings().value("options/language", "en").toString(); + qDebug() << __func__ << ": found lang=" << lang << " in config file"; + return lang; +} + +void Settings::set_language(QString lang) { + qDebug() << __func__ << ": setting lang=" << lang << " in config file"; + QSettings().setValue("options/language", lang); +} + bool Settings::removeFromHushConf(QString confLocation, QString option) { if (confLocation.isEmpty()) diff --git a/src/settings.h b/src/settings.h index d788c7d..32909d5 100644 --- a/src/settings.h +++ b/src/settings.h @@ -89,6 +89,9 @@ public: QString get_currency_name(); void set_currency_name(QString currency_name); + QString get_language(); + void set_language(QString lang); + void setUsingHushConf(QString confLocation); const QString& getHushdConfLocation() { return _confLocation; } From ea1b0d75b0307570ac7e6e0e0d1c62895df9f645 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 28 Nov 2021 23:35:36 -0500 Subject: [PATCH 17/22] Use the default system language and render en_US as English --- src/mainwindow.cpp | 12 +++++++++++- src/settings.cpp | 7 +++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 625762b..1b81c62 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -222,7 +222,7 @@ void MainWindow::loadLanguage(QString& rLanguage) { QString lang = rLanguage; // this allows us to call this function with just a locale such as "zh" - if(lang.size() > 3) { + if(lang.right(1) == ")") { lang.chop(1); // remove trailing ) } @@ -251,6 +251,9 @@ void MainWindow::loadLanguage(QString& rLanguage) { // TODO: this likely wont work for RTL languages like Arabic auto first = QString(languageName.at(0)).toUpper(); languageName = first + languageName.right(languageName.size()-1); + if( lang == "en" ) { + languageName.replace("American ",""); + } ui->statusBar->showMessage(tr("Language changed to") + " " + languageName + " (" + lang + ")"); } } @@ -577,6 +580,13 @@ void MainWindow::setupSettingsModal() { auto first = QString(lang.at(0)).toUpper(); lang = first + lang.right(lang.size()-1); + + if (m_currLang == "en") { + // we have just 1 English translation + // en_US will render as "American English", so fix that + lang.replace("American ",""); + } + qDebug() << __func__ << ": looking for " << lang + " (" + m_currLang + ")"; //qDebug() << __func__ << ": looking for " << m_currLang; int lang_index = settings.comboBoxLanguage->findText(lang + " (" + m_currLang + ")", Qt::MatchExactly); diff --git a/src/settings.cpp b/src/settings.cpp index c408a5e..95f2fba 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -366,8 +366,11 @@ void Settings::set_currency_name(QString currency_name) { } QString Settings::get_language() { - // TODO: use the default system language if none is set - auto lang = QSettings().value("options/language", "en").toString(); + // use the default system language if none is set + QString locale = QLocale::system().name(); + // remove country data, i.e. en_US => en + locale.truncate( locale.lastIndexOf("_")); + auto lang = QSettings().value("options/language", locale).toString(); qDebug() << __func__ << ": found lang=" << lang << " in config file"; return lang; } From 20ce45f754e40c86f4c2bbda5436a2d68b0bbbcd Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 28 Nov 2021 23:56:16 -0500 Subject: [PATCH 18/22] Prevent coredumps from invalid languages in config file --- src/mainwindow.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1b81c62..3db3fa3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -229,20 +229,29 @@ void MainWindow::loadLanguage(QString& rLanguage) { // remove everything up to and including the first ( lang = lang.remove(0, lang.indexOf("(") + 1); - // write this language (the locale shortcode) out to config file - Settings::getInstance()->set_language(lang); - // NOTE: language codes can be 2 or 3 letters // https://www.loc.gov/standards/iso639-2/php/code_list.php + QString languageName; if(m_currLang != lang) { qDebug() << __func__ << ": changing language to lang=" << lang; m_currLang = lang; QLocale locale = QLocale(m_currLang); + + qDebug() << __func__ << ": locale nativeLanguage=" << locale.nativeLanguageName(); + + // an invalid locale such as "zz" will give the C locale which has no native language name + if (locale.nativeLanguageName() == "") { + qDebug() << __func__ << ": detected invalid language in config file, defaulting to en"; + locale = QLocale("en"); + Settings::getInstance()->set_language("en"); + m_currLang = "en"; + lang = "en"; + } qDebug() << __func__ << ": locale=" << locale; QLocale::setDefault(locale); qDebug() << __func__ << ": setDefault locale=" << locale; - QString languageName = locale.nativeLanguageName(); //locale.language()); + languageName = locale.nativeLanguageName(); //locale.language()); qDebug() << __func__ << ": languageName=" << languageName; switchTranslator(m_translator, QString("silentdragon_%1.qm").arg(lang)); @@ -256,6 +265,12 @@ void MainWindow::loadLanguage(QString& rLanguage) { } ui->statusBar->showMessage(tr("Language changed to") + " " + languageName + " (" + lang + ")"); } + + // write this language (the locale shortcode) out to config file + if (lang != "") { + // only write valid languages to config file + Settings::getInstance()->set_language(lang); + } } void MainWindow::changeEvent(QEvent* event) { From 1d05221ac97c2fd7c589af90cc99382734e5c2ba Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 29 Nov 2021 00:02:11 -0500 Subject: [PATCH 19/22] Report currency changes in status bar --- src/mainwindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3db3fa3..7edf7ea 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -415,6 +415,8 @@ void MainWindow::setupSettingsModal() { QObject::connect(settings.comboBoxTheme, &QComboBox::currentTextChanged, [=] (QString theme_name) { this->slot_change_theme(theme_name); // QMessageBox::information(this, tr("Theme Change"), tr("This change can take a few seconds."), QMessageBox::Ok); + // For some reason, changing language also triggers this + //ui->statusBar->showMessage(tr("Theme changed to ") + theme_name); }); @@ -425,6 +427,7 @@ void MainWindow::setupSettingsModal() { QObject::connect(settings.comboBoxCurrency, &QComboBox::currentTextChanged, [=] (QString ticker) { this->slot_change_currency(ticker); rpc->refresh(true); + ui->statusBar->showMessage(tr("Currency changed to") + " " + ticker); // QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok); }); From 9a960c697d69ff119ea263ef857cd948fc7800ad Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 1 Dec 2021 08:45:04 -0500 Subject: [PATCH 20/22] Prevent the translation of theme names, which causes problems --- src/settings.ui | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/settings.ui b/src/settings.ui index 8ed308f..270fdff 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -26,7 +26,7 @@ - 3 + 1 @@ -177,24 +177,22 @@ - - - Language - 0 0 + + Language + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - @@ -205,7 +203,6 @@ - @@ -431,7 +428,6 @@ - @@ -442,27 +438,27 @@ - default + default - blue + blue - light + light - dark + dark - midnight + midnight From 69119491f76ea65d7af4dad94f06a3374a7decfb Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 1 Dec 2021 20:57:56 -0500 Subject: [PATCH 21/22] add more debug to wormhole logging, because coredumps --- src/websockets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/websockets.cpp b/src/websockets.cpp index 743f5c5..fff3126 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -210,9 +210,9 @@ void WormholeClient::onConnected() // On connected, we'll also create a timer to ping it every 4 minutes, since the websocket // will timeout after 5 minutes timer = new QTimer(parent); - qDebug() << "Created QTimer"; + qDebug() << __func__ << ": Created QTimer"; QObject::connect(timer, &QTimer::timeout, [=]() { - qDebug() << "Timer timeout!"; + qDebug() << __func__ << ": Timer timeout! shuttingDown=" << shuttingDown << " m_webSocket=" << m_webSocket; try { if (!shuttingDown && m_webSocket && m_webSocket->isValid()) { auto payload = QJsonDocument(QJsonObject { {"ping", "ping"} }).toJson(); From bc2757300e6c1e95bd5285a13a595801d3dc3e5e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 8 Dec 2021 21:51:06 -0500 Subject: [PATCH 22/22] more websocket debugz --- src/websockets.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/websockets.cpp b/src/websockets.cpp index fff3126..8ec377c 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -153,6 +153,7 @@ void WormholeClient::connect() { void WormholeClient::retryConnect() { QTimer::singleShot(5 * 1000 * pow(2, retryCount), [=]() { + qDebug() << __func__ << ": retryCount=" << retryCount; if (retryCount < 10) { qDebug() << "Retrying websocket connection, count=" << this->retryCount; this->retryCount++; @@ -212,8 +213,8 @@ void WormholeClient::onConnected() timer = new QTimer(parent); qDebug() << __func__ << ": Created QTimer"; QObject::connect(timer, &QTimer::timeout, [=]() { - qDebug() << __func__ << ": Timer timeout! shuttingDown=" << shuttingDown << " m_webSocket=" << m_webSocket; try { + qDebug() << __func__ << ": Timer timeout! shuttingDown=" << shuttingDown << " m_webSocket=" << m_webSocket << " isValid=" << m_webSocket->isValid(); if (!shuttingDown && m_webSocket && m_webSocket->isValid()) { auto payload = QJsonDocument(QJsonObject { {"ping", "ping"} }).toJson(); qint64 bytes = m_webSocket->sendTextMessage(payload); @@ -276,6 +277,7 @@ QString AppDataServer::getSecretHex() { } void AppDataServer::saveNewSecret(QString secretHex) { + qDebug() << __func__ << ": saving secretHex to config file"; QSettings().setValue("mobileapp/secret", secretHex); if (secretHex.isEmpty())