feat(Language): Redesign of Language settings screen
Renamed setting section "Language" to "Language & Currency". Updated link to StatusQ - Needed new `StatusListPicker` component. Added language model in `LanguageStore` and created first view approach for `Language` setting. Added temporal confirmation dialog for Linux OS (since it is currently needed to restart the app to apply changes). Removed no longer used files. Closes #5384
This commit is contained in:
parent
cc249856e4
commit
d7fa1b96d3
|
@ -1 +1 @@
|
||||||
Subproject commit 8297e50b90fc60a82a4712727b83d4d3e4b8e6cb
|
Subproject commit ade6bd2d0df18322705269559f995074a988075c
|
|
@ -1,17 +0,0 @@
|
||||||
var locales = [
|
|
||||||
{locale: "en", name: "English"},
|
|
||||||
{locale: "ar", name: "Arabic"},
|
|
||||||
{locale: "de", name: "Dutch"},
|
|
||||||
{locale: "es", name: "Spanish"},
|
|
||||||
{locale: "fil", name: "Filipino"},
|
|
||||||
{locale: "fr", name: "French"},
|
|
||||||
{locale: "id", name: "Indonesian"},
|
|
||||||
{locale: "it", name: "Italian"},
|
|
||||||
{locale: "ko", name: "Korean"},
|
|
||||||
{locale: "pt_BR", name: "Portuguese (Brazil)"},
|
|
||||||
{locale: "ru", name: "Russian"},
|
|
||||||
{locale: "tr", name: "Turkish"},
|
|
||||||
{locale: "ur", name: "Urdu"},
|
|
||||||
{locale: "zh", name: "Chinese (Mainland China)"},
|
|
||||||
{locale: "zh_TW", name: "Chinese (Taiwan)"}
|
|
||||||
];
|
|
|
@ -1,93 +0,0 @@
|
||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
import shared.popups 1.0
|
|
||||||
import shared.controls 1.0
|
|
||||||
import "../locales.js" as Locales_JSON
|
|
||||||
|
|
||||||
// TODO: replace with StatusQ StatusModal
|
|
||||||
ModalPopup {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
//% "Language"
|
|
||||||
title: qsTrId("Language")
|
|
||||||
|
|
||||||
property var languageStore
|
|
||||||
|
|
||||||
onClosed: {
|
|
||||||
destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
ButtonGroup {
|
|
||||||
id: languageGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: languageChangeConfirmationDialog
|
|
||||||
active: Qt.platform.os === Constants.linux
|
|
||||||
sourceComponent: ConfirmationDialog {
|
|
||||||
property string newLocale
|
|
||||||
header.title: qsTr("Change language")
|
|
||||||
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
|
|
||||||
showCancelButton: true
|
|
||||||
confirmButtonLabel: qsTr("Close the app now")
|
|
||||||
cancelButtonLabel: qsTr("I'll do that later")
|
|
||||||
onConfirmButtonClicked: {
|
|
||||||
root.languageStore.changeLocale(newLocale)
|
|
||||||
Qt.quit();
|
|
||||||
}
|
|
||||||
onCancelButtonClicked: {
|
|
||||||
languageChangeConfirmationDialog.item.close()
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
width: parent.width
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: Style.current.padding
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: Style.current.bigPadding
|
|
||||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
|
||||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: languagesListView
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.rightMargin: Style.current.padding
|
|
||||||
anchors.leftMargin: Style.current.padding
|
|
||||||
model: Locales_JSON.locales
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
delegate: Component {
|
|
||||||
RadioButtonSelector {
|
|
||||||
height: 64
|
|
||||||
anchors.rightMargin: 0
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
title: modelData.name
|
|
||||||
buttonGroup: languageGroup
|
|
||||||
checked: localAppSettings.locale === modelData.locale
|
|
||||||
onCheckedChanged: {
|
|
||||||
if (checked && localAppSettings.locale !== modelData.locale) {
|
|
||||||
if (Qt.platform.os === Constants.linux) {
|
|
||||||
languageChangeConfirmationDialog.item.newLocale = modelData.locale
|
|
||||||
languageChangeConfirmationDialog.item.open()
|
|
||||||
} else {
|
|
||||||
root.languageStore.changeLocale(modelData.locale)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,4 +9,39 @@ QtObject {
|
||||||
function changeLocale(locale) {
|
function changeLocale(locale) {
|
||||||
root.languageModule.changeLocale(locale)
|
root.languageModule.changeLocale(locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initializeLanguageModel() {
|
||||||
|
var isSelected = false
|
||||||
|
for(var i = 0; i < languageModel.count; i++) {
|
||||||
|
if(localAppSettings.locale === root.languageModel.get(i).key) {
|
||||||
|
isSelected = true
|
||||||
|
root.languageModel.get(i).selected = true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
root.languageModel.get(i).selected = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default:
|
||||||
|
if(!isSelected)
|
||||||
|
root.languageModel.get(0).selected = true
|
||||||
|
}
|
||||||
|
|
||||||
|
property ListModel languageModel: ListModel {
|
||||||
|
ListElement {key: "en"; shortName: "English"; name: "English"; category: ""; imageSource: "../../assets/twemoji/26x26/1f1ec-1f1e7.png"; selected: false}
|
||||||
|
ListElement {key: "zh"; shortName: "普通话"; name: "Chinese (Mainland China)"; imageSource: "../../assets/twemoji/26x26/1f1e8-1f1f3.png"; category: ""; selected: false}
|
||||||
|
ListElement {key: "ko"; shortName: "한국어"; name: "Korean"; category: ""; imageSource: "../../assets/twemoji/26x26/1f1f0-1f1f7.png"; selected: false}
|
||||||
|
ListElement {key: "pt_BR"; shortName: "Português"; name: "Portuguese (Brazil)"; category: ""; imageSource: "../../assets/twemoji/26x26/1f1e7-1f1f7.png"; selected: false}
|
||||||
|
ListElement {key: "ru"; shortName: "Русский Язык"; name: "Russian"; category: ""; imageSource: "../../assets/twemoji/26x26/1f1f7-1f1fa.png"; selected: false}
|
||||||
|
ListElement {key: "ar"; shortName: "اَلْعَرَبِيَّةُ"; name: "Arabic"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1f8-1f1e6.png"; selected: false}
|
||||||
|
ListElement {key: "zh_TW"; shortName: "臺灣華語"; name: "Chinese (Taiwan)"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1f9-1f1fc.png"; selected: false}
|
||||||
|
ListElement {key: "de"; shortName: "Nederlands"; name: "Dutch"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1f3-1f1f1.png"; selected: false}
|
||||||
|
ListElement {key: "fil"; shortName: "Wikang Filipino"; name: "Filipino"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1f5-1f1ed.png"; selected: false}
|
||||||
|
ListElement {key: "fr"; shortName: "Français"; name: "French"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1eb-1f1f7.png"; selected: false}
|
||||||
|
ListElement {key: "id"; shortName: "Bahasa Indonesia"; name: "Indonesian"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1ee-1f1e9.png"; selected: false}
|
||||||
|
ListElement {key: "it"; shortName: "Italiano"; name: "Italian"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1ee-1f1f9.png"; selected: false}
|
||||||
|
ListElement {key: "es"; shortName: "Español"; name: "Spanish"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1ea-1f1f8.png"; selected: false}
|
||||||
|
ListElement {key: "tr"; shortName: "Türkçe"; name: "Turkish"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1f9-1f1f7.png"; selected: false}
|
||||||
|
ListElement {key: "ur"; shortName: "اُردُو"; name: "Urdu"; category: "Beta Languages"; imageSource: "../../assets/twemoji/26x26/1f1f5-1f1f0.png"; selected: false}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ QtObject {
|
||||||
text: qsTr("Sound"),
|
text: qsTr("Sound"),
|
||||||
icon: "sound"})
|
icon: "sound"})
|
||||||
append({subsection: Constants.settingsSubsection.language,
|
append({subsection: Constants.settingsSubsection.language,
|
||||||
text: qsTr("Language"),
|
text: qsTr("Language & Currency"),
|
||||||
icon: "language"})
|
icon: "language"})
|
||||||
append({subsection: Constants.settingsSubsection.notifications,
|
append({subsection: Constants.settingsSubsection.notifications,
|
||||||
text: qsTr("Notifications"),
|
text: qsTr("Notifications"),
|
||||||
|
|
|
@ -3,6 +3,8 @@ import QtQuick.Controls 2.13
|
||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.13
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
import shared.panels 1.0
|
||||||
|
import shared.popups 1.0
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
@ -12,42 +14,127 @@ import "../popups"
|
||||||
import "../stores"
|
import "../stores"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: languageContainer
|
id: root
|
||||||
|
|
||||||
|
property LanguageStore languageStore
|
||||||
|
property int profileContentWidth
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property int margins: 64
|
||||||
|
property int zOnTop: 100
|
||||||
|
|
||||||
|
function setViewIdleState() {
|
||||||
|
languagePicker.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
z: d.zOnTop
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
property LanguageStore languageStore
|
onVisibleChanged: { if(!visible) d.setViewIdleState()}
|
||||||
property int profileContentWidth
|
|
||||||
property Component languagePopup: LanguageModal {
|
|
||||||
languageStore: languageContainer.languageStore
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Component.onCompleted: { root.languageStore.initializeLanguageModel() }
|
||||||
|
|
||||||
|
Column {
|
||||||
|
z: d.zOnTop
|
||||||
|
width: 560 - (2 * Style.current.padding)
|
||||||
|
anchors.margins: d.margins
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 64
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
width: profileContentWidth
|
anchors.left: parent.left
|
||||||
|
spacing: 45
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
StatusBaseText {
|
||||||
|
id: title
|
||||||
|
text: qsTr("Language & Currency")
|
||||||
|
font.weight: Font.Bold
|
||||||
|
font.pixelSize: 22
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
anchors.bottomMargin: Style.current.padding
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Item {
|
||||||
id: generalColumn
|
id: language
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
height: 38
|
||||||
|
z: d.zOnTop
|
||||||
|
|
||||||
StatusListItem {
|
StatusBaseText {
|
||||||
//% "Language"
|
text: qsTr("Language")
|
||||||
title: qsTrId("language")
|
anchors.left: parent.left
|
||||||
label: localAppSettings.locale === "" ? qsTrId("default") : localAppSettings.locale
|
font.pixelSize: 15
|
||||||
components: [
|
color: Theme.palette.directColor1
|
||||||
StatusIcon {
|
}
|
||||||
icon: "chevron-down"
|
StatusListPicker {
|
||||||
rotation: 270
|
id: languagePicker
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
|
property string newKey
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: pause
|
||||||
|
interval: 100
|
||||||
|
onTriggered: {
|
||||||
|
// changeLocale function operation blocks a little bit the UI so getting around it with a small pause (timer) in order to get the desired visual behavior
|
||||||
|
root.languageStore.changeLocale(languagePicker.newKey)
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
sensor.onClicked: languagePopup.createObject(languageContainer).open()
|
|
||||||
|
z: d.zOnTop
|
||||||
|
width: 104
|
||||||
|
height: parent.height
|
||||||
|
anchors.right: parent.right
|
||||||
|
inputList: root.languageStore.languageModel
|
||||||
|
searchText: qsTr("Search Languages")
|
||||||
|
|
||||||
|
onItemPickerChanged: {
|
||||||
|
if(selected && localAppSettings.locale !== key) {
|
||||||
|
// TEMPORARY: It should be removed as it is only used in Linux OS but it must be investigated how to change language in execution time, as well, in Linux (will be addressed in another task)
|
||||||
|
if (Qt.platform.os === Constants.linux) {
|
||||||
|
linuxConfirmationDialog.active = true
|
||||||
|
linuxConfirmationDialog.item.newLocale = key
|
||||||
|
linuxConfirmationDialog.item.open()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
languagePicker.newKey = key
|
||||||
|
pause.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Separator {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: -Style.current.padding
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: -Style.current.padding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEMPORARY: It should be removed as it is only used in Linux OS but it must be investigated how to change language in execution time, as well, in Linux (will be addressed in another task)
|
||||||
|
Loader {
|
||||||
|
id: linuxConfirmationDialog
|
||||||
|
active: false
|
||||||
|
sourceComponent: ConfirmationDialog {
|
||||||
|
property string newLocale
|
||||||
|
|
||||||
|
header.title: qsTr("Change language")
|
||||||
|
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
|
||||||
|
confirmButtonLabel: qsTr("Close the app now")
|
||||||
|
onConfirmButtonClicked: {
|
||||||
|
root.languageStore.changeLocale(newLocale)
|
||||||
|
loader.active = false
|
||||||
|
Qt.quit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outsite area
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: { d.setViewIdleState() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,6 @@ StatusModal {
|
||||||
switch (confirmationDialog.btnType) {
|
switch (confirmationDialog.btnType) {
|
||||||
case "warn":
|
case "warn":
|
||||||
return StatusBaseButton.Type.Danger
|
return StatusBaseButton.Type.Danger
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
return StatusBaseButton.Type.Primary
|
return StatusBaseButton.Type.Primary
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue