Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions data/SystemSettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,19 @@ QtObject {
property DataPoint language: DataPoint {
source: "com.victronenergy.settings/Settings/Gui/Language"
onValueChanged: {
if (value !== undefined && !Global.changingLanguage
&& value != Language.toCode(Language.current)) {
Global.changingLanguage = true
Language.setCurrentLanguageCode(value)
Qt.callLater(Global.main.retranslateUi)
if (value !== undefined && !Global.changingLanguage) {
if (Language.needSettingUpdate) {
// a language was set via startup parameter, so update the setting value.
if (value != Language.toCode(Language.current)) {
Qt.callLater(setValue, Language.toCode(Language.current))
}
Language.needSettingUpdate = false
} else if (value != Language.toCode(Language.current)) {
// the setting value changed, and we need to reload the ui
Global.changingLanguage = true
Language.setCurrentLanguageCode(value)
Qt.callLater(Global.main.retranslateUi)
}
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,16 @@ void Language::retranslate()
}
}

bool Language::needSettingUpdate() const
{
return m_needSettingUpdate;
}

void Language::setNeedSettingUpdate(bool v)
{
if (m_needSettingUpdate != v) {
m_needSettingUpdate = v;
emit needSettingUpdateChanged();
}
}

7 changes: 7 additions & 0 deletions src/language.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class Language : public QObject
{
Q_OBJECT
Q_PROPERTY(QLocale::Language current READ getCurrentLanguage WRITE setCurrentLanguage NOTIFY currentLanguageChanged FINAL)
Q_PROPERTY(bool needSettingUpdate READ needSettingUpdate WRITE setNeedSettingUpdate NOTIFY needSettingUpdateChanged)

public:
explicit Language(QQmlEngine* engine);
Language(const Victron::VenusOS::Language&) = delete;
Expand All @@ -78,13 +80,18 @@ class Language : public QObject
QLocale::Language getCurrentLanguage() const;
void setCurrentLanguage(QLocale::Language language);

bool needSettingUpdate() const;
void setNeedSettingUpdate(bool v);

Q_SIGNALS:
void currentLanguageChanged();
void needSettingUpdateChanged();

private:
bool installTranslatorForLanguage(QLocale::Language language);
QLocale::Language m_currentLanguage = QLocale::AnyLanguage;
QQmlEngine* m_qmlEngine = nullptr;
bool m_needSettingUpdate = false;
QHash<QLocale::Language, QTranslator*> m_loadedTranslators;
};

Expand Down
31 changes: 26 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ QString calculateMqttAddressFromPortalId(const QString &portalId)
return calculateMqttAddressFromShard(shardStr);
}

void initBackend(bool *enableFpsCounter)
void initBackend(QString *language, bool *enableFpsCounter)
{
Victron::VenusOS::BackendConnection *backend = Victron::VenusOS::BackendConnection::instance();

QString queryMqttAddress, queryMqttPortalId, queryMqttShard, queryMqttUser, queryMqttPass, queryMqttToken, queryFpsCounter;
QString queryMqttAddress, queryMqttPortalId, queryMqttShard, queryMqttUser, queryMqttPass, queryMqttToken, queryLang, queryFpsCounter;
#if defined(VENUS_WEBASSEMBLY_BUILD)
emscripten_set_visibilitychange_callback(static_cast<void*>(backend), 1, visibilitychange_callback);
emscripten::val webLocation = emscripten::val::global("location");
Expand All @@ -109,6 +109,9 @@ void initBackend(bool *enableFpsCounter)
if (query.hasQueryItem("token")) {
queryMqttToken = QString::fromUtf8(QByteArray::fromPercentEncoding(query.queryItemValue("token").toUtf8())); // e.g.: some JWT token from VRM.
}
if (query.hasQueryItem("lang")) {
queryLang = QString::fromUtf8(QByteArray::fromPercentEncoding(query.queryItemValue("lang").toUtf8())); // e.g.: "en" or "fr" etc
}
if (query.hasQueryItem("fpsCounter")) {
queryFpsCounter = QString::fromUtf8(QByteArray::fromPercentEncoding(query.queryItemValue("fpsCounter").toUtf8())); // e.g.: enabled
}
Expand Down Expand Up @@ -160,6 +163,11 @@ void initBackend(bool *enableFpsCounter)
QGuiApplication::tr("token", "MQTT broker auth token."));
parser.addOption(mqttToken);

QCommandLineOption lang({ "l", "lang" },
QGuiApplication::tr("UI language"),
QGuiApplication::tr("lang", "UI language code"));
parser.addOption(lang);

QCommandLineOption fpsCounter({ "f", "fpsCounter" },
QGuiApplication::tr("Enable FPS counter"));
parser.addOption(fpsCounter);
Expand Down Expand Up @@ -228,7 +236,15 @@ void initBackend(bool *enableFpsCounter)
#endif
}

if (parser.isSet(fpsCounter) || queryFpsCounter.contains(QStringLiteral("enable"))) {
if (language) {
if (parser.isSet(lang)) {
*language = parser.value(lang);
} else if (!queryLang.isEmpty()) {
*language = queryLang;
}
}

if (enableFpsCounter && (parser.isSet(fpsCounter) || queryFpsCounter.contains(QStringLiteral("enable")))) {
*enableFpsCounter = true;
}
}
Expand Down Expand Up @@ -669,15 +685,20 @@ int main(int argc, char *argv[])
QGuiApplication::setApplicationVersion("2.0");

bool enableFpsCounter = false;
initBackend(&enableFpsCounter);
QString languageCode;
initBackend(&languageCode, &enableFpsCounter);

QQmlEngine engine;
engine.setProperty("colorScheme", Victron::VenusOS::Theme::Dark);

/* Force construction of translator */
int languageSingletonId = qmlTypeId("Victron.VenusOS", 2, 0, "Language");
Q_ASSERT(languageSingletonId);
(void)engine.singletonInstance<Victron::VenusOS::Language*>(languageSingletonId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section seems out of date with main at the time of writing this comment, but it is noticed that the Victron::VenusOS::Language::create(&engine); does not specify QQmlEngine::setObjectOwnership(language, QQmlEngine::CppOwnership); and could cause multiple instances if the create() function was called multiple times. Suggest using Meyer's singleton pattern to prevent this.

Victron::VenusOS::Language* language = engine.singletonInstance<Victron::VenusOS::Language*>(languageSingletonId);
if (!languageCode.isEmpty() && languageCode.compare(QStringLiteral("C"), Qt::CaseInsensitive) != 0) {
language->setCurrentLanguageCode(languageCode);
language->setNeedSettingUpdate(true);
}

/* Force construction of fps counter */
int fpsCounterSingletonId = qmlTypeId("Victron.VenusOS", 2, 0, "FrameRateModel");
Expand Down