language switcher

This commit is contained in:
erinn 2019-03-18 16:52:46 -07:00
parent 28c19d7e4b
commit 196e8fad68
9 changed files with 172 additions and 42 deletions

View File

@ -4,6 +4,7 @@ import (
"cwtch.im/cwtch/event" "cwtch.im/cwtch/event"
"cwtch.im/ui/go/constants" "cwtch.im/ui/go/constants"
"cwtch.im/ui/go/cwutil" "cwtch.im/ui/go/cwutil"
"github.com/therecipe/qt/qml"
"cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gobjects"
"cwtch.im/ui/go/the" "cwtch.im/ui/go/the"
@ -19,6 +20,8 @@ type GrandCentralDispatcher struct {
OutgoingMessages chan gobjects.Letter OutgoingMessages chan gobjects.Letter
UIState InterfaceState UIState InterfaceState
QMLEngine *qml.QQmlApplicationEngine
Translator *core.QTranslator
_ string `property:"currentOpenConversation"` _ string `property:"currentOpenConversation"`
_ float32 `property:"themeScale"` _ float32 `property:"themeScale"`
@ -42,6 +45,7 @@ type GrandCentralDispatcher struct {
// settings helpers // settings helpers
_ func(str string) `signal:"InvokePopup"` _ func(str string) `signal:"InvokePopup"`
_ func(zoom, locale string) `signal:"SupplySettings"`
_ func(groupID, name, server, invitation string, accepted bool, addrbooknames, addrbookaddrs []string) `signal:"SupplyGroupSettings"` _ func(groupID, name, server, invitation string, accepted bool, addrbooknames, addrbookaddrs []string) `signal:"SupplyGroupSettings"`
_ func(onion, nick string) `signal:"SupplyPeerSettings"` _ func(onion, nick string) `signal:"SupplyPeerSettings"`
@ -55,12 +59,15 @@ type GrandCentralDispatcher struct {
_ func(server, groupName string) `signal:"createGroup,auto"` _ func(server, groupName string) `signal:"createGroup,auto"`
_ func(groupID string) `signal:"leaveGroup,auto"` _ func(groupID string) `signal:"leaveGroup,auto"`
_ func(groupID string) `signal:"acceptGroup,auto"` _ func(groupID string) `signal:"acceptGroup,auto"`
_ func() `signal:"requestSettings,auto"`
_ func(zoom, locale string) `signal:"saveSettings,auto"`
_ func(groupID string) `signal:"requestGroupSettings,auto"` _ func(groupID string) `signal:"requestGroupSettings,auto"`
_ func(groupID, nick string) `signal:"saveGroupSettings,auto"` _ func(groupID, nick string) `signal:"saveGroupSettings,auto"`
_ func() `signal:"requestPeerSettings,auto"` _ func() `signal:"requestPeerSettings,auto"`
_ func(onion, nick string) `signal:"savePeerSettings,auto"` _ func(onion, nick string) `signal:"savePeerSettings,auto"`
_ func(onion, groupID string) `signal:"inviteToGroup,auto"` _ func(onion, groupID string) `signal:"inviteToGroup,auto"`
_ func(onion, key, nick string) `signal:"setAttribute,auto"` _ func(onion, key, nick string) `signal:"setAttribute,auto"`
_ func(locale string) `signal:"setLocale,auto"`
} }
func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
@ -246,6 +253,25 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
} }
} }
func (this *GrandCentralDispatcher) requestSettings() {
zoom, _ := the.Peer.GetProfile().GetAttribute("settings.zoom")
locale, _ := the.Peer.GetProfile().GetAttribute("settings.locale")
this.SupplySettings(zoom, locale)
}
func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) {
// saveSettings accidentally gets called once when the app first starts but before the app has been prepared
// so let's just ignore that one
if the.CwtchApp == nil {
return
}
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{
event.Key: "settings.zoom",
event.Data: zoom,
}))
}
func (this *GrandCentralDispatcher) requestPeerSettings() { func (this *GrandCentralDispatcher) requestPeerSettings() {
contact := the.Peer.GetContact(this.CurrentOpenConversation()) contact := the.Peer.GetContact(this.CurrentOpenConversation())
if contact == nil { if contact == nil {
@ -479,4 +505,23 @@ func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) {
})) }))
this.UIState.UpdateContactAttribute(onion, key, value) this.UIState.UpdateContactAttribute(onion, key, value)
} }
}
func (this *GrandCentralDispatcher) setLocale(locale string) {
this.SetLocale_helper(locale)
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{
event.Key: "settings.locale",
event.Data: locale,
}))
this.SupplySettings("", locale)
}
func (this *GrandCentralDispatcher) SetLocale_helper(locale string) {
core.QCoreApplication_RemoveTranslator(this.Translator)
this.Translator = core.NewQTranslator(nil)
this.Translator.Load("translation_"+locale, ":/i18n/", "", "")
core.QCoreApplication_InstallTranslator(this.Translator)
this.QMLEngine.Retranslate()
} }

