summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Dashboard.qml316
-rw-r--r--app/TirePressure.qml62
-rw-r--r--app/app.pri3
-rw-r--r--app/app.pro17
-rw-r--r--app/dashboard.qrc6
-rw-r--r--app/images/HMI_Dashboard_Car.pngbin0 -> 244241 bytes
-rw-r--r--app/images/HMI_Dashboard_Fuel_Details.svg48
-rw-r--r--app/images/HMI_Dashboard_Fuel_Icon.svg39
-rw-r--r--app/images/HMI_Dashboard_LeftTire.svg80
-rw-r--r--app/images/HMI_Dashboard_RightTire.svg82
-rw-r--r--app/images/HMI_Dashboard_Speed_Icon.svg53
-rw-r--r--app/images/HMI_Dashboard_TirePressure_OK.svg61
-rw-r--r--app/images/images.qrc11
-rw-r--r--app/main.cpp31
-rw-r--r--app/models/CarsModel.qml35
-rw-r--r--app/models/TireModel.qml64
-rw-r--r--app/models/TripModel.qml19
-rw-r--r--app/models/qmldir9
-rw-r--r--app/translations.pri16
-rw-r--r--app/translations/dashboard_fr_FR.ts106
-rw-r--r--app/translations/dashboard_ja_JP.ts95
-rw-r--r--app/translations/dashboard_zh_CN.ts106
-rw-r--r--app/translator.cpp52
-rw-r--r--app/translator.h32
24 files changed, 1343 insertions, 0 deletions
diff --git a/app/Dashboard.qml b/app/Dashboard.qml
new file mode 100644
index 0000000..61928ab
--- /dev/null
+++ b/app/Dashboard.qml
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2018-2019 TOYOTA MOTOR CORPORATION
+ * Copyright (C) 2016 The Qt Company Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.6
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.0
+import QtWebSockets 1.0
+import Translator 1.0
+
+ApplicationWindow {
+ id: root
+
+ width: container.width * container.scale
+ height: container.height * container.scale
+
+ Translator {
+ id: translator
+ }
+
+ property string api_str: "low-can"
+ property string verb_str: "subscribe"
+ property var msgid_enu: { "call":2, "retok":3, "reterr":4, "event":5 }
+ property string request_str: ""
+ property string status_str: ""
+
+ property double speed_val: 0
+ property double engineSpeed: 0
+ WebSocket {
+ id: websocket
+ url: bindingAddress
+
+ onTextMessageReceived: {
+ var message_json = JSON.parse (message);
+ /*
+ console.log ("Raw response: " + message)
+ console.log ("JSON response: " + message_json)
+ */
+
+ if (message_json[0] == msgid_enu.event) {
+
+ var property_name = message_json[2].event.split("/")[1]
+ if(property_name === "messages.vehicle.average.speed") {
+ speed_val = message_json[2].data.value
+ }
+ else if (property_name === "messages.engine.speed") {
+ engineSpeed = message_json[2].data.value
+ tachometer.value = engineSpeed / 7000
+ }
+ }
+ else
+ {
+ if (message_json[0] != msgid_enu.retok) {
+ console.log ("Return value is not ok !")
+ return
+ }
+ }
+ /* refresh happen */
+ }
+ onStatusChanged: {
+ if (websocket.status == WebSocket.Error) {
+ status_str = "Error: " + websocket.errorString
+ }
+ else
+ if (websocket.status == WebSocket.Open) {
+ status_str = "Socket opened; sending message..."
+ if (verb_str == "subscribe") {
+ request_str ='[' + msgid_enu.call + ',"99998","' + api_str +'/'+ verb_str +'",{ \"event\" : \"vehicle.average.speed\" } ]';
+ websocket.sendTextMessage (request_str)
+ request_str ='[' + msgid_enu.call + ',"99999","' + api_str +'/'+ verb_str +'",{ \"event\" : \"engine.speed\" } ]';
+ websocket.sendTextMessage (request_str)
+ }
+ } else
+ if (websocket.status == WebSocket.Closed) {
+ status_str = "Socket closed"
+ }
+ console.log (status_str)
+ }
+ active: true
+ }
+
+ Item {
+ id: container
+ anchors.centerIn: parent
+ width: 1920
+ height: 720
+ scale: screenInfo.scale_factor()
+
+ Label {
+ id: speed
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: 20
+ text: speed_val.toFixed(0) /* MPH */
+ font.pixelSize: 256
+ }
+ Label {
+ id: unit
+ anchors.left: speed.right
+ anchors.baseline: speed.baseline
+ text: 'MPH'
+ font.pixelSize: 64
+ }
+ Label {
+ anchors.left: unit.left
+ anchors.top: unit.bottom
+ text: '10,000.5 miles'
+ font.pixelSize: 32
+ opacity: 0.5
+ }
+
+ Image {
+ id: car
+ anchors.top: parent.top
+ anchors.topMargin: 50
+ anchors.horizontalCenter: container.horizontalCenter
+ source: './images/HMI_Dashboard_Car.png'
+ }
+
+ TirePressure {
+ anchors.right: car.left
+ anchors.rightMargin: -120
+ anchors.bottom: car.bottom
+ anchors.bottomMargin: -20
+ title: translator.translate(qsTr('LEFT FRONT TIRE'), translator.language)
+ pressure: translator.translate(qsTr('%1 PSI').arg(23.1), translator.language)
+ }
+
+ TirePressure {
+ mirror: true
+ anchors.left: car.right
+ anchors.leftMargin: -100
+ anchors.bottom: car.bottom
+ anchors.bottomMargin: -20
+ title: translator.translate(qsTr('LEFT REAR TIRE'), translator.language)
+ pressure: translator.translate(qsTr('%1 PSI').arg(31.35), translator.language)
+ }
+
+ TirePressure {
+ anchors.right: car.left
+ anchors.rightMargin: -120
+ anchors.bottom: car.top
+ anchors.bottomMargin: -80
+ title: translator.translate(qsTr('RIGHT FRONT TIRE'), translator.language)
+ pressure: translator.translate(qsTr('%1 PSI').arg(24.2), translator.language)
+ }
+
+ TirePressure {
+ mirror: true
+ anchors.left: car.right
+ anchors.leftMargin: -100
+ anchors.bottom: car.top
+ anchors.bottomMargin: -80
+ title: translator.translate(qsTr('RIGHT REAR TIRE'), translator.language)
+ pressure: translator.translate(qsTr('%1 PSI').arg(33.0), translator.language)
+ }
+
+ RowLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 100
+
+ Image {
+ id: speedIcon
+ source: './images/HMI_Dashboard_Speed_Icon.svg'
+ }
+ ProgressBar {
+ id: tachometer
+ Layout.fillWidth: true
+ value: engineSpeed / 65535
+ Label {
+ anchors.left: parent.left
+ anchors.top: parent.bottom
+ anchors.topMargin: 10
+ text: translator.translate(qsTr('(RPM)'), translator.language)
+ font.pixelSize: 26
+ }
+ }
+ Item {
+ width: 30
+ height: 30
+ }
+ Image {
+ id: fuelIcon
+ source: './images/HMI_Dashboard_Fuel_Icon.svg'
+ }
+ ProgressBar {
+ Layout.fillWidth: true
+ value: 0.66
+ Image {
+ anchors.left: parent.left
+ anchors.leftMargin: -40
+ anchors.bottom: parent.top
+ source: './images/HMI_Dashboard_Fuel_Details.svg'
+ GridLayout {
+ anchors.fill: parent
+ columns: 2
+ rowSpacing: -10
+ Label {
+ Layout.fillWidth: true
+ Layout.preferredWidth: 3
+ Layout.fillHeight: true
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignRight
+ text: translator.translate(qsTr('LEVEL:'), translator.language)
+ font.pixelSize: 24
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.preferredWidth: 4
+ Layout.fillHeight: true
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignLeft
+ text: translator.translate(qsTr('%1 GALLONS').arg(9), translator.language)
+ font.pixelSize: 24
+ color: '#00ADDC'
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.preferredWidth: 3
+ Layout.fillHeight: true
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignRight
+ text: translator.translate(qsTr('RANGE:'), translator.language)
+ font.pixelSize: 24
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.preferredWidth: 4
+ Layout.fillHeight: true
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignLeft
+ text: translator.translate(qsTr('%1 MI').arg(9), translator.language)
+ font.pixelSize: 24
+ color: '#00ADDC'
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.preferredWidth: 3
+ Layout.fillHeight: true
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignRight
+ text: translator.translate(qsTr('AVG:'), translator.language)
+ font.pixelSize: 24
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.preferredWidth: 4
+ Layout.fillHeight: true
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignLeft
+ text: translator.translate(qsTr('%1 MPG').arg(25.5), translator.language)
+ font.pixelSize: 24
+ color: '#00ADDC'
+ }
+ }
+ }
+
+ Label {
+ anchors.left: parent.left
+ anchors.top: parent.bottom
+ anchors.topMargin: 10
+ text: translator.translate(qsTr('FUEL'), translator.language)
+ font.pixelSize: 26
+ }
+ }
+ }
+
+ RowLayout {
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ Repeater {
+ model: ListModel {
+ ListElement {
+ code: 'C'
+ language: QT_TR_NOOP('English')
+ }
+ ListElement {
+ code: 'fr_FR'
+ language: QT_TR_NOOP('Français')
+ }
+ ListElement {
+ code: 'ja_JP'
+ language: QT_TR_NOOP('日本語')
+ }
+ ListElement {
+ code: 'zh_CN'
+ language: QT_TR_NOOP('中文简体')
+ }
+ }
+
+ Button {
+ text: qsTr(model.language)
+ onClicked: {
+ translator.language = model.code
+ console.log ("Scale = " + screenInfo.scale_factor())
+ }
+ }
+ }
+ }
+}
+}
diff --git a/app/TirePressure.qml b/app/TirePressure.qml
new file mode 100644
index 0000000..437cf2f
--- /dev/null
+++ b/app/TirePressure.qml
@@ -0,0 +1,62 @@
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+Image {
+ id: root
+ width: sourceSize.width
+ height: sourceSize.height
+ property bool mirror: false
+ property alias title: title.text
+ property alias pressure: pressure.text
+
+ Label {
+ id: title
+ anchors.bottom: pressure.top
+ font.pixelSize: 24
+ }
+
+ Label {
+ id: pressure
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 55
+ anchors.leftMargin: 140
+ anchors.rightMargin: 140
+ color: '#00ADDC'
+ font.pixelSize: 20
+ }
+
+ states: [
+ State {
+ name: 'left'
+ when: !mirror
+ PropertyChanges {
+ target: root
+ source: './images/HMI_Dashboard_LeftTire.svg'
+ }
+ AnchorChanges {
+ target: title
+ anchors.right: pressure.right
+ }
+ AnchorChanges {
+ target: pressure
+ anchors.right: parent.right
+ }
+ },
+ State {
+ name: 'right'
+ when: mirror
+ PropertyChanges {
+ target: root
+ source: './images/HMI_Dashboard_RightTire.svg'
+ }
+ AnchorChanges {
+ target: title
+ anchors.left: pressure.left
+ }
+ AnchorChanges {
+ target: pressure
+ anchors.left: parent.left
+ }
+ }
+ ]
+}
diff --git a/app/app.pri b/app/app.pri
new file mode 100644
index 0000000..f22f540
--- /dev/null
+++ b/app/app.pri
@@ -0,0 +1,3 @@
+TEMPLATE = app
+
+DESTDIR = $${OUT_PWD}/../package/root/bin
diff --git a/app/app.pro b/app/app.pro
new file mode 100644
index 0000000..197675e
--- /dev/null
+++ b/app/app.pro
@@ -0,0 +1,17 @@
+TARGET = dashboard
+QT = quick aglextras
+
+HEADERS += \
+ translator.h
+
+SOURCES = main.cpp \
+ translator.cpp
+
+RESOURCES += \
+ dashboard.qrc \
+ images/images.qrc
+
+include(app.pri)
+
+LANGUAGES = ja_JP fr_FR zh_CN
+include(translations.pri)
diff --git a/app/dashboard.qrc b/app/dashboard.qrc
new file mode 100644
index 0000000..7e8961f
--- /dev/null
+++ b/app/dashboard.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>Dashboard.qml</file>
+ <file>TirePressure.qml</file>
+ </qresource>
+</RCC>
diff --git a/app/images/HMI_Dashboard_Car.png b/app/images/HMI_Dashboard_Car.png
new file mode 100644
index 0000000..9702107
--- /dev/null
+++ b/app/images/HMI_Dashboard_Car.png
Binary files differ
diff --git a/app/images/HMI_Dashboard_Fuel_Details.svg b/app/images/HMI_Dashboard_Fuel_Details.svg
new file mode 100644
index 0000000..a9faad4
--- /dev/null
+++ b/app/images/HMI_Dashboard_Fuel_Details.svg
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_2" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 350 155"
+ style="enable-background:new 0 0 350 155;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#FFFFFF;}
+ .st1{font-family:'Roboto-Regular';}
+ .st2{font-size:20.4887px;}
+ .st3{letter-spacing:3;}
+ .st4{fill:#0DF9FF;}
+ .st5{fill:none;stroke:url(#SVGID_1_);stroke-miterlimit:10;}
+ .st6{fill:none;stroke:url(#SVGID_2_);stroke-miterlimit:10;}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g>
+ <g>
+ <g>
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="44.7964" y1="74.6998" x2="45.7964" y2="74.6998">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <line class="st5" x1="45.3" y1="21.5" x2="45.3" y2="127.9"/>
+ <circle class="st0" cx="45.3" cy="76.7" r="4.8"/>
+ <circle class="st0" cx="45.3" cy="26.3" r="4.8"/>
+ <circle class="st0" cx="45.3" cy="127.4" r="4.8"/>
+ </g>
+ </g>
+ <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="45.2964" y1="26.5846" x2="45.2964" y2="26.5846">
+ <stop offset="0" style="stop-color:#8BC53F"/>
+ <stop offset="1" style="stop-color:#0DF9FF"/>
+ </linearGradient>
+ <path class="st6" d="M45.3,26.6"/>
+ </g>
+ </g>
+</switch>
+</svg>
diff --git a/app/images/HMI_Dashboard_Fuel_Icon.svg b/app/images/HMI_Dashboard_Fuel_Icon.svg
new file mode 100644
index 0000000..afb62a9
--- /dev/null
+++ b/app/images/HMI_Dashboard_Fuel_Icon.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 82 82"
+ style="enable-background:new 0 0 82 82;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
+ .st1{fill:none;stroke:url(#SVGID_1_);stroke-miterlimit:10;}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g>
+ <path class="st0" d="M29.5,20.9L46.7,21c0.3,0,0.6,0.3,0.6,0.6l0,3.8l0,2.2l0,7.1l-18.4-0.1l0-7.1l0-2.2l0-3.8
+ C28.9,21.1,29.2,20.9,29.5,20.9L29.5,20.9z M28.7,17.9c-1.5,0-2.8,1.2-2.8,2.7l-0.2,39.7l-1.5,0c-0.4,0-0.6,0.3-0.6,0.6l0,0
+ l0,0.8l0,1.9l28.6,0.2l0-1.9l0-0.8l0,0c0-0.4-0.3-0.6-0.6-0.6l-1.4,0l0.1-21.7l2.9,0l-0.1,20.4l0,0c0,2.5,2.3,4.8,4.9,4.9
+ c2.3,0.1,4-1,4.8-2.6L63,41.2c-1.6-3.3-4.2-4.6-7.5-4.6l0.1-10.7l-5.2-2.2l0-2.9c0-1.5-1.2-2.7-2.7-2.7L28.7,17.9L28.7,17.9z
+ M50.4,26.2l3,1.1l0,9.1l-3,0L50.4,26.2L50.4,26.2z M55.4,59.5l0.2-20.6c3.2,0.1,5.2,1.7,5.7,5l0,0.2l-0.1,15.2l0,0
+ c0,0,0,0.1,0,0.1l0,0.1l0,0c-0.2,1.1-1.3,2.1-2.9,2.1S55.6,60.6,55.4,59.5L55.4,59.5z"/>
+ </g>
+
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="5.022039e-04" y1="43.56" x2="81.0005" y2="43.56" gradientTransform="matrix(0.9999 1.092937e-02 -1.092937e-02 0.9999 0.978 -3.0001)">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+
+ <ellipse transform="matrix(1.092937e-02 -0.9999 0.9999 1.092937e-02 -0.4457 81.5494)" class="st1" cx="41" cy="41" rx="40" ry="40"/>
+ </g>
+</switch>
+</svg>
diff --git a/app/images/HMI_Dashboard_LeftTire.svg b/app/images/HMI_Dashboard_LeftTire.svg
new file mode 100644
index 0000000..5926fd7
--- /dev/null
+++ b/app/images/HMI_Dashboard_LeftTire.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_3" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 350 155"
+ style="enable-background:new 0 0 350 155;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:url(#SVGID_1_);}
+ .st1{fill:url(#SVGID_2_);}
+ .st2{fill:url(#SVGID_3_);}
+ .st3{fill:#FFFFFF;}
+ .st4{font-family:'Roboto-Regular';}
+ .st5{font-size:17px;}
+ .st6{letter-spacing:3;}
+ .st7{fill:#0DF9FF;}
+ .st8{fill:none;stroke:#0DF9FF;stroke-miterlimit:10;}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g>
+ <g>
+ <g>
+ <g>
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="206.3709" y1="118.8609" x2="280.2765" y2="26.9783">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <polygon class="st0" points="239.8,77.6 238.4,76.2 248.9,65.7 250.3,67.1 "/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="202.6523" y1="115.8698" x2="276.5579" y2="23.9872">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <polygon class="st1" points="238.9,77.1 233.1,71.4 234.5,70 240.3,75.7 "/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="203.8843" y1="116.8608" x2="277.7899" y2="24.9782">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <path class="st2" d="M240.1,93.8c-12.1,0-22-9.9-22-22c0-12.1,9.9-22,22-22c2.4,0,4.8,0.4,7.1,1.2l-0.6,1.9
+ c-2.1-0.7-4.2-1.1-6.5-1.1c-11,0-20,9-20,20s9,20,20,20s20-9,20-20c0-2-0.3-3.9-0.9-5.8l1.9-0.6c0.6,2.1,0.9,4.2,0.9,6.4
+ C262.1,83.9,252.3,93.8,240.1,93.8z"/>
+ </g>
+ </g>
+ </g>
+ <g>
+ <g>
+ <polyline class="st8" points="99.9,86.7 99.9,105.2 328,105.2 "/>
+ <g>
+ <circle class="st7" cx="327.8" cy="105.2" r="3.8"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</switch>
+</svg>
diff --git a/app/images/HMI_Dashboard_RightTire.svg b/app/images/HMI_Dashboard_RightTire.svg
new file mode 100644
index 0000000..fc26c86
--- /dev/null
+++ b/app/images/HMI_Dashboard_RightTire.svg
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 350 155"
+ style="enable-background:new 0 0 350 155;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:url(#SVGID_1_);}
+ .st1{fill:url(#SVGID_2_);}
+ .st2{fill:url(#SVGID_3_);}
+ .st3{fill:#FFFFFF;}
+ .st4{font-family:'Roboto-Regular';}
+ .st5{font-size:17px;}
+ .st6{letter-spacing:3;}
+ .st7{fill:#0DF9FF;}
+ .st8{fill:none;stroke:#0DF9FF;stroke-miterlimit:10;}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g id="Layer_2">
+ <g>
+ <g>
+ <g>
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="70.7484" y1="117.6118" x2="144.654" y2="25.7292">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <polygon class="st0" points="104.2,76.4 102.8,75 113.3,64.4 114.7,65.8 "/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="67.0298" y1="114.6207" x2="140.9354" y2="22.7381">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <polygon class="st1" points="103.2,75.9 97.5,70.1 98.9,68.7 104.6,74.5 "/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="68.2618" y1="115.6117" x2="142.1674" y2="23.729">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <path class="st2" d="M104.5,92.5c-12.1,0-22-9.9-22-22c0-12.1,9.9-22,22-22c2.4,0,4.8,0.4,7.1,1.2l-0.6,1.9
+ c-2.1-0.7-4.2-1.1-6.5-1.1c-11,0-20,9-20,20s9,20,20,20s20-9,20-20c0-2-0.3-3.9-0.9-5.8l1.9-0.6c0.6,2.1,0.9,4.2,0.9,6.4
+ C126.5,82.7,116.6,92.5,104.5,92.5z"/>
+ </g>
+ </g>
+ <g>
+ <g>
+ <polyline class="st8" points="241,85.5 241,104 13,104 "/>
+ <g>
+ <circle class="st7" cx="13.2" cy="104" r="3.8"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="Layer_3">
+ </g>
+ </g>
+</switch>
+</svg>
diff --git a/app/images/HMI_Dashboard_Speed_Icon.svg b/app/images/HMI_Dashboard_Speed_Icon.svg
new file mode 100644
index 0000000..a5f9c1b
--- /dev/null
+++ b/app/images/HMI_Dashboard_Speed_Icon.svg
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 82 82"
+ style="enable-background:new 0 0 82 82;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#FFFFFF;}
+ .st1{fill:none;stroke:url(#SVGID_1_);stroke-miterlimit:10;}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g>
+ <g>
+ <path class="st0" d="M41.1,15.2c-15.5-0.1-28.2,12.4-28.3,28c0,6.9,2.5,13.6,7.1,18.8c0.3,0.4,0.8,0.6,1.3,0.6l39.3,0.2
+ c0.5,0,1-0.2,1.3-0.6c4.7-5.1,7.2-11.8,7.3-18.7C69.2,28,56.7,15.3,41.1,15.2z M60.6,61.1l-39.3-0.2c-4.2-4.7-6.7-10.9-6.6-17.6
+ c0.1-14.6,12-26.3,26.5-26.2c14.6,0.1,26.3,12,26.2,26.5C67.3,50.3,64.8,56.4,60.6,61.1z M43.5,40.9
+ C43.5,40.9,43.5,40.9,43.5,40.9c-2.1-2-8.9-6.2-11.7-8c-0.4-0.2-0.8-0.2-1.1,0.1c-0.3,0.3-0.3,0.8-0.1,1.1
+ c1.8,2.8,5.9,9.7,7.8,11.7c0,0,0.1,0.1,0.1,0.1c0.6,0.6,1.5,1,2.4,1c1.9,0,3.5-1.6,3.5-3.5C44.5,42.4,44.1,41.6,43.5,40.9z"/>
+ <path class="st0" d="M54.7,56.5l-3.5-5.3c-0.3-0.5-0.9-0.8-1.5-0.8l-17.6-0.1c-0.6,0-1.1,0.3-1.5,0.8l-3.5,5.3
+ c-0.4,0.6-0.4,1.2-0.1,1.8s0.9,0.9,1.5,0.9c8.2,0,16.4,0.1,24.6,0.1c0.7,0,1.2-0.3,1.6-0.9C55.1,57.8,55.1,57.1,54.7,56.5z"/>
+ <path class="st0" d="M52.9,22.5c-0.1-0.5-0.4-0.9-0.9-1.1c-3.4-1.7-7.1-2.6-10.8-2.6c-3.8,0-7.5,0.8-10.9,2.5
+ c-0.5,0.2-0.8,0.6-0.9,1.1c-0.1,0.5,0,1,0.3,1.4l3.1,4.4c0.5,0.7,1.4,0.9,2.1,0.6c2-0.9,4.1-1.3,6.3-1.3c2.2,0,4.3,0.5,6.3,1.3
+ c0.8,0.3,1.7,0.1,2.1-0.6l3.1-4.4C52.9,23.5,53,23,52.9,22.5z"/>
+ <path class="st0" d="M58.1,25.7c-0.4-0.4-0.9-0.5-1.4-0.5c-0.5,0-1,0.3-1.3,0.7l-3.1,4.4c-0.5,0.7-0.4,1.6,0.2,2.2
+ c2.8,3,4.3,6.8,4.3,10.9c0,0.3,0,0.6,0,1c-0.1,0.8,0.5,1.6,1.3,1.8l5.2,1.4c0.5,0.1,1,0.1,1.5-0.2c0.4-0.3,0.7-0.7,0.8-1.3
+ c0.1-0.9,0.2-1.8,0.2-2.6C65.6,36.8,63,30.4,58.1,25.7z"/>
+ <path class="st0" d="M29.7,30.2l-3-4.4c-0.3-0.4-0.7-0.7-1.3-0.7c-0.5-0.1-1,0.1-1.4,0.5c-4.9,4.6-7.6,11-7.7,17.7
+ c0,0.9,0,1.8,0.1,2.6c0.1,0.5,0.3,1,0.7,1.3s0.9,0.4,1.4,0.3l5.2-1.4c0.8-0.2,1.4-1,1.3-1.8c0-0.3,0-0.6,0-1
+ c0-4.1,1.6-7.9,4.4-10.9C30.1,31.8,30.2,30.9,29.7,30.2z"/>
+ <g id="Layer_1_2_">
+ </g>
+ </g>
+
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-2.180208e-02" y1="40.8391" x2="80.9782" y2="40.8391" gradientTransform="matrix(0.9999 1.092937e-02 -1.092937e-02 0.9999 0.9706 -0.279)">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+
+ <ellipse transform="matrix(1.092937e-02 -0.9999 0.9999 1.092937e-02 -0.4457 81.5494)" class="st1" cx="41" cy="41" rx="40" ry="40"/>
+ </g>
+ </g>
+</switch>
+</svg>
diff --git a/app/images/HMI_Dashboard_TirePressure_OK.svg b/app/images/HMI_Dashboard_TirePressure_OK.svg
new file mode 100644
index 0000000..8d535b5
--- /dev/null
+++ b/app/images/HMI_Dashboard_TirePressure_OK.svg
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 44 44"
+ style="enable-background:new 0 0 44 44;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:url(#SVGID_1_);}
+ .st1{fill:url(#SVGID_2_);}
+ .st2{fill:url(#SVGID_3_);}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g>
+ <g>
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-11.7622" y1="69.0661" x2="62.1434" y2="-22.8165">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <polygon class="st0" points="21.6,27.8 20.2,26.4 30.8,15.9 32.2,17.3 "/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-15.4808" y1="66.075" x2="58.4248" y2="-25.8076">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <polygon class="st1" points="20.7,27.3 15,21.6 16.4,20.2 22.1,25.9 "/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-14.2488" y1="67.066" x2="59.6568" y2="-24.8166">
+ <stop offset="0" style="stop-color:#00ADDC"/>
+ <stop offset="8.369088e-02" style="stop-color:#0EB7E0"/>
+ <stop offset="0.3637" style="stop-color:#36D4EE"/>
+ <stop offset="0.6195" style="stop-color:#53EAF7"/>
+ <stop offset="0.84" style="stop-color:#65F6FD"/>
+ <stop offset="1" style="stop-color:#6BFBFF"/>
+ </linearGradient>
+ <path class="st2" d="M22,44C9.9,44,0,34.1,0,22C0,9.9,9.9,0,22,0c2.4,0,4.8,0.4,7.1,1.2L28.5,3C26.4,2.3,24.2,2,22,2
+ C11,2,2,11,2,22s9,20,20,20s20-9,20-20c0-2-0.3-3.9-0.9-5.8l1.9-0.6c0.6,2.1,0.9,4.2,0.9,6.4C44,34.1,34.1,44,22,44z"/>
+ </g>
+ </g>
+ </g>
+</switch>
+</svg>
diff --git a/app/images/images.qrc b/app/images/images.qrc
new file mode 100644
index 0000000..a0ad957
--- /dev/null
+++ b/app/images/images.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/images">
+ <file>HMI_Dashboard_Car.png</file>
+ <file>HMI_Dashboard_Fuel_Icon.svg</file>
+ <file>HMI_Dashboard_LeftTire.svg</file>
+ <file>HMI_Dashboard_RightTire.svg</file>
+ <file>HMI_Dashboard_Speed_Icon.svg</file>
+ <file>HMI_Dashboard_TirePressure_OK.svg</file>
+ <file>HMI_Dashboard_Fuel_Details.svg</file>
+ </qresource>
+</RCC>
diff --git a/app/main.cpp b/app/main.cpp
new file mode 100644
index 0000000..3520605
--- /dev/null
+++ b/app/main.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Qt Company Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QtAGLExtras/AGLApplication>
+#include <QtQml/QQmlApplicationEngine>
+#include "translator.h"
+
+int main(int argc, char *argv[])
+{
+ AGLApplication app(argc, argv);
+ app.setApplicationName("Dashboard");
+ app.setupApplicationRole("dashboard");
+
+ qmlRegisterType<Translator>("Translator", 1, 0, "Translator");
+ app.load(QUrl(QStringLiteral("qrc:/Dashboard.qml")));
+ return app.exec();
+}
+
diff --git a/app/models/CarsModel.qml b/app/models/CarsModel.qml
new file mode 100644
index 0000000..3dcdb74
--- /dev/null
+++ b/app/models/CarsModel.qml
@@ -0,0 +1,35 @@
+/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+pragma Singleton
+
+import QtQuick 2.0
+
+ListModel {
+ ListElement {
+ name: "F-Type"
+ mpg: 25
+ tank: 18.5
+ speed: 171
+ image: "images/F-Type_Call_Outs.png"
+ }
+
+ ListElement {
+ name: "Range Rover"
+ mpg: 22
+ tank: 27.7
+ speed: 162
+ image: "images/Range_Rover_Outline_Call_Outs.png"
+ }
+
+ ListElement {
+ name: "Land Rover LR4"
+ mpg: 18
+ tank: 22.8
+ speed: 121
+ image: "images/LR4_Outline_Call_Outs.png"
+ }
+}
diff --git a/app/models/TireModel.qml b/app/models/TireModel.qml
new file mode 100644
index 0000000..5c7e5ab
--- /dev/null
+++ b/app/models/TireModel.qml
@@ -0,0 +1,64 @@
+/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+pragma Singleton
+
+import QtQuick 2.0
+
+Item {
+ property bool metric: false
+ property alias pressure: pressureItem
+
+ function psiToBar(value) {
+ return (metric ? 0.06895 : 1) * value
+ }
+
+ Item {
+ id: pressureItem
+
+ property real frontLeft: psiToBar(28 + flDiff)
+ property real frontRight: psiToBar(28 + frDiff)
+ property real rearLeft: psiToBar(28 + rlDiff)
+ property real rearRight: psiToBar(28 + rrDiff)
+
+ property real flDiff: 0
+ property real frDiff: 0
+ property real rlDiff: 0
+ property real rrDiff: 0
+
+ NumberAnimation on flDiff {
+ from: -5
+ to: 5
+ duration: 5000
+ loops: Animation.Infinite
+ easing.type: Easing.CosineCurve
+ }
+
+ NumberAnimation on frDiff {
+ from: -5
+ to: 5
+ duration: 5300
+ loops: Animation.Infinite
+ easing.type: Easing.CosineCurve
+ }
+
+ NumberAnimation on rlDiff {
+ from: -5
+ to: 5
+ duration: 5700
+ loops: Animation.Infinite
+ easing.type: Easing.CosineCurve
+ }
+
+ NumberAnimation on rrDiff {
+ from: -5
+ to: 5
+ duration: 6100
+ loops: Animation.Infinite
+ easing.type: Easing.CosineCurve
+ }
+ }
+}
diff --git a/app/models/TripModel.qml b/app/models/TripModel.qml
new file mode 100644
index 0000000..f2c4d02
--- /dev/null
+++ b/app/models/TripModel.qml
@@ -0,0 +1,19 @@
+/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+pragma Singleton
+
+import QtQuick 2.0
+
+Item {
+ property bool metric: false
+
+ function milesToKm(value) {
+ return (metric ? 1.60934 : 1) * value
+ }
+
+ property real distance: milesToKm(100000.5)
+}
diff --git a/app/models/qmldir b/app/models/qmldir
new file mode 100644
index 0000000..1dc659e
--- /dev/null
+++ b/app/models/qmldir
@@ -0,0 +1,9 @@
+#/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved.
+# *
+# * This Source Code Form is subject to the terms of the Mozilla Public
+# * License, v. 2.0. If a copy of the MPL was not distributed with this
+# * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+singleton CarsModel 1.0 CarsModel.qml
+singleton TireModel 1.0 TireModel.qml
+singleton TripModel 1.0 TripModel.qml
diff --git a/app/translations.pri b/app/translations.pri
new file mode 100644
index 0000000..81bd94b
--- /dev/null
+++ b/app/translations.pri
@@ -0,0 +1,16 @@
+defineReplace(prependAll) {
+ for(a,$$1):result += $$2$${a}$$3
+ return($$result)
+}
+
+qtPrepareTool(QMAKE_LRELEASE, lrelease)
+TRANSLATIONS = $$prependAll(LANGUAGES, $$PWD/translations/$${TARGET}_,.ts)
+
+qm.depends = $${TRANSLATIONS}
+qm.input = TRANSLATIONS
+qm.output = $$OUT_PWD/../package/root/translations/${QMAKE_FILE_BASE}.qm
+qm.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
+qm.name = LRELEASE ${QMAKE_FILE_IN}
+qm.CONFIG += no_link
+QMAKE_EXTRA_COMPILERS += qm
+PRE_TARGETDEPS += compiler_qm_make_all
diff --git a/app/translations/dashboard_fr_FR.ts b/app/translations/dashboard_fr_FR.ts
new file mode 100644
index 0000000..7699dae
--- /dev/null
+++ b/app/translations/dashboard_fr_FR.ts
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>Dashboard</name>
+ <message>
+ <location filename="../Dashboard.qml" line="138"/>
+ <source>LEFT FRONT TIRE</source>
+ <translation>Pneu Avant Gauche</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="139"/>
+ <location filename="../Dashboard.qml" line="149"/>
+ <location filename="../Dashboard.qml" line="158"/>
+ <location filename="../Dashboard.qml" line="168"/>
+ <source>%1 PSI</source>
+ <translation>Pression %1</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="148"/>
+ <source>LEFT REAR TIRE</source>
+ <translation>Pneu Arrière Gauche</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="157"/>
+ <source>RIGHT FRONT TIRE</source>
+ <translation>Pneu Avant Droit</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="167"/>
+ <source>RIGHT REAR TIRE</source>
+ <translation>Pneu Arrière Droit</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="189"/>
+ <source>(RPM)</source>
+ <translation>Tr/mn</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="219"/>
+ <source>LEVEL:</source>
+ <translation>Niveau:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="228"/>
+ <source>%1 GALLONS</source>
+ <translation>%1 Litres</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="238"/>
+ <source>RANGE:</source>
+ <translation>Autonomie:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="247"/>
+ <source>%1 MI</source>
+ <translation>%1 Km</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="257"/>
+ <source>AVG:</source>
+ <translation>Moyenne:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="266"/>
+ <source>%1 MPG</source>
+ <translation>%1 l/100km</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="277"/>
+ <source>FUEL</source>
+ <translation>Carburant</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="290"/>
+ <source>English</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="294"/>
+ <source>Français</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="298"/>
+ <source>日本語</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="302"/>
+ <source>中文简体</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>main</name>
+ <message>
+ <source>port for binding</source>
+ <translation type="vanished">Port du Binder</translation>
+ </message>
+ <message>
+ <source>secret for binding</source>
+ <translation type="vanished">Secret Binder</translation>
+ </message>
+</context>
+</TS>
diff --git a/app/translations/dashboard_ja_JP.ts b/app/translations/dashboard_ja_JP.ts
new file mode 100644
index 0000000..5dd6e5f
--- /dev/null
+++ b/app/translations/dashboard_ja_JP.ts
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ja_JP">
+<context>
+ <name>Dashboard</name>
+ <message>
+ <location filename="../Dashboard.qml" line="138"/>
+ <source>LEFT FRONT TIRE</source>
+ <translation>左前輪</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="139"/>
+ <location filename="../Dashboard.qml" line="149"/>
+ <location filename="../Dashboard.qml" line="158"/>
+ <location filename="../Dashboard.qml" line="168"/>
+ <source>%1 PSI</source>
+ <translation>空気圧 %1</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="148"/>
+ <source>LEFT REAR TIRE</source>
+ <translation>左後輪</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="157"/>
+ <source>RIGHT FRONT TIRE</source>
+ <translation>右前輪</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="167"/>
+ <source>RIGHT REAR TIRE</source>
+ <translation>右後輪</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="189"/>
+ <source>(RPM)</source>
+ <translation>(RPM)</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="219"/>
+ <source>LEVEL:</source>
+ <translation>レベル:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="228"/>
+ <source>%1 GALLONS</source>
+ <translation>%1 ガロン</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="238"/>
+ <source>RANGE:</source>
+ <translation>レンジ:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="247"/>
+ <source>%1 MI</source>
+ <translation>%1 MI</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="257"/>
+ <source>AVG:</source>
+ <translation>平均:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="266"/>
+ <source>%1 MPG</source>
+ <translation>%1 MPG</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="277"/>
+ <source>FUEL</source>
+ <translation>燃料</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="290"/>
+ <source>English</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="294"/>
+ <source>Français</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="298"/>
+ <source>日本語</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="302"/>
+ <source>中文简体</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/app/translations/dashboard_zh_CN.ts b/app/translations/dashboard_zh_CN.ts
new file mode 100644
index 0000000..a37155a
--- /dev/null
+++ b/app/translations/dashboard_zh_CN.ts
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>Dashboard</name>
+ <message>
+ <location filename="../Dashboard.qml" line="138"/>
+ <source>LEFT FRONT TIRE</source>
+ <translation>左前车胎</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="139"/>
+ <location filename="../Dashboard.qml" line="149"/>
+ <location filename="../Dashboard.qml" line="158"/>
+ <location filename="../Dashboard.qml" line="168"/>
+ <source>%1 PSI</source>
+ <translation>%1 磅每平方英寸(PSI)</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="148"/>
+ <source>LEFT REAR TIRE</source>
+ <translation>左后车胎</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="157"/>
+ <source>RIGHT FRONT TIRE</source>
+ <translation>右前车胎</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="167"/>
+ <source>RIGHT REAR TIRE</source>
+ <translation>右后车胎</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="189"/>
+ <source>(RPM)</source>
+ <translation>引擎转速</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="219"/>
+ <source>LEVEL:</source>
+ <translation>剩余油量:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="228"/>
+ <source>%1 GALLONS</source>
+ <translation>%1 加仑</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="238"/>
+ <source>RANGE:</source>
+ <translation>续航里程:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="247"/>
+ <source>%1 MI</source>
+ <translation>%1 英里</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="257"/>
+ <source>AVG:</source>
+ <translation type="unfinished">平均油耗:</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="266"/>
+ <source>%1 MPG</source>
+ <translation type="unfinished">%1 英里每加仑(MPG)</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="277"/>
+ <source>FUEL</source>
+ <translation>燃油</translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="290"/>
+ <source>English</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="294"/>
+ <source>Français</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="298"/>
+ <source>日本語</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../Dashboard.qml" line="302"/>
+ <source>中文简体</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>main</name>
+ <message>
+ <source>port for binding</source>
+ <translation type="vanished">Binder端口</translation>
+ </message>
+ <message>
+ <source>secret for binding</source>
+ <translation type="vanished">Binder令牌</translation>
+ </message>
+</context>
+</TS>
diff --git a/app/translator.cpp b/app/translator.cpp
new file mode 100644
index 0000000..9b67f13
--- /dev/null
+++ b/app/translator.cpp
@@ -0,0 +1,52 @@
+#include "translator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QLocale>
+#include <QtCore/QTranslator>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+Translator::Translator(QObject *parent)
+ : QObject(parent)
+ , m_language(QStringLiteral("C"))
+ , m_translator(nullptr)
+{
+}
+
+QString Translator::translate(const QString &string, const QString &language) const
+{
+ Q_UNUSED(language)
+ return string;
+}
+
+QString Translator::language() const
+{
+ return m_language;
+}
+
+void Translator::setLanguage(const QString &language)
+{
+ if (m_language == language) return;
+ m_language = language;
+ setTranslator(language);
+ emit languageChanged(language);
+}
+
+void Translator::setTranslator(const QString &language)
+{
+ if (m_translator) {
+ QCoreApplication::removeTranslator(m_translator);
+ } else {
+ m_translator = new QTranslator(this);
+ }
+ QLocale locale(language);
+ QString fileName = QCoreApplication::instance()->applicationName().toLower();
+ qDebug() << "####" << QDir::currentPath() << QCoreApplication::applicationDirPath();
+ if (m_translator->load(locale, fileName, QStringLiteral("_"), QStringLiteral("%1/../translations").arg(QCoreApplication::applicationDirPath()))) {
+ QCoreApplication::installTranslator(m_translator);
+ } else {
+ delete m_translator;
+ m_translator = nullptr;
+ }
+}
+
diff --git a/app/translator.h b/app/translator.h
new file mode 100644
index 0000000..82c5872
--- /dev/null
+++ b/app/translator.h
@@ -0,0 +1,32 @@
+#ifndef TRANSLATOR_H
+#define TRANSLATOR_H
+
+#include <QtCore/QObject>
+
+class QTranslator;
+
+class Translator : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged)
+public:
+ explicit Translator(QObject *parent = nullptr);
+
+ QString language() const;
+
+ Q_INVOKABLE QString translate(const QString &string, const QString &language) const;
+public slots:
+ void setLanguage(const QString &language);
+
+signals:
+ void languageChanged(const QString &language);
+
+private slots:
+ void setTranslator(const QString &language);
+
+private:
+ QString m_language;
+ QTranslator *m_translator;
+};
+
+#endif // TRANSLATOR_H