From fe6c62e9fccf98c1fcdb3a7433e459b58dec6258 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 14 Aug 2018 17:07:42 +0200 Subject: [PATCH] - Added multi-language support and a german translation - Cleaned the code up --- android-sources/AndroidManifest.xml | 3 +- headers/buzzerconn.h | 2 +- qml/BuzzerConn.qml | 41 +++++++ qml/SettingsDialog.qml | 22 ++-- qml/main.qml | 160 ++++++++++++++++------------ qml/qml.qrc | 1 + shared.qrc | 3 + sources/buzzerconn.cpp | 7 +- sources/main.cpp | 8 ++ speedclimbing_stopwatch.pro | 5 +- translations/de_DE.qm | Bin 0 -> 1326 bytes translations/de_DE.ts | 108 +++++++++++++++++++ translations/german.ts | 58 ++++++++++ translations/german_de.qm | Bin 0 -> 1352 bytes translations/german_de.ts | 108 +++++++++++++++++++ 15 files changed, 439 insertions(+), 87 deletions(-) create mode 100644 qml/BuzzerConn.qml create mode 100644 translations/de_DE.qm create mode 100644 translations/de_DE.ts create mode 100644 translations/german.ts create mode 100644 translations/german_de.qm create mode 100644 translations/german_de.ts diff --git a/android-sources/AndroidManifest.xml b/android-sources/AndroidManifest.xml index ffab56b..5b8f6b3 100644 --- a/android-sources/AndroidManifest.xml +++ b/android-sources/AndroidManifest.xml @@ -15,8 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . --> - - + diff --git a/headers/buzzerconn.h b/headers/buzzerconn.h index 51b1616..e033869 100644 --- a/headers/buzzerconn.h +++ b/headers/buzzerconn.h @@ -26,7 +26,7 @@ public: double starttime; bool connected; int connection_progress; - + QString buzz_url; private: QNetworkAccessManager *networkManager; diff --git a/qml/BuzzerConn.qml b/qml/BuzzerConn.qml new file mode 100644 index 0000000..fcd0491 --- /dev/null +++ b/qml/BuzzerConn.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 + +Item { + id: buzzerConn + height: 0 + width: 0 + opacity: 0 + visible: false + + signal pushed() + + Timer { + //timer that refreshes the connection state to the buzzer + id: connectionRefreshTimer + running: root.state !== "RUNNING" && root.state !== "STARTING" + repeat: false + interval: 1000 + onTriggered: { + _cppBuzzerConn.refresh() + connectionRefreshTimer.start() + } + } + + Timer { + id: running_refresh_timer + running: root.state === "RUNNING" + repeat: false + interval: 1 + + onTriggered: { + if(_cppBuzzerConn.buzzer_triggered()){ + buzzerConn.pushed() + + } + if(root.state === "RUNNING"){ + running_refresh_timer.start() + } + } + } + +} diff --git a/qml/SettingsDialog.qml b/qml/SettingsDialog.qml index 8a3219b..9d6d749 100644 --- a/qml/SettingsDialog.qml +++ b/qml/SettingsDialog.qml @@ -167,21 +167,21 @@ Popup { id: settings Column { - property string title: "Options" + property string title: qsTr("Options") id: settings_col /*----Connect to buzzer----*/ ItemDelegate { id: connect_del width: parent.width - text: _cppBuzzerConn.get("connected")===1 ? "connected to buzzer":"connect to buzzer" + text: _cppBuzzerConn.get("connected")===1 ? qsTr("connected to buzzer"):qsTr("connect to buzzer") font.pixelSize: options_stack.text_pixelSize Timer { running: connect_del.scale === 1 repeat: true interval: 10 onTriggered: { - connect_del.text = _cppBuzzerConn.get("connected")===1 ? "connected to buzzer":"connect to buzzer" + connect_del.text = _cppBuzzerConn.get("connected")===1 ? qsTr("connected to buzzer"):qsTr("connect to buzzer") } } @@ -192,19 +192,19 @@ Popup { prog.arcEnd = 0 prog.colorCircle = "grey" prog.opacity = 1 - prog.text = "connecting..." + prog.text = qsTr("connecting...") prog_refresh.running = true if(_cppBuzzerConn.connect()){ prog_refresh.running = false prog.colorCircle = "green" - prog.text = "success!" + prog.text = qsTr("success") prog.arcEnd = 360 } else { prog_refresh.running = false prog.colorCircle = "red" - prog.text = "error!" + prog.text = qsTr("error") prog.arcEnd = 360 } @@ -229,7 +229,7 @@ Popup { /*----Automated Start----*/ ItemDelegate { id: autostart_del - text: "start sequence" + text: qsTr("start sequence") font.pixelSize: options_stack.text_pixelSize width: parent.width @@ -288,7 +288,7 @@ Popup { ItemDelegate { id: ready_delay_del - text: "delay (ms)" + text: qsTr("delay (ms)") enabled: ready_del.checked width: parent.width font.pixelSize: options_stack.text_pixelSize @@ -296,7 +296,7 @@ Popup { TextField { focus: true - placeholderText: "time" + placeholderText: qsTr("time") width: parent.width * 0.3 height: parent.height anchors.right: parent.right @@ -329,7 +329,7 @@ Popup { ItemDelegate { id: at_marks_delay_del - text: "delay (ms)" + text: qsTr("delay (ms)") enabled: at_marks_del.checked width: parent.width height: parent.delegateHeight @@ -338,7 +338,7 @@ Popup { TextField { focus: true - placeholderText: "time" + placeholderText: qsTr("time") width: parent.width * 0.3 height: parent.height anchors.right: parent.right diff --git a/qml/main.qml b/qml/main.qml index 6733f1a..362fd92 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -44,7 +44,11 @@ Window { property double buzzer_offset property double last_button_pressed + property var last_run : { + 'stopp_type': "", 'time': 0 + }; + //set default state to IDLE state: "IDLE" Timer { @@ -58,38 +62,10 @@ Window { } } - Timer { - //timer that refreshes the connection state to the buzzer - id: connectionRefreshTimer - running: root.state !== "RUNNING" && root.state !== "STARTING" - repeat: false - interval: 1000 - onTriggered: { - _cppBuzzerConn.refresh() - connectionRefreshTimer.start() - } - } - - Timer { - id: running_refresh_timer - running: root.state === "RUNNING" - repeat: false - interval: 1 - - onTriggered: { - if(_cppBuzzerConn.buzzer_triggered()){ - //the buzzer was pushed - root.buzzer_offset = _cppBuzzerConn.get("offset") - root.last_button_pressed = _cppBuzzerConn.get("lastpressed") - root.stoppedTime = (root.last_button_pressed + root.buzzer_offset) - root.startTime - root.state = "STOPPED" - //time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec" - console.log("STOPPED: "+root.stoppedTime) - - } - if(root.state === "RUNNING"){ - running_refresh_timer.start() - } + BuzzerConn { + onPushed: { + // the buzzer was pushed + root.stop("buzzer") } } @@ -192,11 +168,18 @@ Window { //height: root.landscape() ? undefined:parent.height * 0.15 Label { id: time - text: "Click start to start" + text: qsTr("Click start to start") anchors.centerIn: parent //font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3 elide: "ElideRight" + + Behavior on text { + enabled: root.state !== "RUNNING" + FadeAnimation { + target: time + } + } } } @@ -238,12 +221,12 @@ Window { } /*---------------------- - Start button + Start / Stop / Reset button ----------------------*/ Button { id : startButt - text: "start" + text: qsTr("start") property int size: root.landscape() ? parent.width * 0.5:parent.height * 0.5 anchors { bottom: parent.bottom @@ -280,34 +263,24 @@ Window { } } + Behavior on text { + //animate a text change + enabled: true + FadeAnimation { + target: startButt_text + } + } + onClicked: { switch(root.state) { - case "": - root.state = "IDLE" case "IDLE": - root.state = "STARTING" - if(_cppAppSettings.loadSetting("at_marks_en") === "true"){ - next_actionTimer.action = "at_marks" - next_actionTimer.interval = _cppAppSettings.loadSetting("at_marks_delay")>0 ? _cppAppSettings.loadSetting("at_marks_delay"):1 - next_actionTimer.start() - return - } - if(_cppAppSettings.loadSetting("ready_en") === "true"){ - next_actionTimer.action = "ready" - next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")>0 ? _cppAppSettings.loadSetting("ready_delay"):1 - next_actionTimer.start() - return - } - - startSound.play() + root.start() break case "RUNNING": - root.stoppedTime = new Date().getTime() - root.startTime - time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec" - root.state = "STOPPED" + root.stop("manual") break case "STOPPED": - root.state = "IDLE" + root.reset() break } } @@ -343,7 +316,7 @@ Window { RoundButton { id: cancelButt - text: "cancel" + text: qsTr("cancel") anchors { right: startButt.right bottom: startButt.bottom @@ -366,13 +339,7 @@ Window { } onClicked: { - root.stoppedTime = 0 - time.text = "false start" - root.state = "STOPPED" - next_actionTimer.stop() - at_marksSound.stop() - readySound.stop() - startSound.stop() + root.stop("false") } Behavior on scale { @@ -537,7 +504,7 @@ Window { State { name: "IDLE" //state for the start page - PropertyChanges { target: time; text: "Click start to start"; font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 } + PropertyChanges { target: time; text: qsTr("Click start to start"); font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 } PropertyChanges { target: time_container; anchors.bottomMargin: root.landscape() ? undefined:parent.height * 0.1; @@ -546,7 +513,7 @@ Window { PropertyChanges { target: startButt; - enabled: true; text: "start"; + enabled: true; text: qsTr("start"); size: root.landscape() ? parent.width * 0.5:parent.height * 0.5 anchors.bottomMargin: parent.height * 0.5 - startButt.height * 0.5 anchors.rightMargin: parent.width * 0.5 - startButt.width * 0.5 @@ -556,7 +523,7 @@ Window { State { name: "STARTING" //state for the start sequence - PropertyChanges { target: startButt; enabled: false; text: "starting..."; + PropertyChanges { target: startButt; enabled: false; text: qsTr("starting..."); anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode) anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode) } @@ -580,13 +547,14 @@ Window { name: "STOPPED" //state when the meassuring is over PropertyChanges { - target: time; text: root.stoppedTime > 0 ? ( root.stoppedTime / 1000 ).toFixed(3) + " sec":"false start"; + target: time; + text: root.stoppedTime > 0 ? ( root.stoppedTime / 1000 ).toFixed(3) + " sec":qsTr("false start"); font.pixelSize: root.landscape() ? parent.width * 0.15:parent.height * 0.1; scale: 1 } PropertyChanges { target: startButt; - enabled: true; text: "reset"; + enabled: true; text: qsTr("reset"); size: root.landscape() ? parent.height * 0.35:parent.height * 0.2; anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.2 - startButt.height * 0.5 anchors.rightMargin: root.landscape() ? parent.height * 0.2 - startButt.height * 0.5:parent.width * 0.5 - startButt.width * 0.5 @@ -613,7 +581,6 @@ Window { Transition { to: "IDLE" NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 } - FadeAnimation { target: time; fadeDuration_out: 1000; fadeDuration_in: 0} }, Transition { @@ -628,5 +595,58 @@ Window { function landscape(){ return(root.height < root.width) } + + /*----Functions to control the stopwatch----*/ + function start(){ + root.state = "STARTING" + if(_cppAppSettings.loadSetting("at_marks_en") === "true"){ + next_actionTimer.action = "at_marks" + next_actionTimer.interval = _cppAppSettings.loadSetting("at_marks_delay")>0 ? _cppAppSettings.loadSetting("at_marks_delay"):1 + next_actionTimer.start() + return + } + if(_cppAppSettings.loadSetting("ready_en") === "true"){ + next_actionTimer.action = "ready" + next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")>0 ? _cppAppSettings.loadSetting("ready_delay"):1 + next_actionTimer.start() + return + } + + startSound.play() + } + + function stop(type){ + switch(type){ + case "buzzer": + //the buzzer was pushed + root.buzzer_offset = _cppBuzzerConn.get("offset") + root.last_button_pressed = _cppBuzzerConn.get("lastpressed") + root.stoppedTime = (root.last_button_pressed + root.buzzer_offset) - root.startTime + root.state = "STOPPED" + //time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec" + console.log("STOPPED: "+root.stoppedTime) + break + case "manual": + //te stop button was pressed + root.stoppedTime = new Date().getTime() - root.startTime + time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec" + root.state = "STOPPED" + break + case "false": + //the cancel button was pressed + root.stoppedTime = 0 + time.text = "false start" + root.state = "STOPPED" + next_actionTimer.stop() + at_marksSound.stop() + readySound.stop() + startSound.stop() + break + } + } + + function reset(){ + root.state = "IDLE" + } } } diff --git a/qml/qml.qrc b/qml/qml.qrc index 0995a25..7680353 100644 --- a/qml/qml.qrc +++ b/qml/qml.qrc @@ -6,5 +6,6 @@ ProgressCircle.qml SettingsDialog.qml SimpleIndicator.qml + BuzzerConn.qml diff --git a/shared.qrc b/shared.qrc index 27896f1..1459577 100644 --- a/shared.qrc +++ b/shared.qrc @@ -15,5 +15,8 @@ sounds/at_marks_2.wav graphics/icons/buzzer_black.png graphics/icons/ok_black.png + translations/german.ts + translations/de_DE.qm + translations/de_DE.ts diff --git a/sources/buzzerconn.cpp b/sources/buzzerconn.cpp index 6f71c0c..a9ce648 100644 --- a/sources/buzzerconn.cpp +++ b/sources/buzzerconn.cpp @@ -25,6 +25,9 @@ BuzzerConn::BuzzerConn(QObject *parent) : QObject(parent) this->date = new QDateTime; this->latest_button_pressed = 0; this->connected = false; + + this->buzz_url = "https://api.itsblue.de/test/buzzerem.php"; + // "http://192.168.4.1" } bool BuzzerConn::connect() @@ -81,7 +84,7 @@ bool BuzzerConn::calcoffset(QList times) QList BuzzerConn::gettimes(int timeout) { QList times; - ReturnData_t ret = senddata(this->networkManager, QUrl("http://192.168.4.1"), timeout); + ReturnData_t ret = senddata(this->networkManager, QUrl(this->buzz_url), timeout); times.append(double(ret.status_code)); if(ret.status_code == 200){ @@ -171,7 +174,7 @@ bool BuzzerConn::refresh() return(false); } QList times; - ReturnData_t ret = senddata(this->reloadNetworkManager, QUrl("http://192.168.4.1"), 1000); + ReturnData_t ret = senddata(this->reloadNetworkManager, QUrl(this->buzz_url), 1000); times.append(double(ret.status_code)); if(ret.status_code == 200){ diff --git a/sources/main.cpp b/sources/main.cpp index cf072a4..50426f1 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -52,6 +52,7 @@ #include "headers/sqlprofilemodel.h" #include "headers/buzzerconn.h" #include "headers/appsettings.h" +#include static void connectToDatabase() { @@ -100,6 +101,13 @@ int main(int argc, char *argv[]) qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlProfileModel"); qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlStorageModel"); + //setup translation engine + //to the language of the system + //if the system language is not found the language is set to english + QTranslator translator; + translator.load(":/translations/"+QLocale::system().name()+".qm"); + app.installTranslator(&translator); + QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) diff --git a/speedclimbing_stopwatch.pro b/speedclimbing_stopwatch.pro index 47ba79a..52665f7 100644 --- a/speedclimbing_stopwatch.pro +++ b/speedclimbing_stopwatch.pro @@ -36,6 +36,8 @@ RESOURCES += \ shared.qrc \ qml/qml.qrc +TRANSLATIONS = translations/de_DE.ts + # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = @@ -53,7 +55,8 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin DISTFILES += \ android-sources/AndroidManifest.xml \ CHANGELOG \ - android-sources/src/MainActivity.java + android-sources/src/MainActivity.java \ +translations/german_de.ts android { ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources diff --git a/translations/de_DE.qm b/translations/de_DE.qm new file mode 100644 index 0000000000000000000000000000000000000000..1e9ac75295353a3d417019bc548f7bce1c9d9b26 GIT binary patch literal 1326 zcmbW0O=uHA6vtmax`~@M+EhxBf?E)hBIKZWDIRS7q6euG5%JW?W|FSikGQj|Zp3pv zs?@3=g&qXGdGO$&B7&C+Rq!r&5WEO}Aoi&L-IhsWSOqhXnYZ)a@BQDKnZwU&W3RtF zxU(@a{$hUh`TH3nx=EQQhlr9N=<50_qSPj}A1x83_tNU;H`xE7BtJgH{=9PfKmqo$ za!pBLCgs+4anbG}e*e|nB&j+xlcBtd~VDD5{W>>&HslGk< z3E$Up_cy+Q`*`Tgk=wvc<-dQu3ww_Nr|V&cT{K56^2i{EY~o~RqqO+T%(Xnju|)>! ze1&_SVK>AvgPBev5k{8i6rw!RXoh@hV{md|U5@4|_H3&45QlZgwz=+Uo}*R$cALBZ z%l7-&Bin3V`!{{GPh*)dWaUHKEEHTWm*X^QbS|p2O+Tp-twL1|bf82Q37V8VwZ=^r zXeCQb#=!>Z1P}{kh9DWJaMyL*iMXH=val$(N=2-~vj}jGesm5NzPQwcPf-F#1Pjz6 z^R&S6UCm-{QxxOqW0J0c?m`&Dc?Mmy9B5k6<*XL`g;Ig8P)Vq6nyM&~L1A5L$_tOV zo+kJupW8Z*lQT%i0jZ-rlNvHOD|}t&Ld5ncOBbLV_f&?YJ;RF4Ql_(TZeei96C?+7=h0 literal 0 HcmV?d00001 diff --git a/translations/de_DE.ts b/translations/de_DE.ts new file mode 100644 index 0000000..6411f5f --- /dev/null +++ b/translations/de_DE.ts @@ -0,0 +1,108 @@ + + + + + SettingsDialog + + + Options + Optionen + + + + + connected to buzzer + Mit Buzzer verbunden + + + + + connect to buzzer + Mit Buzzer verbinden + + + + connecting... + verbinde... + + + + success! + Erfolg + + + + error! + Fehler + + + + start sequence + Start Ablauf + + + + say 'ready' + sage 'ready' + + + + + delay (ms) + Verzögerung (ms) + + + + + time + Zeit + + + + say +'at your marks' + sage +'at your marks' + + + + main + + + Speedclimbing stw + + + + + + Click start to start + Tippe start zum Starten + + + + + start + start + + + + cancel + Abbruch + + + + starting... + starte... + + + + false start + Fehlstart + + + + reset + reset + + + diff --git a/translations/german.ts b/translations/german.ts new file mode 100644 index 0000000..a4c106a --- /dev/null +++ b/translations/german.ts @@ -0,0 +1,58 @@ + + + + + SettingsDialog + + + say 'ready' + fertig + + + + say +'at your marks' + auf die Plätze + + + + main + + + Speedclimbing stw + + + + + + Click start to start + + + + + + start + + + + + cancel + + + + + starting... + + + + + false start + + + + + reset + + + + diff --git a/translations/german_de.qm b/translations/german_de.qm new file mode 100644 index 0000000000000000000000000000000000000000..e8c5c66fa406bc5e27d2a607de6b8cfae22d80a7 GIT binary patch literal 1352 zcmbW0O=uHA6vtoEbQ3o;kW@-3J#0ZtijafiLGWN}6nYSqh=?aAn`vFTA9ZG;ZoCS5 zw4zo)iaiLP#Dky*#ft|kRKcrw6TAq196Wf?{%4zR66+$Efy}(w_kQpH-puTO+8llT z49X#^5AiosZ^5#BcTyi+14q+*XzftVXNd z=Hh?ZT5UgjxWnenf73^{Xsi-OT=`Ikg@UWqYLZ5aPDYis=||K#(dnUu&UonTWXv<0 z+-0Fv@#JI@tU$AXoy9@uCQihm1{Wd_6G>qe(+DYm5`7XLb_C7CryK)^ zB@4|mQ&t$Xgyk_YFUv{v(U@+5E+CDe>tPQq51LgLoHfHl${5w5ODoaprl^5Z0~Cte z7ON^q#e}jXKiA^E&65S`?rer@K@QpITDM<0*|KdeWn#y2bUF%Caqf(Ayu^%EI)NMu z7#!mDbJ;AUjV628>lWAhc(xyO9edu|C=1s;TIjMe9&`NEz;FCw1;zRT=S|ynyauiu zd@uBP>eq*)4Gew5P;MM&*bL2b`<+X47+UpBiq*ye`B~;lzC{dDn9=b{M0Oi9D7fUR hpKktzI{0UC;FY?5VD>++eB|GKTpKO9il}rdwGRDW9WDR> literal 0 HcmV?d00001 diff --git a/translations/german_de.ts b/translations/german_de.ts new file mode 100644 index 0000000..ceb9288 --- /dev/null +++ b/translations/german_de.ts @@ -0,0 +1,108 @@ + + + + + SettingsDialog + + + Options + Einstellungen + + + + + connected to buzzer + Mit Buzzer verbunden + + + + + connect to buzzer + Mit Buzzer verbinden + + + + connecting... + verbinde... + + + + success! + erfolgreich! + + + + error! + fehler! + + + + start sequence + Start Abfolge + + + + say 'ready' + sage 'ready' + + + + + delay (ms) + Verzögerung (ms) + + + + + time + Zeit + + + + say +'at your marks' + sage +'at your marks' + + + + main + + + Speedclimbing stw + + + + + + Click start to start + Tippe start zum Starten + + + + + start + start + + + + cancel + abbruch + + + + starting... + starte... + + + + false start + Fehlstart + + + + reset + reset + + +