View File

@ -258,30 +258,30 @@
<context> <context>
<name>SettingsPane</name> <name>SettingsPane</name>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="17"/> <location filename="../qml/panes/SettingsPane.qml" line="18"/>
<source>cwtch-settings-title</source> <source>cwtch-settings-title</source>
<extracomment>Cwtch Settings title</extracomment> <extracomment>Cwtch Settings title</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="28"/> <location filename="../qml/panes/SettingsPane.qml" line="29"/>
<source>zoom-label</source> <source>zoom-label</source>
<extracomment>Interface zoom (mostly affects text and button sizes)</extracomment> <extracomment>Interface zoom (mostly affects text and button sizes)</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="44"/> <location filename="../qml/panes/SettingsPane.qml" line="45"/>
<source>large-text-label</source> <source>large-text-label</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="50"/> <location filename="../qml/panes/SettingsPane.qml" line="51"/>
<source>default-scaling-text</source> <source>default-scaling-text</source>
<extracomment>&quot;Default size text (scale factor: &quot;</extracomment> <extracomment>&quot;Default size text (scale factor: &quot;</extracomment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="54"/> <location filename="../qml/panes/SettingsPane.qml" line="55"/>
<source>small-text-label</source> <source>small-text-label</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

Binary file not shown.

View File

@ -258,30 +258,30 @@
<context> <context>
<name>SettingsPane</name> <name>SettingsPane</name>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="17"/> <location filename="../qml/panes/SettingsPane.qml" line="18"/>
<source>cwtch-settings-title</source> <source>cwtch-settings-title</source>
<extracomment>Cwtch Settings title</extracomment> <extracomment>Cwtch Settings title</extracomment>
<translation>Cwtch Settings</translation> <translation>Cwtch Settings</translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="28"/> <location filename="../qml/panes/SettingsPane.qml" line="29"/>
<source>zoom-label</source> <source>zoom-label</source>
<extracomment>Interface zoom (mostly affects text and button sizes)</extracomment> <extracomment>Interface zoom (mostly affects text and button sizes)</extracomment>
<translation>Interface zoom (mostly affects text and button sizes)</translation> <translation>Interface zoom (mostly affects text and button sizes)</translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="44"/> <location filename="../qml/panes/SettingsPane.qml" line="45"/>
<source>large-text-label</source> <source>large-text-label</source>
<translation type="unfinished">Large</translation> <translation type="unfinished">Large</translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="50"/> <location filename="../qml/panes/SettingsPane.qml" line="51"/>
<source>default-scaling-text</source> <source>default-scaling-text</source>
<extracomment>&quot;Default size text (scale factor: &quot;</extracomment> <extracomment>&quot;Default size text (scale factor: &quot;</extracomment>
<translation>Default size text (scale factor:</translation> <translation>Default size text (scale factor:</translation>
</message> </message>
<message> <message>
<location filename="../qml/panes/SettingsPane.qml" line="54"/> <location filename="../qml/panes/SettingsPane.qml" line="55"/>
<source>small-text-label</source> <source>small-text-label</source>
<translation>Small</translation> <translation>Small</translation>
</message> </message>

68
main.go
View File

@ -7,19 +7,19 @@ import (
"cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gobjects"
"cwtch.im/ui/go/gothings" "cwtch.im/ui/go/gothings"
"cwtch.im/ui/go/the" "cwtch.im/ui/go/the"
"fmt"
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity" "git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
"git.openprivacy.ca/openprivacy/libricochet-go/log" "git.openprivacy.ca/openprivacy/libricochet-go/log"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/core" "github.com/therecipe/qt/core"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/network" "github.com/therecipe/qt/network"
"github.com/therecipe/qt/qml" "github.com/therecipe/qt/qml"
"github.com/therecipe/qt/quickcontrols2" "github.com/therecipe/qt/quickcontrols2"
"os" "os"
"path"
"runtime"
"path/filepath"
"os/user" "os/user"
"fmt" "path"
"path/filepath"
"runtime"
) )
const androidBaseDir = "/data/data/org.qtproject.example.go/" const androidBaseDir = "/data/data/org.qtproject.example.go/"
@ -57,13 +57,35 @@ func main() {
app := gui.NewQGuiApplication(len(os.Args), os.Args) app := gui.NewQGuiApplication(len(os.Args), os.Args)
app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png")) app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png"))
var translator = core.NewQTranslator(nil) // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings
translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "") translator := core.NewQTranslator(nil)
translator.Load("translation_en", ":/i18n/", "", "")
core.QCoreApplication_InstallTranslator(translator) core.QCoreApplication_InstallTranslator(translator)
gcd.Translator = core.NewQTranslator(nil)
gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "")
core.QCoreApplication_InstallTranslator(gcd.Translator)
core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true) core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
quickcontrols2.QQuickStyle_SetStyle("Universe") quickcontrols2.QQuickStyle_SetStyle("Universe")
engine := qml.NewQQmlApplicationEngine(nil) engine := qml.NewQQmlApplicationEngine(nil)
gcd.QMLEngine = engine
// prevent qt from initiating network connections (possible deanon attempts!)
factory := qml.NewQQmlNetworkAccessManagerFactory()
factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager {
nam := network.NewQNetworkAccessManager(parent)
nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible)
proxy := network.NewQNetworkProxy()
proxy.SetHostName("0.0.0.0")
nam.SetProxy(proxy)
//nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply {
// log.Errorf("network access request detected - possible remote content insertion bug!!!")
// return nil
//})
return nam
})
engine.SetNetworkAccessManagerFactory(factory)
// variables we want to access from inside qml // variables we want to access from inside qml
if runtime.GOOS == "android" { if runtime.GOOS == "android" {
@ -120,21 +142,13 @@ func main() {
go characters.PresencePoller(gcd.UIState.GetContact, gcd.UIState.AddContact, gcd.UIState.UpdateContact) go characters.PresencePoller(gcd.UIState.GetContact, gcd.UIState.AddContact, gcd.UIState.UpdateContact)
go characters.GroupPoller(gcd.UIState.GetContact, gcd.UIState.UpdateContact) go characters.GroupPoller(gcd.UIState.GetContact, gcd.UIState.UpdateContact)
// prevent qt from initiating network connections (possible deanon attempts!) // load ui preferences
factory := qml.NewQQmlNetworkAccessManagerFactory() gcd.RequestSettings()
factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager { locale, exists := the.Peer.GetProfile().GetAttribute("settings.locale")
nam := network.NewQNetworkAccessManager(parent) if exists {
nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible) gcd.SetLocale_helper(locale)
proxy := network.NewQNetworkProxy() }
proxy.SetHostName("0.0.0.0")
nam.SetProxy(proxy)
//nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply {
// log.Errorf("network access request detected - possible remote content insertion bug!!!")
// return nil
//})
return nam
})
engine.SetNetworkAccessManagerFactory(factory)
app.Exec() app.Exec()
acn.Close() acn.Close()
} }
@ -209,12 +223,12 @@ func loadCwtchData(gcd *gothings.GrandCentralDispatcher, acn connectivity.ACN) {
Server: group.GroupServer, Server: group.GroupServer,
Trusted: group.Accepted, Trusted: group.Accepted,
}) })
}
// Only send a join server packet if we haven't joined this server yet... // Only send a join server packet if we haven't joined this server yet...
_,connecting := the.Peer.GetServers()[group.GroupServer] _,connecting := the.Peer.GetServers()[group.GroupServer]
if group.Accepted && !connecting { if group.Accepted && !connecting {
the.Peer.JoinServer(group.GroupServer) the.Peer.JoinServer(group.GroupServer)
}
} }
} }
} }

