Browse Source

Merge branch 'language' into dev

pull/112/head
Duke Leto 2 years ago
parent
commit
e5b795597c
  1. 234
      src/mainwindow.cpp
  2. 23
      src/mainwindow.h
  3. 6
      src/rpc.cpp
  4. 31
      src/settings.cpp
  5. 13
      src/settings.h
  6. 38
      src/settings.ui
  7. 6
      src/websockets.cpp

234
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);
@ -185,6 +186,119 @@ void MainWindow::doClose() {
closeEvent(nullptr);
}
// Called every time, when a menu entry of the language menu is called
void MainWindow::slotLanguageChanged(QString lang)
{
qDebug() << __func__ << ": lang=" << lang;
if(lang != "") {
// load the language
loadLanguage(lang);
QDialog settingsDialog(this);
qDebug() << __func__ << ": retranslating settingsDialog";
settings.retranslateUi(&settingsDialog);
}
}
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);
} else {
qDebug() << __func__ << ": translation path does not exist! " << path + filename;
}
}
void MainWindow::loadLanguage(QString& rLanguage) {
qDebug() << __func__ << ": currLang=" << m_currLang << " rLanguage=" << rLanguage;
QString lang = rLanguage;
// this allows us to call this function with just a locale such as "zh"
if(lang.right(1) == ")") {
lang.chop(1); // remove trailing )
}
// remove everything up to and including the first (
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
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;
languageName = locale.nativeLanguageName(); //locale.language());
qDebug() << __func__ << ": languageName=" << languageName;
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);
if( lang == "en" ) {
languageName.replace("American ","");
}
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) {
if(0 != event) {
switch(event->type()) {
// this event is sent if a translator is loaded
case QEvent::LanguageChange:
qDebug() << __func__ << ": 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() << __func__ << ": QEvent::LocaleChange changeEvent locale=" << locale;
loadLanguage(locale);
}
break;
default:
qDebug() << __func__ << ": " << event->type();
}
}
QMainWindow::changeEvent(event);
}
void MainWindow::closeEvent(QCloseEvent* event) {
QSettings s;
@ -265,7 +379,7 @@ void MainWindow::setupSettingsModal() {
// Set up File -> Settings action
QObject::connect(ui->actionSettings, &QAction::triggered, [=]() {
QDialog settingsDialog(this);
Ui_Settings settings;
//Ui_Settings settings;
settings.setupUi(&settingsDialog);
Settings::saveRestore(&settingsDialog);
@ -300,9 +414,12 @@ 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);
// For some reason, changing language also triggers this
//ui->statusBar->showMessage(tr("Theme changed to ") + theme_name);
});
// Set local currency
QString ticker = Settings::getInstance()->get_currency_name();
int currency_index = settings.comboBoxCurrency->findText(ticker, Qt::MatchExactly);
@ -310,7 +427,8 @@ 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);
ui->statusBar->showMessage(tr("Currency changed to") + " " + ticker);
// QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok);
});
// Save sent transactions
@ -343,9 +461,10 @@ void MainWindow::setupSettingsModal() {
}
//Use Consolidation
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,8 +537,89 @@ void MainWindow::setupSettingsModal() {
settings.testnetTxExplorerUrl->setText(explorer.testnetTxExplorerUrl);
settings.testnetAddressExplorerUrl->setText(explorer.testnetAddressExplorerUrl);
// Connection tab by default
settings.tabWidget->setCurrentIndex(0);
// format systems language
QString defaultLocale = QLocale::system().name(); // e.g. "de_DE"
defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de"
// 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;
//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)");
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";
// 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"
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);
//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=" << m_currLang << " ?= locale=" << locale;
//if (defaultLocale == locale) {
if (m_currLang == locale) {
settings.comboBoxLanguage->setCurrentIndex(i+1);
qDebug() << " set defaultLocale=" << locale << " to checked!!!";
}
}
settings.comboBoxLanguage->model()->sort(0,Qt::AscendingOrder);
qDebug() << __func__ <<": sorted translations";
//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);
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);
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);
// Enable the troubleshooting options only if using embedded hushd
if (!rpc->isEmbedded()) {
@ -1747,7 +1947,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();
@ -1762,9 +1962,17 @@ 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)
{
Settings::getInstance()->set_theme_name(theme_name);
qDebug() << __func__ << ": 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;
@ -1772,10 +1980,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());

23
src/mainwindow.h

@ -6,6 +6,7 @@
#include "precompiled.h"
#include "logger.h"
#include <memory>
#include "ui_settings.h"
// Forward declare to break circular dependency.
class RPC;
@ -64,6 +65,7 @@ public:
void updateFromCombo();
Ui::MainWindow* ui;
Ui_Settings settings;
QLabel* statusLabel;
QLabel* statusIcon;
@ -72,10 +74,21 @@ 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
void changeEvent(QEvent* event);
protected slots:
// this slot is called by the language menu actions
void slotLanguageChanged(QString lang);
private:
void closeEvent(QCloseEvent* event);
void setupSendTab();
void setupPeersTab();
void setupTransactionsTab();
@ -85,8 +98,9 @@ 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();
void setupSettingsModal();
void setupStatusBar();
@ -144,6 +158,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

6
src/rpc.cpp

@ -63,6 +63,12 @@ RPC::RPC(MainWindow* main) {
qDebug() << __func__ << "Done settings up all timers";
usedAddresses = new QMap<QString, bool>();
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() {

31
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};
}
@ -246,10 +257,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);
}
@ -351,6 +365,21 @@ void Settings::set_currency_name(QString currency_name) {
QSettings().setValue("options/currency_name", currency_name);
}
QString Settings::get_language() {
// 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;
}
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())

13
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; }
@ -132,6 +135,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);
@ -146,6 +150,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;
@ -158,12 +166,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<QString, double> prices;

38
src/settings.ui

@ -26,7 +26,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@ -177,6 +177,32 @@
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="langlabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Language</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QComboBox" name="comboBoxLanguage">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QComboBox" name="comboBoxCurrency">
<property name="sizePolicy">
@ -412,27 +438,27 @@
</property>
<item>
<property name="text">
<string>default</string>
<string notr="true">default</string>
</property>
</item>
<item>
<property name="text">
<string>blue</string>
<string notr="true">blue</string>
</property>
</item>
<item>
<property name="text">
<string>light</string>
<string notr="true">light</string>
</property>
</item>
<item>
<property name="text">
<string>dark</string>
<string notr="true">dark</string>
</property>
</item>
<item>
<property name="text">
<string>midnight</string>
<string notr="true">midnight</string>
</property>
</item>
</widget>

6
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++;
@ -210,10 +211,10 @@ 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!";
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())

Loading…
Cancel
Save