View File

@ -32,5 +32,6 @@
<file>qml/widgets/controls/Variables.qml</file> <file>qml/widgets/controls/Variables.qml</file>
<file>i18n/translation_en.qm</file> <file>i18n/translation_en.qm</file>
<file>i18n/translation_de.qm</file> <file>i18n/translation_de.qm</file>
<file>i18n/translation_pt.qm</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -7,6 +7,7 @@ import QtQuick.Window 2.11
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import "../widgets" import "../widgets"
import "../widgets/controls"
ColumnLayout { // settingsPane ColumnLayout { // settingsPane
anchors.fill: parent anchors.fill: parent
@ -36,6 +37,7 @@ ColumnLayout { // settingsPane
updateValueWhileDragging: false updateValueWhileDragging: false
onValueChanged: { onValueChanged: {
gcd.themeScale = zoomSlider.value gcd.themeScale = zoomSlider.value
saveSettings()
} }
width: 400 width: 400
} }
@ -55,11 +57,35 @@ ColumnLayout { // settingsPane
size: 8 size: 8
} }
FlagButton {
emoji: "1f1e8-1f1e6"
locale: "en"
}
FlagButton {
emoji: "1f1e9-1f1ea"
locale: "de"
}
FlagButton {
locale: "pt"
emoji: "1f1e7-1f1f7"
selected: true
}
}//end of column with padding }//end of column with padding
Component.onCompleted: { function saveSettings() {
zoomSlider.value = gcd.themeScale //Screen.pixelDensity / 3.2 // artistic license. set by erinn. fight me before changing // language switcher saves itself because erinn is a bad (read: amazing) programmer
if (zoomSlider.value < zoomSlider.from) zoomSlider.value = zoomSlider.from gcd.saveSettings(zoomSlider.value, "")
if (zoomSlider.value > zoomSlider.to) zoomSlider.value = zoomSlider.to }
Connections {
target: gcd
onSupplySettings: function(zoom, locale) {
if (zoom != "") zoomSlider.value = zoom
// (locale is handled automatically by FlagButton)
}
} }
} }

View File

@ -0,0 +1,43 @@
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import QtQuick.Window 2.11
import QtQuick.Controls 1.4
Rectangle {
width: img.width + 10
height: img.height + 5
property string emoji
color: selected ? windowItem.cwtch_color : windowItem.cwtch_background_color
property bool selected
property string locale
Image {
id: img
anchors.centerIn:parent
opacity: 1.0
source: "qrc:/qml/fonts/twemoji/72x72/" + emoji + ".png"
MouseArea {
anchors.fill: parent
onClicked: {
gcd.setLocale(locale)
}
}
}
Connections {
target: gcd
onSupplySettings: function(zoom, newLocale) {
selected = newLocale == locale
}
}
}

3
ui.pro
View File

@ -17,7 +17,8 @@ SOURCES += \
RESOURCES += qml.qrc RESOURCES += qml.qrc
TRANSLATIONS = i18n/translation_en.ts \ TRANSLATIONS = i18n/translation_en.ts \
i18n/translation_de.ts i18n/translation_de.ts \
i18n/translation_pt.ts
# Additional import path used to resolve QML modules in Qt Creator's code model # Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = QML_IMPORT_PATH =